"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _writableTrackingBuffer = _interopRequireDefault(require("./tracking-buffer/writable-tracking-buffer"));
var crypto = _interopRequireWildcard(require("crypto"));
var _jsMd = _interopRequireDefault(require("js-md4"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class NTLMResponsePayload {
  constructor(loginData) {
    this.data = this.createResponse(loginData);
  }
  toString(indent = '') {
    return indent + 'NTLM Auth';
  }
  createResponse(challenge) {
    const client_nonce = this.createClientNonce();
    const lmv2len = 24;
    const ntlmv2len = 16;
    const domain = challenge.domain;
    const username = challenge.userName;
    const password = challenge.password;
    const ntlmData = challenge.ntlmpacket;
    const server_data = ntlmData.target;
    const server_nonce = ntlmData.nonce;
    const bufferLength = 64 + domain.length * 2 + username.length * 2 + lmv2len + ntlmv2len + 8 + 8 + 8 + 4 + server_data.length + 4;
    const data = new _writableTrackingBuffer.default(bufferLength);
    data.position = 0;
    data.writeString('NTLMSSP\u0000', 'utf8');
    data.writeUInt32LE(0x03);
    const baseIdx = 64;
    const dnIdx = baseIdx;
    const unIdx = dnIdx + domain.length * 2;
    const l2Idx = unIdx + username.length * 2;
    const ntIdx = l2Idx + lmv2len;
    data.writeUInt16LE(lmv2len);
    data.writeUInt16LE(lmv2len);
    data.writeUInt32LE(l2Idx);
    data.writeUInt16LE(ntlmv2len);
    data.writeUInt16LE(ntlmv2len);
    data.writeUInt32LE(ntIdx);
    data.writeUInt16LE(domain.length * 2);
    data.writeUInt16LE(domain.length * 2);
    data.writeUInt32LE(dnIdx);
    data.writeUInt16LE(username.length * 2);
    data.writeUInt16LE(username.length * 2);
    data.writeUInt32LE(unIdx);
    data.writeUInt16LE(0);
    data.writeUInt16LE(0);
    data.writeUInt32LE(baseIdx);
    data.writeUInt16LE(0);
    data.writeUInt16LE(0);
    data.writeUInt32LE(baseIdx);
    data.writeUInt16LE(0x8201);
    data.writeUInt16LE(0x08);
    data.writeString(domain, 'ucs2');
    data.writeString(username, 'ucs2');
    const lmv2Data = this.lmv2Response(domain, username, password, server_nonce, client_nonce);
    data.copyFrom(lmv2Data);
    const genTime = new Date().getTime();
    const ntlmDataBuffer = this.ntlmv2Response(domain, username, password, server_nonce, server_data, client_nonce, genTime);
    data.copyFrom(ntlmDataBuffer);
    data.writeUInt32LE(0x0101);
    data.writeUInt32LE(0x0000);
    const timestamp = this.createTimestamp(genTime);
    data.copyFrom(timestamp);
    data.copyFrom(client_nonce);
    data.writeUInt32LE(0x0000);
    data.copyFrom(server_data);
    data.writeUInt32LE(0x0000);
    return data.data;
  }
  createClientNonce() {
    const client_nonce = Buffer.alloc(8, 0);
    let nidx = 0;
    while (nidx < 8) {
      client_nonce.writeUInt8(Math.ceil(Math.random() * 255), nidx);
      nidx++;
    }
    return client_nonce;
  }
  ntlmv2Response(domain, user, password, serverNonce, targetInfo, clientNonce, mytime) {
    const timestamp = this.createTimestamp(mytime);
    const hash = this.ntv2Hash(domain, user, password);
    const dataLength = 40 + targetInfo.length;
    const data = Buffer.alloc(dataLength, 0);
    serverNonce.copy(data, 0, 0, 8);
    data.writeUInt32LE(0x101, 8);
    data.writeUInt32LE(0x0, 12);
    timestamp.copy(data, 16, 0, 8);
    clientNonce.copy(data, 24, 0, 8);
    data.writeUInt32LE(0x0, 32);
    targetInfo.copy(data, 36, 0, targetInfo.length);
    data.writeUInt32LE(0x0, 36 + targetInfo.length);
    return this.hmacMD5(data, hash);
  }
  createTimestamp(time) {
    const tenthsOfAMicrosecond = (BigInt(time) + BigInt(11644473600)) * BigInt(10000000);
    const lo = Number(tenthsOfAMicrosecond & BigInt(0xffffffff));
    const hi = Number(tenthsOfAMicrosecond >> BigInt(32) & BigInt(0xffffffff));
    const result = Buffer.alloc(8);
    result.writeUInt32LE(lo, 0);
    result.writeUInt32LE(hi, 4);
    return result;
  }
  lmv2Response(domain, user, password, serverNonce, clientNonce) {
    const hash = this.ntv2Hash(domain, user, password);
    const data = Buffer.alloc(serverNonce.length + clientNonce.length, 0);
    serverNonce.copy(data);
    clientNonce.copy(data, serverNonce.length, 0, clientNonce.length);
    const newhash = this.hmacMD5(data, hash);
    const response = Buffer.alloc(newhash.length + clientNonce.length, 0);
    newhash.copy(response);
    clientNonce.copy(response, newhash.length, 0, clientNonce.length);
    return response;
  }
  ntv2Hash(domain, user, password) {
    const hash = this.ntHash(password);
    const identity = Buffer.from(user.toUpperCase() + domain.toUpperCase(), 'ucs2');
    return this.hmacMD5(identity, hash);
  }
  ntHash(text) {
    const unicodeString = Buffer.from(text, 'ucs2');
    return Buffer.from(_jsMd.default.arrayBuffer(unicodeString));
  }
  hmacMD5(data, key) {
    return crypto.createHmac('MD5', key).update(data).digest();
  }
}
var _default = exports.default = NTLMResponsePayload;
module.exports = NTLMResponsePayload;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,[encoded data, 18536 characters]