Skip to content

Commit 7170783

Browse files
feat(NODE-7159)!: remove Kerberos export (#271)
1 parent 8764240 commit 7170783

File tree

5 files changed

+251
-256
lines changed

5 files changed

+251
-256
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ NOTE: The test suite requires an active kerberos deployment.
150150
<dd></dd>
151151
<dt><a href="#GSS_MECH_OID_SPNEGO">GSS_MECH_OID_SPNEGO</a></dt>
152152
<dd></dd>
153+
<dt><a href="#version">version</a></dt>
154+
<dd></dd>
153155
</dl>
154156

155157
## Functions
@@ -295,6 +297,9 @@ Processes a single kerberos server-side step using the supplied client data.
295297
<a name="GSS_MECH_OID_SPNEGO"></a>
296298

297299
## GSS_MECH_OID_SPNEGO
300+
<a name="version"></a>
301+
302+
## version
298303
<a name="checkPassword"></a>
299304

300305
## checkPassword(username, password, service, [defaultRealm])

lib/index.js

Lines changed: 245 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,250 @@
11
'use strict';
22

3-
const kerberos = require('./kerberos');
3+
const { promisify } = require('util');
4+
const { loadBindings } = require('./util');
45

5-
// Get the Kerberos library
6-
module.exports = kerberos;
6+
const kerberos = loadBindings();
7+
const KerberosClient = kerberos.KerberosClient;
8+
const KerberosServer = kerberos.KerberosServer;
79

8-
// Support legacy versions of the mongodb driver which expect this export
9-
module.exports.Kerberos = kerberos;
10+
// GSS Flags
11+
/** @kind constant */
12+
const GSS_C_DELEG_FLAG = 1;
13+
/** @kind constant */
14+
const GSS_C_MUTUAL_FLAG = 2;
15+
/** @kind constant */
16+
const GSS_C_REPLAY_FLAG = 4;
17+
/** @kind constant */
18+
const GSS_C_SEQUENCE_FLAG = 8;
19+
/** @kind constant */
20+
const GSS_C_CONF_FLAG = 16;
21+
/** @kind constant */
22+
const GSS_C_INTEG_FLAG = 32;
23+
/** @kind constant */
24+
const GSS_C_ANON_FLAG = 64;
25+
/** @kind constant */
26+
const GSS_C_PROT_READY_FLAG = 128;
27+
/** @kind constant */
28+
const GSS_C_TRANS_FLAG = 256;
1029

11-
module.exports.version = require('../package.json').version;
30+
// GSS_OID
31+
/** @kind constant */
32+
const GSS_C_NO_OID = 0;
33+
/** @kind constant */
34+
const GSS_MECH_OID_KRB5 = 9;
35+
/** @kind constant */
36+
const GSS_MECH_OID_SPNEGO = 6;
37+
38+
/** @kind constant */
39+
const version = require('../package.json').version;
40+
41+
/**
42+
* @class KerberosClient
43+
*
44+
* @property {string} username The username used for authentication
45+
* @property {string} response The last response received during authentication steps
46+
* @property {string} responseConf Indicates whether confidentiality was applied or not (GSSAPI only)
47+
* @property {boolean} contextComplete Indicates that authentication has successfully completed or not
48+
*/
49+
50+
const promisifiedStep = promisify(KerberosClient.prototype.step);
51+
/**
52+
* Processes a single kerberos client-side step using the supplied server challenge.
53+
*
54+
* @kind function
55+
* @memberof KerberosClient
56+
* @param {string} challenge A string containing the base64-encoded server data (which may be empty for the first step)
57+
* @return {Promise<string>}
58+
*/
59+
KerberosClient.prototype.step = async function step(challenge) {
60+
if (typeof challenge !== 'string') {
61+
throw new TypeError('parameter `challenge` must be a string.');
62+
}
63+
return await promisifiedStep.call(this, challenge);
64+
};
65+
66+
const promsifiedWrap = promisify(KerberosClient.prototype.wrap);
67+
/**
68+
* Perform the client side kerberos wrap step.
69+
*
70+
* @kind function
71+
* @memberof KerberosClient
72+
* @param {string} challenge The response returned after calling `unwrap`
73+
* @param {object} [options] Options
74+
* @param {string} [options.user] The user to authorize
75+
* @param {boolean} [options.protect] Indicates if the wrap should request message confidentiality
76+
* @return {Promise<string>}
77+
*/
78+
KerberosClient.prototype.wrap = async function wrap(challenge, options = {}) {
79+
if (typeof challenge !== 'string') {
80+
throw new TypeError('parameter `challenge` must be a string.');
81+
}
82+
83+
return await promsifiedWrap.call(this, challenge, options);
84+
};
85+
86+
const promisifiedUnwrap = promisify(KerberosClient.prototype.unwrap);
87+
/**
88+
* Perform the client side kerberos unwrap step
89+
*
90+
* @kind function
91+
* @memberof KerberosClient
92+
* @param {string} challenge A string containing the base64-encoded server data
93+
* @return {Promise<string>}
94+
*/
95+
KerberosClient.prototype.unwrap = async function unwrap(challenge) {
96+
if (typeof challenge !== 'string') {
97+
throw new TypeError('parameter `challenge` must be a string.');
98+
}
99+
return await promisifiedUnwrap.call(this, challenge);
100+
};
101+
102+
const promisifiedServerStep = promisify(KerberosServer.prototype.step);
103+
/**
104+
* @class KerberosServer
105+
*
106+
* @property {string} username The username used for authentication
107+
* @property {string} response The last response received during authentication steps
108+
* @property {string} targetName The target used for authentication
109+
* @property {boolean} contextComplete Indicates that authentication has successfully completed or not
110+
*/
111+
112+
/**
113+
* Processes a single kerberos server-side step using the supplied client data.
114+
*
115+
* @kind function
116+
* @memberof KerberosServer
117+
* @param {string} challenge A string containing the base64-encoded client data
118+
* @return {Promise<KerberosServer>}
119+
*/
120+
KerberosServer.prototype.step = async function step(challenge) {
121+
if (typeof challenge !== 'string') {
122+
throw new TypeError('parameter `challenge` must be a string.');
123+
}
124+
return await promisifiedServerStep.call(this, challenge);
125+
};
126+
127+
const promisifiedCheckPassword = promisify(kerberos.checkPassword);
128+
129+
/**
130+
* This function provides a simple way to verify that a user name and password
131+
* match those normally used for Kerberos authentication.
132+
* It does this by checking that the supplied user name and password can be
133+
* used to get a ticket for the supplied service.
134+
* If the user name does not contain a realm, then the default realm supplied
135+
* is used.
136+
*
137+
* For this to work properly the Kerberos must be configured properly on this
138+
* machine.
139+
* That will likely mean ensuring that the edu.mit.Kerberos preference file
140+
* has the correct realms and KDCs listed.
141+
*
142+
* IMPORTANT: This method is vulnerable to KDC spoofing attacks and it should
143+
* only be used for testing. Do not use this in any production system - your
144+
* security could be compromised if you do.
145+
*
146+
* @kind function
147+
* @param {string} username The Kerberos user name. If no realm is supplied, then the `defaultRealm` will be used.
148+
* @param {string} password The password for the user.
149+
* @param {string} service The Kerberos service to check access for.
150+
* @param {string} [defaultRealm] The default realm to use if one is not supplied in the user argument.
151+
* @return {Promise<null>} returns Promise that rejects if the password is invalid
152+
*/
153+
async function checkPassword(username, password, service, defaultRealm) {
154+
if (typeof username !== 'string') {
155+
throw new TypeError('parameter `username` must be a string.');
156+
}
157+
if (typeof password !== 'string') {
158+
throw new TypeError('parameter `password` must be a string.');
159+
}
160+
if (typeof service !== 'string') {
161+
throw new TypeError('parameter `service` must be a string.');
162+
}
163+
if (defaultRealm && typeof defaultRealm !== 'string') {
164+
throw new TypeError('if specified, parameter `defaultRealm` must be a string.');
165+
}
166+
return await promisifiedCheckPassword.call(this, username, password, service, defaultRealm);
167+
}
168+
169+
const promisifiedPrincipalDetails = promisify(kerberos.principalDetails);
170+
/**
171+
* This function returns the service principal for the server given a service type and hostname.
172+
*
173+
* Details are looked up via the `/etc/keytab` file.
174+
*
175+
* @kind function
176+
* @param {string} service The Kerberos service type for the server.
177+
* @param {string} hostname The hostname of the server.
178+
* @return {Promise} returns Promise
179+
*/
180+
async function principalDetails(service, hostname) {
181+
if (typeof service !== 'string') {
182+
throw new TypeError('parameter `service` must be a string.');
183+
}
184+
if (typeof hostname !== 'string') {
185+
throw new TypeError('parameter `hostname` must be a string.');
186+
}
187+
return await promisifiedPrincipalDetails.call(this, service, hostname);
188+
}
189+
190+
const promisifiedInitializeClient = promisify(kerberos.initializeClient);
191+
/**
192+
* Initializes a context for client-side authentication with the given service principal.
193+
*
194+
* @kind function
195+
* @param {string} service A string containing the service principal in the form 'type@fqdn' (e.g. 'imap@mail.apple.com').
196+
* @param {object} [options] Optional settings
197+
* @param {string} [options.principal] Optional string containing the client principal in the form 'user@realm' (e.g. 'jdoe@example.com').
198+
* @param {number} [options.flags] Optional integer used to set GSS flags. (e.g. `GSS_C_DELEG_FLAG\|GSS_C_MUTUAL_FLAG\|GSS_C_SEQUENCE_FLAG` will allow for forwarding credentials to the remote host)
199+
* @param {number} [options.mechOID] Optional GSS mech OID. Defaults to None (GSS_C_NO_OID). Other possible values are `GSS_MECH_OID_KRB5`, `GSS_MECH_OID_SPNEGO`.
200+
* @param {string} [options.user] The username with which to authenticate. Only used on Windows.
201+
* @param {string} [options.pass] The password with which to authenticate. Only used on Windows.
202+
* @return {Promise<KerberosClient>} returns Promise
203+
*/
204+
async function initializeClient(service, options = { mechOID: GSS_C_NO_OID }) {
205+
if (typeof service !== 'string') {
206+
throw new TypeError('parameter `service` must be a string.');
207+
}
208+
return await promisifiedInitializeClient.call(this, service, options);
209+
}
210+
211+
const promisifiedInitializeServer = promisify(kerberos.initializeServer);
212+
213+
/**
214+
* Initializes a context for server-side authentication with the given service principal.
215+
*
216+
* @kind function
217+
* @param {string} service A string containing the service principal in the form 'type@fqdn' (e.g. 'imap@mail.apple.com').
218+
* @return {Promise<KerberosServer>} returns Promise
219+
*/
220+
async function initializeServer(service) {
221+
if (typeof service !== 'string') {
222+
throw new TypeError('parameter `service` must be a string.');
223+
}
224+
return await promisifiedInitializeServer.call(this, service);
225+
}
226+
227+
module.exports = {
228+
initializeClient,
229+
initializeServer,
230+
principalDetails,
231+
checkPassword,
232+
233+
// gss flags
234+
GSS_C_DELEG_FLAG,
235+
GSS_C_MUTUAL_FLAG,
236+
GSS_C_REPLAY_FLAG,
237+
GSS_C_SEQUENCE_FLAG,
238+
GSS_C_CONF_FLAG,
239+
GSS_C_INTEG_FLAG,
240+
GSS_C_ANON_FLAG,
241+
GSS_C_PROT_READY_FLAG,
242+
GSS_C_TRANS_FLAG,
243+
GSS_C_NO_OID,
244+
245+
// mechanism OIDs
246+
GSS_MECH_OID_KRB5,
247+
GSS_MECH_OID_SPNEGO,
248+
249+
version
250+
};

0 commit comments

Comments
 (0)