From ea2fd32b95c0fe3e3dcd2e174ab95b2141a88c7f Mon Sep 17 00:00:00 2001 From: Shervin Sarain Date: Wed, 7 Nov 2018 16:11:49 +0100 Subject: [PATCH] Added type definitions for kerberos npm package --- types/kerberos/index.d.ts | 190 +++++++++++++++++++++++++++++++ types/kerberos/kerberos-tests.ts | 94 +++++++++++++++ types/kerberos/tsconfig.json | 23 ++++ types/kerberos/tslint.json | 1 + 4 files changed, 308 insertions(+) create mode 100644 types/kerberos/index.d.ts create mode 100644 types/kerberos/kerberos-tests.ts create mode 100644 types/kerberos/tsconfig.json create mode 100644 types/kerberos/tslint.json diff --git a/types/kerberos/index.d.ts b/types/kerberos/index.d.ts new file mode 100644 index 0000000000..eaebdb5a84 --- /dev/null +++ b/types/kerberos/index.d.ts @@ -0,0 +1,190 @@ +// Type definitions for kerberos 1.1 +// Project: https://github.com/mongodb-js/kerberos#readme +// Definitions by: Shervin Sarain +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +export const GSS_C_DELEG_FLAG: number; +export const GSS_C_MUTUAL_FLAG: number; +export const GSS_C_REPLAY_FLAG: number; +export const GSS_C_SEQUENCE_FLAG: number; +export const GSS_C_CONF_FLAG: number; +export const GSS_C_INTEG_FLAG: number; +export const GSS_C_ANON_FLAG: number; +export const GSS_C_PROT_READY_FLAG: number; +export const GSS_C_TRANS_FLAG: number; + +export const GSS_C_NO_OID: number; +export const GSS_MECH_OID_KRB5: number; +export const GSS_MECH_OID_SPNEGO: number; + +// Interfaces for configuration objects +/** + * @description Optional settings for *KerberosClient.wrap* method + */ +export interface WrapOptions { + /** + * @description The user to authorize + */ + user?: string; +} + +/** + * @description Optional settings for *KerberosClient.wrap* method + */ +export interface InitializeClientOptions { + /** + * @description Optional string containing the client principal in the form '`user@realm`' + */ + principal?: string; + /** + * @description 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) + */ + gssFlag?: number; + /** + * @description Optional GSS mech OID. Defaults to None (GSS_C_NO_OID). Other possible values are `GSS_MECH_OID_KRB5`, `GSS_MECH_OID_SPNEGO` + */ + mechOID?: number; +} + +export class KerberosClient { + /** + * @description The username used for authentication + */ + username: string; + /** + * @description The last response received during authentication steps + */ + response: string; + /** + * @description Indicates whether confidentiality was applied or not (GSSAPI only) + */ + responseConf: string; + /** + * @description Indicates that authentication has successfully completed or not + */ + contextComplete: boolean; + + /** + * Processes a single kerberos client-side step using the supplied server challenge. + * + * @param challenge A string containing the base64-encoded server data (which may be empty for the first step) + * @param callback + * @return returns Promise if no callback passed + */ + step(challenge: string): Promise; + step(challenge: string, callback: (err: string, clientResponse: string) => any): void; + + /** + * Perform the client side kerberos wrap step. + * + * @param challenge The response returned after calling `unwrap` + * @param options Optional settings + * @param [callback] + * @return returns Promise if no callback passed + */ + wrap(challenge: string, options?: WrapOptions): Promise; + wrap(challenge: string, callback: (err: string, challengeResponse: string) => any): void; + wrap(challenge: string, options: WrapOptions, callback: (err: string, challengeResponse: string) => any): void; + + /** + * Perform the client side kerberos unwrap step + * + * @param challenge A string containing the base64-encoded server data + * @param callback + * @return returns Promise if no callback passed + */ + unwrap(challenge: string): Promise; + unwrap(challenge: string, callback: (err: string, challengeResponse: string) => any): void; +} + +export class KerberosServer { + /** + * @description The username used for authentication + */ + username: string; + /** + * @description The last response received during authentication steps + */ + response: string; + /** + * @description The target used for authentication + */ + targetName: string; + /** + * @description Indicates that authentication has successfully completed or not + */ + contextComplete: boolean; + + /** + * Processes a single kerberos server-side step using the supplied client data. + * + * @param challenge A string containing the base64-encoded client data + * @param callback + * @return returns Promise if no callback passed + */ + step(challenge: string): Promise; + step(challenge: string, callback: (err: string, serverResponse: string) => any): void; +} + +/** + * This function provides a simple way to verify that a user name and password + * match those normally used for Kerberos authentication. + * It does this by checking that the supplied user name and password can be + * used to get a ticket for the supplied service. + * If the user name does not contain a realm, then the default realm supplied + * is used. + * + * For this to work properly the Kerberos must be configured properly on this + * machine. + * That will likely mean ensuring that the edu.mit.Kerberos preference file + * has the correct realms and KDCs listed. + * + * IMPORTANT: This method is vulnerable to KDC spoofing attacks and it should + * only be used for testing. Do not use this in any production system - your + * security could be compromised if you do. + * + * @param username The Kerberos user name. If no realm is supplied, then the `defaultRealm` will be used. + * @param password The password for the user. + * @param service The Kerberos service to check access for. + * @param defaultRealm The default realm to use if one is not supplied in the user argument. + * @param callback + * @return returns Promise if no callback passed + */ +export function checkPassword(name: string, password: string, service: string, defaultRealm?: string): Promise; +export function checkPassword(name: string, password: string, service: string, callback: (err: string) => any): void; +export function checkPassword(name: string, password: string, service: string, defaultRealm: string, callback: (err: string) => any): void; + +/** + * This function returns the service principal for the server given a service type and hostname. + * + * Details are looked up via the `/etc/keytab` file. + * + * @param service The Kerberos service type for the server. + * @param hostname The hostname of the server. + * @param callback + * @return returns Promise if no callback passed + */ +export function principalDetails(service: string, hostname: string): Promise; +export function principalDetails(service: string, hostname: string, callback: (err: string, details: string) => any): void; + +/** + * Initializes a context for client-side authentication with the given service principal. + * + * @param service A string containing the service principal in the form '`type@fqdn`'. + * @param [options] Optional settings + * @param callback + * @return returns Promise if no callback passed + */ +export function initializeClient(service: string, options?: InitializeClientOptions): Promise; +export function initializeClient(service: string, callback: (err: string, client: KerberosClient) => any): void; +export function initializeClient(service: string, options: InitializeClientOptions, callback: (err: string, client: KerberosClient) => any): void; + +/** + * Initializes a context for server-side authentication with the given service principal. + * + * @param service A string containing the service principal in the form 'type@fqdn' (e.g. 'imap@mail.apple.com'). + * @param callback + * @return returns Promise if no callback passed + */ +export function initializeServer(service: string): Promise; +export function initializeServer(service: string, callback: (err: string, server: KerberosServer) => any): void; diff --git a/types/kerberos/kerberos-tests.ts b/types/kerberos/kerberos-tests.ts new file mode 100644 index 0000000000..8d016515c0 --- /dev/null +++ b/types/kerberos/kerberos-tests.ts @@ -0,0 +1,94 @@ +import * as kerberos from 'kerberos'; + +// environment variables +const username = 'administrator'; +const password = 'Password01'; +const realm = 'example.com'; +const hostname = 'hostname.example.com'; +const port = '80'; +let service: string; + +kerberos.principalDetails('HTTP', hostname, (err, details) => { + if (!err) { + return err; + } + return details; +}); + +kerberos.principalDetails('HTTP', hostname).then(details => { + return details; +}).catch(err => { + return err; +}); + +service = `HTTP/${hostname}`; +kerberos.checkPassword(username, password, service, realm.toUpperCase(), err => { + if (!err) { + return true; + } + return err; +}); + +kerberos.checkPassword(username, password, service, realm.toUpperCase()).then(() => { + return true; +}).catch(err => { + return err; +}); + +service = `HTTP@${hostname}`; +kerberos.initializeClient(service, {}, (err, client) => { + kerberos.initializeServer(service, (err, server) => { + client.step('', (err, clientResponse) => { + server.step(clientResponse, (err, serverResponse) => { + client.unwrap(clientResponse, (err, challengeResponse) => { + client.wrap(challengeResponse, { user : "user" }, (err, challengeResponse2) => { + return challengeResponse2; + }); + }); + }); + }); + }); +}); + +service = `HTTP@${hostname}`; +kerberos.initializeClient(service, {}).then(client => { + kerberos.initializeServer(service).then(server => { + client.step('').then(clientResponse => { + server.step(clientResponse).then(serverResponse => { + client.unwrap(clientResponse).then(challengeResponse => { + client.wrap(challengeResponse, { user : "user" }).then(challengeResponse2 => { + return challengeResponse2; + }); + }); + }); + }); + }); +}); + +service = `HTTP@${hostname}`; +const url = `http://${hostname}:${port}/`; + +const mechOID = kerberos.GSS_MECH_OID_KRB5; +kerberos.initializeClient(service, { mechOID }, (err, client) => { + client.step('', (err, kerberosToken) => { + return kerberosToken; + }); +}); + +kerberos.initializeClient(service, { mechOID }).then(client => { + client.step('', (err, kerberosToken) => { + return kerberosToken; + }); +}); + +kerberos.initializeClient(service, (err, client) => { + client.step('', (err, kerberosToken) => { + return kerberosToken; + }); +}); + +kerberos.initializeClient(service).then(client => { + client.step('', (err, kerberosToken) => { + return kerberosToken; + }); +}); diff --git a/types/kerberos/tsconfig.json b/types/kerberos/tsconfig.json new file mode 100644 index 0000000000..c0e3913b2b --- /dev/null +++ b/types/kerberos/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../", + "strictFunctionTypes": true, + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "kerberos-tests.ts" + ] +} diff --git a/types/kerberos/tslint.json b/types/kerberos/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/kerberos/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }