diff --git a/lib/core/auth/gssapi.js b/lib/core/auth/gssapi.js index 66ad0276eb..9a6c110b0e 100644 --- a/lib/core/auth/gssapi.js +++ b/lib/core/auth/gssapi.js @@ -5,88 +5,44 @@ const AuthProvider = require('./auth_provider').AuthProvider; const retrieveKerberos = require('../utils').retrieveKerberos; const MongoError = require('../error').MongoError; -const kGssapiClient = Symbol('GSSAPI_CLIENT'); let kerberos; class GSSAPI extends AuthProvider { - prepare(handshakeDoc, authContext, callback) { - const host = authContext.options.host; - const port = authContext.options.port; - const credentials = authContext.credentials; - if (!host || !port || !credentials) { - return callback( - new MongoError( - `Connection must specify: ${host ? 'host' : ''}, ${port ? 'port' : ''}, ${ - credentials ? 'host' : 'credentials' - }.` - ) - ); - } - if (kerberos == null) { - try { - kerberos = retrieveKerberos(); - } catch (e) { - return callback(e); - } - } - const username = credentials.username; - const password = credentials.password; - const mechanismProperties = credentials.mechanismProperties; - const serviceName = - mechanismProperties['gssapiservicename'] || - mechanismProperties['gssapiServiceName'] || - 'mongodb'; - performGssapiCanonicalizeHostName(host, mechanismProperties, (err, host) => { - if (err) return callback(err); - const initOptions = {}; - if (password != null) { - Object.assign(initOptions, { user: username, password: password }); - } - kerberos.initializeClient( - `${serviceName}${process.platform === 'win32' ? '/' : '@'}${host}`, - initOptions, - (err, client) => { - if (err) return callback(new MongoError(err)); - if (client == null) return callback(); - this[kGssapiClient] = client; - callback(undefined, handshakeDoc); - } - ); - }); - } auth(authContext, callback) { const connection = authContext.connection; const credentials = authContext.credentials; if (credentials == null) return callback(new MongoError('credentials required')); const username = credentials.username; - const client = this[kGssapiClient]; - if (client == null) return callback(new MongoError('gssapi client missing')); function externalCommand(command, cb) { return connection.command('$external.$cmd', command, cb); } - client.step('', (err, payload) => { + makeKerberosClient(authContext, (err, client) => { if (err) return callback(err); - externalCommand(saslStart(payload), (err, response) => { - const result = response.result; + if (client == null) return callback(new MongoError('gssapi client missing')); + client.step('', (err, payload) => { if (err) return callback(err); - negotiate(client, 10, result.payload, (err, payload) => { + externalCommand(saslStart(payload), (err, response) => { if (err) return callback(err); - externalCommand(saslContinue(payload, result.conversationId), (err, response) => { - const result = response.result; + const result = response.result; + negotiate(client, 10, result.payload, (err, payload) => { if (err) return callback(err); - finalize(client, username, result.payload, (err, payload) => { + externalCommand(saslContinue(payload, result.conversationId), (err, response) => { if (err) return callback(err); - externalCommand( - { - saslContinue: 1, - conversationId: result.conversationId, - payload - }, - (err, result) => { - if (err) return callback(err); - callback(undefined, result); - } - ); + const result = response.result; + finalize(client, username, result.payload, (err, payload) => { + if (err) return callback(err); + externalCommand( + { + saslContinue: 1, + conversationId: result.conversationId, + payload + }, + (err, result) => { + if (err) return callback(err); + callback(undefined, result); + } + ); + }); }); }); }); @@ -96,6 +52,50 @@ class GSSAPI extends AuthProvider { } module.exports = GSSAPI; +function makeKerberosClient(authContext, callback) { + const host = authContext.options.host; + const port = authContext.options.port; + const credentials = authContext.credentials; + if (!host || !port || !credentials) { + return callback( + new MongoError( + `Connection must specify: ${host ? 'host' : ''}, ${port ? 'port' : ''}, ${ + credentials ? 'host' : 'credentials' + }.` + ) + ); + } + if (kerberos == null) { + try { + kerberos = retrieveKerberos(); + } catch (e) { + return callback(e); + } + } + const username = credentials.username; + const password = credentials.password; + const mechanismProperties = credentials.mechanismProperties; + const serviceName = + mechanismProperties['gssapiservicename'] || + mechanismProperties['gssapiServiceName'] || + 'mongodb'; + performGssapiCanonicalizeHostName(host, mechanismProperties, (err, host) => { + if (err) return callback(err); + const initOptions = {}; + if (password != null) { + Object.assign(initOptions, { user: username, password: password }); + } + kerberos.initializeClient( + `${serviceName}${process.platform === 'win32' ? '/' : '@'}${host}`, + initOptions, + (err, client) => { + if (err) return callback(new MongoError(err)); + callback(null, client); + } + ); + }); +} + function saslStart(payload) { return { saslStart: 1,