ai-remote 0.4.2 → 0.4.3

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.
Files changed (62) hide show
  1. package/dist/index.js +1 -6
  2. package/dist/protocols/index.js +3 -34
  3. package/dist/protocols/ssh/session.js +17 -608
  4. package/dist/protocols/ssh/terminal.js +6 -190
  5. package/dist/shared/connection.js +1 -113
  6. package/dist/shared/hosts.js +1 -132
  7. package/dist/shared/icons.js +1 -41
  8. package/dist/shared/protocol.js +1 -39
  9. package/dist/shared/signals.js +1 -41
  10. package/package.json +1 -1
  11. package/dist/protocols/rdp/buffer.d.ts +0 -38
  12. package/dist/protocols/rdp/buffer.js +0 -169
  13. package/dist/protocols/rdp/caps.d.ts +0 -49
  14. package/dist/protocols/rdp/caps.js +0 -259
  15. package/dist/protocols/rdp/cert.d.ts +0 -18
  16. package/dist/protocols/rdp/cert.js +0 -134
  17. package/dist/protocols/rdp/client.d.ts +0 -56
  18. package/dist/protocols/rdp/client.js +0 -1069
  19. package/dist/protocols/rdp/cliprdr.d.ts +0 -27
  20. package/dist/protocols/rdp/cliprdr.js +0 -239
  21. package/dist/protocols/rdp/credssp.d.ts +0 -34
  22. package/dist/protocols/rdp/credssp.js +0 -253
  23. package/dist/protocols/rdp/crypto.d.ts +0 -63
  24. package/dist/protocols/rdp/crypto.js +0 -368
  25. package/dist/protocols/rdp/display.d.ts +0 -38
  26. package/dist/protocols/rdp/display.js +0 -588
  27. package/dist/protocols/rdp/gcc.d.ts +0 -23
  28. package/dist/protocols/rdp/gcc.js +0 -131
  29. package/dist/protocols/rdp/keymap.d.ts +0 -9
  30. package/dist/protocols/rdp/keymap.js +0 -131
  31. package/dist/protocols/rdp/mcs.d.ts +0 -40
  32. package/dist/protocols/rdp/mcs.js +0 -222
  33. package/dist/protocols/rdp/ntlm.d.ts +0 -61
  34. package/dist/protocols/rdp/ntlm.js +0 -304
  35. package/dist/protocols/rdp/pdu.d.ts +0 -155
  36. package/dist/protocols/rdp/pdu.js +0 -443
  37. package/dist/protocols/rdp/rail.d.ts +0 -119
  38. package/dist/protocols/rdp/rail.js +0 -382
  39. package/dist/protocols/rdp/rle.d.ts +0 -13
  40. package/dist/protocols/rdp/rle.js +0 -275
  41. package/dist/protocols/rdp/sec.d.ts +0 -59
  42. package/dist/protocols/rdp/sec.js +0 -155
  43. package/dist/protocols/rdp/session.d.ts +0 -62
  44. package/dist/protocols/rdp/session.js +0 -306
  45. package/dist/protocols/rdp/tls.d.ts +0 -18
  46. package/dist/protocols/rdp/tls.js +0 -353
  47. package/dist/protocols/rdp/vchannel.d.ts +0 -28
  48. package/dist/protocols/rdp/vchannel.js +0 -58
  49. package/dist/protocols/rdp/x224.d.ts +0 -40
  50. package/dist/protocols/rdp/x224.js +0 -109
  51. package/dist/protocols/ssh/kex.d.ts +0 -97
  52. package/dist/protocols/ssh/kex.js +0 -176
  53. package/dist/protocols/ssh/messages.d.ts +0 -50
  54. package/dist/protocols/ssh/messages.js +0 -54
  55. package/dist/protocols/ssh/transport.d.ts +0 -62
  56. package/dist/protocols/ssh/transport.js +0 -612
  57. package/dist/protocols/ssh/wire.d.ts +0 -52
  58. package/dist/protocols/ssh/wire.js +0 -188
  59. package/dist/protocols/vnc/input.d.ts +0 -5
  60. package/dist/protocols/vnc/input.js +0 -15
  61. package/dist/protocols/vnc/session.d.ts +0 -12
  62. package/dist/protocols/vnc/session.js +0 -258
@@ -1,353 +0,0 @@
1
- import { Reader, Writer, concatBytes } from "./buffer.js";
2
- import { parseX509PublicKey } from "./cert.js";
3
- import { rsaEncryptPkcs1 } from "./crypto.js";
4
- const TLS_1_2 = 771;
5
- const RECORD = {
6
- CHANGE_CIPHER_SPEC: 20,
7
- ALERT: 21,
8
- HANDSHAKE: 22,
9
- APPLICATION_DATA: 23
10
- };
11
- const HANDSHAKE = {
12
- CLIENT_HELLO: 1,
13
- SERVER_HELLO: 2,
14
- NEW_SESSION_TICKET: 4,
15
- CERTIFICATE: 11,
16
- SERVER_KEY_EXCHANGE: 12,
17
- CERTIFICATE_REQUEST: 13,
18
- SERVER_HELLO_DONE: 14,
19
- CLIENT_KEY_EXCHANGE: 16,
20
- FINISHED: 20
21
- };
22
- const CIPHER_SUITES = {
23
- 156: { name: "TLS_RSA_WITH_AES_128_GCM_SHA256", keyLength: 16, hash: "SHA-256" },
24
- 157: { name: "TLS_RSA_WITH_AES_256_GCM_SHA384", keyLength: 32, hash: "SHA-384" }
25
- };
26
- const ALERT_DESCRIPTIONS = {
27
- 0: "close_notify",
28
- 10: "unexpected_message",
29
- 20: "bad_record_mac",
30
- 40: "handshake_failure",
31
- 42: "bad_certificate",
32
- 46: "certificate_unknown",
33
- 47: "illegal_parameter",
34
- 48: "unknown_ca",
35
- 50: "decode_error",
36
- 51: "decrypt_error",
37
- 70: "protocol_version",
38
- 71: "insufficient_security",
39
- 80: "internal_error",
40
- 90: "user_canceled",
41
- 109: "missing_extension",
42
- 112: "unrecognized_name"
43
- };
44
- const ascii = (text) => new TextEncoder().encode(text);
45
- function u16(value) {
46
- return new Uint8Array([value >> 8 & 255, value & 255]);
47
- }
48
- function u24(value) {
49
- return new Uint8Array([value >> 16 & 255, value >> 8 & 255, value & 255]);
50
- }
51
- function u64(value) {
52
- const out = new Uint8Array(8);
53
- new DataView(out.buffer).setBigUint64(0, BigInt(value));
54
- return out;
55
- }
56
- async function pHash(hash, secret, seed, length) {
57
- const key = await crypto.subtle.importKey("raw", secret, { name: "HMAC", hash }, false, ["sign"]);
58
- const hmac = async (data) => new Uint8Array(await crypto.subtle.sign("HMAC", key, data));
59
- const blocks = [];
60
- let produced = 0;
61
- let a = await hmac(seed);
62
- while (produced < length) {
63
- const block = await hmac(concatBytes(a, seed));
64
- blocks.push(block);
65
- produced += block.length;
66
- a = await hmac(a);
67
- }
68
- return concatBytes(...blocks).subarray(0, length);
69
- }
70
- const prf = (hash, secret, label, seed, length) => pHash(hash, secret, concatBytes(ascii(label), seed), length);
71
- class Tls12Client {
72
- /**
73
- * @param {(bytes: Uint8Array) => void} send write raw bytes to the transport
74
- * @param {(bytes: Uint8Array) => void} onData decrypted application data
75
- * @param {(error: Error) => void} onError fatal protocol failure
76
- */
77
- constructor({ send, onData, onError }) {
78
- this.sendRaw = send;
79
- this.onData = onData;
80
- this.onError = onError;
81
- this.inbound = new Uint8Array(0);
82
- this.transcript = [];
83
- this.established = false;
84
- this.serverPublicKey = null;
85
- this.suite = null;
86
- this.certificates = [];
87
- this.readSequence = 0n;
88
- this.writeSequence = 0n;
89
- this.readEncrypted = false;
90
- this.writeEncrypted = false;
91
- this.queue = Promise.resolve();
92
- this.handshakeDone = new Promise((resolve, reject) => {
93
- this.resolveHandshake = resolve;
94
- this.rejectHandshake = reject;
95
- });
96
- }
97
- // --- handshake ------------------------------------------------------------
98
- async start() {
99
- this.clientRandom = new Uint8Array(32);
100
- crypto.getRandomValues(this.clientRandom);
101
- const extensions = concatBytes(
102
- // signature_algorithms: rsa with sha256, sha384, sha1
103
- u16(13),
104
- u16(10),
105
- u16(8),
106
- new Uint8Array([4, 1, 5, 1, 2, 1, 6, 1]),
107
- // renegotiation_info: empty, which Schannel expects to see
108
- u16(65281),
109
- u16(1),
110
- new Uint8Array([0])
111
- );
112
- const body = concatBytes(
113
- u16(TLS_1_2),
114
- this.clientRandom,
115
- new Uint8Array([0]),
116
- // no session id
117
- u16(4),
118
- u16(156),
119
- u16(157),
120
- // cipher suites
121
- new Uint8Array([1, 0]),
122
- // compression: null
123
- u16(extensions.length),
124
- extensions
125
- );
126
- await this.#sendHandshake(HANDSHAKE.CLIENT_HELLO, body);
127
- return this.handshakeDone;
128
- }
129
- #record(type, payload) {
130
- return concatBytes(new Uint8Array([type]), u16(TLS_1_2), u16(payload.length), payload);
131
- }
132
- async #sendHandshake(type, body) {
133
- const message = concatBytes(new Uint8Array([type]), u24(body.length), body);
134
- this.transcript.push(message);
135
- await this.#sendRecord(RECORD.HANDSHAKE, message);
136
- }
137
- async #sendRecord(type, payload) {
138
- if (!this.writeEncrypted) {
139
- this.sendRaw(this.#record(type, payload));
140
- return;
141
- }
142
- this.sendRaw(this.#record(type, await this.#seal(type, payload)));
143
- }
144
- /** AES-GCM record protection (RFC 5288): explicit nonce, then ciphertext. */
145
- async #seal(type, plaintext) {
146
- const sequence = this.writeSequence++;
147
- const explicitNonce = u64(sequence);
148
- const iv = concatBytes(this.keys.clientIv, explicitNonce);
149
- const aad = concatBytes(u64(sequence), new Uint8Array([type]), u16(TLS_1_2), u16(plaintext.length));
150
- const sealed = await crypto.subtle.encrypt(
151
- { name: "AES-GCM", iv, additionalData: aad, tagLength: 128 },
152
- this.keys.clientKey,
153
- plaintext
154
- );
155
- return concatBytes(explicitNonce, new Uint8Array(sealed));
156
- }
157
- async #open(type, fragment) {
158
- const sequence = this.readSequence++;
159
- const explicitNonce = fragment.subarray(0, 8);
160
- const ciphertext = fragment.subarray(8);
161
- const iv = concatBytes(this.keys.serverIv, explicitNonce);
162
- const aad = concatBytes(
163
- u64(sequence),
164
- new Uint8Array([type]),
165
- u16(TLS_1_2),
166
- u16(ciphertext.length - 16)
167
- );
168
- const opened = await crypto.subtle.decrypt(
169
- { name: "AES-GCM", iv, additionalData: aad, tagLength: 128 },
170
- this.keys.serverKey,
171
- ciphertext
172
- );
173
- return new Uint8Array(opened);
174
- }
175
- async #deriveKeys(preMasterSecret) {
176
- const { hash, keyLength } = this.suite;
177
- this.masterSecret = await prf(
178
- hash,
179
- preMasterSecret,
180
- "master secret",
181
- concatBytes(this.clientRandom, this.serverRandom),
182
- 48
183
- );
184
- const keyBlock = await prf(
185
- hash,
186
- this.masterSecret,
187
- "key expansion",
188
- concatBytes(this.serverRandom, this.clientRandom),
189
- keyLength * 2 + 8
190
- );
191
- const reader = new Reader(keyBlock);
192
- const clientKeyBytes = reader.raw(keyLength);
193
- const serverKeyBytes = reader.raw(keyLength);
194
- this.keys = {
195
- clientKey: await crypto.subtle.importKey("raw", clientKeyBytes, "AES-GCM", false, ["encrypt"]),
196
- serverKey: await crypto.subtle.importKey("raw", serverKeyBytes, "AES-GCM", false, ["decrypt"]),
197
- clientIv: reader.raw(4).slice(),
198
- serverIv: reader.raw(4).slice()
199
- };
200
- }
201
- async #transcriptHash() {
202
- const digest = await crypto.subtle.digest(this.suite.hash, concatBytes(...this.transcript));
203
- return new Uint8Array(digest);
204
- }
205
- async #verifyData(label) {
206
- return prf(this.suite.hash, this.masterSecret, label, await this.#transcriptHash(), 12);
207
- }
208
- // --- inbound --------------------------------------------------------------
209
- /** Feed transport bytes. Calls are serialized, so order is preserved. */
210
- receive(bytes) {
211
- this.queue = this.queue.then(() => this.#consume(bytes)).catch((error) => this.#fail(error));
212
- return this.queue;
213
- }
214
- #fail(error) {
215
- const failure = error instanceof Error ? error : new Error(String(error));
216
- this.rejectHandshake(failure);
217
- if (this.onError) this.onError(failure);
218
- }
219
- async #consume(bytes) {
220
- this.inbound = this.inbound.length === 0 ? bytes : concatBytes(this.inbound, bytes);
221
- while (this.inbound.length >= 5) {
222
- const type = this.inbound[0];
223
- const length = this.inbound[3] << 8 | this.inbound[4];
224
- if (this.inbound.length < 5 + length) return;
225
- const fragment = this.inbound.subarray(5, 5 + length);
226
- this.inbound = this.inbound.subarray(5 + length).slice();
227
- const payload = this.readEncrypted && type !== RECORD.CHANGE_CIPHER_SPEC ? await this.#open(type, fragment) : fragment;
228
- await this.#handleRecord(type, payload);
229
- }
230
- }
231
- async #handleRecord(type, payload) {
232
- if (type === RECORD.ALERT) {
233
- const level = payload[0];
234
- const description = payload[1];
235
- const name = ALERT_DESCRIPTIONS[description] || `alert ${description}`;
236
- if (name === "close_notify") {
237
- this.established = false;
238
- return;
239
- }
240
- throw new Error(`TLS: the host sent a fatal alert: ${name}${level === 1 ? " (warning)" : ""}`);
241
- }
242
- if (type === RECORD.CHANGE_CIPHER_SPEC) {
243
- this.readEncrypted = true;
244
- this.readSequence = 0n;
245
- return;
246
- }
247
- if (type === RECORD.APPLICATION_DATA) {
248
- if (this.onData && payload.length > 0) this.onData(payload);
249
- return;
250
- }
251
- if (type !== RECORD.HANDSHAKE) return;
252
- let offset = 0;
253
- while (offset + 4 <= payload.length) {
254
- const messageType = payload[offset];
255
- const length = payload[offset + 1] << 16 | payload[offset + 2] << 8 | payload[offset + 3];
256
- const message = payload.subarray(offset, offset + 4 + length);
257
- const body = payload.subarray(offset + 4, offset + 4 + length);
258
- offset += 4 + length;
259
- if (messageType !== HANDSHAKE.FINISHED) this.transcript.push(message);
260
- await this.#handleHandshake(messageType, body, message);
261
- }
262
- }
263
- async #handleHandshake(type, body, message) {
264
- switch (type) {
265
- case HANDSHAKE.SERVER_HELLO: {
266
- const reader = new Reader(body);
267
- const version = reader.u16be();
268
- if (version !== TLS_1_2) {
269
- throw new Error(`TLS: the host chose an unsupported version 0x${version.toString(16)}`);
270
- }
271
- this.serverRandom = reader.raw(32).slice();
272
- reader.raw(reader.u8());
273
- const suiteId = reader.u16be();
274
- this.suite = CIPHER_SUITES[suiteId];
275
- if (!this.suite) {
276
- throw new Error(`TLS: the host chose cipher suite 0x${suiteId.toString(16)}, which this client does not implement`);
277
- }
278
- reader.u8();
279
- return;
280
- }
281
- case HANDSHAKE.CERTIFICATE: {
282
- const reader = new Reader(body);
283
- const totalLength = reader.u8() << 16 | reader.u16be();
284
- const end = reader.offset + totalLength;
285
- while (reader.offset < end) {
286
- const certificateLength = reader.u8() << 16 | reader.u16be();
287
- this.certificates.push(reader.raw(certificateLength).slice());
288
- }
289
- if (this.certificates.length === 0) throw new Error("TLS: the host sent no certificate");
290
- this.serverPublicKey = parseX509PublicKey(this.certificates[0]);
291
- return;
292
- }
293
- case HANDSHAKE.CERTIFICATE_REQUEST:
294
- this.certificateRequested = true;
295
- return;
296
- case HANDSHAKE.SERVER_KEY_EXCHANGE:
297
- throw new Error("TLS: the host chose an ephemeral key exchange, which this client does not implement");
298
- case HANDSHAKE.SERVER_HELLO_DONE:
299
- await this.#finishClientHandshake();
300
- return;
301
- case HANDSHAKE.NEW_SESSION_TICKET:
302
- return;
303
- case HANDSHAKE.FINISHED: {
304
- const expected = await this.#verifyData("server finished");
305
- const actual = body.subarray(0, 12);
306
- const matches = expected.length === actual.length && expected.every((byte, i) => byte === actual[i]);
307
- if (!matches) throw new Error("TLS: the host Finished message did not verify");
308
- this.transcript.push(message);
309
- this.established = true;
310
- this.resolveHandshake({
311
- cipherSuite: this.suite.name,
312
- certificates: this.certificates,
313
- publicKey: this.serverPublicKey
314
- });
315
- return;
316
- }
317
- default:
318
- return;
319
- }
320
- }
321
- async #finishClientHandshake() {
322
- if (this.certificateRequested) {
323
- await this.#sendHandshake(HANDSHAKE.CERTIFICATE, u24(0));
324
- }
325
- const preMasterSecret = new Uint8Array(48);
326
- crypto.getRandomValues(preMasterSecret);
327
- preMasterSecret[0] = 3;
328
- preMasterSecret[1] = 3;
329
- const encrypted = rsaEncryptPkcs1(
330
- preMasterSecret,
331
- this.serverPublicKey.modulus,
332
- this.serverPublicKey.exponent
333
- );
334
- await this.#sendHandshake(HANDSHAKE.CLIENT_KEY_EXCHANGE, concatBytes(u16(encrypted.length), encrypted));
335
- await this.#deriveKeys(preMasterSecret);
336
- await this.#sendRecord(RECORD.CHANGE_CIPHER_SPEC, new Uint8Array([1]));
337
- this.writeEncrypted = true;
338
- this.writeSequence = 0n;
339
- await this.#sendHandshake(HANDSHAKE.FINISHED, await this.#verifyData("client finished"));
340
- }
341
- // --- outbound -------------------------------------------------------------
342
- /** Send application data once the handshake has completed. */
343
- write(plaintext) {
344
- this.queue = this.queue.then(async () => {
345
- if (!this.established) throw new Error("TLS: write before the handshake finished");
346
- await this.#sendRecord(RECORD.APPLICATION_DATA, plaintext);
347
- }).catch((error) => this.#fail(error));
348
- return this.queue;
349
- }
350
- }
351
- export {
352
- Tls12Client
353
- };
@@ -1,28 +0,0 @@
1
- /** Channel option bits used when the channel is declared in Client Network Data. */
2
- export declare const CHANNEL_OPTION: {
3
- INITIALIZED: number;
4
- ENCRYPT_RDP: number;
5
- COMPRESS_RDP: number;
6
- SHOW_PROTOCOL: number;
7
- };
8
- export declare const CHANNEL_FLAG_SHOW_PROTOCOL = 16;
9
- /** What RDP itself uses; a host may accept more, but never needs to. */
10
- export declare const CHANNEL_CHUNK_LENGTH = 1600;
11
- /**
12
- * Split one logical channel message into wire chunks, each already carrying its
13
- * CHANNEL_PDU_HEADER. An empty message still produces one chunk, because the
14
- * header is what tells the host anything happened at all.
15
- */
16
- export declare function chunkChannelData(data: Uint8Array, chunkSize?: number, extraFlags?: number): any[];
17
- /**
18
- * Reassemble inbound chunks into whole messages. A chunk that arrives without a
19
- * preceding FIRST is treated as its own message rather than dropped: some hosts
20
- * send small PDUs with both flags set and others with neither.
21
- */
22
- export declare class ChannelReassembler {
23
- private parts;
24
- private expectedLength;
25
- constructor();
26
- /** Returns the completed message, or null while more chunks are pending. */
27
- push(bytes: Uint8Array): Uint8Array<ArrayBufferLike>;
28
- }
@@ -1,58 +0,0 @@
1
- import { Reader, Writer, concatBytes } from "./buffer.js";
2
- const CHANNEL_OPTION = {
3
- INITIALIZED: 2147483648,
4
- ENCRYPT_RDP: 1073741824,
5
- COMPRESS_RDP: 8388608,
6
- SHOW_PROTOCOL: 2097152
7
- };
8
- const CHANNEL_FLAG_FIRST = 1;
9
- const CHANNEL_FLAG_LAST = 2;
10
- const CHANNEL_FLAG_SHOW_PROTOCOL = 16;
11
- const CHANNEL_CHUNK_LENGTH = 1600;
12
- function chunkChannelData(data, chunkSize = CHANNEL_CHUNK_LENGTH, extraFlags = 0) {
13
- const chunks = [];
14
- for (let offset = 0; offset < data.length || offset === 0; offset += chunkSize) {
15
- const slice = data.subarray(offset, offset + chunkSize);
16
- let flags = extraFlags;
17
- if (offset === 0) flags |= CHANNEL_FLAG_FIRST;
18
- if (offset + chunkSize >= data.length) flags |= CHANNEL_FLAG_LAST;
19
- const writer = new Writer(slice.length + 8);
20
- writer.u32le(data.length).u32le(flags).raw(slice);
21
- chunks.push(writer.take());
22
- if (data.length === 0) break;
23
- }
24
- return chunks;
25
- }
26
- class ChannelReassembler {
27
- parts;
28
- expectedLength;
29
- constructor() {
30
- this.parts = [];
31
- this.expectedLength = 0;
32
- }
33
- /** Returns the completed message, or null while more chunks are pending. */
34
- push(bytes) {
35
- if (bytes.length < 8) return null;
36
- const reader = new Reader(bytes);
37
- const totalLength = reader.u32le();
38
- const flags = reader.u32le();
39
- const data = reader.rest();
40
- if (flags & CHANNEL_FLAG_FIRST) {
41
- this.parts = [];
42
- this.expectedLength = totalLength;
43
- }
44
- this.parts.push(data.slice());
45
- const complete = (flags & CHANNEL_FLAG_LAST) !== 0;
46
- if (!complete) return null;
47
- const message = concatBytes(...this.parts);
48
- this.parts = [];
49
- return this.expectedLength && this.expectedLength < message.length ? message.subarray(0, this.expectedLength) : message;
50
- }
51
- }
52
- export {
53
- CHANNEL_CHUNK_LENGTH,
54
- CHANNEL_FLAG_SHOW_PROTOCOL,
55
- CHANNEL_OPTION,
56
- ChannelReassembler,
57
- chunkChannelData
58
- };
@@ -1,40 +0,0 @@
1
- export declare const TPKT_VERSION = 3;
2
- export declare const TPKT_HEADER_LENGTH = 4;
3
- export declare const NEG_FAILURE: {
4
- SSL_REQUIRED: number;
5
- SSL_NOT_ALLOWED: number;
6
- SSL_CERT_NOT_ON_SERVER: number;
7
- INCONSISTENT_FLAGS: number;
8
- HYBRID_REQUIRED: number;
9
- SSL_WITH_USER_AUTH_REQUIRED: number;
10
- };
11
- export declare const NEG_PROTOCOL: {
12
- RDP: number;
13
- SSL: number;
14
- HYBRID: number;
15
- RDSTLS: number;
16
- HYBRID_EX: number;
17
- };
18
- /** X.224 Connection Request, carrying the protocols this client will accept. */
19
- export declare function connectionRequest(requestedProtocols: number): Uint8Array<ArrayBufferLike>;
20
- /**
21
- * Read the X.224 Connection Confirm. Throws with the host's own explanation
22
- * when it refuses the requested protocol.
23
- */
24
- export declare function parseConnectionConfirm(frame: Uint8Array): {
25
- selectedProtocol: number;
26
- negotiated: boolean;
27
- };
28
- /** Wrap a payload in TPKT + X.224 Data. */
29
- export declare function dataFrame(payload: Uint8Array): Uint8Array<ArrayBufferLike>;
30
- /** Strip TPKT + X.224 Data headers from a complete frame. */
31
- export declare function dataPayload(frame: Uint8Array): Uint8Array<ArrayBufferLike>;
32
- /**
33
- * Split a byte stream into whole frames. RDP interleaves two framings on one
34
- * connection: TPKT (first byte 0x03) and fast-path output (any other value),
35
- * each with its own length encoding.
36
- */
37
- export declare function splitFrames(buffer: Uint8Array): {
38
- frames: any[];
39
- rest: Uint8Array<ArrayBufferLike>;
40
- };
@@ -1,109 +0,0 @@
1
- import { Reader, Writer } from "./buffer.js";
2
- const TPKT_VERSION = 3;
3
- const TPKT_HEADER_LENGTH = 4;
4
- const X224_CONNECTION_REQUEST = 224;
5
- const X224_CONNECTION_CONFIRM = 208;
6
- const X224_DATA = 240;
7
- const RDP_NEG_REQ = 1;
8
- const RDP_NEG_RSP = 2;
9
- const RDP_NEG_FAILURE = 3;
10
- const NEG_FAILURE = {
11
- SSL_REQUIRED: 1,
12
- SSL_NOT_ALLOWED: 2,
13
- SSL_CERT_NOT_ON_SERVER: 3,
14
- INCONSISTENT_FLAGS: 4,
15
- HYBRID_REQUIRED: 5,
16
- SSL_WITH_USER_AUTH_REQUIRED: 6
17
- };
18
- const NEG_PROTOCOL = {
19
- RDP: 0,
20
- SSL: 1,
21
- HYBRID: 2,
22
- RDSTLS: 4,
23
- HYBRID_EX: 8
24
- };
25
- const NEG_FAILURE_MESSAGES = {
26
- 1: "The host requires TLS. Choose the TLS security option for this target.",
27
- 2: 'The host does not allow TLS. Choose the "RDP (standard)" security option.',
28
- 3: "The host has no certificate installed, so it cannot negotiate TLS.",
29
- 4: "The host rejected the requested protocol flags as inconsistent.",
30
- 5: 'The host requires Network Level Authentication (NLA/CredSSP). Turn NLA off on the host, or set its security layer to "RDP".',
31
- 6: "The host requires TLS with early user authentication, which this gateway does not support."
32
- };
33
- function connectionRequest(requestedProtocols) {
34
- const writer = new Writer(32);
35
- writer.u8(TPKT_VERSION).u8(0).u16be(19);
36
- writer.u8(14).u8(X224_CONNECTION_REQUEST).u16be(0).u16be(0).u8(0);
37
- writer.u8(RDP_NEG_REQ).u8(0).u16le(8).u32le(requestedProtocols);
38
- return writer.take();
39
- }
40
- function parseConnectionConfirm(frame) {
41
- const reader = new Reader(frame);
42
- reader.skip(TPKT_HEADER_LENGTH);
43
- reader.u8();
44
- const code = reader.u8();
45
- if (code !== X224_CONNECTION_CONFIRM) {
46
- throw new Error(`RDP: expected an X.224 connection confirm, got TPDU code 0x${code.toString(16)}`);
47
- }
48
- reader.skip(5);
49
- if (reader.remaining < 8) return { selectedProtocol: NEG_PROTOCOL.RDP, negotiated: false };
50
- const type = reader.u8();
51
- reader.u8();
52
- reader.u16le();
53
- if (type === RDP_NEG_FAILURE) {
54
- const failureCode = reader.u32le();
55
- const error = new Error(
56
- NEG_FAILURE_MESSAGES[failureCode] || `The host refused the RDP connection (negotiation failure 0x${failureCode.toString(16)}).`
57
- );
58
- error.negotiationFailure = failureCode;
59
- throw error;
60
- }
61
- if (type !== RDP_NEG_RSP) {
62
- return { selectedProtocol: NEG_PROTOCOL.RDP, negotiated: false };
63
- }
64
- return { selectedProtocol: reader.u32le(), negotiated: true };
65
- }
66
- function dataFrame(payload) {
67
- const writer = new Writer(payload.length + 7);
68
- writer.u8(TPKT_VERSION).u8(0).u16be(payload.length + 7);
69
- writer.u8(2).u8(X224_DATA).u8(128);
70
- writer.raw(payload);
71
- return writer.take();
72
- }
73
- function dataPayload(frame) {
74
- if (frame.length < 7) throw new Error("RDP: X.224 data frame is too short");
75
- return frame.subarray(7);
76
- }
77
- function splitFrames(buffer) {
78
- const frames = [];
79
- let offset = 0;
80
- while (buffer.length - offset >= 4) {
81
- let frameLength;
82
- let fastPath = false;
83
- if (buffer[offset] === TPKT_VERSION) {
84
- frameLength = buffer[offset + 2] << 8 | buffer[offset + 3];
85
- if (frameLength < TPKT_HEADER_LENGTH) {
86
- throw new Error("RDP: malformed TPKT length");
87
- }
88
- } else {
89
- fastPath = true;
90
- frameLength = buffer[offset + 1] & 128 ? (buffer[offset + 1] & 127) << 8 | buffer[offset + 2] : buffer[offset + 1];
91
- if (frameLength < 2) throw new Error("RDP: malformed fast-path length");
92
- }
93
- if (buffer.length - offset < frameLength) break;
94
- frames.push({ fastPath, frame: buffer.subarray(offset, offset + frameLength) });
95
- offset += frameLength;
96
- }
97
- return { frames, rest: buffer.subarray(offset) };
98
- }
99
- export {
100
- NEG_FAILURE,
101
- NEG_PROTOCOL,
102
- TPKT_HEADER_LENGTH,
103
- TPKT_VERSION,
104
- connectionRequest,
105
- dataFrame,
106
- dataPayload,
107
- parseConnectionConfirm,
108
- splitFrames
109
- };
@@ -1,97 +0,0 @@
1
- /** Key exchange methods, best first. All of them hash with SHA-256. */
2
- export declare const KEX_ALGORITHMS: {
3
- 'curve25519-sha256': {
4
- type: string;
5
- hash: string;
6
- };
7
- 'curve25519-sha256@libssh.org': {
8
- type: string;
9
- hash: string;
10
- };
11
- 'ecdh-sha2-nistp256': {
12
- type: string;
13
- curve: string;
14
- hash: string;
15
- };
16
- };
17
- /**
18
- * Host key signature algorithms. `keyType` is what appears inside the key blob;
19
- * a modern RSA key is signed with SHA-256 or SHA-512 but still calls itself
20
- * ssh-rsa, so the two names differ there.
21
- */
22
- export declare const HOST_KEY_ALGORITHMS: {
23
- 'ssh-ed25519': {
24
- keyType: string;
25
- kind: string;
26
- };
27
- 'rsa-sha2-512': {
28
- keyType: string;
29
- kind: string;
30
- hash: string;
31
- };
32
- 'rsa-sha2-256': {
33
- keyType: string;
34
- kind: string;
35
- hash: string;
36
- };
37
- 'ecdsa-sha2-nistp256': {
38
- keyType: string;
39
- kind: string;
40
- curve: string;
41
- hash: string;
42
- };
43
- };
44
- /**
45
- * What this browser can actually do. X25519 and Ed25519 are recent additions to
46
- * Web Crypto, so they are probed rather than assumed; the NIST curve and RSA
47
- * have been there all along and always keep the session possible.
48
- */
49
- export declare function negotiableAlgorithms(): Promise<any>;
50
- /** The client half of one key exchange. */
51
- export declare function createKexClient(algorithmName: string): Promise<{
52
- hash: any;
53
- publicKey: Uint8Array<ArrayBuffer>;
54
- sharedSecret(serverPublicKey: any): Promise<Uint8Array<ArrayBuffer>>;
55
- }>;
56
- /** The key type named inside a host key blob, which the algorithm must match. */
57
- export declare function hostKeyType(keyBlob: Uint8Array): string;
58
- /** The SHA256:… fingerprint OpenSSH prints, so a user can compare it. */
59
- export declare function hostKeyFingerprint(keyBlob: Uint8Array): Promise<string>;
60
- /**
61
- * Check that the host owns the key it presented, by verifying its signature
62
- * over the exchange hash. A failure here is fatal: it is what stands between
63
- * the session and a machine in the middle of it.
64
- */
65
- export declare function verifyHostKeySignature({ algorithm, keyBlob, signatureBlob, exchangeHash }: {
66
- algorithm: any;
67
- exchangeHash: any;
68
- keyBlob: any;
69
- signatureBlob: any;
70
- }): Promise<boolean>;
71
- /**
72
- * The exchange hash H (RFC 4253 section 8), which both sides compute from the
73
- * same inputs and the host signs.
74
- */
75
- export declare function exchangeHash({ hash, clientVersion, serverVersion, clientKexInit, serverKexInit, hostKeyBlob, clientPublicKey, serverPublicKey, sharedSecret, }: {
76
- clientKexInit: any;
77
- clientPublicKey: any;
78
- clientVersion: any;
79
- hash: any;
80
- hostKeyBlob: any;
81
- serverKexInit: any;
82
- serverPublicKey: any;
83
- serverVersion: any;
84
- sharedSecret: any;
85
- }): Promise<Uint8Array<ArrayBuffer>>;
86
- /**
87
- * Derive one key from the exchange (RFC 4253 section 7.2), extending it with
88
- * further hash rounds when the cipher wants more bytes than one digest.
89
- */
90
- export declare function deriveKey({ hash, sharedSecret, exchangeHash: h, letter, sessionId, length }: {
91
- exchangeHash: any;
92
- hash: any;
93
- length: any;
94
- letter: any;
95
- sessionId: any;
96
- sharedSecret: any;
97
- }): Promise<Uint8Array<ArrayBuffer>>;