commit 167bdf1a32366f1abc6c7a23d33b18ba1176c0a9
Author: Peter Blazejewicz <[email protected]>
Date: Mon Nov 20 21:54:12 2017 +0100
Use NPM distributed version of httpntlm package
diff --git a/lib/handlers/ntlm.ts b/lib/handlers/ntlm.ts
index 483aff6..bcdd8b2 100644
--- a/lib/handlers/ntlm.ts
+++ b/lib/handlers/ntlm.ts
@@ -5,8 +5,8 @@ import VsoBaseInterfaces = require('../interfaces');
import http = require("http");
import https = require("https");
-var _ = require("underscore");
-var ntlm = require("../opensource/node-http-ntlm/ntlm");
+const _ = require("underscore");
+const ntlm = require("httpntlm");
export class NtlmCredentialHandler implements VsoBaseInterfaces.IRequestHandler {
username: string;
diff --git a/lib/opensource/node-http-ntlm/ntlm.js b/lib/opensource/node-http-ntlm/ntlm.js
deleted file mode 100644
index 5a776c3..0000000
--- a/lib/opensource/node-http-ntlm/ntlm.js
+++ /dev/null
@@ -1,390 +0,0 @@
-var crypto = require('crypto');
-
-var flags = {
- NTLM_NegotiateUnicode : 0x00000001,
- NTLM_NegotiateOEM : 0x00000002,
- NTLM_RequestTarget : 0x00000004,
- NTLM_Unknown9 : 0x00000008,
- NTLM_NegotiateSign : 0x00000010,
- NTLM_NegotiateSeal : 0x00000020,
- NTLM_NegotiateDatagram : 0x00000040,
- NTLM_NegotiateLanManagerKey : 0x00000080,
- NTLM_Unknown8 : 0x00000100,
- NTLM_NegotiateNTLM : 0x00000200,
- NTLM_NegotiateNTOnly : 0x00000400,
- NTLM_Anonymous : 0x00000800,
- NTLM_NegotiateOemDomainSupplied : 0x00001000,
- NTLM_NegotiateOemWorkstationSupplied : 0x00002000,
- NTLM_Unknown6 : 0x00004000,
- NTLM_NegotiateAlwaysSign : 0x00008000,
- NTLM_TargetTypeDomain : 0x00010000,
- NTLM_TargetTypeServer : 0x00020000,
- NTLM_TargetTypeShare : 0x00040000,
- NTLM_NegotiateExtendedSecurity : 0x00080000,
- NTLM_NegotiateIdentify : 0x00100000,
- NTLM_Unknown5 : 0x00200000,
- NTLM_RequestNonNTSessionKey : 0x00400000,
- NTLM_NegotiateTargetInfo : 0x00800000,
- NTLM_Unknown4 : 0x01000000,
- NTLM_NegotiateVersion : 0x02000000,
- NTLM_Unknown3 : 0x04000000,
- NTLM_Unknown2 : 0x08000000,
- NTLM_Unknown1 : 0x10000000,
- NTLM_Negotiate128 : 0x20000000,
- NTLM_NegotiateKeyExchange : 0x40000000,
- NTLM_Negotiate56 : 0x80000000
-};
-var typeflags = {
- NTLM_TYPE1_FLAGS : flags.NTLM_NegotiateUnicode
- + flags.NTLM_NegotiateOEM
- + flags.NTLM_RequestTarget
- + flags.NTLM_NegotiateNTLM
- + flags.NTLM_NegotiateOemDomainSupplied
- + flags.NTLM_NegotiateOemWorkstationSupplied
- + flags.NTLM_NegotiateAlwaysSign
- + flags.NTLM_NegotiateExtendedSecurity
- + flags.NTLM_NegotiateVersion
- + flags.NTLM_Negotiate128
- + flags.NTLM_Negotiate56,
-
- NTLM_TYPE2_FLAGS : flags.NTLM_NegotiateUnicode
- + flags.NTLM_RequestTarget
- + flags.NTLM_NegotiateNTLM
- + flags.NTLM_NegotiateAlwaysSign
- + flags.NTLM_NegotiateExtendedSecurity
- + flags.NTLM_NegotiateTargetInfo
- + flags.NTLM_NegotiateVersion
- + flags.NTLM_Negotiate128
- + flags.NTLM_Negotiate56
-};
-
-function createType1Message(options){
- var domain = escape(options.domain.toUpperCase());
- var workstation = escape(options.workstation.toUpperCase());
- var protocol = 'NTLMSSP\0';
-
- var BODY_LENGTH = 40;
-
- var type1flags = typeflags.NTLM_TYPE1_FLAGS;
- if(!domain || domain === '')
- type1flags = type1flags - flags.NTLM_NegotiateOemDomainSupplied;
-
- var pos = 0;
- var buf = new Buffer(BODY_LENGTH + domain.length + workstation.length);
-
-
- buf.write(protocol, pos, protocol.length); pos += protocol.length; // protocol
- buf.writeUInt32LE(1, pos); pos += 4; // type 1
- buf.writeUInt32LE(type1flags, pos); pos += 4; // TYPE1 flag
-
- buf.writeUInt16LE(domain.length, pos); pos += 2; // domain length
- buf.writeUInt16LE(domain.length, pos); pos += 2; // domain max length
- buf.writeUInt32LE(BODY_LENGTH + workstation.length, pos); pos += 4; // domain buffer offset
-
- buf.writeUInt16LE(workstation.length, pos); pos += 2; // workstation length
- buf.writeUInt16LE(workstation.length, pos); pos += 2; // workstation max length
- buf.writeUInt32LE(BODY_LENGTH, pos); pos += 4; // workstation buffer offset
-
- buf.writeUInt8(5, pos); pos += 1; //ProductMajorVersion
- buf.writeUInt8(1, pos); pos += 1; //ProductMinorVersion
- buf.writeUInt16LE(2600, pos); pos += 2; //ProductBuild
-
- buf.writeUInt8(0 , pos); pos += 1; //VersionReserved1
- buf.writeUInt8(0 , pos); pos += 1; //VersionReserved2
- buf.writeUInt8(0 , pos); pos += 1; //VersionReserved3
- buf.writeUInt8(15, pos); pos += 1; //NTLMRevisionCurrent
-
- buf.write(workstation, pos, workstation.length, 'ascii'); pos += workstation.length; // workstation string
- buf.write(domain , pos, domain.length , 'ascii'); pos += domain.length;
-
- return 'NTLM ' + buf.toString('base64');
-}
-
-function parseType2Message(rawmsg, callback){
- var match = rawmsg.match(/NTLM (.+)?/);
- if(!match || !match[1])
- return callback(new Error("Couldn't find NTLM in the message type2 comming from the server"));
-
- var buf = new Buffer(match[1], 'base64');
-
- var msg = {};
-
- msg.signature = buf.slice(0, 8);
- msg.type = buf.readInt16LE(8);
-
- if(msg.type != 2)
- return callback(new Error("Server didn't return a type 2 message"));
-
- msg.targetNameLen = buf.readInt16LE(12);
- msg.targetNameMaxLen = buf.readInt16LE(14);
- msg.targetNameOffset = buf.readInt32LE(16);
- msg.targetName = buf.slice(msg.targetNameOffset, msg.targetNameOffset + msg.targetNameMaxLen);
-
- msg.negotiateFlags = buf.readInt32LE(20);
- msg.serverChallenge = buf.slice(24, 32);
- msg.reserved = buf.slice(32, 40);
-
- if(msg.negotiateFlags & flags.NTLM_NegotiateTargetInfo){
- msg.targetInfoLen = buf.readInt16LE(40);
- msg.targetInfoMaxLen = buf.readInt16LE(42);
- msg.targetInfoOffset = buf.readInt32LE(44);
- msg.targetInfo = buf.slice(msg.targetInfoOffset, msg.targetInfoOffset + msg.targetInfoLen);
- }
- return msg;
-}
-
-function createType3Message(msg2, options){
- var nonce = msg2.serverChallenge;
- var username = options.username;
- var password = options.password;
- var negotiateFlags = msg2.negotiateFlags;
-
- var isUnicode = negotiateFlags & flags.NTLM_NegotiateUnicode;
- var isNegotiateExtendedSecurity = negotiateFlags & flags.NTLM_NegotiateExtendedSecurity;
-
- var BODY_LENGTH = 72;
-
- var domainName = escape(options.domain.toUpperCase());
- var workstation = escape(options.workstation.toUpperCase());
-
- var workstationBytes, domainNameBytes, usernameBytes, encryptedRandomSessionKeyBytes;
-
- var encryptedRandomSessionKey = "";
- if(isUnicode){
- workstationBytes = new Buffer(workstation, 'utf16le');
- domainNameBytes = new Buffer(domainName, 'utf16le');
- usernameBytes = new Buffer(username, 'utf16le');
- encryptedRandomSessionKeyBytes = new Buffer(encryptedRandomSessionKey, 'utf16le');
- }else{
- workstationBytes = new Buffer(workstation, 'ascii');
- domainNameBytes = new Buffer(domainName, 'ascii');
- usernameBytes = new Buffer(username, 'ascii');
- encryptedRandomSessionKeyBytes = new Buffer(encryptedRandomSessionKey, 'ascii');
- }
-
- var lmChallengeResponse = calc_resp(create_LM_hashed_password_v1(password), nonce);
- var ntChallengeResponse = calc_resp(create_NT_hashed_password_v1(password), nonce);
-
- if(isNegotiateExtendedSecurity){
- var pwhash = create_NT_hashed_password_v1(password);
- var clientChallenge = "";
- for(var i=0; i < 8; i++){
- clientChallenge += String.fromCharCode( Math.floor(Math.random()*256) );
- }
- var clientChallengeBytes = new Buffer(clientChallenge, 'ascii');
- var challenges = ntlm2sr_calc_resp(pwhash, nonce, clientChallengeBytes);
- lmChallengeResponse = challenges.lmChallengeResponse;
- ntChallengeResponse = challenges.ntChallengeResponse;
- }
-
- var signature = 'NTLMSSP\0';
-
- var pos = 0;
- var buf = new Buffer(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length + lmChallengeResponse.length + ntChallengeResponse.length + encryptedRandomSessionKeyBytes.length);
-
- buf.write(signature, pos, signature.length); pos += signature.length;
- buf.writeUInt32LE(3, pos); pos += 4; // type 1
-
- buf.writeUInt16LE(lmChallengeResponse.length, pos); pos += 2; // LmChallengeResponseLen
- buf.writeUInt16LE(lmChallengeResponse.length, pos); pos += 2; // LmChallengeResponseMaxLen
- buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length, pos); pos += 4; // LmChallengeResponseOffset
-
- buf.writeUInt16LE(ntChallengeResponse.length, pos); pos += 2; // NtChallengeResponseLen
- buf.writeUInt16LE(ntChallengeResponse.length, pos); pos += 2; // NtChallengeResponseMaxLen
- buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length + lmChallengeResponse.length, pos); pos += 4; // NtChallengeResponseOffset
-
- buf.writeUInt16LE(domainNameBytes.length, pos); pos += 2; // DomainNameLen
- buf.writeUInt16LE(domainNameBytes.length, pos); pos += 2; // DomainNameMaxLen
- buf.writeUInt32LE(BODY_LENGTH, pos); pos += 4; // DomainNameOffset
-
- buf.writeUInt16LE(usernameBytes.length, pos); pos += 2; // UserNameLen
- buf.writeUInt16LE(usernameBytes.length, pos); pos += 2; // UserNameMaxLen
- buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length, pos); pos += 4; // UserNameOffset
-
- buf.writeUInt16LE(workstationBytes.length, pos); pos += 2; // WorkstationLen
- buf.writeUInt16LE(workstationBytes.length, pos); pos += 2; // WorkstationMaxLen
- buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length + usernameBytes.length, pos); pos += 4; // WorkstationOffset
-
- buf.writeUInt16LE(encryptedRandomSessionKeyBytes.length, pos); pos += 2; // EncryptedRandomSessionKeyLen
- buf.writeUInt16LE(encryptedRandomSessionKeyBytes.length, pos); pos += 2; // EncryptedRandomSessionKeyMaxLen
- buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length + lmChallengeResponse.length + ntChallengeResponse.length, pos); pos += 4; // EncryptedRandomSessionKeyOffset
-
- buf.writeUInt32LE(typeflags.NTLM_TYPE2_FLAGS, pos); pos += 4; // NegotiateFlags
-
- buf.writeUInt8(5, pos); pos++; // ProductMajorVersion
- buf.writeUInt8(1, pos); pos++; // ProductMinorVersion
- buf.writeUInt16LE(2600, pos); pos += 2; // ProductBuild
- buf.writeUInt8(0, pos); pos++; // VersionReserved1
- buf.writeUInt8(0, pos); pos++; // VersionReserved2
- buf.writeUInt8(0, pos); pos++; // VersionReserved3
- buf.writeUInt8(15, pos); pos++; // NTLMRevisionCurrent
-
- domainNameBytes.copy(buf, pos); pos += domainNameBytes.length;
- usernameBytes.copy(buf, pos); pos += usernameBytes.length;
- workstationBytes.copy(buf, pos); pos += workstationBytes.length;
- lmChallengeResponse.copy(buf, pos); pos += lmChallengeResponse.length;
- ntChallengeResponse.copy(buf, pos); pos += ntChallengeResponse.length;
- encryptedRandomSessionKeyBytes.copy(buf, pos); pos += encryptedRandomSessionKeyBytes.length;
-
- return 'NTLM ' + buf.toString('base64');
-}
-
-function create_LM_hashed_password_v1(password){
- // fix the password length to 14 bytes
- password = password.toUpperCase();
- var passwordBytes = new Buffer(password, 'ascii');
-
- var passwordBytesPadded = new Buffer(14);
- passwordBytesPadded.fill("\0");
- var sourceEnd = 14;
- if(passwordBytes.length < 14) sourceEnd = passwordBytes.length;
- passwordBytes.copy(passwordBytesPadded, 0, 0, sourceEnd);
-
- // split into 2 parts of 7 bytes:
- var firstPart = passwordBytesPadded.slice(0,7);
- var secondPart = passwordBytesPadded.slice(7);
-
- function encrypt(buf){
- var key = insertZerosEvery7Bits(buf);
- var des = crypto.createCipheriv('DES-ECB', key, '');
- return des.update("KGS!@#$%"); // page 57 in [MS-NLMP]);
- }
-
- var firstPartEncrypted = encrypt(firstPart);
- var secondPartEncrypted = encrypt(secondPart);
-
- return Buffer.concat([firstPartEncrypted, secondPartEncrypted]);
-}
-
-function insertZerosEvery7Bits(buf){
- var binaryArray = bytes2binaryArray(buf);
- var newBinaryArray = [];
- for(var i=0; i<binaryArray.length; i++){
- newBinaryArray.push(binaryArray[i]);
-
- if((i+1)%7 === 0){
- newBinaryArray.push(0);
- }
- }
- return binaryArray2bytes(newBinaryArray);
-}
-
-function bytes2binaryArray(buf){
- var hex2binary = {
- 0: [0,0,0,0],
- 1: [0,0,0,1],
- 2: [0,0,1,0],
- 3: [0,0,1,1],
- 4: [0,1,0,0],
- 5: [0,1,0,1],
- 6: [0,1,1,0],
- 7: [0,1,1,1],
- 8: [1,0,0,0],
- 9: [1,0,0,1],
- A: [1,0,1,0],
- B: [1,0,1,1],
- C: [1,1,0,0],
- D: [1,1,0,1],
- E: [1,1,1,0],
- F: [1,1,1,1]
- };
-
- var hexString = buf.toString('hex').toUpperCase();
- var array = [];
- for(var i=0; i<hexString.length; i++){
- var hexchar = hexString.charAt(i);
- array = array.concat(hex2binary[hexchar]);
- }
- return array;
-}
-
-function binaryArray2bytes(array){
- var binary2hex = {
- '0000': 0,
- '0001': 1,
- '0010': 2,
- '0011': 3,
- '0100': 4,
- '0101': 5,
- '0110': 6,
- '0111': 7,
- '1000': 8,
- '1001': 9,
- '1010': 'A',
- '1011': 'B',
- '1100': 'C',
- '1101': 'D',
- '1110': 'E',
- '1111': 'F'
- };
-
- var bufArray = [];
-
- for(var i=0; i<array.length; i +=8 ){
- if((i+7) > array.length)
- break;
-
- var binString1 = '' + array[i] + '' + array[i+1] + '' + array[i+2] + '' + array[i+3];
- var binString2 = '' + array[i+4] + '' + array[i+5] + '' + array[i+6] + '' + array[i+7];
- var hexchar1 = binary2hex[binString1];
- var hexchar2 = binary2hex[binString2];
-
- var buf = new Buffer(hexchar1 + '' + hexchar2, 'hex');
- bufArray.push(buf);
- }
-
- return Buffer.concat(bufArray);
-}
-
-function create_NT_hashed_password_v1(password){
- var buf = new Buffer(password, 'utf16le');
- var md4 = crypto.createHash('md4');
- md4.update(buf);
- return new Buffer(md4.digest());
-}
-
-function calc_resp(password_hash, server_challenge){
- // padding with zeros to make the hash 21 bytes long
- var passHashPadded = new Buffer(21);
- passHashPadded.fill("\0");
- password_hash.copy(passHashPadded, 0, 0, password_hash.length);
-
- var resArray = [];
-
- var des = crypto.createCipheriv('DES-ECB', insertZerosEvery7Bits(passHashPadded.slice(0,7)), '');
- resArray.push( des.update(server_challenge.slice(0,8)) );
-
- des = crypto.createCipheriv('DES-ECB', insertZerosEvery7Bits(passHashPadded.slice(7,14)), '');
- resArray.push( des.update(server_challenge.slice(0,8)) );
-
- des = crypto.createCipheriv('DES-ECB', insertZerosEvery7Bits(passHashPadded.slice(14,21)), '');
- resArray.push( des.update(server_challenge.slice(0,8)) );
-
- return Buffer.concat(resArray);
-}
-
-function ntlm2sr_calc_resp(responseKeyNT, serverChallenge, clientChallenge){
- // padding with zeros to make the hash 16 bytes longer
- var lmChallengeResponse = new Buffer(clientChallenge.length + 16);
- lmChallengeResponse.fill("\0");
- clientChallenge.copy(lmChallengeResponse, 0, 0, clientChallenge.length);
-
- var buf = Buffer.concat([serverChallenge, clientChallenge]);
- var md5 = crypto.createHash('md5');
- md5.update(buf);
- var sess = md5.digest();
- var ntChallengeResponse = calc_resp(responseKeyNT, sess.slice(0,8));
-
- return {
- lmChallengeResponse: lmChallengeResponse,
- ntChallengeResponse: ntChallengeResponse
- };
-}
-
-exports.createType1Message = createType1Message;
-exports.parseType2Message = parseType2Message;
-exports.createType3Message = createType3Message;
-
-
-
-
diff --git a/lib/opensource/node-http-ntlm/readme.txt b/lib/opensource/node-http-ntlm/readme.txt
deleted file mode 100644
index b341600..0000000
--- a/lib/opensource/node-http-ntlm/readme.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-// This software (ntlm.js) was copied from a file of the same name at https://github.com/SamDecrock/node-http-ntlm/blob/master/ntlm.js.
-//
-// As of this writing, it is a part of the node-http-ntlm module produced by SamDecrock.
-//
-// It is used as a part of the NTLM support provided by the vso-node-api library.
-//
diff --git a/make.js b/make.js
index db067fe..dee7eeb 100644
--- a/make.js
+++ b/make.js
@@ -28,7 +28,6 @@ target.build = function () {
run(path.join(__dirname, 'node_modules/.bin/tsc') + ' --outDir ' + buildPath);
// cp(rp('dependencies/typings.json'), buildPath);
- cp('-Rf', rp('lib/opensource'), buildPath);
cp(rp('package.json'), buildPath);
cp(rp('README.md'), buildPath);
cp(rp('LICENSE'), buildPath);
diff --git a/package.json b/package.json
index d42420c..6fe0095 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"@types/mocha": "^2.2.41"
},
"dependencies": {
+ "httpntlm": "1.7.5",
"tunnel": "0.0.4",
"underscore": "1.8.3"
}