text: var DbCommand = require('../commands/db_command').DbCommand
    , utils = require('../utils')
    , format = require('util').format;
  
  // Kerberos class
  var Kerberos = null;
  var MongoAuthProcess = null;
  // Try to grab the Kerberos class
  try {
    Kerberos = require('kerberos').Kerberos
    // Authentication process for Mongo
    MongoAuthProcess = require('kerberos').processes.MongoAuthProcess
  } catch(err) {}
  
  var authenticate = function(db, username, password, authdb, options, callback) {
    var numberOfConnections = 0;
    var errorObject = null;  
    var numberOfValidConnections = 0;
    var credentialsValid = false;
  
    // We don't have the Kerberos library
    if(Kerberos == null) return callback(new Error("Kerberos library is not installed"));
  
    if(options['connection'] != null) {
      //if a connection was explicitly passed on options, then we have only one...
      numberOfConnections = 1;
    } else {
      // Get the amount of connections in the pool to ensure we have authenticated all comments
      numberOfConnections = db.serverConfig.allRawConnections().length;
      options['onAll'] = true;
    }
  
    // Set the sspi server name
    var gssapiServiceName = options['gssapiServiceName'] || 'mongodb';
  
    // Grab all the connections
    var connections = db.serverConfig.allRawConnections();
    
    // Authenticate all connections
    for(var i = 0; i < numberOfConnections; i++) {
      // Start Auth process for a connection
      SSIPAuthenticate(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) {
        // Adjust number of connections left to connect
        numberOfConnections = numberOfConnections - 1;
  
        // Ensure we save any error
        if(err) { 
          errorObject = err;
        } else {
          credentialsValid = true;
          numberOfValidConnections = numberOfValidConnections + 1;
        }
  
        // Work around the case where the number of connections are 0
        if(numberOfConnections <= 0 && typeof callback == 'function') {
          var internalCallback = callback;
          callback = null;
  
          if(errorObject == null) {
            // We authenticated correctly save the credentials
            db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName);
            // Return valid callback
            return internalCallback(null, true);          
          } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections
            && credentialsValid) {
              // We authenticated correctly save the credentials
              db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName);
              // Return valid callback
              return internalCallback(null, true);                    
          } else {
            return internalCallback(errorObject, false);
          }
        }
      });    
    }
  }
  
  var SSIPAuthenticate = function(db, username, password, authdb, service_name, connection, callback) {
    // --------------------------------------------------------------
    // Async Version
    // --------------------------------------------------------------
    var command = {
        saslStart: 1
      , mechanism: 'GSSAPI'
      , payload: ''
      , autoAuthorize: 1
    };
  
    // Create authenticator
    var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, service_name);
  
    // Execute first sasl step
    db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
      if(err) return callback(err);
      doc = doc.documents[0];
  
      mongo_auth_process.init(username, password, function(err) {
        if(err) return callback(err);
  
        mongo_auth_process.transition(doc.payload, function(err, payload) {
          if(err) return callback(err);
  
          // Perform the next step against mongod
          var command = {
              saslContinue: 1
            , conversationId: doc.conversationId
            , payload: payload
          };
  
          // Execute the command
          db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
            if(err) return callback(err);
            doc = doc.documents[0];
  
            mongo_auth_process.transition(doc.payload, function(err, payload) {
              if(err) return callback(err);
  
              // Perform the next step against mongod
              var command = {
                  saslContinue: 1
                , conversationId: doc.conversationId
                , payload: payload
              };
  
              // Execute the command
              db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
                if(err) return callback(err);
                doc = doc.documents[0];
                
                mongo_auth_process.transition(doc.payload, function(err, payload) {
                  // Perform the next step against mongod
                  var command = {
                      saslContinue: 1
                    , conversationId: doc.conversationId
                    , payload: payload
                  };
  
                  // Execute the command
                  db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
                    if(err) return callback(err);
                    doc = doc.documents[0];
  
                    if(doc.done) return callback(null, true);
                    callback(new Error("Authentication failed"), false);
                  });        
                });
              });
            });
          });
        });
      });
    });  
  }
  
  exports.authenticate = authenticate;