Skip to content

Commit 93ef9e8

Browse files
authored
fix: move kerberos client setup from prepare to auth (#2655)
NODE-2911
1 parent 3bcd393 commit 93ef9e8

File tree

2 files changed

+73
-81
lines changed

2 files changed

+73
-81
lines changed

src/cmap/auth/gssapi.ts

+72-80
Original file line numberDiff line numberDiff line change
@@ -2,117 +2,109 @@ import { AuthProvider, AuthContext } from './auth_provider';
22
import { MongoError } from '../../error';
33
import { Kerberos, KerberosClient } from '../../deps';
44
import type { Callback } from '../../utils';
5-
import type { HandshakeDocument } from '../connect';
65
import type { Document } from '../../bson';
76

8-
const kGssapiClient = Symbol('GSSAPI_CLIENT');
9-
107
type MechanismProperties = {
118
gssapiCanonicalizeHostName?: boolean;
129
};
1310

1411
import * as dns from 'dns';
1512

1613
export class GSSAPI extends AuthProvider {
17-
[kGssapiClient]: KerberosClient;
18-
prepare(
19-
handshakeDoc: HandshakeDocument,
20-
authContext: AuthContext,
21-
callback: Callback<HandshakeDocument>
22-
): void {
23-
const { host, port } = authContext.options;
24-
const { credentials } = authContext;
25-
if (!host || !port || !credentials) {
26-
return callback(
27-
new MongoError(
28-
`Connection must specify: ${host ? 'host' : ''}, ${port ? 'port' : ''}, ${
29-
credentials ? 'host' : 'credentials'
30-
}.`
31-
)
32-
);
33-
}
34-
35-
if ('kModuleError' in Kerberos) {
36-
return callback(Kerberos['kModuleError']);
37-
}
38-
39-
const { username, password, mechanismProperties } = credentials;
40-
const serviceName =
41-
mechanismProperties['gssapiservicename'] ||
42-
mechanismProperties['gssapiServiceName'] ||
43-
'mongodb';
44-
45-
performGssapiCanonicalizeHostName(
46-
host,
47-
mechanismProperties as MechanismProperties,
48-
(err?: Error | MongoError, host?: string) => {
49-
if (err) return callback(err);
50-
51-
const initOptions = {};
52-
if (password != null) {
53-
Object.assign(initOptions, { user: username, password: password });
54-
}
55-
56-
Kerberos.initializeClient(
57-
`${serviceName}${process.platform === 'win32' ? '/' : '@'}${host}`,
58-
initOptions,
59-
(err: string, client: KerberosClient): void => {
60-
if (err) return callback(new MongoError(err));
61-
if (client == null) return callback();
62-
this[kGssapiClient] = client;
63-
callback(undefined, handshakeDoc);
64-
}
65-
);
66-
}
67-
);
68-
}
69-
7014
auth(authContext: AuthContext, callback: Callback): void {
7115
const { connection, credentials } = authContext;
7216
if (credentials == null) return callback(new MongoError('credentials required'));
7317
const { username } = credentials;
74-
const client = this[kGssapiClient];
75-
if (client == null) return callback(new MongoError('gssapi client missing'));
7618
function externalCommand(
7719
command: Document,
7820
cb: Callback<{ payload: string; conversationId: any }>
7921
) {
8022
return connection.command('$external.$cmd', command, cb);
8123
}
82-
client.step('', (err, payload) => {
24+
makeKerberosClient(authContext, (err, client) => {
8325
if (err) return callback(err);
84-
85-
externalCommand(saslStart(payload), (err, result) => {
26+
if (client == null) return callback(new MongoError('gssapi client missing'));
27+
client.step('', (err, payload) => {
8628
if (err) return callback(err);
87-
if (result == null) return callback();
88-
negotiate(client, 10, result.payload, (err, payload) => {
89-
if (err) return callback(err);
9029

91-
externalCommand(saslContinue(payload, result.conversationId), (err, result) => {
30+
externalCommand(saslStart(payload), (err, result) => {
31+
if (err) return callback(err);
32+
if (result == null) return callback();
33+
negotiate(client, 10, result.payload, (err, payload) => {
9234
if (err) return callback(err);
93-
if (result == null) return callback();
94-
finalize(client, username, result.payload, (err, payload) => {
95-
if (err) return callback(err);
9635

97-
externalCommand(
98-
{
99-
saslContinue: 1,
100-
conversationId: result.conversationId,
101-
payload
102-
},
103-
(err, result) => {
104-
if (err) return callback(err);
105-
106-
callback(undefined, result);
107-
}
108-
);
36+
externalCommand(saslContinue(payload, result.conversationId), (err, result) => {
37+
if (err) return callback(err);
38+
if (result == null) return callback();
39+
finalize(client, username, result.payload, (err, payload) => {
40+
if (err) return callback(err);
41+
42+
externalCommand(
43+
{
44+
saslContinue: 1,
45+
conversationId: result.conversationId,
46+
payload
47+
},
48+
(err, result) => {
49+
if (err) return callback(err);
50+
51+
callback(undefined, result);
52+
}
53+
);
54+
});
10955
});
11056
});
11157
});
11258
});
11359
});
11460
}
11561
}
62+
function makeKerberosClient(authContext: AuthContext, callback: Callback<KerberosClient>): void {
63+
const { host, port } = authContext.options;
64+
const { credentials } = authContext;
65+
if (!host || !port || !credentials) {
66+
return callback(
67+
new MongoError(
68+
`Connection must specify: ${host ? 'host' : ''}, ${port ? 'port' : ''}, ${
69+
credentials ? 'host' : 'credentials'
70+
}.`
71+
)
72+
);
73+
}
74+
75+
if ('kModuleError' in Kerberos) {
76+
return callback(Kerberos['kModuleError']);
77+
}
78+
79+
const { username, password, mechanismProperties } = credentials;
80+
const serviceName =
81+
mechanismProperties['gssapiservicename'] ||
82+
mechanismProperties['gssapiServiceName'] ||
83+
'mongodb';
84+
85+
performGssapiCanonicalizeHostName(
86+
host,
87+
mechanismProperties as MechanismProperties,
88+
(err?: Error | MongoError, host?: string) => {
89+
if (err) return callback(err);
90+
91+
const initOptions = {};
92+
if (password != null) {
93+
Object.assign(initOptions, { user: username, password: password });
94+
}
95+
96+
Kerberos.initializeClient(
97+
`${serviceName}${process.platform === 'win32' ? '/' : '@'}${host}`,
98+
initOptions,
99+
(err: string, client: KerberosClient): void => {
100+
if (err) return callback(new MongoError(err));
101+
callback(undefined, client);
102+
}
103+
);
104+
}
105+
);
106+
}
107+
116108
function saslStart(payload?: string): Document {
117109
return {
118110
saslStart: 1,

test/unit/optional_require.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ describe('optionalRequire', function () {
4141
return this.skip();
4242
}
4343
const gssapi = new GSSAPI();
44-
gssapi.prepare('', new AuthContext(null, true, { host: true, port: true }), error => {
44+
gssapi.auth(new AuthContext(null, true, { host: true, port: true }), error => {
4545
expect(error).to.exist;
4646
expect(error.message).includes('not found');
4747
});

0 commit comments

Comments
 (0)