Skip to content

Commit

Permalink
fix: move kerberos client setup from prepare to auth (#2608)
Browse files Browse the repository at this point in the history
A new KerberosClient should be made for each individual authentication
attempt, rather than the current approach which creates one and shares
it for all attempts.

NODE-2859
  • Loading branch information
emadum authored Nov 6, 2020
1 parent f0cee7a commit 033b6e7
Showing 1 changed file with 66 additions and 66 deletions.
132 changes: 66 additions & 66 deletions lib/core/auth/gssapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
);
});
});
});
});
Expand All @@ -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,
Expand Down

0 comments on commit 033b6e7

Please sign in to comment.