// public methods /// <summary> /// Authenticates the connection against the given database. /// </summary> /// <param name="connection">The connection.</param> /// <param name="credential">The credential.</param> public void Authenticate(MongoConnection connection, MongoCredential credential) { var nonceCommand = new CommandDocument("getnonce", 1); var commandResult = connection.RunCommandAs<CommandResult>(credential.Source, QueryFlags.None, nonceCommand, false); if (!commandResult.Ok) { throw new MongoAuthenticationException( "Error getting nonce for authentication.", new MongoCommandException(commandResult)); } var nonce = commandResult.Response["nonce"].AsString; var passwordDigest = ((PasswordEvidence)credential.Evidence).ComputeMongoCRPasswordDigest(credential.Username); var digest = MongoUtils.Hash(nonce + credential.Username + passwordDigest); var authenticateCommand = new CommandDocument { { "authenticate", 1 }, { "user", credential.Username }, { "nonce", nonce }, { "key", digest } }; commandResult = connection.RunCommandAs<CommandResult>(credential.Source, QueryFlags.None, authenticateCommand, false); if (!commandResult.Ok) { var message = string.Format("Invalid credential for database '{0}'.", credential.Source); throw new MongoAuthenticationException( message, new MongoCommandException(commandResult)); } }
// public methods /// <summary> /// Authenticates the connection against the given database. /// </summary> /// <param name="connection">The connection.</param> /// <param name="credential">The credential.</param> public void Authenticate(MongoConnection connection, MongoCredential credential) { using (var conversation = new SaslConversation()) { var currentStep = _mechanism.Initialize(connection, credential); var command = new CommandDocument { { "saslStart", 1 }, { "mechanism", _mechanism.Name }, { "payload", currentStep.BytesToSendToServer } }; while (true) { CommandResult result; try { result = connection.RunCommandAs<CommandResult>(credential.Source, QueryFlags.SlaveOk, command, true); } catch (MongoCommandException ex) { var message = "Unknown error occured during authentication."; var code = ex.CommandResult.Code; var errmsg = ex.CommandResult.ErrorMessage; if(code.HasValue && errmsg != null) { message = string.Format("Error: {0} - {1}", code, errmsg); } throw new MongoSecurityException(message, ex); } if (result.Response["done"].AsBoolean) { break; } currentStep = currentStep.Transition(conversation, result.Response["payload"].AsByteArray); command = new CommandDocument { { "saslContinue", 1 }, { "conversationId", result.Response["conversationId"].AsInt32 }, { "payload", currentStep.BytesToSendToServer } }; } } }
private void Ping(MongoConnection connection) { try { var pingCommand = new CommandDocument("ping", 1); Stopwatch stopwatch = Stopwatch.StartNew(); connection.RunCommandAs<CommandResult>("admin", QueryFlags.SlaveOk, pingCommand, true); stopwatch.Stop(); var currentAverage = _pingTimeAggregator.Average; _pingTimeAggregator.Include(stopwatch.Elapsed); var newAverage = _pingTimeAggregator.Average; if (currentAverage != newAverage) { OnAveragePingTimeChanged(); } } catch { _pingTimeAggregator.Clear(); SetState(MongoServerState.Disconnected); throw; } }
// private methods private void LookupServerInformation(MongoConnection connection) { IsMasterResult isMasterResult = null; bool ok = false; try { var isMasterCommand = new CommandDocument("ismaster", 1); isMasterResult = connection.RunCommandAs<IsMasterResult>("admin", QueryFlags.SlaveOk, isMasterCommand, false); isMasterResult.Command = isMasterCommand; if (!isMasterResult.Ok) { throw new MongoCommandException(isMasterResult); } MongoServerBuildInfo buildInfo; var buildInfoCommand = new CommandDocument("buildinfo", 1); var buildInfoResult = connection.RunCommandAs<CommandResult>("admin", QueryFlags.SlaveOk, buildInfoCommand, false); if (buildInfoResult.Ok) { buildInfo = MongoServerBuildInfo.FromCommandResult(buildInfoResult); } else { // short term fix: if buildInfo fails due to auth we don't know the server version; see CSHARP-324 if (buildInfoResult.ErrorMessage != "need to login") { throw new MongoCommandException(buildInfoResult); } buildInfo = null; } ReplicaSetInformation replicaSetInformation = null; MongoServerInstanceType instanceType = MongoServerInstanceType.StandAlone; if (isMasterResult.IsReplicaSet) { var peers = isMasterResult.Hosts.Concat(isMasterResult.Passives).Concat(isMasterResult.Arbiters).ToList(); replicaSetInformation = new ReplicaSetInformation(isMasterResult.ReplicaSetName, isMasterResult.Primary, peers, isMasterResult.Tags); instanceType = MongoServerInstanceType.ReplicaSetMember; } else if (isMasterResult.Message != null && isMasterResult.Message == "isdbgrid") { instanceType = MongoServerInstanceType.ShardRouter; } var newServerInfo = new ServerInformation { BuildInfo = buildInfo, InstanceType = instanceType, IsArbiter = isMasterResult.IsArbiterOnly, IsMasterResult = isMasterResult, IsPassive = isMasterResult.IsPassive, IsPrimary = isMasterResult.IsPrimary, IsSecondary = isMasterResult.IsSecondary, MaxDocumentSize = isMasterResult.MaxBsonObjectSize, MaxMessageLength = isMasterResult.MaxMessageLength, ReplicaSetInformation = replicaSetInformation }; MongoServerState currentState; lock (_serverInstanceLock) { currentState = _state; } SetState(currentState, newServerInfo); ok = true; } finally { if (!ok) { ServerInformation currentServerInfo; lock (_serverInstanceLock) { currentServerInfo = _serverInfo; } // keep the current instance type, build info, and replica set info // as these aren't relevent to state and are likely still correct. var newServerInfo = new ServerInformation { BuildInfo = currentServerInfo.BuildInfo, InstanceType = currentServerInfo.InstanceType, IsArbiter = false, IsMasterResult = isMasterResult, IsPassive = false, IsPrimary = false, IsSecondary = false, MaxDocumentSize = currentServerInfo.MaxDocumentSize, MaxMessageLength = currentServerInfo.MaxMessageLength, ReplicaSetInformation = currentServerInfo.ReplicaSetInformation }; SetState(MongoServerState.Disconnected, newServerInfo); } } }