tabby-rdp 0.4.0 → 0.5.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/CHANGELOG.md +118 -0
- package/README.md +94 -5
- package/dist/accountForm.js +4 -3
- package/dist/accountForm.js.map +1 -1
- package/dist/desktop.service.js +454 -54
- package/dist/desktop.service.js.map +1 -1
- package/dist/desktopForm.js +26 -1
- package/dist/desktopForm.js.map +1 -1
- package/dist/desktops.js +17 -1
- package/dist/desktops.js.map +1 -1
- package/dist/drives.js +284 -0
- package/dist/drives.js.map +1 -0
- package/dist/fileTransfer.js +128 -11
- package/dist/fileTransfer.js.map +1 -1
- package/dist/gateway.js +492 -0
- package/dist/gateway.js.map +1 -0
- package/dist/hyperv.js +79 -0
- package/dist/hyperv.js.map +1 -0
- package/dist/ntlm.js +226 -0
- package/dist/ntlm.js.map +1 -0
- package/dist/rdcleanpath.js +167 -26
- package/dist/rdcleanpath.js.map +1 -1
- package/dist/rdpFile.js +34 -0
- package/dist/rdpFile.js.map +1 -1
- package/dist/rdpProfile.js +39 -4
- package/dist/rdpProfile.js.map +1 -1
- package/dist/settingsPage.js +107 -17
- package/dist/settingsPage.js.map +1 -1
- package/dist/signin.js +48 -17
- package/dist/signin.js.map +1 -1
- package/dist/sshChannelStream.js +11 -1
- package/dist/sshChannelStream.js.map +1 -1
- package/dist/ui.js +10 -0
- package/dist/ui.js.map +1 -1
- package/dist/vms.js +20 -3
- package/dist/vms.js.map +1 -1
- package/dist/wake.js +16 -4
- package/dist/wake.js.map +1 -1
- package/package.json +1 -1
- package/vendor/iron-remote-desktop-rdp.js +418 -390
- package/vendor/ironrdp_web_bg.wasm +0 -0
package/dist/hyperv.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HYPERV_PORT = void 0;
|
|
4
|
+
exports.vmId = vmId;
|
|
5
|
+
exports.scanHyperV = scanHyperV;
|
|
6
|
+
exports.hyperVState = hyperVState;
|
|
7
|
+
exports.startHyperV = startHyperV;
|
|
8
|
+
/** VMConnect's port on a Hyper-V host. */
|
|
9
|
+
exports.HYPERV_PORT = 2179;
|
|
10
|
+
const GUID = /^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i;
|
|
11
|
+
/** A VM id as Hyper-V prints it, or '' if this isn't one. */
|
|
12
|
+
function vmId(value) {
|
|
13
|
+
const id = String(value ?? '').trim().replace(/^\{|\}$/g, '');
|
|
14
|
+
return GUID.test(id) ? id.toLowerCase() : '';
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Runs a PowerShell script on the host and returns what it printed. As -EncodedCommand, which reads the same whether
|
|
18
|
+
* the host's SSH shell is cmd.exe or PowerShell, and needs no quoting. Windows PowerShell 5.1 is on every Windows.
|
|
19
|
+
*/
|
|
20
|
+
async function powershell(target, script) {
|
|
21
|
+
const encoded = Buffer.from(`$ProgressPreference = 'SilentlyContinue'\n${script}`, 'utf16le').toString('base64');
|
|
22
|
+
return target.exec(`powershell -NoProfile -NonInteractive -EncodedCommand ${encoded}`, '');
|
|
23
|
+
}
|
|
24
|
+
// One line per VM: TRD_HV <id>|<state>|<name>. Nothing where Hyper-V isn't installed or the account may not list
|
|
25
|
+
// VMs (which takes an administrator of the host, in practice).
|
|
26
|
+
const SCAN = String.raw `
|
|
27
|
+
$ErrorActionPreference = 'SilentlyContinue'
|
|
28
|
+
if (Get-Command Get-VM) { Get-VM | ForEach-Object { 'TRD_HV ' + $_.Id + '|' + $_.State + '|' + $_.Name } }
|
|
29
|
+
`;
|
|
30
|
+
/** The host's Hyper-V VMs, running or not (one that is off is started when opened). Read-only. */
|
|
31
|
+
async function scanHyperV(target) {
|
|
32
|
+
const out = await powershell(target, SCAN);
|
|
33
|
+
const found = [];
|
|
34
|
+
for (const line of out.split('\n')) {
|
|
35
|
+
const m = /^TRD_HV ([^|]+)\|([^|]*)\|(.+?)\s*$/.exec(line.trim());
|
|
36
|
+
const id = vmId(m?.[1]);
|
|
37
|
+
if (m && id && !found.some(f => f.id === id)) {
|
|
38
|
+
found.push({ id, name: m[3], state: m[2] === 'Running' ? 'running' : 'off' });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return found;
|
|
42
|
+
}
|
|
43
|
+
// TRD_HV_STATE <state>|<enhanced session mode state>, or TRD_HV_ERR <why>. The enhanced state is
|
|
44
|
+
// Msvm_ComputerSystem's: 2 when the guest takes enhanced sessions right now (the host allows them, and the guest's
|
|
45
|
+
// Remote Desktop Services answer on its bus), anything else when only the basic console is there.
|
|
46
|
+
const STATE = String.raw `
|
|
47
|
+
try {
|
|
48
|
+
$vm = Get-VM -Id '@@ID@@' -ErrorAction Stop
|
|
49
|
+
$enhanced = (Get-CimInstance -Namespace root\virtualization\v2 -ClassName Msvm_ComputerSystem -Filter "Name='$($vm.Id.ToString().ToUpper())'" -ErrorAction SilentlyContinue).EnhancedSessionModeState
|
|
50
|
+
'TRD_HV_STATE ' + $vm.State + '|' + $enhanced
|
|
51
|
+
} catch { 'TRD_HV_ERR ' + ($_.Exception.Message -replace '\s+', ' ') }
|
|
52
|
+
`;
|
|
53
|
+
/** How a VM is now: running or not, and whether it takes an enhanced session. Throws with the host's reason when it can't say. */
|
|
54
|
+
async function hyperVState(target, id) {
|
|
55
|
+
const out = await powershell(target, STATE.replace('@@ID@@', vmId(id)));
|
|
56
|
+
const state = /^TRD_HV_STATE ([^|]*)\|(\d*)\s*$/m.exec(out);
|
|
57
|
+
if (!state) {
|
|
58
|
+
throw new Error(/^TRD_HV_ERR (.*)$/m.exec(out)?.[1].trim() || 'the host didn\'t answer about the VM (is PowerShell\'s Hyper-V module there, and may this account use it?)');
|
|
59
|
+
}
|
|
60
|
+
return { running: state[1] === 'Running', enhanced: state[2] === '2' };
|
|
61
|
+
}
|
|
62
|
+
const START = String.raw `
|
|
63
|
+
try {
|
|
64
|
+
$vm = Get-VM -Id '@@ID@@' -ErrorAction Stop
|
|
65
|
+
if ($vm.State -eq 'Running') { 'TRD_HV_OK ' + $vm.Name + ' is already running' }
|
|
66
|
+
elseif ($vm.State -eq 'Paused') { Resume-VM -VM $vm -ErrorAction Stop; 'TRD_HV_OK ' + $vm.Name + ' resumed' }
|
|
67
|
+
else { Start-VM -VM $vm -ErrorAction Stop; 'TRD_HV_OK ' + $vm.Name + ' started' }
|
|
68
|
+
} catch { 'TRD_HV_ERR ' + ($_.Exception.Message -replace '\s+', ' ') }
|
|
69
|
+
`;
|
|
70
|
+
/** Starts (or resumes) the VM. Resolves with what was done; throws with the host's reason when it couldn't. */
|
|
71
|
+
async function startHyperV(target, id) {
|
|
72
|
+
const out = await powershell(target, START.replace('@@ID@@', vmId(id)));
|
|
73
|
+
const ok = /^TRD_HV_OK (.*)$/m.exec(out);
|
|
74
|
+
if (!ok) {
|
|
75
|
+
throw new Error(/^TRD_HV_ERR (.*)$/m.exec(out)?.[1].trim() || 'the host didn\'t answer');
|
|
76
|
+
}
|
|
77
|
+
return ok[1].trim();
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=hyperv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyperv.js","sourceRoot":"","sources":["../src/hyperv.ts"],"names":[],"mappings":"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"}
|
package/dist/ntlm.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.md4 = md4;
|
|
4
|
+
exports.ntlmV2Hash = ntlmV2Hash;
|
|
5
|
+
exports.negotiateMessage = negotiateMessage;
|
|
6
|
+
exports.parseChallenge = parseChallenge;
|
|
7
|
+
exports.channelBindingHash = channelBindingHash;
|
|
8
|
+
exports.ntlmV2Response = ntlmV2Response;
|
|
9
|
+
exports.authenticateMessage = authenticateMessage;
|
|
10
|
+
const crypto_1 = require("crypto");
|
|
11
|
+
/**
|
|
12
|
+
* NTLMv2 ([MS-NLMP]), as much as HTTP authentication needs: the three messages, no signing or sealing afterwards.
|
|
13
|
+
* Written out here rather than taken from a package: it is small, and the password passes through it.
|
|
14
|
+
*/
|
|
15
|
+
const SIGNATURE = Buffer.from('NTLMSSP\0', 'latin1');
|
|
16
|
+
const NEGOTIATE_UNICODE = 0x00000001;
|
|
17
|
+
const REQUEST_TARGET = 0x00000004;
|
|
18
|
+
const NEGOTIATE_NTLM = 0x00000200;
|
|
19
|
+
const NEGOTIATE_ALWAYS_SIGN = 0x00008000;
|
|
20
|
+
const NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000;
|
|
21
|
+
const NEGOTIATE_TARGET_INFO = 0x00800000;
|
|
22
|
+
const NEGOTIATE_VERSION = 0x02000000;
|
|
23
|
+
const NEGOTIATE_128 = 0x20000000;
|
|
24
|
+
const NEGOTIATE_56 = 0x80000000;
|
|
25
|
+
// AV pairs of the server's target information.
|
|
26
|
+
const AV_EOL = 0;
|
|
27
|
+
const AV_FLAGS = 6;
|
|
28
|
+
const AV_TIMESTAMP = 7;
|
|
29
|
+
const AV_TARGET_NAME = 9;
|
|
30
|
+
const AV_CHANNEL_BINDINGS = 10;
|
|
31
|
+
/** MsvAvFlags: the authenticate message carries a message integrity code. */
|
|
32
|
+
const AV_FLAG_MIC = 0x2;
|
|
33
|
+
/** MD4 (RFC 1320). The password's hash is one; OpenSSL 3 and BoringSSL no longer offer it. */
|
|
34
|
+
function md4(data) {
|
|
35
|
+
const length = data.length;
|
|
36
|
+
const padded = Buffer.alloc(((length + 8 >> 6) + 1) * 64);
|
|
37
|
+
data.copy(padded);
|
|
38
|
+
padded[length] = 0x80;
|
|
39
|
+
padded.writeUInt32LE(length * 8 >>> 0, padded.length - 8);
|
|
40
|
+
padded.writeUInt32LE(Math.floor(length / 0x20000000), padded.length - 4);
|
|
41
|
+
let [a, b, c, d] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
|
|
42
|
+
const rotl = (x, n) => x << n | x >>> 32 - n;
|
|
43
|
+
const x = new Array(16);
|
|
44
|
+
for (let offset = 0; offset < padded.length; offset += 64) {
|
|
45
|
+
for (let i = 0; i < 16; i++) {
|
|
46
|
+
x[i] = padded.readUInt32LE(offset + i * 4);
|
|
47
|
+
}
|
|
48
|
+
const [aa, bb, cc, dd] = [a, b, c, d];
|
|
49
|
+
const f = (p, q, r, s, k, n) => rotl(p + (q & r | ~q & s) + x[k] | 0, n);
|
|
50
|
+
const g = (p, q, r, s, k, n) => rotl(p + (q & r | q & s | r & s) + x[k] + 0x5a827999 | 0, n);
|
|
51
|
+
const h = (p, q, r, s, k, n) => rotl(p + (q ^ r ^ s) + x[k] + 0x6ed9eba1 | 0, n);
|
|
52
|
+
for (const i of [0, 4, 8, 12]) {
|
|
53
|
+
a = f(a, b, c, d, i, 3);
|
|
54
|
+
d = f(d, a, b, c, i + 1, 7);
|
|
55
|
+
c = f(c, d, a, b, i + 2, 11);
|
|
56
|
+
b = f(b, c, d, a, i + 3, 19);
|
|
57
|
+
}
|
|
58
|
+
for (const i of [0, 1, 2, 3]) {
|
|
59
|
+
a = g(a, b, c, d, i, 3);
|
|
60
|
+
d = g(d, a, b, c, i + 4, 5);
|
|
61
|
+
c = g(c, d, a, b, i + 8, 9);
|
|
62
|
+
b = g(b, c, d, a, i + 12, 13);
|
|
63
|
+
}
|
|
64
|
+
for (const i of [0, 2, 1, 3]) {
|
|
65
|
+
a = h(a, b, c, d, i, 3);
|
|
66
|
+
d = h(d, a, b, c, i + 8, 9);
|
|
67
|
+
c = h(c, d, a, b, i + 4, 11);
|
|
68
|
+
b = h(b, c, d, a, i + 12, 15);
|
|
69
|
+
}
|
|
70
|
+
a = a + aa | 0;
|
|
71
|
+
b = b + bb | 0;
|
|
72
|
+
c = c + cc | 0;
|
|
73
|
+
d = d + dd | 0;
|
|
74
|
+
}
|
|
75
|
+
const out = Buffer.alloc(16);
|
|
76
|
+
out.writeInt32LE(a, 0);
|
|
77
|
+
out.writeInt32LE(b, 4);
|
|
78
|
+
out.writeInt32LE(c, 8);
|
|
79
|
+
out.writeInt32LE(d, 12);
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
const hmacMd5 = (key, ...data) => data.reduce((h, d) => h.update(d), (0, crypto_1.createHmac)('md5', key)).digest();
|
|
83
|
+
const utf16 = (text) => Buffer.from(text, 'utf16le');
|
|
84
|
+
/** NTOWFv2: what the password, user and domain come to. */
|
|
85
|
+
function ntlmV2Hash(username, domain, password) {
|
|
86
|
+
return hmacMd5(md4(utf16(password)), utf16(username.toUpperCase() + domain));
|
|
87
|
+
}
|
|
88
|
+
/** The first message: what this client can do. */
|
|
89
|
+
function negotiateMessage() {
|
|
90
|
+
const message = Buffer.alloc(32);
|
|
91
|
+
SIGNATURE.copy(message);
|
|
92
|
+
message.writeUInt32LE(1, 8);
|
|
93
|
+
message.writeUInt32LE((NEGOTIATE_UNICODE | REQUEST_TARGET | NEGOTIATE_NTLM | NEGOTIATE_ALWAYS_SIGN | NEGOTIATE_EXTENDED_SESSIONSECURITY |
|
|
94
|
+
NEGOTIATE_128 | NEGOTIATE_56) >>> 0, 12);
|
|
95
|
+
// Domain and workstation: none given (their fields point at the end, with no length).
|
|
96
|
+
message.writeUInt32LE(32, 20);
|
|
97
|
+
message.writeUInt32LE(32, 28);
|
|
98
|
+
return message;
|
|
99
|
+
}
|
|
100
|
+
/** The server's challenge message, read: its flags, its challenge and its target information. */
|
|
101
|
+
function parseChallenge(message) {
|
|
102
|
+
if (message.length < 48 || !message.subarray(0, 8).equals(SIGNATURE) || message.readUInt32LE(8) !== 2) {
|
|
103
|
+
throw new Error('not an NTLM challenge');
|
|
104
|
+
}
|
|
105
|
+
const flags = message.readUInt32LE(20);
|
|
106
|
+
const [length, offset] = [message.readUInt16LE(40), message.readUInt32LE(44)];
|
|
107
|
+
if (offset + length > message.length) {
|
|
108
|
+
throw new Error('the NTLM challenge\'s target information is cut short');
|
|
109
|
+
}
|
|
110
|
+
return { flags, challenge: Buffer.from(message.subarray(24, 32)), targetInfo: flags & NEGOTIATE_TARGET_INFO ? Buffer.from(message.subarray(offset, offset + length)) : Buffer.alloc(0) };
|
|
111
|
+
}
|
|
112
|
+
/** One value of the target information's AV pairs, or null. */
|
|
113
|
+
function avPair(info, id) {
|
|
114
|
+
for (let at = 0; at + 4 <= info.length;) {
|
|
115
|
+
const [pair, length] = [info.readUInt16LE(at), info.readUInt16LE(at + 2)];
|
|
116
|
+
if (pair === AV_EOL) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
if (pair === id) {
|
|
120
|
+
return info.subarray(at + 4, at + 4 + length);
|
|
121
|
+
}
|
|
122
|
+
at += 4 + length;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
function pair(id, value) {
|
|
127
|
+
const head = Buffer.alloc(4);
|
|
128
|
+
head.writeUInt16LE(id, 0);
|
|
129
|
+
head.writeUInt16LE(value.length, 2);
|
|
130
|
+
return Buffer.concat([head, value]);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The channel binding's hash ([MS-NLMP] 3.1.5.1.2): MD5 over a gss_channel_bindings_struct with no addresses and the
|
|
134
|
+
* binding as its application data.
|
|
135
|
+
*/
|
|
136
|
+
function channelBindingHash(binding) {
|
|
137
|
+
const head = Buffer.alloc(20);
|
|
138
|
+
head.writeUInt32LE(binding.length, 16);
|
|
139
|
+
return (0, crypto_1.createHash)('md5').update(head).update(binding).digest();
|
|
140
|
+
}
|
|
141
|
+
/** The target information as the client's response carries it back: the server's pairs, and the client's own. */
|
|
142
|
+
function clientTargetInfo(info, client) {
|
|
143
|
+
const pairs = [];
|
|
144
|
+
let flags = client.mic ? AV_FLAG_MIC : 0;
|
|
145
|
+
for (let at = 0; at + 4 <= info.length;) {
|
|
146
|
+
const [id, length] = [info.readUInt16LE(at), info.readUInt16LE(at + 2)];
|
|
147
|
+
if (id === AV_EOL) {
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
if (id === AV_FLAGS && length === 4) {
|
|
151
|
+
flags |= info.readUInt32LE(at + 4);
|
|
152
|
+
}
|
|
153
|
+
else if (id !== AV_CHANNEL_BINDINGS && id !== AV_TARGET_NAME) {
|
|
154
|
+
pairs.push(info.subarray(at, at + 4 + length));
|
|
155
|
+
}
|
|
156
|
+
at += 4 + length;
|
|
157
|
+
}
|
|
158
|
+
if (flags) {
|
|
159
|
+
const value = Buffer.alloc(4);
|
|
160
|
+
value.writeUInt32LE(flags >>> 0);
|
|
161
|
+
pairs.push(pair(AV_FLAGS, value));
|
|
162
|
+
}
|
|
163
|
+
// No binding to give: zeros, as Windows sends them (a server that insists on one refuses those).
|
|
164
|
+
pairs.push(pair(AV_CHANNEL_BINDINGS, client.channelBinding ? channelBindingHash(client.channelBinding) : Buffer.alloc(16)));
|
|
165
|
+
pairs.push(pair(AV_TARGET_NAME, utf16(client.targetName ?? '')));
|
|
166
|
+
return Buffer.concat([...pairs, Buffer.alloc(4)]);
|
|
167
|
+
}
|
|
168
|
+
/** Windows time (100 ns since 1601) of now. */
|
|
169
|
+
function now() {
|
|
170
|
+
const time = Buffer.alloc(8);
|
|
171
|
+
time.writeBigUInt64LE((BigInt(Date.now()) + 11644473600000n) * 10000n);
|
|
172
|
+
return time;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The NTLMv2 response to a challenge ([MS-NLMP] 3.3.2): the proof, with the blob it covers, and the session's base key.
|
|
176
|
+
* `time` and `clientChallenge` are given by tests; otherwise the server's time (or now) and random bytes.
|
|
177
|
+
*/
|
|
178
|
+
function ntlmV2Response(hash, serverChallenge, targetInfo, time, clientChallenge = (0, crypto_1.randomBytes)(8)) {
|
|
179
|
+
const blob = Buffer.concat([
|
|
180
|
+
Buffer.from([1, 1, 0, 0, 0, 0, 0, 0]), time ?? avPair(targetInfo, AV_TIMESTAMP) ?? now(), clientChallenge, Buffer.alloc(4), targetInfo, Buffer.alloc(4),
|
|
181
|
+
]);
|
|
182
|
+
const proof = hmacMd5(hash, serverChallenge, blob);
|
|
183
|
+
return { response: Buffer.concat([proof, blob]), sessionKey: hmacMd5(hash, proof) };
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The third message: the answer to the server's challenge, for this account. `negotiate` and `challenge` are the two
|
|
187
|
+
* messages before it, which its integrity code covers. `user@domain` and `DOMAIN\user` names carry their domain.
|
|
188
|
+
* `channelBinding` and `targetName` say which TLS connection and which service the sign-in is for: servers set up
|
|
189
|
+
* for extended protection (an RD Gateway, by default) refuse a sign-in without them.
|
|
190
|
+
*/
|
|
191
|
+
function authenticateMessage(negotiate, challenge, account) {
|
|
192
|
+
const server = parseChallenge(challenge);
|
|
193
|
+
const split = /^([^\\]+)\\(.+)$/.exec(account.username);
|
|
194
|
+
const [domain, username] = split ? [split[1], split[2]] : [account.domain ?? '', account.username];
|
|
195
|
+
// The server says when it is (a timestamp among its pairs) on every Windows since Vista: the response then
|
|
196
|
+
// carries an integrity code, and the LM response is left empty.
|
|
197
|
+
const timed = !!avPair(server.targetInfo, AV_TIMESTAMP);
|
|
198
|
+
const targetInfo = server.targetInfo.length
|
|
199
|
+
? clientTargetInfo(server.targetInfo, { mic: timed, channelBinding: account.channelBinding, targetName: account.targetName })
|
|
200
|
+
: server.targetInfo;
|
|
201
|
+
const hash = ntlmV2Hash(username, domain, account.password);
|
|
202
|
+
const clientChallenge = (0, crypto_1.randomBytes)(8);
|
|
203
|
+
const { response, sessionKey } = ntlmV2Response(hash, server.challenge, targetInfo, undefined, clientChallenge);
|
|
204
|
+
const lm = timed ? Buffer.alloc(24) : Buffer.concat([hmacMd5(hash, server.challenge, clientChallenge), clientChallenge]);
|
|
205
|
+
const fields = [lm, response, utf16(domain), utf16(username), utf16(account.workstation ?? ''), Buffer.alloc(0)];
|
|
206
|
+
// 64 bytes of fields and flags, 8 of version (none), 16 of integrity code, then what the fields point at.
|
|
207
|
+
const header = Buffer.alloc(88);
|
|
208
|
+
SIGNATURE.copy(header);
|
|
209
|
+
header.writeUInt32LE(3, 8);
|
|
210
|
+
let offset = header.length;
|
|
211
|
+
fields.forEach((field, i) => {
|
|
212
|
+
header.writeUInt16LE(field.length, 12 + i * 8);
|
|
213
|
+
header.writeUInt16LE(field.length, 14 + i * 8);
|
|
214
|
+
header.writeUInt32LE(offset, 16 + i * 8);
|
|
215
|
+
offset += field.length;
|
|
216
|
+
});
|
|
217
|
+
const ours = NEGOTIATE_UNICODE | REQUEST_TARGET | NEGOTIATE_NTLM | NEGOTIATE_ALWAYS_SIGN | NEGOTIATE_EXTENDED_SESSIONSECURITY | NEGOTIATE_TARGET_INFO |
|
|
218
|
+
NEGOTIATE_128 | NEGOTIATE_56;
|
|
219
|
+
header.writeUInt32LE((server.flags & ours & ~NEGOTIATE_VERSION) >>> 0, 60);
|
|
220
|
+
const message = Buffer.concat([header, ...fields]);
|
|
221
|
+
if (timed) {
|
|
222
|
+
hmacMd5(sessionKey, negotiate, challenge, message).copy(message, 72);
|
|
223
|
+
}
|
|
224
|
+
return message;
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=ntlm.js.map
|
package/dist/ntlm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ntlm.js","sourceRoot":"","sources":["../src/ntlm.ts"],"names":[],"mappings":"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"}
|