/// <summary>
 /// Initializes the mechanism.
 /// </summary>
 /// <param name="connection">The connection.</param>
 /// <param name="credentials">The credentials.</param>
 /// <returns>The initial step.</returns>
 public ISaslStep Initialize(Internal.MongoConnection connection, MongoCredentials credentials)
 {
     return new ManagedDigestMD5Implementation(
         connection.ServerInstance.Address.Host,
         credentials.Username,
         ((PasswordEvidence)credentials.Evidence).Password);
 }       
        // public methods
        /// <summary>
        /// Authenticates the connection against the given database.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="credentials">The credentials.</param>
        public void Authenticate(MongoConnection connection, MongoCredentials credentials)
        {
            var nonceCommand = new CommandDocument("getnonce", 1);
            var commandResult = connection.RunCommand(credentials.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 = MongoUtils.Hash(credentials.Username + ":mongo:" + ((PasswordEvidence)credentials.Evidence).Password);
            var digest = MongoUtils.Hash(nonce + credentials.Username + passwordDigest);
            var authenticateCommand = new CommandDocument
                {
                    { "authenticate", 1 },
                    { "user", credentials.Username },
                    { "nonce", nonce },
                    { "key", digest }
                };

            commandResult = connection.RunCommand(credentials.Source, QueryFlags.None, authenticateCommand, false);
            if (!commandResult.Ok)
            {
                var message = string.Format("Invalid credentials for database '{0}'.", credentials.Source);
                throw new MongoAuthenticationException(
                    message,
                    new MongoCommandException(commandResult));
            }
        }
        // private methods
        private void Authenticate(MongoCredentials credentials, List<string> serverSupportedMethods)
        {
            foreach (var clientSupportedMethod in __clientSupportedMethods)
            {
                if (serverSupportedMethods.Contains(clientSupportedMethod.Name) && clientSupportedMethod.CanUse(credentials))
                {
                    clientSupportedMethod.Authenticate(_connection, credentials);
                    return;
                }
            }

            var message = string.Format("Unable to negotiate a protocol to authenticate. Credentials for source {0}, username {1} over protocol {2} could not be authenticated", credentials.Source, credentials.Username, credentials.AuthenticationProtocol);
            throw new MongoSecurityException(message);
        }
        /// <summary>
        /// Initializes the mechanism.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="credentials">The credentials.</param>
        /// <returns>The initial step.</returns>
        public ISaslStep Initialize(MongoConnection connection, MongoCredentials credentials)
        {
            // TODO: provide an override to force the use of gsasl?
            bool useGsasl = !Environment.OSVersion.Platform.ToString().Contains("Win");
            if (useGsasl)
            {
                throw new NotImplementedException("Gssapi Support on Non-Windows Machinse is Not Implemented.");
                //return new GsaslGssapiImplementation(
                //    connection.ServerInstance.Address.Host,
                //    credentials.Username,
                //    credentials.Evidence);
            }

            return new WindowsGssapiImplementation(
                connection.ServerInstance.Address.Host,
                credentials.Username,
                credentials.Evidence);
        }
        // public methods
        /// <summary>
        /// Authenticates the connection against the given database.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="credentials">The credentials.</param>
        public void Authenticate(MongoConnection connection, MongoCredentials credentials)
        {
            using (var conversation = new SaslConversation())
            {
                var currentStep = _mechanism.Initialize(connection, credentials);

                var command = new CommandDocument
                {
                    { "saslStart", 1 },
                    { "mechanism", _mechanism.Name },
                    { "payload", currentStep.BytesToSendToServer }
                };

                while (true)
                {
                    var result = connection.RunCommand(credentials.Source, QueryFlags.SlaveOk, command, true);
                    var code = result.Response["code"].AsInt32;
                    if (code != 0)
                    {
                        HandleError(result, code);
                    }
                    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 }
                    };
                }
            }
        }
 /// <summary>
 /// Initializes the mechanism.
 /// </summary>
 /// <param name="connection">The connection.</param>
 /// <param name="credentials">The credentials.</param>
 /// <returns>The initial step.</returns>
 public ISaslStep Initialize(MongoConnection connection, MongoCredentials credentials)
 {
     return new ManagedCramMD5Implementation(credentials.Username, ((PasswordEvidence)credentials.Evidence).Password);
     //return new GsaslCramMD5Implementation(identity);
 }
 /// <summary>
 /// Determines whether this instance can use the specified credentials.
 /// </summary>
 /// <param name="credentials">The credentials.</param>
 /// <returns>
 ///   <c>true</c> if this instance can use the specified credentials; otherwise, <c>false</c>.
 /// </returns>
 public bool CanUse(MongoCredentials credentials)
 {
     return _mechanism.CanUse(credentials);
 }
Exemple #8
0
 public bool DatabaseExists(string databaseName, MongoCredentials adminCredentials)
 {
     return(_mongoServer.DatabaseExists(databaseName, adminCredentials));
 }
Exemple #9
0
 IMongoDatabase IMongoServer.this[string databaseName, MongoCredentials credentials, SafeMode safeMode]
 {
     get { return(new MongoDatabaseProxy(_mongoServer[databaseName, credentials, safeMode])); }
 }
 // constructors
 public Authentication(MongoCredentials credentials)
 {
     _credentials = credentials;
     _lastUsed    = DateTime.UtcNow;
 }
        internal MongoConnection AcquireConnection(string databaseName, MongoCredentials credentials, AcquireConnectionOptions options)
        {
            MongoConnection connectionToClose = null;
            try
            {
                DateTime timeoutAt = DateTime.UtcNow + options.WaitQueueTimeout;

                lock (_connectionPoolLock)
                {
                    if (_waitQueueSize >= _settings.WaitQueueSize && !options.OkToExceedWaitQueueSize)
                    {
                        throw new MongoConnectionException("Too many threads are already waiting for a connection.");
                    }

                    _waitQueueSize += 1;
                    try
                    {
                        while (true)
                        {
                            if (_availableConnections.Count > 0)
                            {
                                // first try to find the most recently used connection that is already authenticated for this database
                                for (int i = _availableConnections.Count - 1; i >= 0; i--)
                                {
                                    var connection = _availableConnections[i];
                                    if (connection.IsExpired())
                                    {
                                        _availableConnections.RemoveAt(i);
                                        connectionToClose = connection;
                                        return new MongoConnection(this);
                                    }
                                    else if (connection.IsAuthenticated(databaseName, credentials))
                                    {
                                        _availableConnections.RemoveAt(i);
                                        return connection;
                                    }
                                }

                                // otherwise find the most recently used connection that can be authenticated for this database
                                for (int i = _availableConnections.Count - 1; i >= 0; i--)
                                {
                                    var connection = _availableConnections[i];
                                    if (connection.CanAuthenticate(databaseName, credentials))
                                    {
                                        _availableConnections.RemoveAt(i);
                                        return connection;
                                    }
                                }

                                // otherwise replace the least recently used connection with a brand new one
                                // if this happens a lot the connection pool size should be increased
                                connectionToClose = _availableConnections[0];
                                _availableConnections.RemoveAt(0);
                                return new MongoConnection(this);
                            }

                            // avoid waiting by creating a new connection if options allow it
                            if (options.OkToAvoidWaitingByCreatingNewConnection)
                            {
                                if (_poolSize < _settings.MaxConnectionPoolSize || options.OkToExceedMaxConnectionPoolSize)
                                {
                                    // make sure connection is created successfully before incrementing poolSize
                                    // connection will be opened later outside of the lock
                                    var connection = new MongoConnection(this);
                                    _poolSize += 1;
                                    return connection;
                                }
                            }

                            // wait for a connection to be released
                            var timeRemaining = timeoutAt - DateTime.UtcNow;
                            if (timeRemaining > TimeSpan.Zero)
                            {
                                // other methods should call Monitor.Pulse whenever:
                                // 1. an available connection is added _availableConnections
                                // 2. the _poolSize changes
                                Monitor.Wait(_connectionPoolLock, timeRemaining);
                            }
                            else
                            {
                                if (options.OkToExceedMaxConnectionPoolSize)
                                {
                                    // make sure connection is created successfully before incrementing poolSize
                                    // connection will be opened later outside of the lock
                                    var connection = new MongoConnection(this);
                                    _poolSize += 1;
                                    return connection;
                                }
                                else
                                {
                                    throw new TimeoutException("Timeout waiting for a MongoConnection.");
                                }
                            }
                        }
                    }
                    finally
                    {
                        _waitQueueSize -= 1;
                    }
                }
            }
            finally
            {
                if (connectionToClose != null)
                {
                    try
                    {
                        connectionToClose.Close();
                    }
                    catch
                    {
                        // ignore exceptions
                    }
                }
            }
        }
        // internal methods
        internal MongoConnection AcquireConnection(string databaseName, MongoCredentials credentials)
        {
            lock (_connectionPoolLock)
            {
                if (_waitQueueSize >= _settings.WaitQueueSize)
                {
                    throw new MongoConnectionException("Too many threads are already waiting for a connection.");
                }

                _waitQueueSize += 1;
                try
                {
                    DateTime timeoutAt = DateTime.UtcNow + _settings.WaitQueueTimeout;
                    while (true)
                    {
                        if (_availableConnections.Count > 0)
                        {
                            // first try to find the most recently used connection that is already authenticated for this database
                            for (int i = _availableConnections.Count - 1; i >= 0; i--)
                            {
                                if (_availableConnections[i].IsAuthenticated(databaseName, credentials))
                                {
                                    var connection = _availableConnections[i];
                                    _availableConnections.RemoveAt(i);
                                    return connection;
                                }
                            }

                            // otherwise find the most recently used connection that can be authenticated for this database
                            for (int i = _availableConnections.Count - 1; i >= 0; i--)
                            {
                                if (_availableConnections[i].CanAuthenticate(databaseName, credentials))
                                {
                                    var connection = _availableConnections[i];
                                    _availableConnections.RemoveAt(i);
                                    return connection;
                                }
                            }

                            // otherwise replace the least recently used connection with a brand new one
                            // if this happens a lot the connection pool size should be increased
                            _availableConnections[0].Close();
                            _availableConnections.RemoveAt(0);
                            return new MongoConnection(this);
                        }

                        // create a new connection if maximum pool size has not been reached
                        if (_poolSize < _settings.MaxConnectionPoolSize)
                        {
                            // make sure connection is created successfully before incrementing poolSize
                            // connection will be opened later outside of the lock
                            var connection = new MongoConnection(this);
                            _poolSize += 1;
                            return connection;
                        }

                        // wait for a connection to be released
                        var timeRemaining = timeoutAt - DateTime.UtcNow;
                        if (timeRemaining > TimeSpan.Zero)
                        {
                            Monitor.Wait(_connectionPoolLock, timeRemaining);
                        }
                        else
                        {
                            throw new TimeoutException("Timeout waiting for a MongoConnection.");
                        }
                    }
                }
                finally
                {
                    _waitQueueSize -= 1;
                }
            }
        }
 // internal methods
 internal MongoConnection AcquireConnection(string databaseName, MongoCredentials credentials)
 {
     return AcquireConnection(databaseName, credentials, _defaultAcquireConnectionOptions);
 }
 /// <summary>
 /// Determines whether this instance can use the specified credentials.
 /// </summary>
 /// <param name="credentials">The credentials.</param>
 /// <returns>
 ///   <c>true</c> if this instance can use the specified credentials; otherwise, <c>false</c>.
 /// </returns>
 public bool CanUse(MongoCredentials credentials)
 {
     return credentials.AuthenticationProtocol == MongoAuthenticationProtocol.Strongest &&
         credentials.Evidence is PasswordEvidence;
 }
 public void AddUser(MongoCredentials credentials, bool readOnly)
 {
     _mongoDatabase.AddUser(credentials, readOnly);
 }
 public void AddUser(MongoCredentials credentials)
 {
     _mongoDatabase.AddUser(credentials);
 }
 public CommandResult RenameCollection(string oldCollectionName, string newCollectionName, MongoCredentials adminCredentials)
 {
     return(_mongoDatabase.RenameCollection(oldCollectionName, newCollectionName, adminCredentials));
 }
        // internal methods
        internal MongoConnection AcquireConnection(string databaseName, MongoCredentials credentials)
        {
            lock (_connectionPoolLock)
            {
                if (_waitQueueSize >= _settings.WaitQueueSize)
                {
                    throw new MongoConnectionException("Too many threads are already waiting for a connection.");
                }

                _waitQueueSize += 1;
                try
                {
                    DateTime timeoutAt = DateTime.UtcNow + _settings.WaitQueueTimeout;
                    while (true)
                    {
                        if (_availableConnections.Count > 0)
                        {
                            // first try to find the most recently used connection that is already authenticated for this database
                            for (int i = _availableConnections.Count - 1; i >= 0; i--)
                            {
                                if (_availableConnections[i].IsAuthenticated(databaseName, credentials))
                                {
                                    var connection = _availableConnections[i];
                                    _availableConnections.RemoveAt(i);
                                    return(connection);
                                }
                            }

                            // otherwise find the most recently used connection that can be authenticated for this database
                            for (int i = _availableConnections.Count - 1; i >= 0; i--)
                            {
                                if (_availableConnections[i].CanAuthenticate(databaseName, credentials))
                                {
                                    var connection = _availableConnections[i];
                                    _availableConnections.RemoveAt(i);
                                    return(connection);
                                }
                            }

                            // otherwise replace the least recently used connection with a brand new one
                            // if this happens a lot the connection pool size should be increased
                            _availableConnections[0].Close();
                            _availableConnections.RemoveAt(0);
                            return(new MongoConnection(this));
                        }

                        // create a new connection if maximum pool size has not been reached
                        if (_poolSize < _settings.MaxConnectionPoolSize)
                        {
                            // make sure connection is created successfully before incrementing poolSize
                            // connection will be opened later outside of the lock
                            var connection = new MongoConnection(this);
                            _poolSize += 1;
                            return(connection);
                        }

                        // wait for a connection to be released
                        var timeRemaining = timeoutAt - DateTime.UtcNow;
                        if (timeRemaining > TimeSpan.Zero)
                        {
                            Monitor.Wait(_connectionPoolLock, timeRemaining);
                        }
                        else
                        {
                            throw new TimeoutException("Timeout waiting for a MongoConnection.");
                        }
                    }
                }
                finally
                {
                    _waitQueueSize -= 1;
                }
            }
        }
 // public methods
 /// <summary>
 /// Determines whether this instance can authenticate with the specified credentials.
 /// </summary>
 /// <param name="credentials">The credentials.</param>
 /// <returns>
 ///   <c>true</c> if this instance can authenticate with the specified credentials; otherwise, <c>false</c>.
 /// </returns>
 /// <exception cref="System.NotImplementedException"></exception>
 public bool CanUse(MongoCredentials credentials)
 {
     return credentials.AuthenticationProtocol == MongoAuthenticationProtocol.Gssapi && 
         credentials.Identity is MongoExternalIdentity;
 }
Exemple #20
0
        private MongoUser GetMongoUser()
        {
            var credentials = new MongoCredentials(this.UserName, this.Password, this.Admin);

            return(new MongoUser(credentials, !credentials.Admin));
        }
Exemple #21
0
 // constructors
 public Authentication(MongoCredentials credentials)
 {
     this.credentials = credentials;
     this.lastUsed    = DateTime.UtcNow;
 }