diff options
Diffstat (limited to 'server/modules/axios-ntlm/lib/ntlm.js')
-rw-r--r-- | server/modules/axios-ntlm/lib/ntlm.js | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/server/modules/axios-ntlm/lib/ntlm.js b/server/modules/axios-ntlm/lib/ntlm.js new file mode 100644 index 0000000..54490c0 --- /dev/null +++ b/server/modules/axios-ntlm/lib/ntlm.js @@ -0,0 +1,220 @@ +'use strict'; +// Original file https://raw.githubusercontent.com/elasticio/node-ntlm-client/master/lib/ntlm.js +var os = require('os'), flags = require('./flags'), hash = require('./hash'); +var NTLMSIGNATURE = "NTLMSSP\0"; +function createType1Message(workstation, target) { + var dataPos = 32, pos = 0, buf = new Buffer.alloc(1024); + workstation = workstation === undefined ? os.hostname() : workstation; + target = target === undefined ? '' : target; + //signature + buf.write(NTLMSIGNATURE, pos, NTLMSIGNATURE.length, 'ascii'); + pos += NTLMSIGNATURE.length; + //message type + buf.writeUInt32LE(1, pos); + pos += 4; + //flags + buf.writeUInt32LE(flags.NTLMFLAG_NEGOTIATE_OEM | + flags.NTLMFLAG_REQUEST_TARGET | + flags.NTLMFLAG_NEGOTIATE_NTLM_KEY | + flags.NTLMFLAG_NEGOTIATE_NTLM2_KEY | + flags.NTLMFLAG_NEGOTIATE_ALWAYS_SIGN, pos); + pos += 4; + //domain security buffer + buf.writeUInt16LE(target.length, pos); + pos += 2; + buf.writeUInt16LE(target.length, pos); + pos += 2; + buf.writeUInt32LE(target.length === 0 ? 0 : dataPos, pos); + pos += 4; + if (target.length > 0) { + dataPos += buf.write(target, dataPos, 'ascii'); + } + //workstation security buffer + buf.writeUInt16LE(workstation.length, pos); + pos += 2; + buf.writeUInt16LE(workstation.length, pos); + pos += 2; + buf.writeUInt32LE(workstation.length === 0 ? 0 : dataPos, pos); + pos += 4; + if (workstation.length > 0) { + dataPos += buf.write(workstation, dataPos, 'ascii'); + } + return 'NTLM ' + buf.toString('base64', 0, dataPos); +} +function decodeType2Message(str) { + if (str === undefined) { + throw new Error('Invalid argument'); + } + //convenience + if (Object.prototype.toString.call(str) !== '[object String]') { + if (str.hasOwnProperty('headers') && str.headers.hasOwnProperty('www-authenticate')) { + str = str.headers['www-authenticate']; + } + else { + throw new Error('Invalid argument'); + } + } + var ntlmMatch = /^NTLM ([^,\s]+)/.exec(str); + if (ntlmMatch) { + str = ntlmMatch[1]; + } + var buf = new Buffer.from(str, 'base64'), obj = {}; + //check signature + if (buf.toString('ascii', 0, NTLMSIGNATURE.length) !== NTLMSIGNATURE) { + throw new Error('Invalid message signature: ' + str); + } + //check message type + if (buf.readUInt32LE(NTLMSIGNATURE.length) !== 2) { + throw new Error('Invalid message type (no type 2)'); + } + //read flags + obj.flags = buf.readUInt32LE(20); + obj.encoding = (obj.flags & flags.NTLMFLAG_NEGOTIATE_OEM) ? 'ascii' : 'ucs2'; + obj.version = (obj.flags & flags.NTLMFLAG_NEGOTIATE_NTLM2_KEY) ? 2 : 1; + obj.challenge = buf.slice(24, 32); + //read target name + obj.targetName = (function () { + var length = buf.readUInt16LE(12); + //skipping allocated space + var offset = buf.readUInt32LE(16); + if (length === 0) { + return ''; + } + if ((offset + length) > buf.length || offset < 32) { + throw new Error('Bad type 2 message'); + } + return buf.toString(obj.encoding, offset, offset + length); + })(); + //read target info + if (obj.flags & flags.NTLMFLAG_NEGOTIATE_TARGET_INFO) { + obj.targetInfo = (function () { + var info = {}; + var length = buf.readUInt16LE(40); + //skipping allocated space + var offset = buf.readUInt32LE(44); + var targetInfoBuffer = new Buffer.alloc(length); + buf.copy(targetInfoBuffer, 0, offset, offset + length); + if (length === 0) { + return info; + } + if ((offset + length) > buf.length || offset < 32) { + throw new Error('Bad type 2 message'); + } + var pos = offset; + while (pos < (offset + length)) { + var blockType = buf.readUInt16LE(pos); + pos += 2; + var blockLength = buf.readUInt16LE(pos); + pos += 2; + if (blockType === 0) { + //reached the terminator subblock + break; + } + var blockTypeStr = void 0; + switch (blockType) { + case 1: + blockTypeStr = 'SERVER'; + break; + case 2: + blockTypeStr = 'DOMAIN'; + break; + case 3: + blockTypeStr = 'FQDN'; + break; + case 4: + blockTypeStr = 'DNS'; + break; + case 5: + blockTypeStr = 'PARENT_DNS'; + break; + default: + blockTypeStr = ''; + break; + } + if (blockTypeStr) { + info[blockTypeStr] = buf.toString('ucs2', pos, pos + blockLength); + } + pos += blockLength; + } + return { + parsed: info, + buffer: targetInfoBuffer + }; + })(); + } + return obj; +} +function createType3Message(type2Message, username, password, workstation, target) { + var dataPos = 52, buf = new Buffer.alloc(1024); + if (workstation === undefined) { + workstation = os.hostname(); + } + if (target === undefined) { + target = type2Message.targetName; + } + //signature + buf.write(NTLMSIGNATURE, 0, NTLMSIGNATURE.length, 'ascii'); + //message type + buf.writeUInt32LE(3, 8); + if (type2Message.version === 2) { + dataPos = 64; + var ntlmHash = hash.createNTLMHash(password), nonce = hash.createPseudoRandomValue(16), lmv2 = hash.createLMv2Response(type2Message, username, ntlmHash, nonce, target), ntlmv2 = hash.createNTLMv2Response(type2Message, username, ntlmHash, nonce, target); + //lmv2 security buffer + buf.writeUInt16LE(lmv2.length, 12); + buf.writeUInt16LE(lmv2.length, 14); + buf.writeUInt32LE(dataPos, 16); + lmv2.copy(buf, dataPos); + dataPos += lmv2.length; + //ntlmv2 security buffer + buf.writeUInt16LE(ntlmv2.length, 20); + buf.writeUInt16LE(ntlmv2.length, 22); + buf.writeUInt32LE(dataPos, 24); + ntlmv2.copy(buf, dataPos); + dataPos += ntlmv2.length; + } + else { + var lmHash = hash.createLMHash(password), ntlmHash = hash.createNTLMHash(password), lm = hash.createLMResponse(type2Message.challenge, lmHash), ntlm = hash.createNTLMResponse(type2Message.challenge, ntlmHash); + //lm security buffer + buf.writeUInt16LE(lm.length, 12); + buf.writeUInt16LE(lm.length, 14); + buf.writeUInt32LE(dataPos, 16); + lm.copy(buf, dataPos); + dataPos += lm.length; + //ntlm security buffer + buf.writeUInt16LE(ntlm.length, 20); + buf.writeUInt16LE(ntlm.length, 22); + buf.writeUInt32LE(dataPos, 24); + ntlm.copy(buf, dataPos); + dataPos += ntlm.length; + } + //target name security buffer + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? target.length : target.length * 2, 28); + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? target.length : target.length * 2, 30); + buf.writeUInt32LE(dataPos, 32); + dataPos += buf.write(target, dataPos, type2Message.encoding); + //user name security buffer + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? username.length : username.length * 2, 36); + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? username.length : username.length * 2, 38); + buf.writeUInt32LE(dataPos, 40); + dataPos += buf.write(username, dataPos, type2Message.encoding); + //workstation name security buffer + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? workstation.length : workstation.length * 2, 44); + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? workstation.length : workstation.length * 2, 46); + buf.writeUInt32LE(dataPos, 48); + dataPos += buf.write(workstation, dataPos, type2Message.encoding); + if (type2Message.version === 2) { + //session key security buffer + buf.writeUInt16LE(0, 52); + buf.writeUInt16LE(0, 54); + buf.writeUInt32LE(0, 56); + //flags + buf.writeUInt32LE(type2Message.flags, 60); + } + return 'NTLM ' + buf.toString('base64', 0, dataPos); +} +module.exports = { + createType1Message: createType1Message, + decodeType2Message: decodeType2Message, + createType3Message: createType3Message +}; +//# sourceMappingURL=ntlm.js.map
\ No newline at end of file |