ai-remote 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +7 -0
- package/dist/protocols/index.js +35 -0
- package/dist/protocols/index.js.map +7 -0
- package/dist/protocols/rdp/buffer.js +170 -0
- package/dist/protocols/rdp/buffer.js.map +7 -0
- package/dist/protocols/rdp/caps.js +260 -0
- package/dist/protocols/rdp/caps.js.map +7 -0
- package/dist/protocols/rdp/cert.js +135 -0
- package/dist/protocols/rdp/cert.js.map +7 -0
- package/dist/protocols/rdp/client.js +1068 -0
- package/dist/protocols/rdp/client.js.map +7 -0
- package/dist/protocols/rdp/cliprdr.js +240 -0
- package/dist/protocols/rdp/cliprdr.js.map +7 -0
- package/dist/protocols/rdp/credssp.js +254 -0
- package/dist/protocols/rdp/credssp.js.map +7 -0
- package/dist/protocols/rdp/crypto.js +369 -0
- package/dist/protocols/rdp/crypto.js.map +7 -0
- package/dist/protocols/rdp/display.js +589 -0
- package/dist/protocols/rdp/display.js.map +7 -0
- package/dist/protocols/rdp/gcc.js +132 -0
- package/dist/protocols/rdp/gcc.js.map +7 -0
- package/dist/protocols/rdp/keymap.js +132 -0
- package/dist/protocols/rdp/keymap.js.map +7 -0
- package/dist/protocols/rdp/mcs.js +223 -0
- package/dist/protocols/rdp/mcs.js.map +7 -0
- package/dist/protocols/rdp/ntlm.js +305 -0
- package/dist/protocols/rdp/ntlm.js.map +7 -0
- package/dist/protocols/rdp/pdu.js +444 -0
- package/dist/protocols/rdp/pdu.js.map +7 -0
- package/dist/protocols/rdp/rail.js +383 -0
- package/dist/protocols/rdp/rail.js.map +7 -0
- package/dist/protocols/rdp/rle.js +276 -0
- package/dist/protocols/rdp/rle.js.map +7 -0
- package/dist/protocols/rdp/sec.js +156 -0
- package/dist/protocols/rdp/sec.js.map +7 -0
- package/dist/protocols/rdp/session.js +307 -0
- package/dist/protocols/rdp/session.js.map +7 -0
- package/dist/protocols/rdp/tls.js +354 -0
- package/dist/protocols/rdp/tls.js.map +7 -0
- package/dist/protocols/rdp/vchannel.js +59 -0
- package/dist/protocols/rdp/vchannel.js.map +7 -0
- package/dist/protocols/rdp/x224.js +110 -0
- package/dist/protocols/rdp/x224.js.map +7 -0
- package/dist/protocols/ssh/kex.js +177 -0
- package/dist/protocols/ssh/kex.js.map +7 -0
- package/dist/protocols/ssh/messages.js +55 -0
- package/dist/protocols/ssh/messages.js.map +7 -0
- package/dist/protocols/ssh/session.js +608 -0
- package/dist/protocols/ssh/session.js.map +7 -0
- package/dist/protocols/ssh/terminal.js +191 -0
- package/dist/protocols/ssh/terminal.js.map +7 -0
- package/dist/protocols/ssh/transport.js +611 -0
- package/dist/protocols/ssh/transport.js.map +7 -0
- package/dist/protocols/ssh/wire.js +189 -0
- package/dist/protocols/ssh/wire.js.map +7 -0
- package/dist/protocols/types.js +1 -0
- package/dist/protocols/types.js.map +7 -0
- package/dist/protocols/vnc/input.js +16 -0
- package/dist/protocols/vnc/input.js.map +7 -0
- package/dist/protocols/vnc/session.js +259 -0
- package/dist/protocols/vnc/session.js.map +7 -0
- package/dist/shared/connection.js +114 -0
- package/dist/shared/connection.js.map +7 -0
- package/dist/shared/device.js +1 -0
- package/dist/shared/device.js.map +7 -0
- package/dist/shared/hosts.js +133 -0
- package/dist/shared/hosts.js.map +7 -0
- package/dist/shared/icons.js +42 -0
- package/dist/shared/icons.js.map +7 -0
- package/dist/shared/protocol.js +40 -0
- package/dist/shared/protocol.js.map +7 -0
- package/dist/shared/signals.js +42 -0
- package/dist/shared/signals.js.map +7 -0
- package/package.json +82 -0
- package/src/index.ts +14 -0
- package/src/protocols/index.ts +72 -0
- package/src/protocols/rdp/buffer.ts +204 -0
- package/src/protocols/rdp/caps.ts +304 -0
- package/src/protocols/rdp/cert.ts +190 -0
- package/src/protocols/rdp/client.ts +1363 -0
- package/src/protocols/rdp/cliprdr.ts +344 -0
- package/src/protocols/rdp/credssp.ts +319 -0
- package/src/protocols/rdp/crypto.ts +416 -0
- package/src/protocols/rdp/display.ts +750 -0
- package/src/protocols/rdp/gcc.ts +162 -0
- package/src/protocols/rdp/keymap.ts +68 -0
- package/src/protocols/rdp/mcs.ts +283 -0
- package/src/protocols/rdp/ntlm.ts +380 -0
- package/src/protocols/rdp/pdu.ts +497 -0
- package/src/protocols/rdp/rail.ts +480 -0
- package/src/protocols/rdp/rle.ts +343 -0
- package/src/protocols/rdp/sec.ts +184 -0
- package/src/protocols/rdp/session.ts +393 -0
- package/src/protocols/rdp/tls.ts +452 -0
- package/src/protocols/rdp/vchannel.ts +89 -0
- package/src/protocols/rdp/x224.ts +139 -0
- package/src/protocols/ssh/kex.ts +227 -0
- package/src/protocols/ssh/messages.ts +54 -0
- package/src/protocols/ssh/session.ts +878 -0
- package/src/protocols/ssh/terminal.ts +242 -0
- package/src/protocols/ssh/transport.ts +732 -0
- package/src/protocols/ssh/wire.ts +220 -0
- package/src/protocols/types.ts +146 -0
- package/src/protocols/vnc/input.ts +13 -0
- package/src/protocols/vnc/novnc.d.ts +75 -0
- package/src/protocols/vnc/session.ts +367 -0
- package/src/shared/connection.ts +206 -0
- package/src/shared/device.ts +28 -0
- package/src/shared/hosts.ts +240 -0
- package/src/shared/icons.ts +49 -0
- package/src/shared/protocol.ts +55 -0
- package/src/shared/signals.ts +67 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/protocols/rdp/mcs.ts"],
|
|
4
|
+
"sourcesContent": ["// MCS (T.125) connect sequence and domain PDUs, with the BER and PER encoding\n// rules they need. MS-RDPBCGR 2.2.1.3 - 2.2.1.8.\n\nimport { Reader, Writer, concatBytes } from './buffer';\nimport { dataFrame, dataPayload } from './x224';\n\nexport const MCS_BASE_CHANNEL_ID = 1001;\nexport const MCS_GLOBAL_CHANNEL_ID = 1003;\n\nconst DOMAIN_MCSPDU = {\n ERECT_DOMAIN_REQUEST: 1,\n DISCONNECT_PROVIDER_ULTIMATUM: 8,\n ATTACH_USER_REQUEST: 10,\n ATTACH_USER_CONFIRM: 11,\n CHANNEL_JOIN_REQUEST: 14,\n CHANNEL_JOIN_CONFIRM: 15,\n SEND_DATA_REQUEST: 25,\n SEND_DATA_INDICATION: 26,\n};\n\nconst DISCONNECT_REASONS = {\n 0: 'The host closed the RDP session (domain disconnected).',\n 1: 'The host closed the RDP session (provider initiated).',\n 2: 'The host closed the RDP session (token purged).',\n 3: 'The host closed the RDP session (user requested).',\n 4: 'The host closed the RDP session (channel purged).',\n};\n\n// --- BER --------------------------------------------------------------------\n\nfunction berLength(length: number) {\n if (length > 0xff) return new Uint8Array([0x82, (length >> 8) & 0xff, length & 0xff]);\n if (length > 0x7f) return new Uint8Array([0x81, length]);\n return new Uint8Array([length]);\n}\n\nfunction berTlv(tag: number, content: Uint8Array) {\n return concatBytes(new Uint8Array(tag), berLength(content.length), content);\n}\n\nfunction berInteger(value: number) {\n let body;\n if (value < 0x80) body = new Uint8Array([value]);\n else if (value < 0x8000) body = new Uint8Array([value >> 8, value & 0xff]);\n else if (value < 0x800000) body = new Uint8Array([value >> 16, (value >> 8) & 0xff, value & 0xff]);\n else body = new Uint8Array([value >>> 24, (value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff]);\n return berTlv([0x02], body);\n}\n\nconst berOctetString = (bytes: Uint8Array) => berTlv([0x04], bytes);\nconst berBoolean = (value: number) => berTlv([0x01], new Uint8Array([value ? 0xff : 0x00]));\n\n/** DomainParameters ::= SEQUENCE of eight INTEGERs (T.125). */\nfunction berDomainParameters(values: readonly number[]) {\n return berTlv([0x30], concatBytes(...values.map(berInteger)));\n}\n\n// --- PER --------------------------------------------------------------------\n\nfunction perLength(writer: Writer, length: number) {\n if (length > 0x7f) writer.u16be(0x8000 | length);\n else writer.u8(length);\n return writer;\n}\n\nfunction perReadLength(reader: Reader) {\n const first = reader.u8();\n return first & 0x80 ? ((first & 0x7f) << 8) | reader.u8() : first;\n}\n\n// --- GCC Conference Create Request (T.124) ----------------------------------\n\nconst T124_OBJECT_IDENTIFIER = new Uint8Array([0x05, 0x00, 0x14, 0x7c, 0x00, 0x01]);\nconst H221_CLIENT_KEY = new Uint8Array([0x44, 0x75, 0x63, 0x61]); // \"Duca\"\nconst H221_SERVER_KEY = new Uint8Array([0x4d, 0x63, 0x44, 0x6e]); // \"McDn\"\n\nfunction gccConferenceCreateRequest(clientData: Uint8Array) {\n const writer = new Writer(clientData.length + 32);\n\n writer.u8(0); // ConnectData::t124Identifier, choice 0\n writer.raw(T124_OBJECT_IDENTIFIER); // ITU-T T.124 object identifier\n perLength(writer, clientData.length + 14);\n\n writer.u8(0); // ConnectGCCPDU: conferenceCreateRequest\n writer.u8(0x08); // ConferenceCreateRequest::conferenceName present\n writer.u8(0x00); // numeric string length (min 1)\n writer.u8(0x10); // conference name \"1\"\n writer.u8(0x00); // padding\n writer.u8(0x01); // one set of UserData\n writer.u8(0xc0); // UserData::value present, valueless choice\n writer.u8(0x00); // h221NonStandard length (fixed 4)\n writer.raw(H221_CLIENT_KEY);\n perLength(writer, clientData.length);\n writer.raw(clientData);\n\n return writer.take();\n}\n\n/**\n * Pull the server data blocks out of a GCC Conference Create Response.\n *\n * The response is PER-encoded with several variable-length fields in front of\n * the payload; locating the server's H.221 key is both shorter and sturdier\n * than replaying every one of those fields.\n */\nfunction gccServerDataBlocks(userData: Uint8Array) {\n for (let i = 0; i + 4 <= userData.length; i++) {\n if (\n userData[i] === H221_SERVER_KEY[0] &&\n userData[i + 1] === H221_SERVER_KEY[1] &&\n userData[i + 2] === H221_SERVER_KEY[2] &&\n userData[i + 3] === H221_SERVER_KEY[3]\n ) {\n const reader = new Reader(userData, i + 4);\n const length = perReadLength(reader);\n const blocks = reader.rest();\n return blocks.subarray(0, Math.min(length, blocks.length));\n }\n }\n throw new Error('RDP: the host response contained no GCC server data');\n}\n\n// --- Connect Initial / Response ---------------------------------------------\n\nconst DOMAIN_TARGET = [34, 2, 0, 1, 0, 1, 0xffff, 2];\nconst DOMAIN_MINIMUM = [1, 1, 1, 1, 0, 1, 0x420, 2];\nconst DOMAIN_MAXIMUM = [0xffff, 0xfc17, 0xffff, 1, 0, 1, 0xffff, 2];\n\nexport function connectInitial(clientData: Uint8Array) {\n const userData = gccConferenceCreateRequest(clientData);\n const content = concatBytes(\n berOctetString(new Uint8Array([0x01])), // callingDomainSelector\n berOctetString(new Uint8Array([0x01])), // calledDomainSelector\n berBoolean(true), // upwardFlag\n berDomainParameters(DOMAIN_TARGET),\n berDomainParameters(DOMAIN_MINIMUM),\n berDomainParameters(DOMAIN_MAXIMUM),\n berOctetString(userData)\n );\n\n // [APPLICATION 101] IMPLICIT SEQUENCE\n return dataFrame(berTlv([0x7f, 0x65], content));\n}\n\n/** Walk one BER TLV at the reader's position. */\nfunction readBerTlv(reader: Reader) {\n let tag = reader.u8();\n if ((tag & 0x1f) === 0x1f) tag = (tag << 8) | reader.u8();\n\n let length = reader.u8();\n if (length & 0x80) {\n const byteCount = length & 0x7f;\n length = 0;\n for (let i = 0; i < byteCount; i++) length = (length << 8) | reader.u8();\n }\n\n return { tag, value: reader.raw(length) };\n}\n\nexport function parseConnectResponse(frame: Uint8Array) {\n const reader = new Reader(dataPayload(frame));\n const outer = readBerTlv(reader);\n if (outer.tag !== 0x7f66) {\n throw new Error(`RDP: expected an MCS connect response, got BER tag 0x${outer.tag.toString(16)}`);\n }\n\n const inner = new Reader(outer.value);\n const result = readBerTlv(inner); // result ENUMERATED\n readBerTlv(inner); // calledConnectId\n readBerTlv(inner); // domainParameters\n const userData = readBerTlv(inner); // userData OCTET STRING\n\n if (result.value[0] !== 0) {\n throw new Error(`RDP: the host rejected the MCS connection (result ${result.value[0]})`);\n }\n\n return gccServerDataBlocks(userData.value);\n}\n\n// --- Domain PDUs ------------------------------------------------------------\n\nconst domainHeader = (pdu: Uint8Array) => pdu << 2;\n\nexport function erectDomainRequest() {\n const writer = new Writer(8);\n writer.u8(domainHeader(DOMAIN_MCSPDU.ERECT_DOMAIN_REQUEST));\n writer.u8(1).u8(0); // subHeight: PER integer 0\n writer.u8(1).u8(0); // subInterval: PER integer 0\n return dataFrame(writer.take());\n}\n\nexport function attachUserRequest() {\n return dataFrame(new Uint8Array([domainHeader(DOMAIN_MCSPDU.ATTACH_USER_REQUEST)]));\n}\n\nexport function parseAttachUserConfirm(frame: Uint8Array) {\n const reader = new Reader(dataPayload(frame));\n const header = reader.u8();\n if (header >> 2 !== DOMAIN_MCSPDU.ATTACH_USER_CONFIRM) {\n throw new Error(`RDP: expected an MCS attach-user confirm, got PDU ${header >> 2}`);\n }\n\n const result = reader.u8();\n if (result !== 0) throw new Error(`RDP: the host refused to attach a user (result ${result})`);\n\n // The initiator is only present when the header's low bit says so.\n const userId = header & 0x02 ? reader.u16be() + MCS_BASE_CHANNEL_ID : MCS_BASE_CHANNEL_ID;\n return { userId };\n}\n\nexport function channelJoinRequest(userId: number, channelId: number) {\n const writer = new Writer(8);\n writer.u8(domainHeader(DOMAIN_MCSPDU.CHANNEL_JOIN_REQUEST));\n writer.u16be(userId - MCS_BASE_CHANNEL_ID);\n writer.u16be(channelId);\n return dataFrame(writer.take());\n}\n\nexport function parseChannelJoinConfirm(frame: Uint8Array) {\n const reader = new Reader(dataPayload(frame));\n const header = reader.u8();\n if (header >> 2 !== DOMAIN_MCSPDU.CHANNEL_JOIN_CONFIRM) {\n throw new Error(`RDP: expected an MCS channel-join confirm, got PDU ${header >> 2}`);\n }\n\n const result = reader.u8();\n reader.u16be(); // initiator\n const requested = reader.u16be();\n if (result !== 0) {\n throw new Error(`RDP: the host refused to join channel ${requested} (result ${result})`);\n }\n\n // The confirmed channel id is normally echoed after the requested one.\n const channelId = reader.remaining >= 2 ? reader.u16be() : requested;\n return { channelId: channelId || requested };\n}\n\nexport function sendDataRequest(userId: number, channelId: number, payload: Uint8Array) {\n const writer = new Writer(payload.length + 16);\n writer.u8(domainHeader(DOMAIN_MCSPDU.SEND_DATA_REQUEST));\n writer.u16be(userId - MCS_BASE_CHANNEL_ID);\n writer.u16be(channelId);\n writer.u8(0x70); // dataPriority high, segmentation begin + end\n perLength(writer, payload.length);\n writer.raw(payload);\n return dataFrame(writer.take());\n}\n\n/**\n * Classify an inbound X.224 data frame. Everything the server sends after the\n * connect sequence arrives as a send-data indication on some channel.\n */\nexport function parseDomainPdu(frame: Uint8Array) {\n const reader = new Reader(dataPayload(frame));\n const header = reader.u8();\n const type = header >> 2;\n\n if (type === DOMAIN_MCSPDU.SEND_DATA_INDICATION) {\n reader.u16be(); // initiator\n const channelId = reader.u16be();\n reader.u8(); // flags\n const length = perReadLength(reader);\n const payload = reader.rest();\n return {\n type: 'send-data',\n channelId,\n payload: payload.subarray(0, Math.min(length, payload.length)),\n };\n }\n\n if (type === DOMAIN_MCSPDU.DISCONNECT_PROVIDER_ULTIMATUM) {\n // The reason straddles a byte boundary: one bit from the header, one from\n // the byte that follows (MS-RDPBCGR 2.2.2.3).\n const reason = ((header & 0x01) << 1) | (reader.remaining > 0 ? reader.u8() >> 7 : 0);\n return {\n type: 'disconnect',\n reason,\n message: DISCONNECT_REASONS[reason] || `The host closed the RDP session (reason ${reason}).`,\n };\n }\n\n return { type: 'other', mcsPduType: type };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { Writer, concatBytes } from "./buffer";
|
|
2
|
+
import { md5, rc4Crypt, rc4Init } from "./crypto";
|
|
3
|
+
function rotl32(value, count) {
|
|
4
|
+
return value << count | value >>> 32 - count;
|
|
5
|
+
}
|
|
6
|
+
function md4(message) {
|
|
7
|
+
const blockCount = Math.floor((message.length + 8) / 64) + 1;
|
|
8
|
+
const padded = new Uint8Array(blockCount * 64);
|
|
9
|
+
padded.set(message);
|
|
10
|
+
padded[message.length] = 128;
|
|
11
|
+
const view = new DataView(padded.buffer);
|
|
12
|
+
const bitLength = message.length * 8;
|
|
13
|
+
view.setUint32(padded.length - 8, bitLength >>> 0, true);
|
|
14
|
+
view.setUint32(padded.length - 4, Math.floor(bitLength / 4294967296), true);
|
|
15
|
+
let a0 = 1732584193, b0 = 4023233417, c0 = 2562383102, d0 = 271733878;
|
|
16
|
+
const x = new Uint32Array(16);
|
|
17
|
+
const round1Shifts = [3, 7, 11, 19];
|
|
18
|
+
const round2Order = [0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15];
|
|
19
|
+
const round2Shifts = [3, 5, 9, 13];
|
|
20
|
+
const round3Order = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15];
|
|
21
|
+
const round3Shifts = [3, 9, 11, 15];
|
|
22
|
+
for (let block = 0; block < blockCount; block++) {
|
|
23
|
+
for (let i = 0; i < 16; i++) x[i] = view.getUint32(block * 64 + i * 4, true);
|
|
24
|
+
let a = a0, b = b0, c = c0, d = d0;
|
|
25
|
+
const step = (value, shift) => rotl32(value | 0, shift);
|
|
26
|
+
for (let i = 0; i < 16; i++) {
|
|
27
|
+
const f = b & c | ~b & d;
|
|
28
|
+
const shift = round1Shifts[i % 4];
|
|
29
|
+
const next = step(a + f + x[i] | 0, shift);
|
|
30
|
+
a = d;
|
|
31
|
+
d = c;
|
|
32
|
+
c = b;
|
|
33
|
+
b = next;
|
|
34
|
+
}
|
|
35
|
+
for (let i = 0; i < 16; i++) {
|
|
36
|
+
const g = b & c | b & d | c & d;
|
|
37
|
+
const shift = round2Shifts[i % 4];
|
|
38
|
+
const next = step(a + g + x[round2Order[i]] + 1518500249 | 0, shift);
|
|
39
|
+
a = d;
|
|
40
|
+
d = c;
|
|
41
|
+
c = b;
|
|
42
|
+
b = next;
|
|
43
|
+
}
|
|
44
|
+
for (let i = 0; i < 16; i++) {
|
|
45
|
+
const h = b ^ c ^ d;
|
|
46
|
+
const shift = round3Shifts[i % 4];
|
|
47
|
+
const next = step(a + h + x[round3Order[i]] + 1859775393 | 0, shift);
|
|
48
|
+
a = d;
|
|
49
|
+
d = c;
|
|
50
|
+
c = b;
|
|
51
|
+
b = next;
|
|
52
|
+
}
|
|
53
|
+
a0 = a0 + a | 0;
|
|
54
|
+
b0 = b0 + b | 0;
|
|
55
|
+
c0 = c0 + c | 0;
|
|
56
|
+
d0 = d0 + d | 0;
|
|
57
|
+
}
|
|
58
|
+
const digest = new Uint8Array(16);
|
|
59
|
+
const out = new DataView(digest.buffer);
|
|
60
|
+
out.setUint32(0, a0 >>> 0, true);
|
|
61
|
+
out.setUint32(4, b0 >>> 0, true);
|
|
62
|
+
out.setUint32(8, c0 >>> 0, true);
|
|
63
|
+
out.setUint32(12, d0 >>> 0, true);
|
|
64
|
+
return digest;
|
|
65
|
+
}
|
|
66
|
+
function hmacMd5(key, message) {
|
|
67
|
+
const blockSize = 64;
|
|
68
|
+
const normalized = key.length > blockSize ? md5(key) : key;
|
|
69
|
+
const padded = new Uint8Array(blockSize);
|
|
70
|
+
padded.set(normalized);
|
|
71
|
+
const inner = new Uint8Array(blockSize);
|
|
72
|
+
const outer = new Uint8Array(blockSize);
|
|
73
|
+
for (let i = 0; i < blockSize; i++) {
|
|
74
|
+
inner[i] = padded[i] ^ 54;
|
|
75
|
+
outer[i] = padded[i] ^ 92;
|
|
76
|
+
}
|
|
77
|
+
return md5(concatBytes(outer, md5(concatBytes(inner, message))));
|
|
78
|
+
}
|
|
79
|
+
const NTLMSSP_SIGNATURE = new Uint8Array([78, 84, 76, 77, 83, 83, 80, 0]);
|
|
80
|
+
const NTLM_FLAG = {
|
|
81
|
+
UNICODE: 1,
|
|
82
|
+
REQUEST_TARGET: 4,
|
|
83
|
+
SIGN: 16,
|
|
84
|
+
SEAL: 32,
|
|
85
|
+
NTLM: 512,
|
|
86
|
+
ALWAYS_SIGN: 32768,
|
|
87
|
+
EXTENDED_SESSION_SECURITY: 524288,
|
|
88
|
+
TARGET_INFO: 8388608,
|
|
89
|
+
VERSION: 33554432,
|
|
90
|
+
KEY_128: 536870912,
|
|
91
|
+
KEY_EXCH: 1073741824,
|
|
92
|
+
KEY_56: 2147483648
|
|
93
|
+
};
|
|
94
|
+
const CLIENT_FLAGS = NTLM_FLAG.UNICODE | NTLM_FLAG.REQUEST_TARGET | NTLM_FLAG.SIGN | NTLM_FLAG.SEAL | NTLM_FLAG.NTLM | NTLM_FLAG.ALWAYS_SIGN | NTLM_FLAG.EXTENDED_SESSION_SECURITY | NTLM_FLAG.TARGET_INFO | NTLM_FLAG.VERSION | NTLM_FLAG.KEY_128 | NTLM_FLAG.KEY_EXCH | NTLM_FLAG.KEY_56;
|
|
95
|
+
const MSV_AV_EOL = 0;
|
|
96
|
+
const MSV_AV_TIMESTAMP = 7;
|
|
97
|
+
const MSV_AV_FLAGS = 6;
|
|
98
|
+
const MSV_AV_FLAGS_MIC = 2;
|
|
99
|
+
const utf16 = (text) => {
|
|
100
|
+
const writer = new Writer(text.length * 2 + 2);
|
|
101
|
+
writer.utf16le(text);
|
|
102
|
+
return writer.take();
|
|
103
|
+
};
|
|
104
|
+
const VERSION_FIELD = new Uint8Array([10, 0, 99, 69, 0, 0, 0, 15]);
|
|
105
|
+
function negotiateMessage() {
|
|
106
|
+
const writer = new Writer(40);
|
|
107
|
+
writer.raw(NTLMSSP_SIGNATURE);
|
|
108
|
+
writer.u32le(1);
|
|
109
|
+
writer.u32le(CLIENT_FLAGS >>> 0);
|
|
110
|
+
writer.u16le(0).u16le(0).u32le(0);
|
|
111
|
+
writer.u16le(0).u16le(0).u32le(0);
|
|
112
|
+
writer.raw(VERSION_FIELD);
|
|
113
|
+
return writer.take();
|
|
114
|
+
}
|
|
115
|
+
function parseChallengeMessage(bytes) {
|
|
116
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
117
|
+
if (view.getUint32(8, true) !== 2) {
|
|
118
|
+
throw new Error("NTLM: the host did not answer with a challenge message");
|
|
119
|
+
}
|
|
120
|
+
const targetNameLength = view.getUint16(12, true);
|
|
121
|
+
const targetNameOffset = view.getUint32(16, true);
|
|
122
|
+
const flags = view.getUint32(20, true);
|
|
123
|
+
const serverChallenge = bytes.subarray(24, 32).slice();
|
|
124
|
+
const targetInfoLength = view.getUint16(40, true);
|
|
125
|
+
const targetInfoOffset = view.getUint32(44, true);
|
|
126
|
+
return {
|
|
127
|
+
flags,
|
|
128
|
+
serverChallenge,
|
|
129
|
+
targetName: bytes.subarray(targetNameOffset, targetNameOffset + targetNameLength).slice(),
|
|
130
|
+
targetInfo: bytes.subarray(targetInfoOffset, targetInfoOffset + targetInfoLength).slice()
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function readAvPairs(targetInfo) {
|
|
134
|
+
const pairs = [];
|
|
135
|
+
let offset = 0;
|
|
136
|
+
const view = new DataView(targetInfo.buffer, targetInfo.byteOffset, targetInfo.byteLength);
|
|
137
|
+
while (offset + 4 <= targetInfo.length) {
|
|
138
|
+
const id = view.getUint16(offset, true);
|
|
139
|
+
const length = view.getUint16(offset + 2, true);
|
|
140
|
+
const value = targetInfo.subarray(offset + 4, offset + 4 + length);
|
|
141
|
+
offset += 4 + length;
|
|
142
|
+
if (id === MSV_AV_EOL) break;
|
|
143
|
+
pairs.push({ id, value });
|
|
144
|
+
}
|
|
145
|
+
return pairs;
|
|
146
|
+
}
|
|
147
|
+
function writeAvPairs(pairs) {
|
|
148
|
+
const writer = new Writer(256);
|
|
149
|
+
for (const pair of pairs) {
|
|
150
|
+
writer.u16le(pair.id);
|
|
151
|
+
writer.u16le(pair.value.length);
|
|
152
|
+
writer.raw(pair.value);
|
|
153
|
+
}
|
|
154
|
+
writer.u16le(MSV_AV_EOL).u16le(0);
|
|
155
|
+
return writer.take();
|
|
156
|
+
}
|
|
157
|
+
function fileTimeNow() {
|
|
158
|
+
const ticks = (BigInt(Date.now()) + 11644473600000n) * 10000n;
|
|
159
|
+
const out = new Uint8Array(8);
|
|
160
|
+
new DataView(out.buffer).setBigUint64(0, ticks, true);
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
function authenticateMessage({ username, domain, password, challenge, negotiateBytes, challengeBytes }) {
|
|
164
|
+
const responseKey = hmacMd5(
|
|
165
|
+
md4(utf16(password)),
|
|
166
|
+
utf16(username.toUpperCase() + domain)
|
|
167
|
+
);
|
|
168
|
+
const pairs = readAvPairs(challenge.targetInfo);
|
|
169
|
+
const timestamp = pairs.find((pair) => pair.id === MSV_AV_TIMESTAMP)?.value.slice() || fileTimeNow();
|
|
170
|
+
const flagsPair = pairs.find((pair) => pair.id === MSV_AV_FLAGS);
|
|
171
|
+
if (flagsPair) {
|
|
172
|
+
const view = new DataView(flagsPair.value.buffer, flagsPair.value.byteOffset, 4);
|
|
173
|
+
view.setUint32(0, view.getUint32(0, true) | MSV_AV_FLAGS_MIC, true);
|
|
174
|
+
} else {
|
|
175
|
+
const value = new Uint8Array(4);
|
|
176
|
+
new DataView(value.buffer).setUint32(0, MSV_AV_FLAGS_MIC, true);
|
|
177
|
+
pairs.push({ id: MSV_AV_FLAGS, value });
|
|
178
|
+
}
|
|
179
|
+
const targetInfo = writeAvPairs(pairs);
|
|
180
|
+
const clientChallenge = new Uint8Array(8);
|
|
181
|
+
crypto.getRandomValues(clientChallenge);
|
|
182
|
+
const temp = concatBytes(
|
|
183
|
+
new Uint8Array([1, 1, 0, 0, 0, 0, 0, 0]),
|
|
184
|
+
// version, reserved
|
|
185
|
+
timestamp,
|
|
186
|
+
clientChallenge,
|
|
187
|
+
new Uint8Array(4),
|
|
188
|
+
targetInfo,
|
|
189
|
+
new Uint8Array(4)
|
|
190
|
+
);
|
|
191
|
+
const proof = hmacMd5(responseKey, concatBytes(challenge.serverChallenge, temp));
|
|
192
|
+
const ntResponse = concatBytes(proof, temp);
|
|
193
|
+
const sessionBaseKey = hmacMd5(responseKey, proof);
|
|
194
|
+
const exportedSessionKey = new Uint8Array(16);
|
|
195
|
+
crypto.getRandomValues(exportedSessionKey);
|
|
196
|
+
const encryptedSessionKey = rc4Crypt(rc4Init(sessionBaseKey), exportedSessionKey);
|
|
197
|
+
const domainBytes = utf16Trimmed(domain);
|
|
198
|
+
const userBytes = utf16Trimmed(username);
|
|
199
|
+
const workstationBytes = utf16Trimmed("");
|
|
200
|
+
const lmResponse = new Uint8Array(24);
|
|
201
|
+
const headerLength = 72;
|
|
202
|
+
let offset = headerLength;
|
|
203
|
+
const layout = [];
|
|
204
|
+
const place = (bytes) => {
|
|
205
|
+
layout.push({ bytes, offset });
|
|
206
|
+
offset += bytes.length;
|
|
207
|
+
return layout[layout.length - 1];
|
|
208
|
+
};
|
|
209
|
+
const lm = place(lmResponse);
|
|
210
|
+
const nt = place(ntResponse);
|
|
211
|
+
const dom = place(domainBytes);
|
|
212
|
+
const user = place(userBytes);
|
|
213
|
+
const workstation = place(workstationBytes);
|
|
214
|
+
const sessionKey = place(encryptedSessionKey);
|
|
215
|
+
const writer = new Writer(offset + 16);
|
|
216
|
+
writer.raw(NTLMSSP_SIGNATURE);
|
|
217
|
+
writer.u32le(3);
|
|
218
|
+
const field = (entry) => {
|
|
219
|
+
writer.u16le(entry.bytes.length);
|
|
220
|
+
writer.u16le(entry.bytes.length);
|
|
221
|
+
writer.u32le(entry.offset + 16);
|
|
222
|
+
};
|
|
223
|
+
field(lm);
|
|
224
|
+
field(nt);
|
|
225
|
+
field(dom);
|
|
226
|
+
field(user);
|
|
227
|
+
field(workstation);
|
|
228
|
+
field(sessionKey);
|
|
229
|
+
writer.u32le(CLIENT_FLAGS >>> 0);
|
|
230
|
+
writer.raw(VERSION_FIELD);
|
|
231
|
+
writer.zeros(16);
|
|
232
|
+
for (const entry of layout) writer.raw(entry.bytes);
|
|
233
|
+
const message = writer.take();
|
|
234
|
+
const mic = hmacMd5(
|
|
235
|
+
exportedSessionKey,
|
|
236
|
+
concatBytes(negotiateBytes, challengeBytes, message)
|
|
237
|
+
);
|
|
238
|
+
message.set(mic, headerLength);
|
|
239
|
+
return {
|
|
240
|
+
message,
|
|
241
|
+
exportedSessionKey,
|
|
242
|
+
keys: sessionKeys(exportedSessionKey)
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function utf16Trimmed(text) {
|
|
246
|
+
if (!text) return new Uint8Array(0);
|
|
247
|
+
const bytes = utf16(text);
|
|
248
|
+
return bytes.subarray(0, text.length * 2).slice();
|
|
249
|
+
}
|
|
250
|
+
const CLIENT_SIGNING = "session key to client-to-server signing key magic constant\0";
|
|
251
|
+
const SERVER_SIGNING = "session key to server-to-client signing key magic constant\0";
|
|
252
|
+
const CLIENT_SEALING = "session key to client-to-server sealing key magic constant\0";
|
|
253
|
+
const SERVER_SEALING = "session key to server-to-client sealing key magic constant\0";
|
|
254
|
+
function sessionKeys(exportedSessionKey) {
|
|
255
|
+
const derive = (label) => md5(concatBytes(exportedSessionKey, new TextEncoder().encode(label)));
|
|
256
|
+
return {
|
|
257
|
+
clientSigningKey: derive(CLIENT_SIGNING),
|
|
258
|
+
serverSigningKey: derive(SERVER_SIGNING),
|
|
259
|
+
clientSealing: rc4Init(derive(CLIENT_SEALING)),
|
|
260
|
+
serverSealing: rc4Init(derive(SERVER_SEALING))
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
class NtlmSealer {
|
|
264
|
+
keys;
|
|
265
|
+
sendSequence;
|
|
266
|
+
receiveSequence;
|
|
267
|
+
constructor(keys) {
|
|
268
|
+
this.keys = keys;
|
|
269
|
+
this.sendSequence = 0;
|
|
270
|
+
this.receiveSequence = 0;
|
|
271
|
+
}
|
|
272
|
+
seal(plaintext) {
|
|
273
|
+
const sequence = new Uint8Array(4);
|
|
274
|
+
new DataView(sequence.buffer).setUint32(0, this.sendSequence, true);
|
|
275
|
+
const digest = hmacMd5(this.keys.clientSigningKey, concatBytes(sequence, plaintext));
|
|
276
|
+
const sealed = rc4Crypt(this.keys.clientSealing, plaintext);
|
|
277
|
+
const checksum = rc4Crypt(this.keys.clientSealing, digest.subarray(0, 8));
|
|
278
|
+
this.sendSequence += 1;
|
|
279
|
+
return concatBytes(new Uint8Array([1, 0, 0, 0]), checksum, sequence, sealed);
|
|
280
|
+
}
|
|
281
|
+
unseal(bytes) {
|
|
282
|
+
if (bytes.length < 16) throw new Error("NTLM: sealed message is too short");
|
|
283
|
+
const sealed = bytes.subarray(16);
|
|
284
|
+
const plaintext = rc4Crypt(this.keys.serverSealing, sealed);
|
|
285
|
+
const sequence = bytes.subarray(12, 16);
|
|
286
|
+
const digest = hmacMd5(this.keys.serverSigningKey, concatBytes(sequence, plaintext));
|
|
287
|
+
const expected = rc4Crypt(this.keys.serverSealing, digest.subarray(0, 8));
|
|
288
|
+
const actual = bytes.subarray(4, 12);
|
|
289
|
+
if (!expected.every((byte, i) => byte === actual[i])) {
|
|
290
|
+
throw new Error("NTLM: the host signature did not verify");
|
|
291
|
+
}
|
|
292
|
+
this.receiveSequence += 1;
|
|
293
|
+
return plaintext;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
export {
|
|
297
|
+
NTLM_FLAG,
|
|
298
|
+
NtlmSealer,
|
|
299
|
+
authenticateMessage,
|
|
300
|
+
hmacMd5,
|
|
301
|
+
md4,
|
|
302
|
+
negotiateMessage,
|
|
303
|
+
parseChallengeMessage
|
|
304
|
+
};
|
|
305
|
+
//# sourceMappingURL=ntlm.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/protocols/rdp/ntlm.ts"],
|
|
4
|
+
"sourcesContent": ["// NTLMv2 (MS-NLMP), the authentication CredSSP carries for a local Windows\n// account. MD5, RC4 and the HMAC construction already exist for RDP Standard\n// Security; only MD4 and the NTLM message formats are new here.\n\nimport { Writer, concatBytes } from './buffer';\nimport { md5, rc4Crypt, rc4Init } from './crypto';\n\n// --- MD4 (RFC 1320), used only to hash the password ------------------------\n\nfunction rotl32(value, count: number) {\n return (value << count) | (value >>> (32 - count));\n}\n\nexport function md4(message: string) {\n const blockCount = Math.floor((message.length + 8) / 64) + 1;\n const padded = new Uint8Array(blockCount * 64);\n padded.set(message);\n padded[message.length] = 0x80;\n\n const view = new DataView(padded.buffer);\n const bitLength = message.length * 8;\n view.setUint32(padded.length - 8, bitLength >>> 0, true);\n view.setUint32(padded.length - 4, Math.floor(bitLength / 4294967296), true);\n\n let a0 = 0x67452301, b0 = 0xefcdab89, c0 = 0x98badcfe, d0 = 0x10325476;\n const x = new Uint32Array(16);\n\n const round1Shifts = [3, 7, 11, 19];\n const round2Order = [0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15];\n const round2Shifts = [3, 5, 9, 13];\n const round3Order = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15];\n const round3Shifts = [3, 9, 11, 15];\n\n for (let block = 0; block < blockCount; block++) {\n for (let i = 0; i < 16; i++) x[i] = view.getUint32(block * 64 + i * 4, true);\n\n let a = a0, b = b0, c = c0, d = d0;\n const step = (value, shift) => rotl32(value | 0, shift);\n\n for (let i = 0; i < 16; i++) {\n const f = (b & c) | (~b & d);\n const shift = round1Shifts[i % 4];\n const next = step((a + f + x[i]) | 0, shift);\n a = d; d = c; c = b; b = next;\n }\n for (let i = 0; i < 16; i++) {\n const g = (b & c) | (b & d) | (c & d);\n const shift = round2Shifts[i % 4];\n const next = step((a + g + x[round2Order[i]] + 0x5a827999) | 0, shift);\n a = d; d = c; c = b; b = next;\n }\n for (let i = 0; i < 16; i++) {\n const h = b ^ c ^ d;\n const shift = round3Shifts[i % 4];\n const next = step((a + h + x[round3Order[i]] + 0x6ed9eba1) | 0, shift);\n a = d; d = c; c = b; b = next;\n }\n\n a0 = (a0 + a) | 0;\n b0 = (b0 + b) | 0;\n c0 = (c0 + c) | 0;\n d0 = (d0 + d) | 0;\n }\n\n const digest = new Uint8Array(16);\n const out = new DataView(digest.buffer);\n out.setUint32(0, a0 >>> 0, true);\n out.setUint32(4, b0 >>> 0, true);\n out.setUint32(8, c0 >>> 0, true);\n out.setUint32(12, d0 >>> 0, true);\n return digest;\n}\n\n/** HMAC-MD5. WebCrypto has no MD5, so it is built from the MD5 here. */\nexport function hmacMd5(key: Uint8Array, message: string) {\n const blockSize = 64;\n const normalized = key.length > blockSize ? md5(key) : key;\n const padded = new Uint8Array(blockSize);\n padded.set(normalized);\n\n const inner = new Uint8Array(blockSize);\n const outer = new Uint8Array(blockSize);\n for (let i = 0; i < blockSize; i++) {\n inner[i] = padded[i] ^ 0x36;\n outer[i] = padded[i] ^ 0x5c;\n }\n\n return md5(concatBytes(outer, md5(concatBytes(inner, message))));\n}\n\n// --- NTLM messages ----------------------------------------------------------\n\nconst NTLMSSP_SIGNATURE = new Uint8Array([0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00]);\n\nexport const NTLM_FLAG = {\n UNICODE: 0x00000001,\n REQUEST_TARGET: 0x00000004,\n SIGN: 0x00000010,\n SEAL: 0x00000020,\n NTLM: 0x00000200,\n ALWAYS_SIGN: 0x00008000,\n EXTENDED_SESSION_SECURITY: 0x00080000,\n TARGET_INFO: 0x00800000,\n VERSION: 0x02000000,\n KEY_128: 0x20000000,\n KEY_EXCH: 0x40000000,\n KEY_56: 0x80000000,\n};\n\n// CredSSP needs SEAL and KEY_EXCH: the sealing keys are what protect the\n// public-key binding and the credentials.\nconst CLIENT_FLAGS =\n NTLM_FLAG.UNICODE |\n NTLM_FLAG.REQUEST_TARGET |\n NTLM_FLAG.SIGN |\n NTLM_FLAG.SEAL |\n NTLM_FLAG.NTLM |\n NTLM_FLAG.ALWAYS_SIGN |\n NTLM_FLAG.EXTENDED_SESSION_SECURITY |\n NTLM_FLAG.TARGET_INFO |\n NTLM_FLAG.VERSION |\n NTLM_FLAG.KEY_128 |\n NTLM_FLAG.KEY_EXCH |\n NTLM_FLAG.KEY_56;\n\nconst MSV_AV_EOL = 0x0000;\nconst MSV_AV_TIMESTAMP = 0x0007;\nconst MSV_AV_FLAGS = 0x0006;\nconst MSV_AV_FLAGS_MIC = 0x00000002;\n\nconst utf16 = (text: string) => {\n const writer = new Writer(text.length * 2 + 2);\n writer.utf16le(text);\n return writer.take();\n};\n\n/** Windows 10 build 19041, which is what a current client reports. */\nconst VERSION_FIELD = new Uint8Array([10, 0, 0x63, 0x45, 0x00, 0x00, 0x00, 0x0f]);\n\nexport function negotiateMessage() {\n const writer = new Writer(40);\n writer.raw(NTLMSSP_SIGNATURE);\n writer.u32le(1); // MessageType: NEGOTIATE\n writer.u32le(CLIENT_FLAGS >>> 0);\n writer.u16le(0).u16le(0).u32le(0); // DomainNameFields: absent\n writer.u16le(0).u16le(0).u32le(0); // WorkstationFields: absent\n writer.raw(VERSION_FIELD);\n return writer.take();\n}\n\nexport function parseChallengeMessage(bytes: Uint8Array) {\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n if (view.getUint32(8, true) !== 2) {\n throw new Error('NTLM: the host did not answer with a challenge message');\n }\n\n const targetNameLength = view.getUint16(12, true);\n const targetNameOffset = view.getUint32(16, true);\n const flags = view.getUint32(20, true);\n const serverChallenge = bytes.subarray(24, 32).slice();\n const targetInfoLength = view.getUint16(40, true);\n const targetInfoOffset = view.getUint32(44, true);\n\n return {\n flags,\n serverChallenge,\n targetName: bytes.subarray(targetNameOffset, targetNameOffset + targetNameLength).slice(),\n targetInfo: bytes.subarray(targetInfoOffset, targetInfoOffset + targetInfoLength).slice(),\n };\n}\n\n/** Walk the AV pair list the host sent, so its timestamp can be reused. */\nfunction readAvPairs(targetInfo) {\n const pairs = [];\n let offset = 0;\n const view = new DataView(targetInfo.buffer, targetInfo.byteOffset, targetInfo.byteLength);\n\n while (offset + 4 <= targetInfo.length) {\n const id = view.getUint16(offset, true);\n const length = view.getUint16(offset + 2, true);\n const value = targetInfo.subarray(offset + 4, offset + 4 + length);\n offset += 4 + length;\n if (id === MSV_AV_EOL) break;\n pairs.push({ id, value });\n }\n\n return pairs;\n}\n\nfunction writeAvPairs(pairs) {\n const writer = new Writer(256);\n for (const pair of pairs) {\n writer.u16le(pair.id);\n writer.u16le(pair.value.length);\n writer.raw(pair.value);\n }\n writer.u16le(MSV_AV_EOL).u16le(0);\n return writer.take();\n}\n\n/** Windows FILETIME: 100ns ticks since 1601. */\nfunction fileTimeNow() {\n const ticks = (BigInt(Date.now()) + 11644473600000n) * 10000n;\n const out = new Uint8Array(8);\n new DataView(out.buffer).setBigUint64(0, ticks, true);\n return out;\n}\n\n/**\n * Build the AUTHENTICATE message plus every key CredSSP needs afterwards.\n *\n * The MIC is always sent: a current Windows host expects one, and sending it\n * obliges the client to flag it in the AV pair list, which in turn feeds the\n * NTProofStr -- so the modified list has to be the one that goes on the wire.\n */\nexport function authenticateMessage({ username, domain, password, challenge, negotiateBytes, challengeBytes }) {\n const responseKey = hmacMd5(\n md4(utf16(password)),\n utf16(username.toUpperCase() + domain)\n );\n\n const pairs = readAvPairs(challenge.targetInfo);\n const timestamp = pairs.find((pair) => pair.id === MSV_AV_TIMESTAMP)?.value.slice() || fileTimeNow();\n\n const flagsPair = pairs.find((pair) => pair.id === MSV_AV_FLAGS);\n if (flagsPair) {\n const view = new DataView(flagsPair.value.buffer, flagsPair.value.byteOffset, 4);\n view.setUint32(0, view.getUint32(0, true) | MSV_AV_FLAGS_MIC, true);\n } else {\n const value = new Uint8Array(4);\n new DataView(value.buffer).setUint32(0, MSV_AV_FLAGS_MIC, true);\n pairs.push({ id: MSV_AV_FLAGS, value });\n }\n const targetInfo = writeAvPairs(pairs);\n\n const clientChallenge = new Uint8Array(8);\n crypto.getRandomValues(clientChallenge);\n\n const temp = concatBytes(\n new Uint8Array([0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), // version, reserved\n timestamp,\n clientChallenge,\n new Uint8Array(4),\n targetInfo,\n new Uint8Array(4)\n );\n\n const proof = hmacMd5(responseKey, concatBytes(challenge.serverChallenge, temp));\n const ntResponse = concatBytes(proof, temp);\n const sessionBaseKey = hmacMd5(responseKey, proof);\n\n // With KEY_EXCH the client picks the session key and sends it sealed.\n const exportedSessionKey = new Uint8Array(16);\n crypto.getRandomValues(exportedSessionKey);\n const encryptedSessionKey = rc4Crypt(rc4Init(sessionBaseKey), exportedSessionKey);\n\n const domainBytes = utf16Trimmed(domain);\n const userBytes = utf16Trimmed(username);\n const workstationBytes = utf16Trimmed('');\n const lmResponse = new Uint8Array(24);\n\n const headerLength = 72;\n let offset = headerLength;\n const layout = [];\n const place = (bytes: Uint8Array) => {\n layout.push({ bytes, offset });\n offset += bytes.length;\n return layout[layout.length - 1];\n };\n\n const lm = place(lmResponse);\n const nt = place(ntResponse);\n const dom = place(domainBytes);\n const user = place(userBytes);\n const workstation = place(workstationBytes);\n const sessionKey = place(encryptedSessionKey);\n\n const writer = new Writer(offset + 16);\n writer.raw(NTLMSSP_SIGNATURE);\n writer.u32le(3); // MessageType: AUTHENTICATE\n const field = (entry) => {\n writer.u16le(entry.bytes.length);\n writer.u16le(entry.bytes.length);\n writer.u32le(entry.offset + 16); // the MIC sits between header and payload\n };\n field(lm);\n field(nt);\n field(dom);\n field(user);\n field(workstation);\n field(sessionKey);\n writer.u32le(CLIENT_FLAGS >>> 0);\n writer.raw(VERSION_FIELD);\n writer.zeros(16); // MIC, filled in below\n for (const entry of layout) writer.raw(entry.bytes);\n\n const message = writer.take();\n const mic = hmacMd5(\n exportedSessionKey,\n concatBytes(negotiateBytes, challengeBytes, message)\n );\n message.set(mic, headerLength);\n\n return {\n message,\n exportedSessionKey,\n keys: sessionKeys(exportedSessionKey),\n };\n}\n\nfunction utf16Trimmed(text: string) {\n if (!text) return new Uint8Array(0);\n const bytes = utf16(text);\n // utf16le() appends no terminator, but Writer sizing may leave slack.\n return bytes.subarray(0, text.length * 2).slice();\n}\n\nconst CLIENT_SIGNING = 'session key to client-to-server signing key magic constant\\0';\nconst SERVER_SIGNING = 'session key to server-to-client signing key magic constant\\0';\nconst CLIENT_SEALING = 'session key to client-to-server sealing key magic constant\\0';\nconst SERVER_SEALING = 'session key to server-to-client sealing key magic constant\\0';\n\nfunction sessionKeys(exportedSessionKey) {\n const derive = (label: string) => md5(concatBytes(exportedSessionKey, new TextEncoder().encode(label)));\n\n return {\n clientSigningKey: derive(CLIENT_SIGNING),\n serverSigningKey: derive(SERVER_SIGNING),\n clientSealing: rc4Init(derive(CLIENT_SEALING)),\n serverSealing: rc4Init(derive(SERVER_SEALING)),\n };\n}\n\n/**\n * NTLM message confidentiality (MS-NLMP 3.4.3). The signature covers the\n * plaintext, and both the payload and the checksum draw from the same RC4\n * stream -- payload first.\n */\nexport class NtlmSealer {\n private readonly keys: NtlmSessionKeys;\n private sendSequence: number;\n private receiveSequence: number;\n\n constructor(keys) {\n this.keys = keys;\n this.sendSequence = 0;\n this.receiveSequence = 0;\n }\n\n seal(plaintext: Uint8Array) {\n const sequence = new Uint8Array(4);\n new DataView(sequence.buffer).setUint32(0, this.sendSequence, true);\n\n const digest = hmacMd5(this.keys.clientSigningKey, concatBytes(sequence, plaintext));\n const sealed = rc4Crypt(this.keys.clientSealing, plaintext);\n const checksum = rc4Crypt(this.keys.clientSealing, digest.subarray(0, 8));\n\n this.sendSequence += 1;\n return concatBytes(new Uint8Array([1, 0, 0, 0]), checksum, sequence, sealed);\n }\n\n unseal(bytes: Uint8Array) {\n if (bytes.length < 16) throw new Error('NTLM: sealed message is too short');\n const sealed = bytes.subarray(16);\n const plaintext = rc4Crypt(this.keys.serverSealing, sealed);\n\n // The checksum is verified so a tampered pubKeyAuth is reported as such\n // rather than surfacing later as a confusing protocol error.\n const sequence = bytes.subarray(12, 16);\n const digest = hmacMd5(this.keys.serverSigningKey, concatBytes(sequence, plaintext));\n const expected = rc4Crypt(this.keys.serverSealing, digest.subarray(0, 8));\n const actual = bytes.subarray(4, 12);\n if (!expected.every((byte, i) => byte === actual[i])) {\n throw new Error('NTLM: the host signature did not verify');\n }\n\n this.receiveSequence += 1;\n return plaintext;\n }\n}\n"],
|
|
5
|
+
"mappings": "AAIA,SAAS,QAAQ,mBAAmB;AACpC,SAAS,KAAK,UAAU,eAAe;AAIvC,SAAS,OAAO,OAAO,OAAe;AACpC,SAAQ,SAAS,QAAU,UAAW,KAAK;AAC7C;AAEO,SAAS,IAAI,SAAiB;AACnC,QAAM,aAAa,KAAK,OAAO,QAAQ,SAAS,KAAK,EAAE,IAAI;AAC3D,QAAM,SAAS,IAAI,WAAW,aAAa,EAAE;AAC7C,SAAO,IAAI,OAAO;AAClB,SAAO,QAAQ,MAAM,IAAI;AAEzB,QAAM,OAAO,IAAI,SAAS,OAAO,MAAM;AACvC,QAAM,YAAY,QAAQ,SAAS;AACnC,OAAK,UAAU,OAAO,SAAS,GAAG,cAAc,GAAG,IAAI;AACvD,OAAK,UAAU,OAAO,SAAS,GAAG,KAAK,MAAM,YAAY,UAAU,GAAG,IAAI;AAE1E,MAAI,KAAK,YAAY,KAAK,YAAY,KAAK,YAAY,KAAK;AAC5D,QAAM,IAAI,IAAI,YAAY,EAAE;AAE5B,QAAM,eAAe,CAAC,GAAG,GAAG,IAAI,EAAE;AAClC,QAAM,cAAc,CAAC,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;AACzE,QAAM,eAAe,CAAC,GAAG,GAAG,GAAG,EAAE;AACjC,QAAM,cAAc,CAAC,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,EAAE;AACzE,QAAM,eAAe,CAAC,GAAG,GAAG,IAAI,EAAE;AAElC,WAAS,QAAQ,GAAG,QAAQ,YAAY,SAAS;AAC/C,aAAS,IAAI,GAAG,IAAI,IAAI,IAAK,GAAE,CAAC,IAAI,KAAK,UAAU,QAAQ,KAAK,IAAI,GAAG,IAAI;AAE3E,QAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAChC,UAAM,OAAO,CAAC,OAAO,UAAU,OAAO,QAAQ,GAAG,KAAK;AAEtD,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,IAAK,IAAI,IAAM,CAAC,IAAI;AAC1B,YAAM,QAAQ,aAAa,IAAI,CAAC;AAChC,YAAM,OAAO,KAAM,IAAI,IAAI,EAAE,CAAC,IAAK,GAAG,KAAK;AAC3C,UAAI;AAAG,UAAI;AAAG,UAAI;AAAG,UAAI;AAAA,IAC3B;AACA,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,IAAK,IAAI,IAAM,IAAI,IAAM,IAAI;AACnC,YAAM,QAAQ,aAAa,IAAI,CAAC;AAChC,YAAM,OAAO,KAAM,IAAI,IAAI,EAAE,YAAY,CAAC,CAAC,IAAI,aAAc,GAAG,KAAK;AACrE,UAAI;AAAG,UAAI;AAAG,UAAI;AAAG,UAAI;AAAA,IAC3B;AACA,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,IAAI,IAAI,IAAI;AAClB,YAAM,QAAQ,aAAa,IAAI,CAAC;AAChC,YAAM,OAAO,KAAM,IAAI,IAAI,EAAE,YAAY,CAAC,CAAC,IAAI,aAAc,GAAG,KAAK;AACrE,UAAI;AAAG,UAAI;AAAG,UAAI;AAAG,UAAI;AAAA,IAC3B;AAEA,SAAM,KAAK,IAAK;AAChB,SAAM,KAAK,IAAK;AAChB,SAAM,KAAK,IAAK;AAChB,SAAM,KAAK,IAAK;AAAA,EAClB;AAEA,QAAM,SAAS,IAAI,WAAW,EAAE;AAChC,QAAM,MAAM,IAAI,SAAS,OAAO,MAAM;AACtC,MAAI,UAAU,GAAG,OAAO,GAAG,IAAI;AAC/B,MAAI,UAAU,GAAG,OAAO,GAAG,IAAI;AAC/B,MAAI,UAAU,GAAG,OAAO,GAAG,IAAI;AAC/B,MAAI,UAAU,IAAI,OAAO,GAAG,IAAI;AAChC,SAAO;AACT;AAGO,SAAS,QAAQ,KAAiB,SAAiB;AACxD,QAAM,YAAY;AAClB,QAAM,aAAa,IAAI,SAAS,YAAY,IAAI,GAAG,IAAI;AACvD,QAAM,SAAS,IAAI,WAAW,SAAS;AACvC,SAAO,IAAI,UAAU;AAErB,QAAM,QAAQ,IAAI,WAAW,SAAS;AACtC,QAAM,QAAQ,IAAI,WAAW,SAAS;AACtC,WAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,UAAM,CAAC,IAAI,OAAO,CAAC,IAAI;AACvB,UAAM,CAAC,IAAI,OAAO,CAAC,IAAI;AAAA,EACzB;AAEA,SAAO,IAAI,YAAY,OAAO,IAAI,YAAY,OAAO,OAAO,CAAC,CAAC,CAAC;AACjE;AAIA,MAAM,oBAAoB,IAAI,WAAW,CAAC,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,CAAI,CAAC;AAElF,MAAM,YAAY;AAAA,EACvB,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,2BAA2B;AAAA,EAC3B,aAAa;AAAA,EACb,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AACV;AAIA,MAAM,eACJ,UAAU,UACV,UAAU,iBACV,UAAU,OACV,UAAU,OACV,UAAU,OACV,UAAU,cACV,UAAU,4BACV,UAAU,cACV,UAAU,UACV,UAAU,UACV,UAAU,WACV,UAAU;AAEZ,MAAM,aAAa;AACnB,MAAM,mBAAmB;AACzB,MAAM,eAAe;AACrB,MAAM,mBAAmB;AAEzB,MAAM,QAAQ,CAAC,SAAiB;AAC9B,QAAM,SAAS,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC;AAC7C,SAAO,QAAQ,IAAI;AACnB,SAAO,OAAO,KAAK;AACrB;AAGA,MAAM,gBAAgB,IAAI,WAAW,CAAC,IAAI,GAAG,IAAM,IAAM,GAAM,GAAM,GAAM,EAAI,CAAC;AAEzE,SAAS,mBAAmB;AACjC,QAAM,SAAS,IAAI,OAAO,EAAE;AAC5B,SAAO,IAAI,iBAAiB;AAC5B,SAAO,MAAM,CAAC;AACd,SAAO,MAAM,iBAAiB,CAAC;AAC/B,SAAO,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC;AAChC,SAAO,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC;AAChC,SAAO,IAAI,aAAa;AACxB,SAAO,OAAO,KAAK;AACrB;AAEO,SAAS,sBAAsB,OAAmB;AACvD,QAAM,OAAO,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAC1E,MAAI,KAAK,UAAU,GAAG,IAAI,MAAM,GAAG;AACjC,UAAM,IAAI,MAAM,wDAAwD;AAAA,EAC1E;AAEA,QAAM,mBAAmB,KAAK,UAAU,IAAI,IAAI;AAChD,QAAM,mBAAmB,KAAK,UAAU,IAAI,IAAI;AAChD,QAAM,QAAQ,KAAK,UAAU,IAAI,IAAI;AACrC,QAAM,kBAAkB,MAAM,SAAS,IAAI,EAAE,EAAE,MAAM;AACrD,QAAM,mBAAmB,KAAK,UAAU,IAAI,IAAI;AAChD,QAAM,mBAAmB,KAAK,UAAU,IAAI,IAAI;AAEhD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,MAAM,SAAS,kBAAkB,mBAAmB,gBAAgB,EAAE,MAAM;AAAA,IACxF,YAAY,MAAM,SAAS,kBAAkB,mBAAmB,gBAAgB,EAAE,MAAM;AAAA,EAC1F;AACF;AAGA,SAAS,YAAY,YAAY;AAC/B,QAAM,QAAQ,CAAC;AACf,MAAI,SAAS;AACb,QAAM,OAAO,IAAI,SAAS,WAAW,QAAQ,WAAW,YAAY,WAAW,UAAU;AAEzF,SAAO,SAAS,KAAK,WAAW,QAAQ;AACtC,UAAM,KAAK,KAAK,UAAU,QAAQ,IAAI;AACtC,UAAM,SAAS,KAAK,UAAU,SAAS,GAAG,IAAI;AAC9C,UAAM,QAAQ,WAAW,SAAS,SAAS,GAAG,SAAS,IAAI,MAAM;AACjE,cAAU,IAAI;AACd,QAAI,OAAO,WAAY;AACvB,UAAM,KAAK,EAAE,IAAI,MAAM,CAAC;AAAA,EAC1B;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,OAAO;AAC3B,QAAM,SAAS,IAAI,OAAO,GAAG;AAC7B,aAAW,QAAQ,OAAO;AACxB,WAAO,MAAM,KAAK,EAAE;AACpB,WAAO,MAAM,KAAK,MAAM,MAAM;AAC9B,WAAO,IAAI,KAAK,KAAK;AAAA,EACvB;AACA,SAAO,MAAM,UAAU,EAAE,MAAM,CAAC;AAChC,SAAO,OAAO,KAAK;AACrB;AAGA,SAAS,cAAc;AACrB,QAAM,SAAS,OAAO,KAAK,IAAI,CAAC,IAAI,mBAAmB;AACvD,QAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,MAAI,SAAS,IAAI,MAAM,EAAE,aAAa,GAAG,OAAO,IAAI;AACpD,SAAO;AACT;AASO,SAAS,oBAAoB,EAAE,UAAU,QAAQ,UAAU,WAAW,gBAAgB,eAAe,GAAG;AAC7G,QAAM,cAAc;AAAA,IAClB,IAAI,MAAM,QAAQ,CAAC;AAAA,IACnB,MAAM,SAAS,YAAY,IAAI,MAAM;AAAA,EACvC;AAEA,QAAM,QAAQ,YAAY,UAAU,UAAU;AAC9C,QAAM,YAAY,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,gBAAgB,GAAG,MAAM,MAAM,KAAK,YAAY;AAEnG,QAAM,YAAY,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,YAAY;AAC/D,MAAI,WAAW;AACb,UAAM,OAAO,IAAI,SAAS,UAAU,MAAM,QAAQ,UAAU,MAAM,YAAY,CAAC;AAC/E,SAAK,UAAU,GAAG,KAAK,UAAU,GAAG,IAAI,IAAI,kBAAkB,IAAI;AAAA,EACpE,OAAO;AACL,UAAM,QAAQ,IAAI,WAAW,CAAC;AAC9B,QAAI,SAAS,MAAM,MAAM,EAAE,UAAU,GAAG,kBAAkB,IAAI;AAC9D,UAAM,KAAK,EAAE,IAAI,cAAc,MAAM,CAAC;AAAA,EACxC;AACA,QAAM,aAAa,aAAa,KAAK;AAErC,QAAM,kBAAkB,IAAI,WAAW,CAAC;AACxC,SAAO,gBAAgB,eAAe;AAEtC,QAAM,OAAO;AAAA,IACX,IAAI,WAAW,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI,CAAC;AAAA;AAAA,IAC/D;AAAA,IACA;AAAA,IACA,IAAI,WAAW,CAAC;AAAA,IAChB;AAAA,IACA,IAAI,WAAW,CAAC;AAAA,EAClB;AAEA,QAAM,QAAQ,QAAQ,aAAa,YAAY,UAAU,iBAAiB,IAAI,CAAC;AAC/E,QAAM,aAAa,YAAY,OAAO,IAAI;AAC1C,QAAM,iBAAiB,QAAQ,aAAa,KAAK;AAGjD,QAAM,qBAAqB,IAAI,WAAW,EAAE;AAC5C,SAAO,gBAAgB,kBAAkB;AACzC,QAAM,sBAAsB,SAAS,QAAQ,cAAc,GAAG,kBAAkB;AAEhF,QAAM,cAAc,aAAa,MAAM;AACvC,QAAM,YAAY,aAAa,QAAQ;AACvC,QAAM,mBAAmB,aAAa,EAAE;AACxC,QAAM,aAAa,IAAI,WAAW,EAAE;AAEpC,QAAM,eAAe;AACrB,MAAI,SAAS;AACb,QAAM,SAAS,CAAC;AAChB,QAAM,QAAQ,CAAC,UAAsB;AACnC,WAAO,KAAK,EAAE,OAAO,OAAO,CAAC;AAC7B,cAAU,MAAM;AAChB,WAAO,OAAO,OAAO,SAAS,CAAC;AAAA,EACjC;AAEA,QAAM,KAAK,MAAM,UAAU;AAC3B,QAAM,KAAK,MAAM,UAAU;AAC3B,QAAM,MAAM,MAAM,WAAW;AAC7B,QAAM,OAAO,MAAM,SAAS;AAC5B,QAAM,cAAc,MAAM,gBAAgB;AAC1C,QAAM,aAAa,MAAM,mBAAmB;AAE5C,QAAM,SAAS,IAAI,OAAO,SAAS,EAAE;AACrC,SAAO,IAAI,iBAAiB;AAC5B,SAAO,MAAM,CAAC;AACd,QAAM,QAAQ,CAAC,UAAU;AACvB,WAAO,MAAM,MAAM,MAAM,MAAM;AAC/B,WAAO,MAAM,MAAM,MAAM,MAAM;AAC/B,WAAO,MAAM,MAAM,SAAS,EAAE;AAAA,EAChC;AACA,QAAM,EAAE;AACR,QAAM,EAAE;AACR,QAAM,GAAG;AACT,QAAM,IAAI;AACV,QAAM,WAAW;AACjB,QAAM,UAAU;AAChB,SAAO,MAAM,iBAAiB,CAAC;AAC/B,SAAO,IAAI,aAAa;AACxB,SAAO,MAAM,EAAE;AACf,aAAW,SAAS,OAAQ,QAAO,IAAI,MAAM,KAAK;AAElD,QAAM,UAAU,OAAO,KAAK;AAC5B,QAAM,MAAM;AAAA,IACV;AAAA,IACA,YAAY,gBAAgB,gBAAgB,OAAO;AAAA,EACrD;AACA,UAAQ,IAAI,KAAK,YAAY;AAE7B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,YAAY,kBAAkB;AAAA,EACtC;AACF;AAEA,SAAS,aAAa,MAAc;AAClC,MAAI,CAAC,KAAM,QAAO,IAAI,WAAW,CAAC;AAClC,QAAM,QAAQ,MAAM,IAAI;AAExB,SAAO,MAAM,SAAS,GAAG,KAAK,SAAS,CAAC,EAAE,MAAM;AAClD;AAEA,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AAEvB,SAAS,YAAY,oBAAoB;AACvC,QAAM,SAAS,CAAC,UAAkB,IAAI,YAAY,oBAAoB,IAAI,YAAY,EAAE,OAAO,KAAK,CAAC,CAAC;AAEtG,SAAO;AAAA,IACL,kBAAkB,OAAO,cAAc;AAAA,IACvC,kBAAkB,OAAO,cAAc;AAAA,IACvC,eAAe,QAAQ,OAAO,cAAc,CAAC;AAAA,IAC7C,eAAe,QAAQ,OAAO,cAAc,CAAC;AAAA,EAC/C;AACF;AAOO,MAAM,WAAW;AAAA,EACL;AAAA,EACT;AAAA,EACA;AAAA,EAER,YAAY,MAAM;AAChB,SAAK,OAAO;AACZ,SAAK,eAAe;AACpB,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,KAAK,WAAuB;AAC1B,UAAM,WAAW,IAAI,WAAW,CAAC;AACjC,QAAI,SAAS,SAAS,MAAM,EAAE,UAAU,GAAG,KAAK,cAAc,IAAI;AAElE,UAAM,SAAS,QAAQ,KAAK,KAAK,kBAAkB,YAAY,UAAU,SAAS,CAAC;AACnF,UAAM,SAAS,SAAS,KAAK,KAAK,eAAe,SAAS;AAC1D,UAAM,WAAW,SAAS,KAAK,KAAK,eAAe,OAAO,SAAS,GAAG,CAAC,CAAC;AAExE,SAAK,gBAAgB;AACrB,WAAO,YAAY,IAAI,WAAW,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,UAAU,UAAU,MAAM;AAAA,EAC7E;AAAA,EAEA,OAAO,OAAmB;AACxB,QAAI,MAAM,SAAS,GAAI,OAAM,IAAI,MAAM,mCAAmC;AAC1E,UAAM,SAAS,MAAM,SAAS,EAAE;AAChC,UAAM,YAAY,SAAS,KAAK,KAAK,eAAe,MAAM;AAI1D,UAAM,WAAW,MAAM,SAAS,IAAI,EAAE;AACtC,UAAM,SAAS,QAAQ,KAAK,KAAK,kBAAkB,YAAY,UAAU,SAAS,CAAC;AACnF,UAAM,WAAW,SAAS,KAAK,KAAK,eAAe,OAAO,SAAS,GAAG,CAAC,CAAC;AACxE,UAAM,SAAS,MAAM,SAAS,GAAG,EAAE;AACnC,QAAI,CAAC,SAAS,MAAM,CAAC,MAAM,MAAM,SAAS,OAAO,CAAC,CAAC,GAAG;AACpD,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,SAAK,mBAAmB;AACxB,WAAO;AAAA,EACT;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|