mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-10-31 11:29:20 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			220 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| '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
 |