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.
Files changed (114) hide show
  1. package/README.md +50 -0
  2. package/dist/index.js +7 -0
  3. package/dist/index.js.map +7 -0
  4. package/dist/protocols/index.js +35 -0
  5. package/dist/protocols/index.js.map +7 -0
  6. package/dist/protocols/rdp/buffer.js +170 -0
  7. package/dist/protocols/rdp/buffer.js.map +7 -0
  8. package/dist/protocols/rdp/caps.js +260 -0
  9. package/dist/protocols/rdp/caps.js.map +7 -0
  10. package/dist/protocols/rdp/cert.js +135 -0
  11. package/dist/protocols/rdp/cert.js.map +7 -0
  12. package/dist/protocols/rdp/client.js +1068 -0
  13. package/dist/protocols/rdp/client.js.map +7 -0
  14. package/dist/protocols/rdp/cliprdr.js +240 -0
  15. package/dist/protocols/rdp/cliprdr.js.map +7 -0
  16. package/dist/protocols/rdp/credssp.js +254 -0
  17. package/dist/protocols/rdp/credssp.js.map +7 -0
  18. package/dist/protocols/rdp/crypto.js +369 -0
  19. package/dist/protocols/rdp/crypto.js.map +7 -0
  20. package/dist/protocols/rdp/display.js +589 -0
  21. package/dist/protocols/rdp/display.js.map +7 -0
  22. package/dist/protocols/rdp/gcc.js +132 -0
  23. package/dist/protocols/rdp/gcc.js.map +7 -0
  24. package/dist/protocols/rdp/keymap.js +132 -0
  25. package/dist/protocols/rdp/keymap.js.map +7 -0
  26. package/dist/protocols/rdp/mcs.js +223 -0
  27. package/dist/protocols/rdp/mcs.js.map +7 -0
  28. package/dist/protocols/rdp/ntlm.js +305 -0
  29. package/dist/protocols/rdp/ntlm.js.map +7 -0
  30. package/dist/protocols/rdp/pdu.js +444 -0
  31. package/dist/protocols/rdp/pdu.js.map +7 -0
  32. package/dist/protocols/rdp/rail.js +383 -0
  33. package/dist/protocols/rdp/rail.js.map +7 -0
  34. package/dist/protocols/rdp/rle.js +276 -0
  35. package/dist/protocols/rdp/rle.js.map +7 -0
  36. package/dist/protocols/rdp/sec.js +156 -0
  37. package/dist/protocols/rdp/sec.js.map +7 -0
  38. package/dist/protocols/rdp/session.js +307 -0
  39. package/dist/protocols/rdp/session.js.map +7 -0
  40. package/dist/protocols/rdp/tls.js +354 -0
  41. package/dist/protocols/rdp/tls.js.map +7 -0
  42. package/dist/protocols/rdp/vchannel.js +59 -0
  43. package/dist/protocols/rdp/vchannel.js.map +7 -0
  44. package/dist/protocols/rdp/x224.js +110 -0
  45. package/dist/protocols/rdp/x224.js.map +7 -0
  46. package/dist/protocols/ssh/kex.js +177 -0
  47. package/dist/protocols/ssh/kex.js.map +7 -0
  48. package/dist/protocols/ssh/messages.js +55 -0
  49. package/dist/protocols/ssh/messages.js.map +7 -0
  50. package/dist/protocols/ssh/session.js +608 -0
  51. package/dist/protocols/ssh/session.js.map +7 -0
  52. package/dist/protocols/ssh/terminal.js +191 -0
  53. package/dist/protocols/ssh/terminal.js.map +7 -0
  54. package/dist/protocols/ssh/transport.js +611 -0
  55. package/dist/protocols/ssh/transport.js.map +7 -0
  56. package/dist/protocols/ssh/wire.js +189 -0
  57. package/dist/protocols/ssh/wire.js.map +7 -0
  58. package/dist/protocols/types.js +1 -0
  59. package/dist/protocols/types.js.map +7 -0
  60. package/dist/protocols/vnc/input.js +16 -0
  61. package/dist/protocols/vnc/input.js.map +7 -0
  62. package/dist/protocols/vnc/session.js +259 -0
  63. package/dist/protocols/vnc/session.js.map +7 -0
  64. package/dist/shared/connection.js +114 -0
  65. package/dist/shared/connection.js.map +7 -0
  66. package/dist/shared/device.js +1 -0
  67. package/dist/shared/device.js.map +7 -0
  68. package/dist/shared/hosts.js +133 -0
  69. package/dist/shared/hosts.js.map +7 -0
  70. package/dist/shared/icons.js +42 -0
  71. package/dist/shared/icons.js.map +7 -0
  72. package/dist/shared/protocol.js +40 -0
  73. package/dist/shared/protocol.js.map +7 -0
  74. package/dist/shared/signals.js +42 -0
  75. package/dist/shared/signals.js.map +7 -0
  76. package/package.json +82 -0
  77. package/src/index.ts +14 -0
  78. package/src/protocols/index.ts +72 -0
  79. package/src/protocols/rdp/buffer.ts +204 -0
  80. package/src/protocols/rdp/caps.ts +304 -0
  81. package/src/protocols/rdp/cert.ts +190 -0
  82. package/src/protocols/rdp/client.ts +1363 -0
  83. package/src/protocols/rdp/cliprdr.ts +344 -0
  84. package/src/protocols/rdp/credssp.ts +319 -0
  85. package/src/protocols/rdp/crypto.ts +416 -0
  86. package/src/protocols/rdp/display.ts +750 -0
  87. package/src/protocols/rdp/gcc.ts +162 -0
  88. package/src/protocols/rdp/keymap.ts +68 -0
  89. package/src/protocols/rdp/mcs.ts +283 -0
  90. package/src/protocols/rdp/ntlm.ts +380 -0
  91. package/src/protocols/rdp/pdu.ts +497 -0
  92. package/src/protocols/rdp/rail.ts +480 -0
  93. package/src/protocols/rdp/rle.ts +343 -0
  94. package/src/protocols/rdp/sec.ts +184 -0
  95. package/src/protocols/rdp/session.ts +393 -0
  96. package/src/protocols/rdp/tls.ts +452 -0
  97. package/src/protocols/rdp/vchannel.ts +89 -0
  98. package/src/protocols/rdp/x224.ts +139 -0
  99. package/src/protocols/ssh/kex.ts +227 -0
  100. package/src/protocols/ssh/messages.ts +54 -0
  101. package/src/protocols/ssh/session.ts +878 -0
  102. package/src/protocols/ssh/terminal.ts +242 -0
  103. package/src/protocols/ssh/transport.ts +732 -0
  104. package/src/protocols/ssh/wire.ts +220 -0
  105. package/src/protocols/types.ts +146 -0
  106. package/src/protocols/vnc/input.ts +13 -0
  107. package/src/protocols/vnc/novnc.d.ts +75 -0
  108. package/src/protocols/vnc/session.ts +367 -0
  109. package/src/shared/connection.ts +206 -0
  110. package/src/shared/device.ts +28 -0
  111. package/src/shared/hosts.ts +240 -0
  112. package/src/shared/icons.ts +49 -0
  113. package/src/shared/protocol.ts +55 -0
  114. package/src/shared/signals.ts +67 -0
@@ -0,0 +1,383 @@
1
+ import { Reader, Writer } from "./buffer";
2
+ const RAIL_ORDER = {
3
+ EXEC: 1,
4
+ ACTIVATE: 2,
5
+ SYSPARAM: 3,
6
+ SYSCOMMAND: 4,
7
+ HANDSHAKE: 5,
8
+ WINDOW_MOVE: 8,
9
+ CLIENT_STATUS: 11,
10
+ EXEC_RESULT: 128,
11
+ HANDSHAKE_EX: 19
12
+ };
13
+ const RAIL_EXEC_RESULT = {
14
+ 0: "The remote application started.",
15
+ 1: "The RemoteApp host could not load its application monitoring hook.",
16
+ 2: "The RemoteApp host could not decode the application launch request.",
17
+ 3: "The requested application is not in the host RemoteApp allowlist.",
18
+ 5: "The requested remote application was not found.",
19
+ 6: "The RemoteApp host could not start the requested application.",
20
+ 7: "The RemoteApp session is locked and cannot start the application."
21
+ };
22
+ const SYS_COMMAND = {
23
+ MINIMIZE: 61472,
24
+ MAXIMIZE: 61488,
25
+ CLOSE: 61536,
26
+ RESTORE: 61728
27
+ };
28
+ const SHOW_STATE = {
29
+ HIDDEN: 0,
30
+ MINIMIZED: 2,
31
+ MAXIMIZED: 3,
32
+ NORMAL: 5
33
+ };
34
+ const WINDOW_ORDER = {
35
+ TYPE_WINDOW: 16777216,
36
+ STATE_NEW: 268435456,
37
+ STATE_DELETED: 536870912,
38
+ ICON: 1073741824,
39
+ CACHED_ICON: 2147483648
40
+ };
41
+ const WINDOW_FIELD = {
42
+ OWNER: 2,
43
+ TITLE: 4,
44
+ STYLE: 8,
45
+ SHOW: 16,
46
+ WND_RECTS: 256,
47
+ WND_SIZE: 1024,
48
+ WND_OFFSET: 2048,
49
+ CLIENT_AREA_OFFSET: 16384,
50
+ CLIENT_DELTA: 32768,
51
+ CLIENT_AREA_SIZE: 65536,
52
+ RP_CONTENT: 131072,
53
+ ROOT_PARENT: 262144,
54
+ VISIBILITY: 524288,
55
+ VIS_OFFSET: 2097152
56
+ };
57
+ const STYLE_CHILD = 1073741824;
58
+ const EX_STYLE_TOOLWINDOW = 128;
59
+ const EX_STYLE_NOACTIVATE = 134217728;
60
+ const DRAWING_ORDER_CLASS_MASK = 3;
61
+ const DRAWING_ORDER_ALT_SECONDARY = 2;
62
+ const ALTSEC_WINDOW = 11;
63
+ const CLIENT_BUILD = 2600;
64
+ const CLIENT_STATUS_SUPPRESS_ICON_ORDERS = 1024;
65
+ const SYSTEM_PARAMETER = {
66
+ MOUSE_BUTTON_SWAP: 33,
67
+ DRAG_FULL_WINDOWS: 37,
68
+ WORK_AREA: 47,
69
+ HIGH_CONTRAST: 67,
70
+ KEYBOARD_PREF: 69,
71
+ KEYBOARD_CUES: 4107
72
+ };
73
+ function utf16Bytes(text) {
74
+ const writer = new Writer(text.length * 2);
75
+ writer.utf16le(text);
76
+ return writer.take();
77
+ }
78
+ function pdu(orderType, body) {
79
+ const writer = new Writer(body.length + 4);
80
+ writer.u16le(orderType).u16le(body.length + 4).raw(body);
81
+ return writer.take();
82
+ }
83
+ function signed32(value) {
84
+ return value | 0;
85
+ }
86
+ function railHandshake(buildNumber = CLIENT_BUILD) {
87
+ return pdu(RAIL_ORDER.HANDSHAKE, new Writer(4).u32le(buildNumber).take());
88
+ }
89
+ function railClientStatus(flags = CLIENT_STATUS_SUPPRESS_ICON_ORDERS) {
90
+ return pdu(RAIL_ORDER.CLIENT_STATUS, new Writer(4).u32le(flags).take());
91
+ }
92
+ function railBooleanSystemParameter(parameter, enabled) {
93
+ return pdu(RAIL_ORDER.SYSPARAM, new Writer(5).u32le(parameter).u8(enabled ? 1 : 0).take());
94
+ }
95
+ function railHighContrast() {
96
+ const body = new Writer(16);
97
+ body.u32le(SYSTEM_PARAMETER.HIGH_CONTRAST);
98
+ body.u32le(126);
99
+ body.u32le(2);
100
+ body.u16le(0).u16le(0);
101
+ return pdu(RAIL_ORDER.SYSPARAM, body.take());
102
+ }
103
+ function railWorkArea(width, height) {
104
+ const body = new Writer(12);
105
+ body.u32le(SYSTEM_PARAMETER.WORK_AREA);
106
+ body.u16le(0).u16le(0).u16le(width).u16le(height);
107
+ return pdu(RAIL_ORDER.SYSPARAM, body.take());
108
+ }
109
+ function railSystemParameters(width, height) {
110
+ return [
111
+ railHighContrast(),
112
+ railBooleanSystemParameter(SYSTEM_PARAMETER.MOUSE_BUTTON_SWAP, false),
113
+ railBooleanSystemParameter(SYSTEM_PARAMETER.KEYBOARD_PREF, false),
114
+ railBooleanSystemParameter(SYSTEM_PARAMETER.DRAG_FULL_WINDOWS, true),
115
+ railBooleanSystemParameter(SYSTEM_PARAMETER.KEYBOARD_CUES, false),
116
+ railWorkArea(width, height)
117
+ ];
118
+ }
119
+ function railActivate(windowId, enabled = true) {
120
+ const body = new Writer(5);
121
+ body.u32le(windowId).u8(enabled ? 1 : 0);
122
+ return pdu(RAIL_ORDER.ACTIVATE, body.take());
123
+ }
124
+ function railSysCommand(windowId, command) {
125
+ const body = new Writer(6);
126
+ body.u32le(windowId).u16le(command);
127
+ return pdu(RAIL_ORDER.SYSCOMMAND, body.take());
128
+ }
129
+ function railWindowMove(windowId, { left, top, right, bottom }) {
130
+ const body = new Writer(12);
131
+ body.u32le(windowId);
132
+ body.u16le(left & 65535).u16le(top & 65535);
133
+ body.u16le(right & 65535).u16le(bottom & 65535);
134
+ return pdu(RAIL_ORDER.WINDOW_MOVE, body.take());
135
+ }
136
+ function railExecute({ program, workingDir = "", arguments: args = "" }) {
137
+ const exe = utf16Bytes(program || "");
138
+ const cwd = utf16Bytes(workingDir || "");
139
+ const argv = utf16Bytes(args || "");
140
+ if (exe.length === 0 || exe.length > 520) {
141
+ throw new Error("RemoteApp program must be between 1 and 260 Unicode characters.");
142
+ }
143
+ if (cwd.length > 520) throw new Error("RemoteApp working directory is too long.");
144
+ if (argv.length > 16e3) throw new Error("RemoteApp arguments are too long.");
145
+ const body = new Writer(8 + exe.length + cwd.length + argv.length);
146
+ body.u16le(0);
147
+ body.u16le(exe.length).u16le(cwd.length).u16le(argv.length);
148
+ body.raw(exe).raw(cwd).raw(argv);
149
+ return pdu(RAIL_ORDER.EXEC, body.take());
150
+ }
151
+ function decodeUtf16(bytes) {
152
+ let result = "";
153
+ for (let i = 0; i + 1 < bytes.length; i += 2) {
154
+ const codeUnit = bytes[i] | bytes[i + 1] << 8;
155
+ if (codeUnit === 0) break;
156
+ result += String.fromCharCode(codeUnit);
157
+ }
158
+ return result;
159
+ }
160
+ function readRectangles(reader, count) {
161
+ const rectangles = [];
162
+ for (let index = 0; index < count && reader.remaining >= 8; index++) {
163
+ const left = reader.u16le();
164
+ const top = reader.u16le();
165
+ const right = reader.u16le();
166
+ const bottom = reader.u16le();
167
+ rectangles.push({ left, top, right, bottom });
168
+ }
169
+ return rectangles;
170
+ }
171
+ function parseWindowFields(reader, fieldFlags) {
172
+ const fields = {};
173
+ if (fieldFlags & WINDOW_FIELD.OWNER) fields.ownerWindowId = reader.u32le();
174
+ if (fieldFlags & WINDOW_FIELD.STYLE) {
175
+ fields.style = reader.u32le();
176
+ fields.extendedStyle = reader.u32le();
177
+ }
178
+ if (fieldFlags & WINDOW_FIELD.SHOW) fields.showState = reader.u8();
179
+ if (fieldFlags & WINDOW_FIELD.TITLE) {
180
+ const titleBytes = reader.u16le();
181
+ fields.title = decodeUtf16(reader.raw(Math.min(titleBytes, reader.remaining)));
182
+ }
183
+ if (fieldFlags & WINDOW_FIELD.CLIENT_AREA_OFFSET) {
184
+ fields.clientOffsetX = signed32(reader.u32le());
185
+ fields.clientOffsetY = signed32(reader.u32le());
186
+ }
187
+ if (fieldFlags & WINDOW_FIELD.CLIENT_AREA_SIZE) {
188
+ fields.clientWidth = signed32(reader.u32le());
189
+ fields.clientHeight = signed32(reader.u32le());
190
+ }
191
+ if (fieldFlags & WINDOW_FIELD.RP_CONTENT) reader.u8();
192
+ if (fieldFlags & WINDOW_FIELD.ROOT_PARENT) reader.u32le();
193
+ if (fieldFlags & WINDOW_FIELD.WND_OFFSET) {
194
+ fields.x = signed32(reader.u32le());
195
+ fields.y = signed32(reader.u32le());
196
+ }
197
+ if (fieldFlags & WINDOW_FIELD.CLIENT_DELTA) {
198
+ reader.u32le();
199
+ reader.u32le();
200
+ }
201
+ if (fieldFlags & WINDOW_FIELD.WND_SIZE) {
202
+ fields.width = signed32(reader.u32le());
203
+ fields.height = signed32(reader.u32le());
204
+ }
205
+ if (fieldFlags & WINDOW_FIELD.WND_RECTS) {
206
+ fields.windowRects = readRectangles(reader, reader.u16le());
207
+ }
208
+ if (fieldFlags & WINDOW_FIELD.VIS_OFFSET) {
209
+ fields.visibleOffsetX = signed32(reader.u32le());
210
+ fields.visibleOffsetY = signed32(reader.u32le());
211
+ }
212
+ if (fieldFlags & WINDOW_FIELD.VISIBILITY) {
213
+ fields.visibilityRects = readRectangles(reader, reader.u16le());
214
+ }
215
+ return fields;
216
+ }
217
+ function isPrimaryWindow(candidate) {
218
+ if (!candidate) return false;
219
+ if (candidate.ownerWindowId) return false;
220
+ if ((candidate.style || 0) & STYLE_CHILD) return false;
221
+ if ((candidate.extendedStyle || 0) & (EX_STYLE_TOOLWINDOW | EX_STYLE_NOACTIVATE)) return false;
222
+ return true;
223
+ }
224
+ function parseRemoteAppWindowOrders(reader) {
225
+ if (reader.remaining < 6) throw new Error("RDP RemoteApp orders update is truncated.");
226
+ reader.u16le();
227
+ const numberOrders = reader.u16le();
228
+ reader.u16le();
229
+ const events = [];
230
+ for (let index = 0; index < numberOrders && reader.remaining > 0; index++) {
231
+ const orderStart = reader.offset;
232
+ const controlFlags = reader.u8();
233
+ const orderClass = controlFlags & DRAWING_ORDER_CLASS_MASK;
234
+ const orderType = controlFlags >> 2;
235
+ if (orderClass !== DRAWING_ORDER_ALT_SECONDARY || orderType !== ALTSEC_WINDOW) break;
236
+ if (reader.remaining < 6) throw new Error("RDP RemoteApp window-order header is truncated.");
237
+ const orderSize = reader.u16le();
238
+ const fieldFlags = reader.u32le();
239
+ const orderEnd = orderStart + orderSize;
240
+ if (orderSize < 7 || orderEnd > reader.bytes.length) {
241
+ throw new Error("RDP RemoteApp window order has an invalid size.");
242
+ }
243
+ const describesWindow = Boolean(fieldFlags & WINDOW_ORDER.TYPE_WINDOW);
244
+ const isIconOrder = Boolean(fieldFlags & (WINDOW_ORDER.ICON | WINDOW_ORDER.CACHED_ICON));
245
+ if (describesWindow && !isIconOrder && orderEnd - reader.offset >= 4) {
246
+ const windowId = reader.u32le();
247
+ let fields = {};
248
+ try {
249
+ fields = parseWindowFields(reader, fieldFlags);
250
+ } catch (error) {
251
+ console.warn("[RDP] Dropped an unreadable RemoteApp window order", {
252
+ windowId,
253
+ fieldFlags: `0x${(fieldFlags >>> 0).toString(16)}`,
254
+ error: error instanceof Error ? error.message : String(error)
255
+ });
256
+ }
257
+ let type = "update";
258
+ if (fieldFlags & WINDOW_ORDER.STATE_DELETED) type = "deleted";
259
+ else if (fieldFlags & WINDOW_ORDER.STATE_NEW) type = "new";
260
+ events.push({ type, windowId, fieldFlags, ...fields });
261
+ }
262
+ reader.offset = orderEnd;
263
+ if (reader.offset <= orderStart) break;
264
+ }
265
+ return events;
266
+ }
267
+ function parseRailPdus(bytes) {
268
+ const reader = new Reader(bytes);
269
+ const messages = [];
270
+ while (reader.remaining >= 4) {
271
+ const orderType = reader.u16le();
272
+ const orderLength = reader.u16le();
273
+ if (orderLength < 4 || orderLength - 4 > reader.remaining) {
274
+ throw new Error("RDP RemoteApp channel delivered a malformed PDU.");
275
+ }
276
+ const body = new Reader(reader.raw(orderLength - 4));
277
+ if (orderType === RAIL_ORDER.HANDSHAKE && body.remaining >= 4) {
278
+ messages.push({ type: "handshake", buildNumber: body.u32le() });
279
+ continue;
280
+ }
281
+ if (orderType === RAIL_ORDER.HANDSHAKE_EX && body.remaining >= 8) {
282
+ messages.push({ type: "handshake", buildNumber: body.u32le(), flags: body.u32le(), extended: true });
283
+ continue;
284
+ }
285
+ if (orderType === RAIL_ORDER.EXEC_RESULT && body.remaining >= 12) {
286
+ const flags = body.u16le();
287
+ const result = body.u16le();
288
+ const rawResult = body.u32le();
289
+ body.u16le();
290
+ const nameLength = body.u16le();
291
+ const program = decodeUtf16(body.raw(Math.min(nameLength, body.remaining)));
292
+ messages.push({ type: "execute-result", flags, result, rawResult, program });
293
+ continue;
294
+ }
295
+ messages.push({ type: "unknown", orderType, body: body.rest().slice() });
296
+ }
297
+ return messages;
298
+ }
299
+ class RailChannel {
300
+ application;
301
+ width;
302
+ height;
303
+ send;
304
+ onReady;
305
+ onResult;
306
+ started;
307
+ constructor({ application, width, height, send, onReady, onResult }) {
308
+ this.application = application;
309
+ this.width = width;
310
+ this.height = height;
311
+ this.send = send;
312
+ this.onReady = onReady;
313
+ this.onResult = onResult;
314
+ this.started = false;
315
+ }
316
+ receive(bytes) {
317
+ for (const message of parseRailPdus(bytes)) {
318
+ if (message.type === "handshake") {
319
+ if (this.started) continue;
320
+ this.started = true;
321
+ this.send(railHandshake(CLIENT_BUILD));
322
+ this.send(railClientStatus());
323
+ for (const systemParameter of railSystemParameters(this.width, this.height)) {
324
+ this.send(systemParameter);
325
+ }
326
+ this.send(railExecute(this.application));
327
+ this.onReady?.(message);
328
+ continue;
329
+ }
330
+ if (message.type === "execute-result") {
331
+ this.onResult?.({
332
+ ...message,
333
+ ok: message.result === 0,
334
+ message: RAIL_EXEC_RESULT[message.result] || `The RemoteApp host returned launch result 0x${message.result.toString(16).padStart(4, "0")}.`
335
+ });
336
+ }
337
+ }
338
+ }
339
+ /** Republish the client's work area, which is what maximize resizes into. */
340
+ setWorkArea(width, height) {
341
+ if (!this.started || width <= 0 || height <= 0) return false;
342
+ if (width === this.width && height === this.height) return false;
343
+ this.width = width;
344
+ this.height = height;
345
+ this.send(railWorkArea(width, height));
346
+ return true;
347
+ }
348
+ activate(windowId) {
349
+ if (!this.started) return false;
350
+ this.send(railActivate(windowId, true));
351
+ return true;
352
+ }
353
+ sysCommand(windowId, command) {
354
+ if (!this.started) return false;
355
+ this.send(railSysCommand(windowId, command));
356
+ return true;
357
+ }
358
+ moveWindow(windowId, rectangle) {
359
+ if (!this.started) return false;
360
+ this.send(railWindowMove(windowId, rectangle));
361
+ return true;
362
+ }
363
+ }
364
+ export {
365
+ RAIL_EXEC_RESULT,
366
+ RAIL_ORDER,
367
+ RailChannel,
368
+ SHOW_STATE,
369
+ SYS_COMMAND,
370
+ WINDOW_ORDER,
371
+ isPrimaryWindow,
372
+ parseRailPdus,
373
+ parseRemoteAppWindowOrders,
374
+ railActivate,
375
+ railClientStatus,
376
+ railExecute,
377
+ railHandshake,
378
+ railSysCommand,
379
+ railSystemParameters,
380
+ railWindowMove,
381
+ railWorkArea
382
+ };
383
+ //# sourceMappingURL=rail.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/protocols/rdp/rail.ts"],
4
+ "sourcesContent": ["// Remote Applications Integrated Locally (RAIL), MS-RDPERP.\n//\n// This module owns the RAIL static virtual-channel messages. Window pixels\n// still use the ordinary RDP graphics path; RAIL supplies the session mode,\n// application launch request, and window lifecycle metadata around them.\n\nimport { Reader, Writer } from './buffer';\n\nexport const RAIL_ORDER = {\n EXEC: 0x0001,\n ACTIVATE: 0x0002,\n SYSPARAM: 0x0003,\n SYSCOMMAND: 0x0004,\n HANDSHAKE: 0x0005,\n WINDOW_MOVE: 0x0008,\n CLIENT_STATUS: 0x000b,\n EXEC_RESULT: 0x0080,\n HANDSHAKE_EX: 0x0013,\n};\n\nexport const RAIL_EXEC_RESULT = {\n 0x0000: 'The remote application started.',\n 0x0001: 'The RemoteApp host could not load its application monitoring hook.',\n 0x0002: 'The RemoteApp host could not decode the application launch request.',\n 0x0003: 'The requested application is not in the host RemoteApp allowlist.',\n 0x0005: 'The requested remote application was not found.',\n 0x0006: 'The RemoteApp host could not start the requested application.',\n 0x0007: 'The RemoteApp session is locked and cannot start the application.',\n};\n\n/** WM_SYSCOMMAND values a RAIL client may ask the host to apply to a window. */\nexport const SYS_COMMAND = {\n MINIMIZE: 0xf020,\n MAXIMIZE: 0xf030,\n CLOSE: 0xf060,\n RESTORE: 0xf120,\n};\n\n/** SW_* show states reported by a window order's ShowState field. */\nexport const SHOW_STATE = {\n HIDDEN: 0,\n MINIMIZED: 2,\n MAXIMIZED: 3,\n NORMAL: 5,\n};\n\nexport const WINDOW_ORDER = {\n TYPE_WINDOW: 0x01000000,\n STATE_NEW: 0x10000000,\n STATE_DELETED: 0x20000000,\n ICON: 0x40000000,\n CACHED_ICON: 0x80000000,\n};\n\n/**\n * Window Information Order fields (MS-RDPERP 2.2.1.3.1.2.1). A field is present\n * only when its flag is set, and present fields arrive in the fixed order the\n * parser below reads them in, so an unrecognised combination cannot be skipped\n * field by field -- the order's own size is what re-syncs the stream.\n */\nconst WINDOW_FIELD = {\n OWNER: 0x00000002,\n TITLE: 0x00000004,\n STYLE: 0x00000008,\n SHOW: 0x00000010,\n WND_RECTS: 0x00000100,\n WND_SIZE: 0x00000400,\n WND_OFFSET: 0x00000800,\n CLIENT_AREA_OFFSET: 0x00004000,\n CLIENT_DELTA: 0x00008000,\n CLIENT_AREA_SIZE: 0x00010000,\n RP_CONTENT: 0x00020000,\n ROOT_PARENT: 0x00040000,\n VISIBILITY: 0x00080000,\n VIS_OFFSET: 0x00200000,\n};\n\n/** Window styles that mark a window as something other than the app's own. */\nconst STYLE_CHILD = 0x40000000;\nconst EX_STYLE_TOOLWINDOW = 0x00000080;\nconst EX_STYLE_NOACTIVATE = 0x08000000;\n\nconst DRAWING_ORDER_CLASS_MASK = 0x03;\nconst DRAWING_ORDER_ALT_SECONDARY = 0x02;\nconst ALTSEC_WINDOW = 0x0b;\n\nconst CLIENT_BUILD = 2600;\nconst CLIENT_STATUS_SUPPRESS_ICON_ORDERS = 0x00000400;\n\nconst SYSTEM_PARAMETER = {\n MOUSE_BUTTON_SWAP: 0x00000021,\n DRAG_FULL_WINDOWS: 0x00000025,\n WORK_AREA: 0x0000002f,\n HIGH_CONTRAST: 0x00000043,\n KEYBOARD_PREF: 0x00000045,\n KEYBOARD_CUES: 0x0000100b,\n};\n\nfunction utf16Bytes(text: string) {\n const writer = new Writer(text.length * 2);\n writer.utf16le(text);\n return writer.take();\n}\n\nfunction pdu(orderType, body: Uint8Array) {\n const writer = new Writer(body.length + 4);\n writer.u16le(orderType).u16le(body.length + 4).raw(body);\n return writer.take();\n}\n\n/** Window coordinates are signed: an off-screen or bordered window is normal. */\nfunction signed32(value) {\n return value | 0;\n}\n\nexport function railHandshake(buildNumber = CLIENT_BUILD) {\n return pdu(RAIL_ORDER.HANDSHAKE, new Writer(4).u32le(buildNumber).take());\n}\n\nexport function railClientStatus(flags = CLIENT_STATUS_SUPPRESS_ICON_ORDERS) {\n return pdu(RAIL_ORDER.CLIENT_STATUS, new Writer(4).u32le(flags).take());\n}\n\nfunction railBooleanSystemParameter(parameter, enabled: boolean) {\n return pdu(RAIL_ORDER.SYSPARAM, new Writer(5).u32le(parameter).u8(enabled ? 1 : 0).take());\n}\n\nfunction railHighContrast() {\n const body = new Writer(16);\n body.u32le(SYSTEM_PARAMETER.HIGH_CONTRAST);\n body.u32le(0x0000007e); // HCF_AVAILABLE through HCF_HOTKEYAVAILABLE\n body.u32le(2); // empty color scheme including its terminator\n body.u16le(0).u16le(0); // UNICODE_STRING length and terminator\n return pdu(RAIL_ORDER.SYSPARAM, body.take());\n}\n\n/**\n * SPI_SETWORKAREA. This is how a RAIL client tells the host how much room it\n * has, and the host maximizes remote windows into it. Sending it again during\n * the session is what keeps a maximized window matched to the browser window.\n */\nexport function railWorkArea(width: number, height: number) {\n const body = new Writer(12);\n body.u32le(SYSTEM_PARAMETER.WORK_AREA);\n body.u16le(0).u16le(0).u16le(width).u16le(height);\n return pdu(RAIL_ORDER.SYSPARAM, body.take());\n}\n\nexport function railSystemParameters(width: number, height: number) {\n return [\n railHighContrast(),\n railBooleanSystemParameter(SYSTEM_PARAMETER.MOUSE_BUTTON_SWAP, false),\n railBooleanSystemParameter(SYSTEM_PARAMETER.KEYBOARD_PREF, false),\n railBooleanSystemParameter(SYSTEM_PARAMETER.DRAG_FULL_WINDOWS, true),\n railBooleanSystemParameter(SYSTEM_PARAMETER.KEYBOARD_CUES, false),\n railWorkArea(width, height),\n ];\n}\n\n/** TS_RAIL_ORDER_ACTIVATE: give (or take) input focus for one remote window. */\nexport function railActivate(windowId: number, enabled = true) {\n const body = new Writer(5);\n body.u32le(windowId).u8(enabled ? 1 : 0);\n return pdu(RAIL_ORDER.ACTIVATE, body.take());\n}\n\n/** TS_RAIL_ORDER_SYSCOMMAND: minimize, maximize, restore or close a window. */\nexport function railSysCommand(windowId: number, command: string) {\n const body = new Writer(6);\n body.u32le(windowId).u16le(command);\n return pdu(RAIL_ORDER.SYSCOMMAND, body.take());\n}\n\n/**\n * TS_RAIL_ORDER_WINDOWMOVE. A client that draws remote windows itself sends\n * this when the user finishes moving or resizing one; the host then applies\n * the rectangle to the real window. It is the only way to give a remote window\n * an exact size, which is what fitting one to the browser viewport needs.\n */\nexport function railWindowMove(windowId: number, { left, top, right, bottom }) {\n const body = new Writer(12);\n body.u32le(windowId);\n body.u16le(left & 0xffff).u16le(top & 0xffff);\n body.u16le(right & 0xffff).u16le(bottom & 0xffff);\n return pdu(RAIL_ORDER.WINDOW_MOVE, body.take());\n}\n\n/** Build TS_RAIL_ORDER_EXEC. Strings are UTF-16LE and are not terminated. */\nexport function railExecute({ program, workingDir = '', arguments: args = '' }) {\n const exe = utf16Bytes(program || '');\n const cwd = utf16Bytes(workingDir || '');\n const argv = utf16Bytes(args || '');\n\n if (exe.length === 0 || exe.length > 520) {\n throw new Error('RemoteApp program must be between 1 and 260 Unicode characters.');\n }\n if (cwd.length > 520) throw new Error('RemoteApp working directory is too long.');\n if (argv.length > 16000) throw new Error('RemoteApp arguments are too long.');\n\n const body = new Writer(8 + exe.length + cwd.length + argv.length);\n body.u16le(0); // executable, with no environment expansion requested\n body.u16le(exe.length).u16le(cwd.length).u16le(argv.length);\n body.raw(exe).raw(cwd).raw(argv);\n return pdu(RAIL_ORDER.EXEC, body.take());\n}\n\nfunction decodeUtf16(bytes: Uint8Array) {\n let result = '';\n for (let i = 0; i + 1 < bytes.length; i += 2) {\n const codeUnit = bytes[i] | (bytes[i + 1] << 8);\n if (codeUnit === 0) break;\n result += String.fromCharCode(codeUnit);\n }\n return result;\n}\n\nfunction readRectangles(reader: Reader, count: number) {\n const rectangles = [];\n for (let index = 0; index < count && reader.remaining >= 8; index++) {\n const left = reader.u16le();\n const top = reader.u16le();\n const right = reader.u16le();\n const bottom = reader.u16le();\n rectangles.push({ left, top, right, bottom });\n }\n return rectangles;\n}\n\n/**\n * Read the present fields of one Window Information Order. Fields the client\n * has no use for are still read, because every later field's position depends\n * on them.\n */\nfunction parseWindowFields(reader: Reader, fieldFlags) {\n const fields = {};\n\n if (fieldFlags & WINDOW_FIELD.OWNER) fields.ownerWindowId = reader.u32le();\n if (fieldFlags & WINDOW_FIELD.STYLE) {\n fields.style = reader.u32le();\n fields.extendedStyle = reader.u32le();\n }\n if (fieldFlags & WINDOW_FIELD.SHOW) fields.showState = reader.u8();\n if (fieldFlags & WINDOW_FIELD.TITLE) {\n const titleBytes = reader.u16le();\n fields.title = decodeUtf16(reader.raw(Math.min(titleBytes, reader.remaining)));\n }\n if (fieldFlags & WINDOW_FIELD.CLIENT_AREA_OFFSET) {\n fields.clientOffsetX = signed32(reader.u32le());\n fields.clientOffsetY = signed32(reader.u32le());\n }\n if (fieldFlags & WINDOW_FIELD.CLIENT_AREA_SIZE) {\n fields.clientWidth = signed32(reader.u32le());\n fields.clientHeight = signed32(reader.u32le());\n }\n if (fieldFlags & WINDOW_FIELD.RP_CONTENT) reader.u8();\n if (fieldFlags & WINDOW_FIELD.ROOT_PARENT) reader.u32le();\n if (fieldFlags & WINDOW_FIELD.WND_OFFSET) {\n fields.x = signed32(reader.u32le());\n fields.y = signed32(reader.u32le());\n }\n if (fieldFlags & WINDOW_FIELD.CLIENT_DELTA) {\n reader.u32le();\n reader.u32le();\n }\n if (fieldFlags & WINDOW_FIELD.WND_SIZE) {\n fields.width = signed32(reader.u32le());\n fields.height = signed32(reader.u32le());\n }\n if (fieldFlags & WINDOW_FIELD.WND_RECTS) {\n fields.windowRects = readRectangles(reader, reader.u16le());\n }\n if (fieldFlags & WINDOW_FIELD.VIS_OFFSET) {\n fields.visibleOffsetX = signed32(reader.u32le());\n fields.visibleOffsetY = signed32(reader.u32le());\n }\n if (fieldFlags & WINDOW_FIELD.VISIBILITY) {\n fields.visibilityRects = readRectangles(reader, reader.u16le());\n }\n\n return fields;\n}\n\n/**\n * True for a window the session exists to show: not a child, not a tool\n * window, and not one of the never-activated popups a Chromium or Electron\n * application creates for menus, tooltips and drag images.\n */\nexport function isPrimaryWindow(candidate) {\n if (!candidate) return false;\n if (candidate.ownerWindowId) return false;\n if ((candidate.style || 0) & STYLE_CHILD) return false;\n if ((candidate.extendedStyle || 0) & (EX_STYLE_TOOLWINDOW | EX_STYLE_NOACTIVATE)) return false;\n return true;\n}\n\n/**\n * Parse the window lifecycle subset of TS_UPDATE_ORDERS_PDU_DATA.\n *\n * RemoteApp window orders are Alternate Secondary orders and, unlike ordinary\n * drawing orders, carry their total size in every header. That lets the parser\n * read the fields it understands and then seek to the next order, rather than\n * having to understand every icon, notification and desktop order to stay in\n * sync with the stream.\n */\nexport function parseRemoteAppWindowOrders(reader: Reader) {\n if (reader.remaining < 6) throw new Error('RDP RemoteApp orders update is truncated.');\n\n reader.u16le(); // pad2OctetsA\n const numberOrders = reader.u16le();\n reader.u16le(); // pad2OctetsB\n const events = [];\n\n for (let index = 0; index < numberOrders && reader.remaining > 0; index++) {\n const orderStart = reader.offset;\n const controlFlags = reader.u8();\n const orderClass = controlFlags & DRAWING_ORDER_CLASS_MASK;\n const orderType = controlFlags >> 2;\n\n // No primary drawing orders are advertised. If a broken host mixes one in,\n // stop rather than guessing its variable-length encoding and losing sync.\n if (orderClass !== DRAWING_ORDER_ALT_SECONDARY || orderType !== ALTSEC_WINDOW) break;\n if (reader.remaining < 6) throw new Error('RDP RemoteApp window-order header is truncated.');\n\n const orderSize = reader.u16le();\n const fieldFlags = reader.u32le();\n const orderEnd = orderStart + orderSize;\n if (orderSize < 7 || orderEnd > reader.bytes.length) {\n throw new Error('RDP RemoteApp window order has an invalid size.');\n }\n\n const describesWindow = Boolean(fieldFlags & WINDOW_ORDER.TYPE_WINDOW);\n const isIconOrder = Boolean(fieldFlags & (WINDOW_ORDER.ICON | WINDOW_ORDER.CACHED_ICON));\n\n if (describesWindow && !isIconOrder && orderEnd - reader.offset >= 4) {\n const windowId = reader.u32le();\n // A malformed order must not take the session down: the next update\n // repeats the window state anyway, and the seek below keeps the stream\n // aligned either way.\n let fields = {};\n try {\n fields = parseWindowFields(reader, fieldFlags);\n } catch (error) {\n console.warn('[RDP] Dropped an unreadable RemoteApp window order', {\n windowId,\n fieldFlags: `0x${(fieldFlags >>> 0).toString(16)}`,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n let type = 'update';\n if (fieldFlags & WINDOW_ORDER.STATE_DELETED) type = 'deleted';\n else if (fieldFlags & WINDOW_ORDER.STATE_NEW) type = 'new';\n events.push({ type, windowId, fieldFlags, ...fields });\n }\n\n // The order's own size is authoritative, so an order carrying fields this\n // parser skipped still leaves the reader on the next order's first byte.\n reader.offset = orderEnd;\n if (reader.offset <= orderStart) break;\n }\n\n return events;\n}\n\n/** Parse one or more complete RAIL PDUs delivered in a channel message. */\nexport function parseRailPdus(bytes: Uint8Array) {\n const reader = new Reader(bytes);\n const messages = [];\n\n while (reader.remaining >= 4) {\n const orderType = reader.u16le();\n const orderLength = reader.u16le();\n if (orderLength < 4 || orderLength - 4 > reader.remaining) {\n throw new Error('RDP RemoteApp channel delivered a malformed PDU.');\n }\n\n const body = new Reader(reader.raw(orderLength - 4));\n if (orderType === RAIL_ORDER.HANDSHAKE && body.remaining >= 4) {\n messages.push({ type: 'handshake', buildNumber: body.u32le() });\n continue;\n }\n if (orderType === RAIL_ORDER.HANDSHAKE_EX && body.remaining >= 8) {\n messages.push({ type: 'handshake', buildNumber: body.u32le(), flags: body.u32le(), extended: true });\n continue;\n }\n if (orderType === RAIL_ORDER.EXEC_RESULT && body.remaining >= 12) {\n const flags = body.u16le();\n const result = body.u16le();\n const rawResult = body.u32le();\n body.u16le(); // padding\n const nameLength = body.u16le();\n const program = decodeUtf16(body.raw(Math.min(nameLength, body.remaining)));\n messages.push({ type: 'execute-result', flags, result, rawResult, program });\n continue;\n }\n\n messages.push({ type: 'unknown', orderType, body: body.rest().slice() });\n }\n\n return messages;\n}\n\n/**\n * Minimal RAIL endpoint for the browser client. It deliberately suppresses\n * icon orders because the browser currently presents the RemoteApp session in\n * one canvas rather than creating a local OS window per remote window.\n */\nexport class RailChannel {\n private readonly application: RemoteAppLaunch;\n private width: number;\n private height: number;\n private readonly send: (bytes: Uint8Array) => void;\n private readonly onReady: () => void;\n private readonly onResult: (result: RailResult) => void;\n private started: boolean;\n\n constructor({ application, width, height, send, onReady, onResult }) {\n this.application = application;\n this.width = width;\n this.height = height;\n this.send = send;\n this.onReady = onReady;\n this.onResult = onResult;\n this.started = false;\n }\n\n receive(bytes: Uint8Array) {\n for (const message of parseRailPdus(bytes)) {\n if (message.type === 'handshake') {\n if (this.started) continue;\n this.started = true;\n this.send(railHandshake(CLIENT_BUILD));\n this.send(railClientStatus());\n for (const systemParameter of railSystemParameters(this.width, this.height)) {\n this.send(systemParameter);\n }\n this.send(railExecute(this.application));\n this.onReady?.(message);\n continue;\n }\n\n if (message.type === 'execute-result') {\n this.onResult?.({\n ...message,\n ok: message.result === 0,\n message: RAIL_EXEC_RESULT[message.result] ||\n `The RemoteApp host returned launch result 0x${message.result.toString(16).padStart(4, '0')}.`,\n });\n }\n }\n }\n\n /** Republish the client's work area, which is what maximize resizes into. */\n setWorkArea(width: number, height: number) {\n if (!this.started || width <= 0 || height <= 0) return false;\n if (width === this.width && height === this.height) return false;\n this.width = width;\n this.height = height;\n this.send(railWorkArea(width, height));\n return true;\n }\n\n activate(windowId: number) {\n if (!this.started) return false;\n this.send(railActivate(windowId, true));\n return true;\n }\n\n sysCommand(windowId: number, command: string) {\n if (!this.started) return false;\n this.send(railSysCommand(windowId, command));\n return true;\n }\n\n moveWindow(windowId: number, rectangle) {\n if (!this.started) return false;\n this.send(railWindowMove(windowId, rectangle));\n return true;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }