'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