ai-remote 0.4.0 → 0.4.2

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 (166) hide show
  1. package/{src/index.ts → dist/index.d.ts} +0 -1
  2. package/dist/index.js +0 -1
  3. package/dist/protocols/index.d.ts +31 -0
  4. package/dist/protocols/index.js +0 -1
  5. package/dist/protocols/rdp/buffer.d.ts +38 -0
  6. package/dist/protocols/rdp/buffer.js +0 -1
  7. package/dist/protocols/rdp/caps.d.ts +49 -0
  8. package/dist/protocols/rdp/caps.js +0 -1
  9. package/dist/protocols/rdp/cert.d.ts +18 -0
  10. package/dist/protocols/rdp/cert.js +0 -1
  11. package/dist/protocols/rdp/client.d.ts +56 -0
  12. package/dist/protocols/rdp/client.js +0 -1
  13. package/dist/protocols/rdp/cliprdr.d.ts +27 -0
  14. package/dist/protocols/rdp/cliprdr.js +0 -1
  15. package/dist/protocols/rdp/credssp.d.ts +34 -0
  16. package/dist/protocols/rdp/credssp.js +0 -1
  17. package/dist/protocols/rdp/crypto.d.ts +63 -0
  18. package/dist/protocols/rdp/crypto.js +0 -1
  19. package/dist/protocols/rdp/display.d.ts +38 -0
  20. package/dist/protocols/rdp/display.js +0 -1
  21. package/dist/protocols/rdp/gcc.d.ts +23 -0
  22. package/dist/protocols/rdp/gcc.js +0 -1
  23. package/dist/protocols/rdp/keymap.d.ts +9 -0
  24. package/dist/protocols/rdp/keymap.js +0 -1
  25. package/dist/protocols/rdp/mcs.d.ts +40 -0
  26. package/dist/protocols/rdp/mcs.js +0 -1
  27. package/dist/protocols/rdp/ntlm.d.ts +61 -0
  28. package/dist/protocols/rdp/ntlm.js +0 -1
  29. package/dist/protocols/rdp/pdu.d.ts +155 -0
  30. package/dist/protocols/rdp/pdu.js +0 -1
  31. package/dist/protocols/rdp/rail.d.ts +119 -0
  32. package/dist/protocols/rdp/rail.js +0 -1
  33. package/dist/protocols/rdp/rle.d.ts +13 -0
  34. package/dist/protocols/rdp/rle.js +0 -1
  35. package/dist/protocols/rdp/sec.d.ts +59 -0
  36. package/dist/protocols/rdp/sec.js +0 -1
  37. package/dist/protocols/rdp/session.d.ts +62 -0
  38. package/dist/protocols/rdp/session.js +0 -1
  39. package/dist/protocols/rdp/tls.d.ts +18 -0
  40. package/dist/protocols/rdp/tls.js +0 -1
  41. package/dist/protocols/rdp/vchannel.d.ts +28 -0
  42. package/dist/protocols/rdp/vchannel.js +0 -1
  43. package/dist/protocols/rdp/x224.d.ts +40 -0
  44. package/dist/protocols/rdp/x224.js +0 -1
  45. package/dist/protocols/ssh/kex.d.ts +97 -0
  46. package/dist/protocols/ssh/kex.js +0 -1
  47. package/dist/protocols/ssh/messages.d.ts +50 -0
  48. package/dist/protocols/ssh/messages.js +0 -1
  49. package/dist/protocols/ssh/session.d.ts +66 -0
  50. package/dist/protocols/ssh/session.js +0 -1
  51. package/dist/protocols/ssh/terminal.d.ts +46 -0
  52. package/dist/protocols/ssh/terminal.js +0 -1
  53. package/dist/protocols/ssh/transport.d.ts +62 -0
  54. package/dist/protocols/ssh/transport.js +0 -1
  55. package/dist/protocols/ssh/wire.d.ts +52 -0
  56. package/dist/protocols/ssh/wire.js +0 -1
  57. package/dist/protocols/types.d.ts +127 -0
  58. package/dist/protocols/types.js +0 -1
  59. package/dist/protocols/vnc/input.d.ts +5 -0
  60. package/dist/protocols/vnc/input.js +0 -1
  61. package/dist/protocols/vnc/session.d.ts +12 -0
  62. package/dist/protocols/vnc/session.js +0 -1
  63. package/dist/shared/connection.d.ts +81 -0
  64. package/dist/shared/connection.js +0 -1
  65. package/dist/shared/device.d.ts +26 -0
  66. package/dist/shared/device.js +0 -1
  67. package/dist/shared/hosts.d.ts +63 -0
  68. package/dist/shared/hosts.js +0 -1
  69. package/dist/shared/icons.d.ts +46 -0
  70. package/dist/shared/icons.js +0 -1
  71. package/dist/shared/protocol.d.ts +28 -0
  72. package/dist/shared/protocol.js +0 -1
  73. package/dist/shared/signals.d.ts +37 -0
  74. package/dist/shared/signals.js +0 -1
  75. package/package.json +10 -11
  76. package/dist/index.js.map +0 -7
  77. package/dist/protocols/index.js.map +0 -7
  78. package/dist/protocols/rdp/buffer.js.map +0 -7
  79. package/dist/protocols/rdp/caps.js.map +0 -7
  80. package/dist/protocols/rdp/cert.js.map +0 -7
  81. package/dist/protocols/rdp/client.js.map +0 -7
  82. package/dist/protocols/rdp/cliprdr.js.map +0 -7
  83. package/dist/protocols/rdp/credssp.js.map +0 -7
  84. package/dist/protocols/rdp/crypto.js.map +0 -7
  85. package/dist/protocols/rdp/display.js.map +0 -7
  86. package/dist/protocols/rdp/gcc.js.map +0 -7
  87. package/dist/protocols/rdp/keymap.js.map +0 -7
  88. package/dist/protocols/rdp/mcs.js.map +0 -7
  89. package/dist/protocols/rdp/ntlm.js.map +0 -7
  90. package/dist/protocols/rdp/pdu.js.map +0 -7
  91. package/dist/protocols/rdp/rail.js.map +0 -7
  92. package/dist/protocols/rdp/rle.js.map +0 -7
  93. package/dist/protocols/rdp/sec.js.map +0 -7
  94. package/dist/protocols/rdp/session.js.map +0 -7
  95. package/dist/protocols/rdp/tls.js.map +0 -7
  96. package/dist/protocols/rdp/vchannel.js.map +0 -7
  97. package/dist/protocols/rdp/x224.js.map +0 -7
  98. package/dist/protocols/ssh/kex.js.map +0 -7
  99. package/dist/protocols/ssh/messages.js.map +0 -7
  100. package/dist/protocols/ssh/session.js.map +0 -7
  101. package/dist/protocols/ssh/terminal.js.map +0 -7
  102. package/dist/protocols/ssh/transport.js.map +0 -7
  103. package/dist/protocols/ssh/wire.js.map +0 -7
  104. package/dist/protocols/types.js.map +0 -7
  105. package/dist/protocols/vnc/input.js.map +0 -7
  106. package/dist/protocols/vnc/session.js.map +0 -7
  107. package/dist/shared/connection.js.map +0 -7
  108. package/dist/shared/device.js.map +0 -7
  109. package/dist/shared/hosts.js.map +0 -7
  110. package/dist/shared/icons.js.map +0 -7
  111. package/dist/shared/protocol.js.map +0 -7
  112. package/dist/shared/signals.js.map +0 -7
  113. package/src/cli/cli.ts +0 -462
  114. package/src/cli/daemon.ts +0 -306
  115. package/src/cli/framebuffer.ts +0 -115
  116. package/src/cli/generated/viewer-bundle.ts +0 -5
  117. package/src/cli/ipc.ts +0 -78
  118. package/src/cli/native/window.swift +0 -151
  119. package/src/cli/paths.ts +0 -28
  120. package/src/cli/png.ts +0 -106
  121. package/src/cli/session.ts +0 -263
  122. package/src/cli/shell.ts +0 -184
  123. package/src/cli/transport.ts +0 -86
  124. package/src/cli/viewer-client/assets.d.ts +0 -4
  125. package/src/cli/viewer-client/main.ts +0 -323
  126. package/src/cli/viewer-page.ts +0 -138
  127. package/src/cli/viewer.ts +0 -296
  128. package/src/cli/window.ts +0 -140
  129. package/src/cli/wsserver.ts +0 -144
  130. package/src/protocols/index.ts +0 -72
  131. package/src/protocols/rdp/buffer.ts +0 -204
  132. package/src/protocols/rdp/caps.ts +0 -304
  133. package/src/protocols/rdp/cert.ts +0 -190
  134. package/src/protocols/rdp/client.ts +0 -1371
  135. package/src/protocols/rdp/cliprdr.ts +0 -344
  136. package/src/protocols/rdp/credssp.ts +0 -319
  137. package/src/protocols/rdp/crypto.ts +0 -416
  138. package/src/protocols/rdp/display.ts +0 -750
  139. package/src/protocols/rdp/gcc.ts +0 -162
  140. package/src/protocols/rdp/keymap.ts +0 -68
  141. package/src/protocols/rdp/mcs.ts +0 -283
  142. package/src/protocols/rdp/ntlm.ts +0 -380
  143. package/src/protocols/rdp/pdu.ts +0 -497
  144. package/src/protocols/rdp/rail.ts +0 -480
  145. package/src/protocols/rdp/rle.ts +0 -343
  146. package/src/protocols/rdp/sec.ts +0 -184
  147. package/src/protocols/rdp/session.ts +0 -393
  148. package/src/protocols/rdp/tls.ts +0 -452
  149. package/src/protocols/rdp/vchannel.ts +0 -89
  150. package/src/protocols/rdp/x224.ts +0 -139
  151. package/src/protocols/ssh/kex.ts +0 -227
  152. package/src/protocols/ssh/messages.ts +0 -54
  153. package/src/protocols/ssh/session.ts +0 -879
  154. package/src/protocols/ssh/terminal.ts +0 -242
  155. package/src/protocols/ssh/transport.ts +0 -745
  156. package/src/protocols/ssh/wire.ts +0 -220
  157. package/src/protocols/types.ts +0 -146
  158. package/src/protocols/vnc/input.ts +0 -13
  159. package/src/protocols/vnc/novnc.d.ts +0 -75
  160. package/src/protocols/vnc/session.ts +0 -367
  161. package/src/shared/connection.ts +0 -206
  162. package/src/shared/device.ts +0 -28
  163. package/src/shared/hosts.ts +0 -240
  164. package/src/shared/icons.ts +0 -49
  165. package/src/shared/protocol.ts +0 -55
  166. package/src/shared/signals.ts +0 -67
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/protocols/rdp/credssp.ts"],
4
- "sourcesContent": ["// CredSSP (MS-CSSP): the protocol behind RDP's Network Level Authentication.\n//\n// It runs inside the TLS channel and does three things in order: authenticate\n// with NTLM, prove to the host that the TLS certificate we were shown is the\n// one the host actually holds, and only then hand over the credentials. The\n// second step is why this gateway needs its own TLS client -- the proof is\n// computed over the host certificate's public key, which no runtime here\n// exposes for a TLS session it established on our behalf.\n\nimport { concatBytes } from './buffer';\nimport { NtlmSealer, authenticateMessage, negotiateMessage, parseChallengeMessage } from './ntlm';\n\nconst CREDSSP_VERSION = 6;\n\n// MS-CSSP 3.1.5: from version 5 the binding is a hash over a client nonce and\n// the public key, rather than the bare public key.\nconst CLIENT_TO_SERVER_MAGIC = 'CredSSP Client-To-Server Binding Hash\\0';\nconst SERVER_TO_CLIENT_MAGIC = 'CredSSP Server-To-Client Binding Hash\\0';\n\nconst NT_STATUS_MESSAGES = {\n 0xc000006d: 'The host rejected the username or password (STATUS_LOGON_FAILURE).',\n 0xc000006e: 'The account is not allowed to sign in right now (STATUS_ACCOUNT_RESTRICTION).',\n 0xc000006f: 'The account is outside its permitted logon hours.',\n 0xc0000070: 'The account is not allowed to sign in from this machine (STATUS_INVALID_WORKSTATION).',\n 0xc0000071: 'The account password has expired.',\n 0xc0000072: 'The account is disabled.',\n 0xc000015b: 'The account is not allowed the Remote Desktop logon type -- add it to the Remote Desktop Users group.',\n 0xc0000193: 'The account has expired.',\n 0xc0000224: 'The account must change its password before signing in.',\n 0xc0000234: 'The account is locked out.',\n 0x8009030c: 'The host denied the logon (SEC_E_LOGON_DENIED).',\n 0x80090308: 'The host rejected the authentication token (SEC_E_INVALID_TOKEN).',\n 0x80090302: 'The host rejected the CredSSP exchange (SEC_E_UNSUPPORTED_FUNCTION) -- usually a public-key binding mismatch.',\n};\n\n// --- DER --------------------------------------------------------------------\n\nfunction derLength(length: number) {\n if (length < 0x80) return new Uint8Array([length]);\n if (length <= 0xff) return new Uint8Array([0x81, length]);\n if (length <= 0xffff) return new Uint8Array([0x82, length >> 8, length & 0xff]);\n return new Uint8Array([0x83, (length >> 16) & 0xff, (length >> 8) & 0xff, length & 0xff]);\n}\n\nconst derTlv = (tag, content: Uint8Array) => concatBytes(new Uint8Array([tag]), derLength(content.length), content);\nconst derSequence = (...parts) => derTlv(0x30, concatBytes(...parts));\nconst derOctetString = (bytes: Uint8Array) => derTlv(0x04, bytes);\nconst derContext = (index, content: Uint8Array) => derTlv(0xa0 | index, content);\n\nfunction derInteger(value) {\n const bytes = [];\n let remaining = value;\n do {\n bytes.unshift(remaining & 0xff);\n remaining >>>= 8;\n } while (remaining > 0);\n // A leading bit of 1 would read as negative.\n if (bytes[0] & 0x80) bytes.unshift(0x00);\n return derTlv(0x02, new Uint8Array(bytes));\n}\n\nfunction derRead(bytes: Uint8Array, offset: number) {\n const tag = bytes[offset];\n let cursor = offset + 1;\n let length = bytes[cursor++];\n\n if (length & 0x80) {\n const count = length & 0x7f;\n length = 0;\n for (let i = 0; i < count; i++) length = (length << 8) | bytes[cursor++];\n }\n\n return { tag, content: bytes.subarray(cursor, cursor + length), end: cursor + length };\n}\n\n/** Total encoded length of the DER element starting at `offset`, or 0 if partial. */\nfunction derElementLength(bytes: Uint8Array, offset = 0) {\n if (bytes.length - offset < 2) return 0;\n let cursor = offset + 1;\n let length = bytes[cursor++];\n\n if (length & 0x80) {\n const count = length & 0x7f;\n if (bytes.length - cursor < count) return 0;\n length = 0;\n for (let i = 0; i < count; i++) length = (length << 8) | bytes[cursor++];\n }\n\n const total = cursor - offset + length;\n return bytes.length - offset < total ? 0 : total;\n}\n\nfunction encodeTsRequest({ version, negoToken, authInfo, pubKeyAuth, clientNonce }) {\n const parts = [derContext(0, derInteger(version))];\n\n if (negoToken) {\n parts.push(derContext(1, derSequence(derSequence(derContext(0, derOctetString(negoToken))))));\n }\n if (authInfo) parts.push(derContext(2, derOctetString(authInfo)));\n if (pubKeyAuth) parts.push(derContext(3, derOctetString(pubKeyAuth)));\n if (clientNonce) parts.push(derContext(5, derOctetString(clientNonce)));\n\n return derSequence(...parts);\n}\n\nfunction decodeTsRequest(bytes: Uint8Array) {\n const outer = derRead(bytes, 0);\n const result = { version: 0, negoToken: null, authInfo: null, pubKeyAuth: null, errorCode: 0 };\n\n let offset = 0;\n while (offset < outer.content.length) {\n const field = derRead(outer.content, offset);\n offset = field.end;\n const index = field.tag & 0x1f;\n\n if (index === 0) {\n result.version = derRead(field.content, 0).content[0];\n continue;\n }\n if (index === 1) {\n const sequence = derRead(field.content, 0); // SEQUENCE OF\n const item = derRead(sequence.content, 0); // SEQUENCE\n const token = derRead(item.content, 0); // [0] OCTET STRING\n result.negoToken = derRead(token.content, 0).content;\n continue;\n }\n if (index === 2) {\n result.authInfo = derRead(field.content, 0).content;\n continue;\n }\n if (index === 3) {\n result.pubKeyAuth = derRead(field.content, 0).content;\n continue;\n }\n if (index === 4) {\n const value = derRead(field.content, 0).content;\n let code = 0;\n for (const byte of value) code = ((code << 8) | byte) >>> 0;\n result.errorCode = code;\n continue;\n }\n }\n\n return result;\n}\n\n/** TSCredentials wrapping TSPasswordCreds (MS-CSSP 2.2.1.2). */\nfunction encodeCredentials(domain: string, username: string, password: string) {\n const utf16 = (text: string) => {\n const out = new Uint8Array(text.length * 2);\n const view = new DataView(out.buffer);\n for (let i = 0; i < text.length; i++) view.setUint16(i * 2, text.charCodeAt(i), true);\n return out;\n };\n\n const passwordCreds = derSequence(\n derContext(0, derOctetString(utf16(domain))),\n derContext(1, derOctetString(utf16(username))),\n derContext(2, derOctetString(utf16(password)))\n );\n\n return derSequence(\n derContext(0, derInteger(1)), // credType: password\n derContext(1, derOctetString(passwordCreds))\n );\n}\n\nexport class CredSspClient {\n private readonly username: string;\n private readonly domain: string;\n private readonly password: string;\n private readonly serverPublicKey: Uint8Array;\n private readonly send: (bytes: Uint8Array) => void;\n private readonly log: (message: string, detail?: unknown) => void;\n private inbound: Uint8Array;\n private waiters: Array<{ resolve: (bytes: Uint8Array) => void; reject: (error: Error) => void }>;\n\n constructor({ username, domain, password, serverPublicKey, send, log }) {\n this.username = username || '';\n this.domain = domain || '';\n this.password = password || '';\n this.serverPublicKey = serverPublicKey;\n this.send = send;\n this.log = log || (() => {});\n\n this.inbound = new Uint8Array(0);\n this.waiters = [];\n }\n\n /** Feed decrypted TLS application data. */\n receive(bytes: Uint8Array) {\n this.inbound = this.inbound.length === 0 ? bytes : concatBytes(this.inbound, bytes);\n\n // TSRequests are self-delimiting, so several can share one TLS record.\n for (;;) {\n const length = derElementLength(this.inbound);\n if (length === 0) return;\n\n const request = decodeTsRequest(this.inbound.subarray(0, length));\n this.inbound = this.inbound.subarray(length).slice();\n\n const waiter = this.waiters.shift();\n if (waiter) waiter.resolve(request);\n }\n }\n\n #next(timeoutMs = 15000) {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new Error('CredSSP: the host did not answer within 15s')),\n timeoutMs\n );\n this.waiters.push({\n resolve: (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n });\n });\n }\n\n async #bindingHash(magic, nonce) {\n const digest = await crypto.subtle.digest(\n 'SHA-256',\n concatBytes(new TextEncoder().encode(magic), nonce, this.serverPublicKey)\n );\n return new Uint8Array(digest);\n }\n\n async authenticate() {\n const negotiate = negotiateMessage();\n this.send(encodeTsRequest({ version: CREDSSP_VERSION, negoToken: negotiate }));\n this.log('CredSSP', 'sent NTLM NEGOTIATE');\n\n const challengeRequest = await this.#next();\n if (challengeRequest.errorCode) throw new Error(this.#statusMessage(challengeRequest.errorCode));\n if (!challengeRequest.negoToken) throw new Error('CredSSP: the host sent no NTLM challenge');\n\n const challengeBytes = challengeRequest.negoToken.slice();\n const challenge = parseChallengeMessage(challengeBytes);\n const targetName = new TextDecoder('utf-16le').decode(challenge.targetName);\n this.log('CredSSP', `received NTLM CHALLENGE from \"${targetName}\" (host CredSSP version ${challengeRequest.version})`);\n\n if (!this.username) {\n return {\n authenticated: false,\n reachedChallenge: true,\n hostVersion: challengeRequest.version,\n targetName,\n note: 'no credentials supplied, stopping after the challenge',\n };\n }\n\n const { message, keys } = authenticateMessage({\n username: this.username,\n domain: this.domain,\n password: this.password,\n challenge,\n negotiateBytes: negotiate,\n challengeBytes,\n });\n\n const sealer = new NtlmSealer(keys);\n const clientNonce = new Uint8Array(32);\n crypto.getRandomValues(clientNonce);\n\n // Hosts older than CredSSP 5 expect the bare public key instead of a hash.\n const legacy = challengeRequest.version < 5;\n const binding = legacy\n ? this.serverPublicKey\n : await this.#bindingHash(CLIENT_TO_SERVER_MAGIC, clientNonce);\n\n this.send(encodeTsRequest({\n version: CREDSSP_VERSION,\n negoToken: message,\n pubKeyAuth: sealer.seal(binding),\n clientNonce: legacy ? null : clientNonce,\n }));\n this.log('CredSSP', `sent NTLM AUTHENTICATE with the ${legacy ? 'legacy' : 'hashed'} public-key binding`);\n\n const response = await this.#next();\n if (response.errorCode) throw new Error(this.#statusMessage(response.errorCode));\n if (!response.pubKeyAuth) throw new Error('CredSSP: the host returned no public-key confirmation');\n\n const confirmed = sealer.unseal(response.pubKeyAuth);\n const expected = legacy\n ? this.#incrementedPublicKey()\n : await this.#bindingHash(SERVER_TO_CLIENT_MAGIC, clientNonce);\n\n if (confirmed.length !== expected.length || !expected.every((byte, i) => byte === confirmed[i])) {\n throw new Error(\n 'CredSSP: the host public-key confirmation did not match. The TLS session is not the one the host authenticated, which is what this check exists to catch.'\n );\n }\n this.log('CredSSP', 'host confirmed the public-key binding');\n\n this.send(encodeTsRequest({\n version: CREDSSP_VERSION,\n authInfo: sealer.seal(encodeCredentials(this.domain, this.username, this.password)),\n }));\n this.log('CredSSP', 'sent credentials');\n\n return { authenticated: true, hostVersion: challengeRequest.version, targetName };\n }\n\n /** Legacy confirmation is the public key with its first byte incremented. */\n #incrementedPublicKey() {\n const expected = this.serverPublicKey.slice();\n expected[0] = (expected[0] + 1) & 0xff;\n return expected;\n }\n\n #statusMessage(errorCode) {\n return (\n NT_STATUS_MESSAGES[errorCode] ||\n `CredSSP: the host reported error 0x${errorCode.toString(16).padStart(8, '0')}.`\n );\n }\n}\n"],
5
- "mappings": "AASA,SAAS,mBAAmB;AAC5B,SAAS,YAAY,qBAAqB,kBAAkB,6BAA6B;AAEzF,MAAM,kBAAkB;AAIxB,MAAM,yBAAyB;AAC/B,MAAM,yBAAyB;AAE/B,MAAM,qBAAqB;AAAA,EACzB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AACd;AAIA,SAAS,UAAU,QAAgB;AACjC,MAAI,SAAS,IAAM,QAAO,IAAI,WAAW,CAAC,MAAM,CAAC;AACjD,MAAI,UAAU,IAAM,QAAO,IAAI,WAAW,CAAC,KAAM,MAAM,CAAC;AACxD,MAAI,UAAU,MAAQ,QAAO,IAAI,WAAW,CAAC,KAAM,UAAU,GAAG,SAAS,GAAI,CAAC;AAC9E,SAAO,IAAI,WAAW,CAAC,KAAO,UAAU,KAAM,KAAO,UAAU,IAAK,KAAM,SAAS,GAAI,CAAC;AAC1F;AAEA,MAAM,SAAS,CAAC,KAAK,YAAwB,YAAY,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,UAAU,QAAQ,MAAM,GAAG,OAAO;AAClH,MAAM,cAAc,IAAI,UAAU,OAAO,IAAM,YAAY,GAAG,KAAK,CAAC;AACpE,MAAM,iBAAiB,CAAC,UAAsB,OAAO,GAAM,KAAK;AAChE,MAAM,aAAa,CAAC,OAAO,YAAwB,OAAO,MAAO,OAAO,OAAO;AAE/E,SAAS,WAAW,OAAO;AACzB,QAAM,QAAQ,CAAC;AACf,MAAI,YAAY;AAChB,KAAG;AACD,UAAM,QAAQ,YAAY,GAAI;AAC9B,mBAAe;AAAA,EACjB,SAAS,YAAY;AAErB,MAAI,MAAM,CAAC,IAAI,IAAM,OAAM,QAAQ,CAAI;AACvC,SAAO,OAAO,GAAM,IAAI,WAAW,KAAK,CAAC;AAC3C;AAEA,SAAS,QAAQ,OAAmB,QAAgB;AAClD,QAAM,MAAM,MAAM,MAAM;AACxB,MAAI,SAAS,SAAS;AACtB,MAAI,SAAS,MAAM,QAAQ;AAE3B,MAAI,SAAS,KAAM;AACjB,UAAM,QAAQ,SAAS;AACvB,aAAS;AACT,aAAS,IAAI,GAAG,IAAI,OAAO,IAAK,UAAU,UAAU,IAAK,MAAM,QAAQ;AAAA,EACzE;AAEA,SAAO,EAAE,KAAK,SAAS,MAAM,SAAS,QAAQ,SAAS,MAAM,GAAG,KAAK,SAAS,OAAO;AACvF;AAGA,SAAS,iBAAiB,OAAmB,SAAS,GAAG;AACvD,MAAI,MAAM,SAAS,SAAS,EAAG,QAAO;AACtC,MAAI,SAAS,SAAS;AACtB,MAAI,SAAS,MAAM,QAAQ;AAE3B,MAAI,SAAS,KAAM;AACjB,UAAM,QAAQ,SAAS;AACvB,QAAI,MAAM,SAAS,SAAS,MAAO,QAAO;AAC1C,aAAS;AACT,aAAS,IAAI,GAAG,IAAI,OAAO,IAAK,UAAU,UAAU,IAAK,MAAM,QAAQ;AAAA,EACzE;AAEA,QAAM,QAAQ,SAAS,SAAS;AAChC,SAAO,MAAM,SAAS,SAAS,QAAQ,IAAI;AAC7C;AAEA,SAAS,gBAAgB,EAAE,SAAS,WAAW,UAAU,YAAY,YAAY,GAAG;AAClF,QAAM,QAAQ,CAAC,WAAW,GAAG,WAAW,OAAO,CAAC,CAAC;AAEjD,MAAI,WAAW;AACb,UAAM,KAAK,WAAW,GAAG,YAAY,YAAY,WAAW,GAAG,eAAe,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAAA,EAC9F;AACA,MAAI,SAAU,OAAM,KAAK,WAAW,GAAG,eAAe,QAAQ,CAAC,CAAC;AAChE,MAAI,WAAY,OAAM,KAAK,WAAW,GAAG,eAAe,UAAU,CAAC,CAAC;AACpE,MAAI,YAAa,OAAM,KAAK,WAAW,GAAG,eAAe,WAAW,CAAC,CAAC;AAEtE,SAAO,YAAY,GAAG,KAAK;AAC7B;AAEA,SAAS,gBAAgB,OAAmB;AAC1C,QAAM,QAAQ,QAAQ,OAAO,CAAC;AAC9B,QAAM,SAAS,EAAE,SAAS,GAAG,WAAW,MAAM,UAAU,MAAM,YAAY,MAAM,WAAW,EAAE;AAE7F,MAAI,SAAS;AACb,SAAO,SAAS,MAAM,QAAQ,QAAQ;AACpC,UAAM,QAAQ,QAAQ,MAAM,SAAS,MAAM;AAC3C,aAAS,MAAM;AACf,UAAM,QAAQ,MAAM,MAAM;AAE1B,QAAI,UAAU,GAAG;AACf,aAAO,UAAU,QAAQ,MAAM,SAAS,CAAC,EAAE,QAAQ,CAAC;AACpD;AAAA,IACF;AACA,QAAI,UAAU,GAAG;AACf,YAAM,WAAW,QAAQ,MAAM,SAAS,CAAC;AACzC,YAAM,OAAO,QAAQ,SAAS,SAAS,CAAC;AACxC,YAAM,QAAQ,QAAQ,KAAK,SAAS,CAAC;AACrC,aAAO,YAAY,QAAQ,MAAM,SAAS,CAAC,EAAE;AAC7C;AAAA,IACF;AACA,QAAI,UAAU,GAAG;AACf,aAAO,WAAW,QAAQ,MAAM,SAAS,CAAC,EAAE;AAC5C;AAAA,IACF;AACA,QAAI,UAAU,GAAG;AACf,aAAO,aAAa,QAAQ,MAAM,SAAS,CAAC,EAAE;AAC9C;AAAA,IACF;AACA,QAAI,UAAU,GAAG;AACf,YAAM,QAAQ,QAAQ,MAAM,SAAS,CAAC,EAAE;AACxC,UAAI,OAAO;AACX,iBAAW,QAAQ,MAAO,SAAS,QAAQ,IAAK,UAAU;AAC1D,aAAO,YAAY;AACnB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAGA,SAAS,kBAAkB,QAAgB,UAAkB,UAAkB;AAC7E,QAAM,QAAQ,CAAC,SAAiB;AAC9B,UAAM,MAAM,IAAI,WAAW,KAAK,SAAS,CAAC;AAC1C,UAAM,OAAO,IAAI,SAAS,IAAI,MAAM;AACpC,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,IAAK,MAAK,UAAU,IAAI,GAAG,KAAK,WAAW,CAAC,GAAG,IAAI;AACpF,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB;AAAA,IACpB,WAAW,GAAG,eAAe,MAAM,MAAM,CAAC,CAAC;AAAA,IAC3C,WAAW,GAAG,eAAe,MAAM,QAAQ,CAAC,CAAC;AAAA,IAC7C,WAAW,GAAG,eAAe,MAAM,QAAQ,CAAC,CAAC;AAAA,EAC/C;AAEA,SAAO;AAAA,IACL,WAAW,GAAG,WAAW,CAAC,CAAC;AAAA;AAAA,IAC3B,WAAW,GAAG,eAAe,aAAa,CAAC;AAAA,EAC7C;AACF;AAEO,MAAM,cAAc;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA;AAAA,EAER,YAAY,EAAE,UAAU,QAAQ,UAAU,iBAAiB,MAAM,IAAI,GAAG;AACtE,SAAK,WAAW,YAAY;AAC5B,SAAK,SAAS,UAAU;AACxB,SAAK,WAAW,YAAY;AAC5B,SAAK,kBAAkB;AACvB,SAAK,OAAO;AACZ,SAAK,MAAM,QAAQ,MAAM;AAAA,IAAC;AAE1B,SAAK,UAAU,IAAI,WAAW,CAAC;AAC/B,SAAK,UAAU,CAAC;AAAA,EAClB;AAAA;AAAA,EAGA,QAAQ,OAAmB;AACzB,SAAK,UAAU,KAAK,QAAQ,WAAW,IAAI,QAAQ,YAAY,KAAK,SAAS,KAAK;AAGlF,eAAS;AACP,YAAM,SAAS,iBAAiB,KAAK,OAAO;AAC5C,UAAI,WAAW,EAAG;AAElB,YAAM,UAAU,gBAAgB,KAAK,QAAQ,SAAS,GAAG,MAAM,CAAC;AAChE,WAAK,UAAU,KAAK,QAAQ,SAAS,MAAM,EAAE,MAAM;AAEnD,YAAM,SAAS,KAAK,QAAQ,MAAM;AAClC,UAAI,OAAQ,QAAO,QAAQ,OAAO;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,MAAO;AACvB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,QAAQ;AAAA,QACZ,MAAM,OAAO,IAAI,MAAM,6CAA6C,CAAC;AAAA,QACrE;AAAA,MACF;AACA,WAAK,QAAQ,KAAK;AAAA,QAChB,SAAS,CAAC,UAAU;AAClB,uBAAa,KAAK;AAClB,kBAAQ,KAAK;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aAAa,OAAO,OAAO;AAC/B,UAAM,SAAS,MAAM,OAAO,OAAO;AAAA,MACjC;AAAA,MACA,YAAY,IAAI,YAAY,EAAE,OAAO,KAAK,GAAG,OAAO,KAAK,eAAe;AAAA,IAC1E;AACA,WAAO,IAAI,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEA,MAAM,eAAe;AACnB,UAAM,YAAY,iBAAiB;AACnC,SAAK,KAAK,gBAAgB,EAAE,SAAS,iBAAiB,WAAW,UAAU,CAAC,CAAC;AAC7E,SAAK,IAAI,WAAW,qBAAqB;AAEzC,UAAM,mBAAmB,MAAM,KAAK,MAAM;AAC1C,QAAI,iBAAiB,UAAW,OAAM,IAAI,MAAM,KAAK,eAAe,iBAAiB,SAAS,CAAC;AAC/F,QAAI,CAAC,iBAAiB,UAAW,OAAM,IAAI,MAAM,0CAA0C;AAE3F,UAAM,iBAAiB,iBAAiB,UAAU,MAAM;AACxD,UAAM,YAAY,sBAAsB,cAAc;AACtD,UAAM,aAAa,IAAI,YAAY,UAAU,EAAE,OAAO,UAAU,UAAU;AAC1E,SAAK,IAAI,WAAW,iCAAiC,UAAU,2BAA2B,iBAAiB,OAAO,GAAG;AAErH,QAAI,CAAC,KAAK,UAAU;AAClB,aAAO;AAAA,QACL,eAAe;AAAA,QACf,kBAAkB;AAAA,QAClB,aAAa,iBAAiB;AAAA,QAC9B;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,KAAK,IAAI,oBAAoB;AAAA,MAC5C,UAAU,KAAK;AAAA,MACf,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf;AAAA,MACA,gBAAgB;AAAA,MAChB;AAAA,IACF,CAAC;AAED,UAAM,SAAS,IAAI,WAAW,IAAI;AAClC,UAAM,cAAc,IAAI,WAAW,EAAE;AACrC,WAAO,gBAAgB,WAAW;AAGlC,UAAM,SAAS,iBAAiB,UAAU;AAC1C,UAAM,UAAU,SACZ,KAAK,kBACL,MAAM,KAAK,aAAa,wBAAwB,WAAW;AAE/D,SAAK,KAAK,gBAAgB;AAAA,MACxB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY,OAAO,KAAK,OAAO;AAAA,MAC/B,aAAa,SAAS,OAAO;AAAA,IAC/B,CAAC,CAAC;AACF,SAAK,IAAI,WAAW,mCAAmC,SAAS,WAAW,QAAQ,qBAAqB;AAExG,UAAM,WAAW,MAAM,KAAK,MAAM;AAClC,QAAI,SAAS,UAAW,OAAM,IAAI,MAAM,KAAK,eAAe,SAAS,SAAS,CAAC;AAC/E,QAAI,CAAC,SAAS,WAAY,OAAM,IAAI,MAAM,uDAAuD;AAEjG,UAAM,YAAY,OAAO,OAAO,SAAS,UAAU;AACnD,UAAM,WAAW,SACb,KAAK,sBAAsB,IAC3B,MAAM,KAAK,aAAa,wBAAwB,WAAW;AAE/D,QAAI,UAAU,WAAW,SAAS,UAAU,CAAC,SAAS,MAAM,CAAC,MAAM,MAAM,SAAS,UAAU,CAAC,CAAC,GAAG;AAC/F,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,SAAK,IAAI,WAAW,uCAAuC;AAE3D,SAAK,KAAK,gBAAgB;AAAA,MACxB,SAAS;AAAA,MACT,UAAU,OAAO,KAAK,kBAAkB,KAAK,QAAQ,KAAK,UAAU,KAAK,QAAQ,CAAC;AAAA,IACpF,CAAC,CAAC;AACF,SAAK,IAAI,WAAW,kBAAkB;AAEtC,WAAO,EAAE,eAAe,MAAM,aAAa,iBAAiB,SAAS,WAAW;AAAA,EAClF;AAAA;AAAA,EAGA,wBAAwB;AACtB,UAAM,WAAW,KAAK,gBAAgB,MAAM;AAC5C,aAAS,CAAC,IAAK,SAAS,CAAC,IAAI,IAAK;AAClC,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,WAAW;AACxB,WACE,mBAAmB,SAAS,KAC5B,sCAAsC,UAAU,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,EAEjF;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/protocols/rdp/crypto.ts"],
4
- "sourcesContent": ["// ---------------------------------------------------------------------------\n// Crypto primitives for the RDP Standard Security layer (MS-RDPBCGR 5.3).\n//\n// RDP's own encryption layer predates anything WebCrypto exposes: it needs\n// synchronous MD5 and SHA-1 for a per-PDU MAC, RC4 stream state that persists\n// across PDUs, and textbook RSA against the key the server hands out in its\n// certificate. All of it is small, so it lives here rather than as a\n// dependency, and every function is deliberately synchronous -- the packet path\n// runs inside WebSocket message handlers.\n// ---------------------------------------------------------------------------\n\n// --- MD5 -------------------------------------------------------------------\n\nconst MD5_SHIFTS = [\n 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,\n 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,\n 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,\n 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,\n];\n\n// K[i] = floor(abs(sin(i + 1)) * 2^32) -- generated so the table cannot be mistyped.\nconst MD5_K = new Uint32Array(\n Array.from({ length: 64 }, (_, i) => Math.floor(Math.abs(Math.sin(i + 1)) * 4294967296))\n);\n\nfunction rotl32(value: Uint8Array, count: number) {\n return (value << count) | (value >>> (32 - count));\n}\n\nexport function md5(message: Uint8Array) {\n const bitLength = message.length * 8;\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 // Length is appended as a 64-bit little-endian bit count.\n const tail = new DataView(padded.buffer, padded.byteLength - 8, 8);\n tail.setUint32(0, bitLength >>> 0, true);\n tail.setUint32(4, Math.floor(bitLength / 4294967296), true);\n\n let a0 = 0x67452301, b0 = 0xefcdab89, c0 = 0x98badcfe, d0 = 0x10325476;\n const words = new Uint32Array(16);\n const view = new DataView(padded.buffer, padded.byteOffset, padded.byteLength);\n\n for (let block = 0; block < blockCount; block++) {\n for (let i = 0; i < 16; i++) words[i] = view.getUint32(block * 64 + i * 4, true);\n\n let a = a0, b = b0, c = c0, d = d0;\n for (let i = 0; i < 64; i++) {\n let f;\n let g;\n if (i < 16) {\n f = (b & c) | (~b & d);\n g = i;\n } else if (i < 32) {\n f = (d & b) | (~d & c);\n g = (5 * i + 1) % 16;\n } else if (i < 48) {\n f = b ^ c ^ d;\n g = (3 * i + 5) % 16;\n } else {\n f = c ^ (b | ~d);\n g = (7 * i) % 16;\n }\n\n const temp = d;\n d = c;\n c = b;\n const sum = (a + f + MD5_K[i] + words[g]) | 0;\n b = (b + rotl32(sum, MD5_SHIFTS[i])) | 0;\n a = temp;\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// --- SHA-1 -----------------------------------------------------------------\n\nexport function sha1(message: Uint8Array) {\n const bitLength = message.length * 8;\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 tail = new DataView(padded.buffer, padded.byteLength - 8, 8);\n tail.setUint32(0, Math.floor(bitLength / 4294967296));\n tail.setUint32(4, bitLength >>> 0);\n\n let h0 = 0x67452301, h1 = 0xefcdab89, h2 = 0x98badcfe, h3 = 0x10325476, h4 = 0xc3d2e1f0;\n const words = new Uint32Array(80);\n const view = new DataView(padded.buffer, padded.byteOffset, padded.byteLength);\n\n for (let block = 0; block < blockCount; block++) {\n for (let i = 0; i < 16; i++) words[i] = view.getUint32(block * 64 + i * 4);\n for (let i = 16; i < 80; i++) {\n words[i] = rotl32(words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16], 1);\n }\n\n let a = h0, b = h1, c = h2, d = h3, e = h4;\n for (let i = 0; i < 80; i++) {\n let f;\n let k;\n if (i < 20) {\n f = (b & c) | (~b & d);\n k = 0x5a827999;\n } else if (i < 40) {\n f = b ^ c ^ d;\n k = 0x6ed9eba1;\n } else if (i < 60) {\n f = (b & c) | (b & d) | (c & d);\n k = 0x8f1bbcdc;\n } else {\n f = b ^ c ^ d;\n k = 0xca62c1d6;\n }\n\n const temp = (rotl32(a, 5) + f + e + k + words[i]) | 0;\n e = d;\n d = c;\n c = rotl32(b, 30);\n b = a;\n a = temp;\n }\n\n h0 = (h0 + a) | 0;\n h1 = (h1 + b) | 0;\n h2 = (h2 + c) | 0;\n h3 = (h3 + d) | 0;\n h4 = (h4 + e) | 0;\n }\n\n const digest = new Uint8Array(20);\n const out = new DataView(digest.buffer);\n [h0, h1, h2, h3, h4].forEach((word, i) => out.setUint32(i * 4, word >>> 0));\n return digest;\n}\n\n// --- RC4 -------------------------------------------------------------------\n\n/** RC4 keystream position. RDP re-keys every 4096 PDUs, so this is mutable. */\nexport interface Rc4State {\n s: Uint8Array;\n i: number;\n j: number;\n}\n\n/** The five values MS-RDPBCGR 5.3.5 derives from the two randoms. */\nexport interface SessionKeys {\n macKey: Uint8Array;\n keyLength: number;\n is40Bit: boolean;\n initialDecryptKey: Uint8Array;\n initialEncryptKey: Uint8Array;\n decryptKey: Uint8Array;\n encryptKey: Uint8Array;\n}\n\nexport function rc4Init(key: Uint8Array): Rc4State {\n const s = new Uint8Array(256);\n for (let i = 0; i < 256; i++) s[i] = i;\n\n let j = 0;\n for (let i = 0; i < 256; i++) {\n j = (j + (s[i] ?? 0) + (key[i % key.length] ?? 0)) & 0xff;\n const t = s[i] ?? 0;\n s[i] = s[j] ?? 0;\n s[j] = t;\n }\n return { s, i: 0, j: 0 };\n}\n\n/** RC4 is symmetric, so this both encrypts and decrypts. State advances. */\nexport function rc4Crypt(state, data: Uint8Array) {\n const out = new Uint8Array(data.length);\n const { s } = state;\n let { i, j } = state;\n\n for (let n = 0; n < data.length; n++) {\n i = (i + 1) & 0xff;\n j = (j + s[i]) & 0xff;\n const t = s[i];\n s[i] = s[j];\n s[j] = t;\n out[n] = data[n] ^ s[(s[i] + s[j]) & 0xff];\n }\n\n state.i = i;\n state.j = j;\n return out;\n}\n\n// --- RSA -------------------------------------------------------------------\n\nfunction bigIntFromLe(bytes: Uint8Array) {\n let value = 0n;\n for (let i = bytes.length - 1; i >= 0; i--) value = (value << 8n) | BigInt(bytes[i]);\n return value;\n}\n\nfunction bigIntToLe(value: Uint8Array, length: number) {\n const out = new Uint8Array(length);\n let remaining = value;\n for (let i = 0; i < length; i++) {\n out[i] = Number(remaining & 0xffn);\n remaining >>= 8n;\n }\n return out;\n}\n\nfunction modPow(base: bigint, exponent: bigint, modulus: bigint) {\n let result = 1n;\n let b = base % modulus;\n let e = exponent;\n while (e > 0n) {\n if (e & 1n) result = (result * b) % modulus;\n b = (b * b) % modulus;\n e >>= 1n;\n }\n return result;\n}\n\n/**\n * Textbook RSA over little-endian buffers, which is what RDP's Security\n * Exchange PDU carries: the client random is raised to the server's public\n * exponent with no padding scheme (MS-RDPBCGR 5.3.4.1).\n */\nexport function rsaEncrypt(dataLe: Uint8Array, modulusLe: Uint8Array, exponentLe: Uint8Array) {\n const modulus = bigIntFromLe(modulusLe);\n const exponent = bigIntFromLe(exponentLe);\n const value = bigIntFromLe(dataLe);\n if (value >= modulus) throw new Error('RDP: client random is larger than the server RSA modulus');\n return bigIntToLe(modPow(value, exponent, modulus), modulusLe.length);\n}\n\n/**\n * RSAES-PKCS1-v1_5 encryption over big-endian buffers, which is what TLS uses\n * for an RSA key exchange. WebCrypto only offers OAEP, so the padding is built\n * here and the modular exponentiation reuses the same BigInt path as RDP.\n */\nexport function rsaEncryptPkcs1(message: Uint8Array, modulusBe: Uint8Array, exponentBe: Uint8Array) {\n const bigIntFromBe = (bytes: Uint8Array) => {\n let value = 0n;\n for (const byte of bytes) value = (value << 8n) | BigInt(byte);\n return value;\n };\n\n const modulus = bigIntFromBe(modulusBe);\n const exponent = bigIntFromBe(exponentBe);\n const keyLength = modulusBe.length;\n if (message.length > keyLength - 11) {\n throw new Error('TLS: RSA message is too long for this key');\n }\n\n // EM = 0x00 || 0x02 || non-zero padding || 0x00 || message\n const block = new Uint8Array(keyLength);\n block[0] = 0x00;\n block[1] = 0x02;\n const paddingLength = keyLength - message.length - 3;\n const padding = new Uint8Array(paddingLength);\n crypto.getRandomValues(padding);\n for (let i = 0; i < paddingLength; i++) {\n // A padding byte of zero would be read as the separator.\n while (padding[i] === 0) padding[i] = Math.max(1, crypto.getRandomValues(new Uint8Array(1))[0]);\n block[2 + i] = padding[i];\n }\n block[2 + paddingLength] = 0x00;\n block.set(message, 3 + paddingLength);\n\n const cipher = modPow(bigIntFromBe(block), exponent, modulus);\n const out = new Uint8Array(keyLength);\n let remaining = cipher;\n for (let i = keyLength - 1; i >= 0; i--) {\n out[i] = Number(remaining & 0xffn);\n remaining >>= 8n;\n }\n return out;\n}\n\n// --- RDP key derivation (MS-RDPBCGR 5.3.5) ---------------------------------\n\nconst PAD1 = new Uint8Array(40).fill(0x36);\nconst PAD2 = new Uint8Array(48).fill(0x5c);\n\nexport const ENCRYPTION_METHOD = {\n NONE: 0x00000000,\n BIT_40: 0x00000001,\n BIT_128: 0x00000002,\n BIT_56: 0x00000008,\n FIPS: 0x00000010,\n};\n\nfunction concat(...parts) {\n const total = parts.reduce((sum, part) => sum + part.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n return out;\n}\n\n/** SaltedHash(S, I) = MD5(S + SHA1(I + S + clientRandom + serverRandom)) */\nfunction saltedHash(secret: Uint8Array, salt: Uint8Array, clientRandom: Uint8Array, serverRandom: Uint8Array) {\n return md5(concat(secret, sha1(concat(salt, secret, clientRandom, serverRandom))));\n}\n\n/** FinalHash(K) = MD5(K + clientRandom + serverRandom) */\nfunction finalHash(key: Uint8Array, clientRandom: Uint8Array, serverRandom: Uint8Array) {\n return md5(concat(key, clientRandom, serverRandom));\n}\n\nconst SALT_A = new Uint8Array([0x41]);\nconst SALT_BB = new Uint8Array([0x42, 0x42]);\nconst SALT_CCC = new Uint8Array([0x43, 0x43, 0x43]);\nconst SALT_X = new Uint8Array([0x58]);\nconst SALT_YY = new Uint8Array([0x59, 0x59]);\nconst SALT_ZZZ = new Uint8Array([0x5a, 0x5a, 0x5a]);\n\n/**\n * A 40-bit or 56-bit session key is a 64-bit key with known leading bytes;\n * only the remaining entropy is secret (MS-RDPBCGR 5.3.5.1).\n */\nfunction reduceKey(key: Uint8Array, keyLength, is40Bit) {\n if (keyLength !== 8) return key.slice(0, keyLength);\n\n const reduced = key.slice(0, 8);\n reduced[0] = 0xd1;\n if (is40Bit) {\n reduced[1] = 0x26;\n reduced[2] = 0x9e;\n }\n return reduced;\n}\n\nexport function keyLengthForMethod(encryptionMethod: number) {\n if (encryptionMethod === ENCRYPTION_METHOD.BIT_40) return 8;\n if (encryptionMethod === ENCRYPTION_METHOD.BIT_56) return 8;\n return 16;\n}\n\n/**\n * Derive the MAC key and both directional RC4 keys from the two random values\n * exchanged during connection.\n */\nexport function deriveSessionKeys(clientRandom: Uint8Array, serverRandom: Uint8Array, encryptionMethod: number) {\n const preMasterSecret = concat(clientRandom.subarray(0, 24), serverRandom.subarray(0, 24));\n\n const masterSecret = concat(\n saltedHash(preMasterSecret, SALT_A, clientRandom, serverRandom),\n saltedHash(preMasterSecret, SALT_BB, clientRandom, serverRandom),\n saltedHash(preMasterSecret, SALT_CCC, clientRandom, serverRandom)\n );\n\n const sessionKeyBlob = concat(\n saltedHash(masterSecret, SALT_X, clientRandom, serverRandom),\n saltedHash(masterSecret, SALT_YY, clientRandom, serverRandom),\n saltedHash(masterSecret, SALT_ZZZ, clientRandom, serverRandom)\n );\n\n const keyLength = keyLengthForMethod(encryptionMethod);\n const is40Bit = encryptionMethod === ENCRYPTION_METHOD.BIT_40;\n\n const applyReduction = (key: Uint8Array) => reduceKey(key, keyLength, is40Bit);\n\n const macKey = applyReduction(sessionKeyBlob.subarray(0, 16));\n const decryptKey = applyReduction(finalHash(sessionKeyBlob.subarray(16, 32), clientRandom, serverRandom));\n const encryptKey = applyReduction(finalHash(sessionKeyBlob.subarray(32, 48), clientRandom, serverRandom));\n\n return {\n macKey,\n keyLength,\n is40Bit,\n // Session-key updates always restart from these initial values.\n initialDecryptKey: decryptKey.slice(),\n initialEncryptKey: encryptKey.slice(),\n decryptKey,\n encryptKey,\n };\n}\n\n/**\n * MACSignature = First64Bits(MD5(macKey + Pad2 + SHA1(macKey + Pad1 + len + data)))\n */\nexport function macSignature(macKey, data: Uint8Array) {\n const lengthField = new Uint8Array(4);\n new DataView(lengthField.buffer).setUint32(0, data.length, true);\n const inner = sha1(concat(macKey, PAD1, lengthField, data));\n return md5(concat(macKey, PAD2, inner)).subarray(0, 8);\n}\n\n/**\n * Every 4096 PDUs the RC4 key is refreshed from the initial key\n * (MS-RDPBCGR 5.3.7.1). The refreshed key is salted with itself.\n */\nexport function updateSessionKey(initialKey, currentKey, keyLength, is40Bit) {\n const inner = sha1(concat(initialKey, PAD1, currentKey));\n const nextKey = md5(concat(initialKey, PAD2, inner)).slice(0, keyLength);\n\n const salted = rc4Crypt(rc4Init(nextKey), nextKey);\n return reduceKey(salted, keyLength, is40Bit);\n}\n"],
5
- "mappings": "AAaA,MAAM,aAAa;AAAA,EACjB;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EACxD;AAAA,EAAG;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAG;AAAA,EAAI;AAAA,EACpD;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EACxD;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAC1D;AAGA,MAAM,QAAQ,IAAI;AAAA,EAChB,MAAM,KAAK,EAAE,QAAQ,GAAG,GAAG,CAAC,GAAG,MAAM,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC;AACzF;AAEA,SAAS,OAAO,OAAmB,OAAe;AAChD,SAAQ,SAAS,QAAU,UAAW,KAAK;AAC7C;AAEO,SAAS,IAAI,SAAqB;AACvC,QAAM,YAAY,QAAQ,SAAS;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;AAGzB,QAAM,OAAO,IAAI,SAAS,OAAO,QAAQ,OAAO,aAAa,GAAG,CAAC;AACjE,OAAK,UAAU,GAAG,cAAc,GAAG,IAAI;AACvC,OAAK,UAAU,GAAG,KAAK,MAAM,YAAY,UAAU,GAAG,IAAI;AAE1D,MAAI,KAAK,YAAY,KAAK,YAAY,KAAK,YAAY,KAAK;AAC5D,QAAM,QAAQ,IAAI,YAAY,EAAE;AAChC,QAAM,OAAO,IAAI,SAAS,OAAO,QAAQ,OAAO,YAAY,OAAO,UAAU;AAE7E,WAAS,QAAQ,GAAG,QAAQ,YAAY,SAAS;AAC/C,aAAS,IAAI,GAAG,IAAI,IAAI,IAAK,OAAM,CAAC,IAAI,KAAK,UAAU,QAAQ,KAAK,IAAI,GAAG,IAAI;AAE/E,QAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAChC,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAI;AACJ,UAAI;AACJ,UAAI,IAAI,IAAI;AACV,YAAK,IAAI,IAAM,CAAC,IAAI;AACpB,YAAI;AAAA,MACN,WAAW,IAAI,IAAI;AACjB,YAAK,IAAI,IAAM,CAAC,IAAI;AACpB,aAAK,IAAI,IAAI,KAAK;AAAA,MACpB,WAAW,IAAI,IAAI;AACjB,YAAI,IAAI,IAAI;AACZ,aAAK,IAAI,IAAI,KAAK;AAAA,MACpB,OAAO;AACL,YAAI,KAAK,IAAI,CAAC;AACd,YAAK,IAAI,IAAK;AAAA,MAChB;AAEA,YAAM,OAAO;AACb,UAAI;AACJ,UAAI;AACJ,YAAM,MAAO,IAAI,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,IAAK;AAC5C,UAAK,IAAI,OAAO,KAAK,WAAW,CAAC,CAAC,IAAK;AACvC,UAAI;AAAA,IACN;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;AAIO,SAAS,KAAK,SAAqB;AACxC,QAAM,YAAY,QAAQ,SAAS;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,QAAQ,OAAO,aAAa,GAAG,CAAC;AACjE,OAAK,UAAU,GAAG,KAAK,MAAM,YAAY,UAAU,CAAC;AACpD,OAAK,UAAU,GAAG,cAAc,CAAC;AAEjC,MAAI,KAAK,YAAY,KAAK,YAAY,KAAK,YAAY,KAAK,WAAY,KAAK;AAC7E,QAAM,QAAQ,IAAI,YAAY,EAAE;AAChC,QAAM,OAAO,IAAI,SAAS,OAAO,QAAQ,OAAO,YAAY,OAAO,UAAU;AAE7E,WAAS,QAAQ,GAAG,QAAQ,YAAY,SAAS;AAC/C,aAAS,IAAI,GAAG,IAAI,IAAI,IAAK,OAAM,CAAC,IAAI,KAAK,UAAU,QAAQ,KAAK,IAAI,CAAC;AACzE,aAAS,IAAI,IAAI,IAAI,IAAI,KAAK;AAC5B,YAAM,CAAC,IAAI,OAAO,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,GAAG,CAAC;AAAA,IAClF;AAEA,QAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AACxC,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAI;AACJ,UAAI;AACJ,UAAI,IAAI,IAAI;AACV,YAAK,IAAI,IAAM,CAAC,IAAI;AACpB,YAAI;AAAA,MACN,WAAW,IAAI,IAAI;AACjB,YAAI,IAAI,IAAI;AACZ,YAAI;AAAA,MACN,WAAW,IAAI,IAAI;AACjB,YAAK,IAAI,IAAM,IAAI,IAAM,IAAI;AAC7B,YAAI;AAAA,MACN,OAAO;AACL,YAAI,IAAI,IAAI;AACZ,YAAI;AAAA,MACN;AAEA,YAAM,OAAQ,OAAO,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC,IAAK;AACrD,UAAI;AACJ,UAAI;AACJ,UAAI,OAAO,GAAG,EAAE;AAChB,UAAI;AACJ,UAAI;AAAA,IACN;AAEA,SAAM,KAAK,IAAK;AAChB,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,GAAC,IAAI,IAAI,IAAI,IAAI,EAAE,EAAE,QAAQ,CAAC,MAAM,MAAM,IAAI,UAAU,IAAI,GAAG,SAAS,CAAC,CAAC;AAC1E,SAAO;AACT;AAsBO,SAAS,QAAQ,KAA2B;AACjD,QAAM,IAAI,IAAI,WAAW,GAAG;AAC5B,WAAS,IAAI,GAAG,IAAI,KAAK,IAAK,GAAE,CAAC,IAAI;AAErC,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,QAAK,KAAK,EAAE,CAAC,KAAK,MAAM,IAAI,IAAI,IAAI,MAAM,KAAK,KAAM;AACrD,UAAM,IAAI,EAAE,CAAC,KAAK;AAClB,MAAE,CAAC,IAAI,EAAE,CAAC,KAAK;AACf,MAAE,CAAC,IAAI;AAAA,EACT;AACA,SAAO,EAAE,GAAG,GAAG,GAAG,GAAG,EAAE;AACzB;AAGO,SAAS,SAAS,OAAO,MAAkB;AAChD,QAAM,MAAM,IAAI,WAAW,KAAK,MAAM;AACtC,QAAM,EAAE,EAAE,IAAI;AACd,MAAI,EAAE,GAAG,EAAE,IAAI;AAEf,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAK,IAAI,IAAK;AACd,QAAK,IAAI,EAAE,CAAC,IAAK;AACjB,UAAM,IAAI,EAAE,CAAC;AACb,MAAE,CAAC,IAAI,EAAE,CAAC;AACV,MAAE,CAAC,IAAI;AACP,QAAI,CAAC,IAAI,KAAK,CAAC,IAAI,EAAG,EAAE,CAAC,IAAI,EAAE,CAAC,IAAK,GAAI;AAAA,EAC3C;AAEA,QAAM,IAAI;AACV,QAAM,IAAI;AACV,SAAO;AACT;AAIA,SAAS,aAAa,OAAmB;AACvC,MAAI,QAAQ;AACZ,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,IAAK,SAAS,SAAS,KAAM,OAAO,MAAM,CAAC,CAAC;AACnF,SAAO;AACT;AAEA,SAAS,WAAW,OAAmB,QAAgB;AACrD,QAAM,MAAM,IAAI,WAAW,MAAM;AACjC,MAAI,YAAY;AAChB,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,QAAI,CAAC,IAAI,OAAO,YAAY,KAAK;AACjC,kBAAc;AAAA,EAChB;AACA,SAAO;AACT;AAEA,SAAS,OAAO,MAAc,UAAkB,SAAiB;AAC/D,MAAI,SAAS;AACb,MAAI,IAAI,OAAO;AACf,MAAI,IAAI;AACR,SAAO,IAAI,IAAI;AACb,QAAI,IAAI,GAAI,UAAU,SAAS,IAAK;AACpC,QAAK,IAAI,IAAK;AACd,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAOO,SAAS,WAAW,QAAoB,WAAuB,YAAwB;AAC5F,QAAM,UAAU,aAAa,SAAS;AACtC,QAAM,WAAW,aAAa,UAAU;AACxC,QAAM,QAAQ,aAAa,MAAM;AACjC,MAAI,SAAS,QAAS,OAAM,IAAI,MAAM,0DAA0D;AAChG,SAAO,WAAW,OAAO,OAAO,UAAU,OAAO,GAAG,UAAU,MAAM;AACtE;AAOO,SAAS,gBAAgB,SAAqB,WAAuB,YAAwB;AAClG,QAAM,eAAe,CAAC,UAAsB;AAC1C,QAAI,QAAQ;AACZ,eAAW,QAAQ,MAAO,SAAS,SAAS,KAAM,OAAO,IAAI;AAC7D,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,aAAa,SAAS;AACtC,QAAM,WAAW,aAAa,UAAU;AACxC,QAAM,YAAY,UAAU;AAC5B,MAAI,QAAQ,SAAS,YAAY,IAAI;AACnC,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAGA,QAAM,QAAQ,IAAI,WAAW,SAAS;AACtC,QAAM,CAAC,IAAI;AACX,QAAM,CAAC,IAAI;AACX,QAAM,gBAAgB,YAAY,QAAQ,SAAS;AACnD,QAAM,UAAU,IAAI,WAAW,aAAa;AAC5C,SAAO,gBAAgB,OAAO;AAC9B,WAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AAEtC,WAAO,QAAQ,CAAC,MAAM,EAAG,SAAQ,CAAC,IAAI,KAAK,IAAI,GAAG,OAAO,gBAAgB,IAAI,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;AAC9F,UAAM,IAAI,CAAC,IAAI,QAAQ,CAAC;AAAA,EAC1B;AACA,QAAM,IAAI,aAAa,IAAI;AAC3B,QAAM,IAAI,SAAS,IAAI,aAAa;AAEpC,QAAM,SAAS,OAAO,aAAa,KAAK,GAAG,UAAU,OAAO;AAC5D,QAAM,MAAM,IAAI,WAAW,SAAS;AACpC,MAAI,YAAY;AAChB,WAAS,IAAI,YAAY,GAAG,KAAK,GAAG,KAAK;AACvC,QAAI,CAAC,IAAI,OAAO,YAAY,KAAK;AACjC,kBAAc;AAAA,EAChB;AACA,SAAO;AACT;AAIA,MAAM,OAAO,IAAI,WAAW,EAAE,EAAE,KAAK,EAAI;AACzC,MAAM,OAAO,IAAI,WAAW,EAAE,EAAE,KAAK,EAAI;AAElC,MAAM,oBAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AACR;AAEA,SAAS,UAAU,OAAO;AACxB,QAAM,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,QAAQ,CAAC;AAC9D,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,SAAS;AACb,aAAW,QAAQ,OAAO;AACxB,QAAI,IAAI,MAAM,MAAM;AACpB,cAAU,KAAK;AAAA,EACjB;AACA,SAAO;AACT;AAGA,SAAS,WAAW,QAAoB,MAAkB,cAA0B,cAA0B;AAC5G,SAAO,IAAI,OAAO,QAAQ,KAAK,OAAO,MAAM,QAAQ,cAAc,YAAY,CAAC,CAAC,CAAC;AACnF;AAGA,SAAS,UAAU,KAAiB,cAA0B,cAA0B;AACtF,SAAO,IAAI,OAAO,KAAK,cAAc,YAAY,CAAC;AACpD;AAEA,MAAM,SAAS,IAAI,WAAW,CAAC,EAAI,CAAC;AACpC,MAAM,UAAU,IAAI,WAAW,CAAC,IAAM,EAAI,CAAC;AAC3C,MAAM,WAAW,IAAI,WAAW,CAAC,IAAM,IAAM,EAAI,CAAC;AAClD,MAAM,SAAS,IAAI,WAAW,CAAC,EAAI,CAAC;AACpC,MAAM,UAAU,IAAI,WAAW,CAAC,IAAM,EAAI,CAAC;AAC3C,MAAM,WAAW,IAAI,WAAW,CAAC,IAAM,IAAM,EAAI,CAAC;AAMlD,SAAS,UAAU,KAAiB,WAAW,SAAS;AACtD,MAAI,cAAc,EAAG,QAAO,IAAI,MAAM,GAAG,SAAS;AAElD,QAAM,UAAU,IAAI,MAAM,GAAG,CAAC;AAC9B,UAAQ,CAAC,IAAI;AACb,MAAI,SAAS;AACX,YAAQ,CAAC,IAAI;AACb,YAAQ,CAAC,IAAI;AAAA,EACf;AACA,SAAO;AACT;AAEO,SAAS,mBAAmB,kBAA0B;AAC3D,MAAI,qBAAqB,kBAAkB,OAAQ,QAAO;AAC1D,MAAI,qBAAqB,kBAAkB,OAAQ,QAAO;AAC1D,SAAO;AACT;AAMO,SAAS,kBAAkB,cAA0B,cAA0B,kBAA0B;AAC9G,QAAM,kBAAkB,OAAO,aAAa,SAAS,GAAG,EAAE,GAAG,aAAa,SAAS,GAAG,EAAE,CAAC;AAEzF,QAAM,eAAe;AAAA,IACnB,WAAW,iBAAiB,QAAQ,cAAc,YAAY;AAAA,IAC9D,WAAW,iBAAiB,SAAS,cAAc,YAAY;AAAA,IAC/D,WAAW,iBAAiB,UAAU,cAAc,YAAY;AAAA,EAClE;AAEA,QAAM,iBAAiB;AAAA,IACrB,WAAW,cAAc,QAAQ,cAAc,YAAY;AAAA,IAC3D,WAAW,cAAc,SAAS,cAAc,YAAY;AAAA,IAC5D,WAAW,cAAc,UAAU,cAAc,YAAY;AAAA,EAC/D;AAEA,QAAM,YAAY,mBAAmB,gBAAgB;AACrD,QAAM,UAAU,qBAAqB,kBAAkB;AAEvD,QAAM,iBAAiB,CAAC,QAAoB,UAAU,KAAK,WAAW,OAAO;AAE7E,QAAM,SAAS,eAAe,eAAe,SAAS,GAAG,EAAE,CAAC;AAC5D,QAAM,aAAa,eAAe,UAAU,eAAe,SAAS,IAAI,EAAE,GAAG,cAAc,YAAY,CAAC;AACxG,QAAM,aAAa,eAAe,UAAU,eAAe,SAAS,IAAI,EAAE,GAAG,cAAc,YAAY,CAAC;AAExG,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA,mBAAmB,WAAW,MAAM;AAAA,IACpC,mBAAmB,WAAW,MAAM;AAAA,IACpC;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,aAAa,QAAQ,MAAkB;AACrD,QAAM,cAAc,IAAI,WAAW,CAAC;AACpC,MAAI,SAAS,YAAY,MAAM,EAAE,UAAU,GAAG,KAAK,QAAQ,IAAI;AAC/D,QAAM,QAAQ,KAAK,OAAO,QAAQ,MAAM,aAAa,IAAI,CAAC;AAC1D,SAAO,IAAI,OAAO,QAAQ,MAAM,KAAK,CAAC,EAAE,SAAS,GAAG,CAAC;AACvD;AAMO,SAAS,iBAAiB,YAAY,YAAY,WAAW,SAAS;AAC3E,QAAM,QAAQ,KAAK,OAAO,YAAY,MAAM,UAAU,CAAC;AACvD,QAAM,UAAU,IAAI,OAAO,YAAY,MAAM,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS;AAEvE,QAAM,SAAS,SAAS,QAAQ,OAAO,GAAG,OAAO;AACjD,SAAO,UAAU,QAAQ,WAAW,OAAO;AAC7C;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/protocols/rdp/display.ts"],
4
- "sourcesContent": ["// Canvas rendering and input capture for an RDP session.\n//\n// The host sends rectangles of pixels and a cursor shape; this module paints\n// them, maps browser events back into desktop coordinates, and turns key events\n// into the scancodes RDP expects.\n\nimport { decodeBitmapRect } from './rle';\nimport { TOGGLE_FLAG } from './pdu';\n\n/**\n * On a Mac the editing shortcuts live on Command, and Windows expects them on\n * Control. Sending Command through as the Windows key -- which is what its\n * scancode means -- would make copy and paste unreachable, so it is translated\n * instead. The Special Keys panel still sends a real Windows key.\n */\nconst IS_MAC = /Mac|iPod|iPhone|iPad/.test(\n globalThis.navigator?.platform || globalThis.navigator?.userAgent || ''\n);\n\nconst COMMAND_TO_CONTROL = {\n MetaLeft: 'ControlLeft',\n MetaRight: 'ControlRight',\n};\n\n// Trackpads emit many small wheel events. Waiting for roughly one line of\n// accumulated motion prevents each tiny event from becoming a full RDP notch.\nconst WHEEL_STEP_PIXELS = 60;\nconst WHEEL_LINE_PIXELS = 16;\n\n/** Two fingers dragged this far, per notch, count as one wheel click. */\nconst TOUCH_SCROLL_STEP = 20;\n\n/**\n * How far past \"the whole desktop is visible\" a pinch may go. Eight is well\n * past readable on any phone; the floor of 1 is the fitted view, because\n * zooming out beyond the window only adds letterboxing.\n */\nconst MAX_ZOOM = 8;\nconst MIN_ZOOM = 1;\n\n\nexport class RdpDisplay {\n constructor(container) {\n this.container = container;\n this.canvas = document.createElement('canvas');\n this.canvas.tabIndex = 0;\n this.canvas.style.display = 'block';\n this.canvas.style.position = 'absolute';\n this.canvas.style.outline = 'none';\n this.canvas.style.imageRendering = 'auto';\n this.canvas.style.boxShadow = 'none';\n this.context = this.canvas.getContext('2d', { alpha: false });\n\n // The canvas is always the whole remote desktop, and this element decides\n // how much of it is on screen. A full-desktop session shows all of it; a\n // RemoteApp session shows only the application's own window, because\n // RemoteApp paints nothing around it.\n this.viewportElement = document.createElement('div');\n this.viewportElement.style.position = 'relative';\n this.viewportElement.style.overflow = 'hidden';\n this.viewportElement.style.margin = 'auto';\n this.viewportElement.style.background = '#000';\n this.viewportElement.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.8)';\n this.viewportElement.appendChild(this.canvas);\n\n container.replaceChildren(this.viewportElement);\n\n // The element that actually scrolls when the desktop is larger than the\n // window. `container` grows with its contents, so it is the wrong thing to\n // measure the available space against.\n this.scrollHost = container.parentElement || container;\n\n this.width = 0;\n this.height = 0;\n this.viewport = { x: 0, y: 0, width: 0, height: 0 };\n this.scale = 1;\n this.scaleViewport = true;\n // A multiplier on top of the fitted scale. 1 shows the whole desktop.\n this.zoom = 1;\n // Once the user has pinched, their zoom is theirs to keep: rotating the\n // phone should not silently throw it away.\n this.userZoomed = false;\n this.viewOnly = false;\n this.client = null;\n this.palette = null;\n this.cursorCache = new Map();\n this.heldKeys = new Set();\n this.keyboardSynced = false;\n\n // Turning the phone changes which axis is the tight one; applyScale picks\n // the opening zoom up again unless the user has since chosen their own.\n this.onWindowResize = () => this.applyScale();\n window.addEventListener('resize', this.onWindowResize);\n\n // The workspace also changes width without the window changing at all --\n // the SSH panel docking beside it, for one -- and no `resize` is fired for\n // that, so the desktop would keep the scale it had before the panel opened.\n this.resizeObserver = typeof ResizeObserver === 'function'\n ? new ResizeObserver(() => this.applyScale())\n : null;\n this.resizeObserver?.observe(this.scrollHost);\n }\n\n resize(width: number, height: number) {\n this.width = width;\n this.height = height;\n this.canvas.width = width;\n this.canvas.height = height;\n\n this.context.fillStyle = '#000';\n this.context.fillRect(0, 0, width, height);\n this.setViewport({ x: 0, y: 0, width, height });\n }\n\n /**\n * Choose the part of the desktop that is on screen. Everything else about\n * the session -- painting, input coordinates, the remote pointer -- keeps\n * working in desktop coordinates, so only the framing changes here.\n */\n setViewport({ x = 0, y = 0, width, height } = {}) {\n if (!this.width || !this.height) return;\n\n const left = Math.max(0, Math.min(this.width - 1, Math.floor(x)));\n const top = Math.max(0, Math.min(this.height - 1, Math.floor(y)));\n this.viewport = {\n x: left,\n y: top,\n width: Math.max(1, Math.min(this.width - left, Math.floor(width || this.width))),\n height: Math.max(1, Math.min(this.height - top, Math.floor(height || this.height))),\n };\n\n // The toolbar reads the resolution off the canvas, and a screenshot of a\n // RemoteApp session should be the window rather than the desktop it sits on.\n this.canvas.dataset.viewport = [\n this.viewport.x, this.viewport.y, this.viewport.width, this.viewport.height,\n ].join(',');\n this.applyScale();\n }\n\n /** The space a fitted desktop has to fit into: the window, not the content. */\n #available() {\n const host = this.scrollHost;\n return {\n width: host.clientWidth || this.container.clientWidth || 1,\n height: host.clientHeight || this.container.clientHeight || 1,\n };\n }\n\n /** The scale at which the whole desktop is on screen, letterboxed. */\n #fitScale(available = this.#available()) {\n const fitted = Math.min(\n available.width / this.viewport.width,\n available.height / this.viewport.height\n );\n return Number.isFinite(fitted) && fitted > 0 ? fitted : 1;\n }\n\n /**\n * The zoom to open a session at.\n *\n * On a laptop the fitted view is the right one: the whole desktop is on\n * screen and readable, and that is where this stays. On a phone it is not --\n * a 1024x768 desktop fitted to a 375pt-wide window lands at about a third of\n * full size, a band of unreadable pixels across the middle of a tall black\n * screen. When fitting would land under LEGIBLE_SCALE the desktop is scaled\n * to fill the window instead: the short edge matches exactly and the long one\n * is panned. Everything is still reachable, and a pinch still gets back to\n * the whole desktop. Legible first and complete second is the right way round\n * on a screen this size.\n */\n #defaultZoom() {\n return 1;\n }\n\n applyScale() {\n if (!this.width || !this.height) return;\n const viewport = this.viewport;\n\n // Measured once and shared, so the zoom and the scale it multiplies can\n // never come from two different layouts. Turning the phone fires `resize`\n // while the new size is still settling, and reading it twice there is how\n // the desktop ends up fitted on one axis and filled on the other.\n const available = this.#available();\n const fitted = this.#fitScale(available);\n if (!this.userZoomed) this.zoom = this.#defaultZoom();\n\n const scale = (this.scaleViewport ? fitted : 1) * this.zoom;\n this.scale = scale;\n\n // Sized in exact fractions of a pixel rather than whole ones: rounding the\n // two axes apart is what makes a scaled desktop very slightly the wrong\n // shape, which is visible as soon as the scale factor is small -- a phone\n // fitting a 1024x768 desktop into 375 points, for instance.\n this.viewportElement.style.width = `${viewport.width * scale}px`;\n this.viewportElement.style.height = `${viewport.height * scale}px`;\n this.canvas.style.width = `${this.width * scale}px`;\n this.canvas.style.height = `${this.height * scale}px`;\n this.canvas.style.left = `${-viewport.x * scale}px`;\n this.canvas.style.top = `${-viewport.y * scale}px`;\n }\n\n /**\n * Zoom about a point, keeping whatever is under it in place. `focal` is in\n * client coordinates -- the midpoint between two fingers, usually.\n */\n setZoom(next, focal = null) {\n const clamped = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, next));\n if (!Number.isFinite(clamped) || clamped === this.zoom) return;\n\n const host = this.scrollHost;\n const before = this.scale;\n const bounds = host.getBoundingClientRect();\n const anchorX = focal ? focal.x - bounds.left : bounds.width / 2;\n const anchorY = focal ? focal.y - bounds.top : bounds.height / 2;\n const contentX = host.scrollLeft + anchorX;\n const contentY = host.scrollTop + anchorY;\n\n this.zoom = clamped;\n this.applyScale();\n\n const ratio = before > 0 ? this.scale / before : 1;\n host.scrollLeft = contentX * ratio - anchorX;\n host.scrollTop = contentY * ratio - anchorY;\n }\n\n /** Move the visible window over the desktop. Returns what it actually used. */\n panBy(dx, dy) {\n const host = this.scrollHost;\n const beforeX = host.scrollLeft;\n const beforeY = host.scrollTop;\n host.scrollLeft = beforeX - dx;\n host.scrollTop = beforeY - dy;\n return {\n x: beforeX - host.scrollLeft,\n y: beforeY - host.scrollTop,\n };\n }\n\n /** True when the desktop is larger than the window on either axis. */\n canPan() {\n if (this.zoom <= 1.05) return false;\n const host = this.scrollHost;\n return host.scrollWidth > host.clientWidth + 2 || host.scrollHeight > host.clientHeight + 2;\n }\n\n setScaleViewport(enabled: boolean) {\n this.scaleViewport = enabled;\n if (!enabled) this.userZoomed = false;\n this.applyScale();\n }\n\n /** Back to the opening view: whole desktop fitted on screen. */\n resetZoom() {\n this.userZoomed = false;\n this.zoom = 1;\n this.applyScale();\n const host = this.scrollHost;\n host.scrollLeft = 0;\n host.scrollTop = 0;\n }\n\n drawRects(rects, palette) {\n if (palette) this.palette = palette;\n\n for (const rect of rects) {\n if (rect.width === 0 || rect.height === 0) continue;\n try {\n const rgba = decodeBitmapRect(rect, this.palette);\n const image = new ImageData(rgba, rect.width, rect.height);\n this.context.putImageData(image, rect.left, rect.top);\n } catch (error) {\n // One malformed rectangle must not kill the session; the next full\n // update repaints the area anyway.\n console.warn('[RDP] Dropped an undecodable bitmap rectangle', {\n geometry: `${rect.width}x${rect.height}+${rect.left}+${rect.top}`,\n bitsPerPixel: rect.bitsPerPixel,\n compressed: rect.compressed,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n\n // --- cursor ---------------------------------------------------------------\n\n /**\n * Turn an RDP pointer bitmap into a CSS cursor. RDP stores both masks\n * bottom-up with rows padded to an even number of bytes, and a set AND-mask\n * bit means \"leave this pixel alone\", which becomes transparency here.\n */\n #cursorFromPointer(pointer) {\n const { width, height, xorBpp, xorMask, andMask, hotSpotX, hotSpotY } = pointer;\n if (!width || !height) return null;\n\n const xorBytesPerRow = Math.ceil((width * xorBpp) / 8 / 2) * 2;\n const andBytesPerRow = Math.ceil(width / 8 / 2) * 2;\n const rgba = new Uint8ClampedArray(width * height * 4);\n\n for (let y = 0; y < height; y++) {\n const sourceRow = height - 1 - y; // bottom-up\n for (let x = 0; x < width; x++) {\n const andByte = andMask[sourceRow * andBytesPerRow + (x >> 3)];\n const transparent = andByte !== undefined && (andByte & (0x80 >> (x & 7))) !== 0;\n\n let r = 0;\n let g = 0;\n let b = 0;\n let a = transparent ? 0 : 255;\n\n if (xorBpp === 1) {\n const bit = xorMask[sourceRow * xorBytesPerRow + (x >> 3)] & (0x80 >> (x & 7));\n r = g = b = bit ? 255 : 0;\n } else {\n const bytesPerPixel = xorBpp / 8;\n const offset = sourceRow * xorBytesPerRow + x * bytesPerPixel;\n if (xorBpp === 16) {\n const value = xorMask[offset] | (xorMask[offset + 1] << 8);\n r = ((value >> 11) & 0x1f) * 255 / 31;\n g = ((value >> 5) & 0x3f) * 255 / 63;\n b = (value & 0x1f) * 255 / 31;\n } else {\n b = xorMask[offset] || 0;\n g = xorMask[offset + 1] || 0;\n r = xorMask[offset + 2] || 0;\n if (xorBpp === 32 && xorMask[offset + 3] !== undefined && andMask.length === 0) {\n a = xorMask[offset + 3];\n }\n }\n }\n\n const target = (y * width + x) * 4;\n rgba[target] = r;\n rgba[target + 1] = g;\n rgba[target + 2] = b;\n rgba[target + 3] = a;\n }\n }\n\n const cursorCanvas = document.createElement('canvas');\n cursorCanvas.width = width;\n cursorCanvas.height = height;\n cursorCanvas.getContext('2d').putImageData(new ImageData(rgba, width, height), 0, 0);\n\n const hotX = Math.min(hotSpotX || 0, width - 1);\n const hotY = Math.min(hotSpotY || 0, height - 1);\n return `url(${cursorCanvas.toDataURL('image/png')}) ${hotX} ${hotY}, default`;\n }\n\n applyPointer(pointer) {\n if (pointer.kind === 'system') {\n this.canvas.style.cursor = pointer.hidden ? 'none' : 'default';\n return;\n }\n\n if (pointer.kind === 'position') {\n // Host-driven pointer warps cannot move the real mouse; ignore them and\n // let the local pointer stay where the user put it.\n return;\n }\n\n if (pointer.kind === 'cached') {\n const cached = this.cursorCache.get(pointer.cacheIndex);\n if (cached) this.canvas.style.cursor = cached;\n return;\n }\n\n if (pointer.kind === 'bitmap') {\n try {\n const cursor = this.#cursorFromPointer(pointer);\n if (!cursor) return;\n this.cursorCache.set(pointer.cacheIndex, cursor);\n this.canvas.style.cursor = cursor;\n } catch (error) {\n console.warn('[RDP] Could not build a cursor from the host pointer update', error);\n }\n }\n }\n\n // --- input ----------------------------------------------------------------\n\n #toRemote(event) {\n const bounds = this.canvas.getBoundingClientRect();\n const scaleX = this.width / (bounds.width || 1);\n const scaleY = this.height / (bounds.height || 1);\n return {\n x: Math.max(0, Math.min(this.width - 1, (event.clientX - bounds.left) * scaleX)),\n y: Math.max(0, Math.min(this.height - 1, (event.clientY - bounds.top) * scaleY)),\n };\n }\n\n #syncKeyboardOnce(event) {\n if (this.keyboardSynced || !this.client) return;\n this.keyboardSynced = true;\n\n let flags = 0;\n if (event.getModifierState?.('CapsLock')) flags |= TOGGLE_FLAG.CAPS_LOCK;\n if (event.getModifierState?.('NumLock')) flags |= TOGGLE_FLAG.NUM_LOCK;\n if (event.getModifierState?.('ScrollLock')) flags |= TOGGLE_FLAG.SCROLL_LOCK;\n this.client.sendKeyboardSync(flags);\n }\n\n attachInput(client) {\n this.client = client;\n this.keyboardSynced = false;\n\n const canSend = () => this.client && this.client.connected && !this.viewOnly;\n\n let pendingMove = null;\n let moveScheduled = false;\n let pendingWheelDelta = 0;\n let touchIsDown = false;\n let lastTouchX = 0;\n let lastTouchY = 0;\n let lastTouchScrollY = 0;\n let lastTouchScrollX = 0;\n let gestureStartMid = { x: 0, y: 0 };\n let gestureStartDistance = 0;\n let lastPinchDistance = 0;\n let pendingTouchWheelDelta = 0;\n let touchMode = null;\n\n const touchMidpoint = (touches) => ({\n x: (touches[0].clientX + touches[1].clientX) / 2,\n y: (touches[0].clientY + touches[1].clientY) / 2,\n });\n\n const touchDistance = (touches) => Math.hypot(\n touches[0].clientX - touches[1].clientX,\n touches[0].clientY - touches[1].clientY\n );\n const flushMove = () => {\n moveScheduled = false;\n if (pendingMove && canSend()) this.client.sendMouseMove(pendingMove.x, pendingMove.y);\n pendingMove = null;\n };\n\n this.handlers = {\n mousemove: (event) => {\n if (!canSend()) return;\n pendingMove = this.#toRemote(event);\n if (!moveScheduled) {\n moveScheduled = true;\n requestAnimationFrame(flushMove);\n }\n },\n mousedown: (event) => {\n this.canvas.focus();\n if (!canSend()) return;\n event.preventDefault();\n const { x, y } = this.#toRemote(event);\n this.client.sendMouseButton(event.button, true, x, y);\n },\n mouseup: (event) => {\n if (!canSend()) return;\n event.preventDefault();\n const { x, y } = this.#toRemote(event);\n this.client.sendMouseButton(event.button, false, x, y);\n },\n contextmenu: (event) => event.preventDefault(),\n wheel: (event) => {\n if (!canSend()) return;\n event.preventDefault();\n\n let delta = event.deltaY;\n if (event.deltaMode === WheelEvent.DOM_DELTA_LINE) delta *= WHEEL_LINE_PIXELS;\n if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n delta *= Math.max(1, this.canvas.clientHeight || this.height);\n }\n if (!delta) return;\n\n // Do not let a partial gesture in one direction accelerate the next\n // gesture in the opposite direction.\n if (pendingWheelDelta && Math.sign(pendingWheelDelta) !== Math.sign(delta)) {\n pendingWheelDelta = 0;\n }\n pendingWheelDelta += delta;\n if (Math.abs(pendingWheelDelta) < WHEEL_STEP_PIXELS) return;\n\n const direction = Math.sign(pendingWheelDelta);\n pendingWheelDelta -= direction * WHEEL_STEP_PIXELS;\n const { x, y } = this.#toRemote(event);\n this.client.sendWheel(direction, x, y);\n },\n touchstart: (event) => {\n this.canvas.focus();\n if (!canSend()) return;\n event.preventDefault();\n\n if (event.touches.length === 1) {\n touchMode = 'tap';\n const touch = event.touches[0];\n lastTouchX = touch.clientX;\n lastTouchY = touch.clientY;\n const { x, y } = this.#toRemote(touch);\n this.client.sendMouseMove(x, y);\n this.client.sendMouseButton(0, true, x, y);\n touchIsDown = true;\n } else if (event.touches.length === 2) {\n touchMode = 'undecided';\n if (touchIsDown) {\n const { x, y } = this.#toRemote({ clientX: lastTouchX, clientY: lastTouchY });\n this.client.sendMouseButton(0, false, x, y);\n touchIsDown = false;\n }\n const mid = touchMidpoint(event.touches);\n const dist = touchDistance(event.touches);\n gestureStartMid = { x: mid.x, y: mid.y };\n gestureStartDistance = dist;\n lastTouchScrollY = mid.y;\n lastTouchScrollX = mid.x;\n lastPinchDistance = dist;\n pendingTouchWheelDelta = 0;\n }\n },\n touchmove: (event) => {\n if (!canSend()) return;\n event.preventDefault();\n\n if (event.touches.length === 1 && touchMode === 'tap') {\n const touch = event.touches[0];\n lastTouchX = touch.clientX;\n lastTouchY = touch.clientY;\n const { x, y } = this.#toRemote(touch);\n this.client.sendMouseMove(x, y);\n } else if (event.touches.length === 2) {\n const mid = touchMidpoint(event.touches);\n const currX = mid.x;\n const currY = mid.y;\n const distance = touchDistance(event.touches);\n const deltaY = lastTouchScrollY - currY;\n const deltaX = lastTouchScrollX - currX;\n lastTouchScrollY = currY;\n lastTouchScrollX = currX;\n\n const totalMove = Math.hypot(currX - gestureStartMid.x, currY - gestureStartMid.y);\n const pinchDelta = Math.abs(distance - gestureStartDistance);\n const pinchRatio = gestureStartDistance > 0 ? distance / gestureStartDistance : 1;\n\n if (touchMode === 'undecided' || touchMode === 'gesture') {\n // Disambiguate between pinch-to-zoom and two-finger scroll\n if (pinchDelta > 20 && Math.abs(pinchRatio - 1) > 0.15 && pinchDelta > totalMove * 0.8) {\n touchMode = 'pinch';\n } else if (totalMove > 8) {\n touchMode = 'scroll';\n }\n }\n\n if (touchMode === 'pinch') {\n if (lastPinchDistance > 0 && Math.abs(distance - lastPinchDistance) > 1) {\n this.userZoomed = true;\n this.setZoom(this.zoom * (distance / lastPinchDistance), { x: currX, y: currY });\n }\n lastPinchDistance = distance;\n } else if (touchMode === 'scroll') {\n lastPinchDistance = distance;\n\n // A zoomed-in desktop pans; a fitted desktop turns the remote mouse wheel.\n if (this.canPan()) {\n this.panBy(deltaX * -1, deltaY * -1);\n pendingTouchWheelDelta = 0;\n return;\n }\n\n if (deltaY && pendingTouchWheelDelta\n && Math.sign(pendingTouchWheelDelta) !== Math.sign(deltaY)) {\n pendingTouchWheelDelta = 0;\n }\n pendingTouchWheelDelta += deltaY;\n\n while (Math.abs(pendingTouchWheelDelta) >= TOUCH_SCROLL_STEP) {\n const direction = Math.sign(pendingTouchWheelDelta);\n pendingTouchWheelDelta -= direction * TOUCH_SCROLL_STEP;\n const { x, y } = this.#toRemote({ clientX: currX, clientY: currY });\n this.client.sendWheel(direction, x, y);\n }\n }\n }\n },\n touchend: (event) => {\n if (!canSend()) return;\n event.preventDefault();\n\n if (event.touches.length === 0) {\n if (touchIsDown) {\n const { x, y } = this.#toRemote({ clientX: lastTouchX, clientY: lastTouchY });\n this.client.sendMouseButton(0, false, x, y);\n touchIsDown = false;\n }\n if (touchMode === 'pinch' && this.zoom <= 1.05) {\n this.resetZoom();\n }\n touchMode = null;\n pendingTouchWheelDelta = 0;\n lastPinchDistance = 0;\n } else if (event.touches.length === 1) {\n // A finger lifted mid-gesture leaves one behind that was never a tap;\n // letting it fall through would press the mouse where it happens to\n // rest. The gesture ends here and the stray finger is ignored.\n if (touchMode === 'gesture' || touchMode === 'pinch' || touchMode === 'scroll' || touchMode === 'undecided') {\n if (touchMode === 'pinch' && this.zoom <= 1.05) {\n this.resetZoom();\n }\n touchMode = null;\n lastPinchDistance = 0;\n pendingTouchWheelDelta = 0;\n }\n }\n },\n touchcancel: (event) => {\n if (!canSend()) return;\n if (touchIsDown) {\n const { x, y } = this.#toRemote({ clientX: lastTouchX, clientY: lastTouchY });\n this.client.sendMouseButton(0, false, x, y);\n touchIsDown = false;\n }\n if (touchMode === 'pinch' && this.zoom <= 1.05) {\n this.resetZoom();\n }\n touchMode = null;\n pendingTouchWheelDelta = 0;\n lastPinchDistance = 0;\n },\n keydown: (event) => {\n if (!canSend()) return;\n this.#syncKeyboardOnce(event);\n\n // Paste is the browser's to deliver: preventing the default here would\n // stop the paste event that carries the text the host is about to ask\n // for. The keystroke is sent from the paste handler instead.\n if (this.#isPasteShortcut(event)) return;\n\n const code = this.#translateCode(event.code);\n if (!this.client.sendKeyByCode(code, true)) return;\n event.preventDefault();\n\n // macOS withholds keyup while Command is held, which would leave the\n // key stuck down on the host. Releasing it at once is the only way to\n // keep the shortcut from repeating forever.\n if (IS_MAC && event.metaKey && !COMMAND_TO_CONTROL[event.code]) {\n this.client.sendKeyByCode(code, false);\n return;\n }\n\n this.heldKeys.add(code);\n },\n keyup: (event) => {\n if (!canSend()) return;\n if (this.#isPasteShortcut(event)) return;\n\n const code = this.#translateCode(event.code);\n if (this.client.sendKeyByCode(code, false)) {\n this.heldKeys.delete(code);\n event.preventDefault();\n }\n },\n paste: (event) => {\n if (!canSend()) return;\n\n /**\n * Only when the screen is what is being pasted into.\n *\n * This listener is on the document because a canvas cannot receive a\n * paste event of its own -- which means *every* paste in the page\n * arrives here, including one typed into the assistant's message box or\n * a password field. Without this guard the text went two places at\n * once: into the box the user was looking at, and into whatever window\n * happened to be open on the far machine.\n *\n * Focus is the test. The remote screen holds it when the remote screen\n * is what you are working in, and nothing else does at the same time.\n * (The terminal never had this problem because xterm stops the event\n * from propagating; a text field cannot be relied on to do that.)\n */\n const target = event.target;\n const onTheScreen = target instanceof Node && this.container.contains(target);\n if (document.activeElement !== this.canvas && !onTheScreen) return;\n\n event.preventDefault();\n const text = event.clipboardData?.getData('text/plain') || '';\n if (text) this.client.pasteToHost(text);\n },\n blur: () => this.releaseAllKeys(),\n };\n\n this.canvas.addEventListener('mousemove', this.handlers.mousemove);\n this.canvas.addEventListener('mousedown', this.handlers.mousedown);\n this.canvas.addEventListener('mouseup', this.handlers.mouseup);\n this.canvas.addEventListener('contextmenu', this.handlers.contextmenu);\n this.canvas.addEventListener('wheel', this.handlers.wheel, { passive: false });\n this.canvas.addEventListener('touchstart', this.handlers.touchstart, { passive: false });\n this.canvas.addEventListener('touchmove', this.handlers.touchmove, { passive: false });\n this.canvas.addEventListener('touchend', this.handlers.touchend, { passive: false });\n this.canvas.addEventListener('touchcancel', this.handlers.touchcancel, { passive: false });\n this.canvas.addEventListener('keydown', this.handlers.keydown);\n this.canvas.addEventListener('keyup', this.handlers.keyup);\n this.canvas.addEventListener('blur', this.handlers.blur);\n // A canvas is not editable, so the paste event lands on the document. The\n // handler checks that the canvas has focus before treating it as its own.\n document.addEventListener('paste', this.handlers.paste);\n }\n\n /** Command on a Mac stands in for Control everywhere the host is concerned. */\n #translateCode(code: number) {\n return IS_MAC ? COMMAND_TO_CONTROL[code] || code : code;\n }\n\n #isPasteShortcut(event) {\n if (event.code !== 'KeyV') return false;\n return IS_MAC ? event.metaKey : event.ctrlKey;\n }\n\n /** A key held while focus moves away would otherwise stay down on the host. */\n releaseAllKeys() {\n if (!this.client) return;\n for (const code of this.heldKeys) this.client.sendKeyByCode(code, false);\n this.heldKeys.clear();\n }\n\n focus() {\n this.canvas.focus();\n }\n\n blur() {\n this.canvas.blur();\n }\n\n destroy() {\n this.releaseAllKeys();\n window.removeEventListener('resize', this.onWindowResize);\n this.resizeObserver?.disconnect();\n\n if (this.handlers) {\n this.canvas.removeEventListener('mousemove', this.handlers.mousemove);\n this.canvas.removeEventListener('mousedown', this.handlers.mousedown);\n this.canvas.removeEventListener('mouseup', this.handlers.mouseup);\n this.canvas.removeEventListener('contextmenu', this.handlers.contextmenu);\n this.canvas.removeEventListener('wheel', this.handlers.wheel);\n this.canvas.removeEventListener('touchstart', this.handlers.touchstart);\n this.canvas.removeEventListener('touchmove', this.handlers.touchmove);\n this.canvas.removeEventListener('touchend', this.handlers.touchend);\n this.canvas.removeEventListener('touchcancel', this.handlers.touchcancel);\n this.canvas.removeEventListener('keydown', this.handlers.keydown);\n this.canvas.removeEventListener('keyup', this.handlers.keyup);\n this.canvas.removeEventListener('blur', this.handlers.blur);\n document.removeEventListener('paste', this.handlers.paste);\n }\n\n this.client = null;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/protocols/rdp/gcc.ts"],
4
- "sourcesContent": ["// GCC user data: what the client says about itself in the MCS connect request,\n// and what the host answers with (MS-RDPBCGR 2.2.1.3 / 2.2.1.4).\n\nimport { Reader, Writer, concatBytes } from './buffer';\nimport { parseServerCertificate } from './cert';\n\nconst CS_CORE = 0xc001;\nconst CS_SECURITY = 0xc002;\nconst CS_NET = 0xc003;\nconst CS_CLUSTER = 0xc004;\n\nconst SC_CORE = 0x0c01;\nconst SC_SECURITY = 0x0c02;\nconst SC_NET = 0x0c03;\n\n/** RDP 5.0 and later. Anything newer would oblige us to speak newer PDUs. */\nexport const RDP_VERSION_5_PLUS = 0x00080004;\n\nconst COLOR_16BPP = 0xca03;\nconst RNS_UD_SAS_DEL = 0xaa03;\nconst SUPPORT_ERRINFO_PDU = 0x0001;\n\nexport const ENCRYPTION_LEVEL = {\n NONE: 0,\n LOW: 1,\n CLIENT_COMPATIBLE: 2,\n HIGH: 3,\n FIPS: 4,\n};\n\nfunction userDataBlock(type: number, body: Uint8Array) {\n const writer = new Writer(body.length + 4);\n writer.u16le(type).u16le(body.length + 4).raw(body);\n return writer.take();\n}\n\n/**\n * TS_UD_CS_CORE. The desktop size asked for here is a request: the host answers\n * with the size it actually chose in its Demand Active PDU.\n */\nfunction clientCoreData({ width, height, clientName, keyboardLayout, selectedProtocol }) {\n const writer = new Writer(256);\n\n writer.u32le(RDP_VERSION_5_PLUS);\n writer.u16le(width);\n writer.u16le(height);\n writer.u16le(COLOR_16BPP);\n writer.u16le(RNS_UD_SAS_DEL);\n writer.u32le(keyboardLayout);\n writer.u32le(2600); // clientBuild\n writer.utf16le(clientName, 32); // clientName, 15 chars + NUL\n writer.u32le(4); // keyboardType: IBM enhanced\n writer.u32le(0); // keyboardSubType\n writer.u32le(12); // keyboardFunctionKey\n writer.zeros(64); // imeFileName\n writer.u16le(COLOR_16BPP); // postBeta2ColorDepth\n writer.u16le(1); // clientProductId\n writer.u32le(0); // serialNumber\n writer.u16le(16); // highColorDepth\n writer.u16le(0x0007); // supportedColorDepths: 15/16/24\n writer.u16le(SUPPORT_ERRINFO_PDU); // earlyCapabilityFlags\n writer.zeros(64); // clientDigProductId\n writer.u8(0); // connectionType: unknown\n writer.u8(0); // pad\n writer.u32le(selectedProtocol); // serverSelectedProtocol\n\n return userDataBlock(CS_CORE, writer.take());\n}\n\n/** TS_UD_CS_SEC. FIPS is deliberately absent -- this client does not do it. */\nfunction clientSecurityData(encryptionMethods: number) {\n const writer = new Writer(8);\n writer.u32le(encryptionMethods);\n writer.u32le(0); // extEncryptionMethods, French locale only\n return userDataBlock(CS_SECURITY, writer.take());\n}\n\n/** TS_UD_CS_CLUSTER, needed so the host reports redirection instead of hanging. */\nfunction clientClusterData() {\n const writer = new Writer(8);\n writer.u32le(0x0000000d); // REDIRECTION_SUPPORTED | redirection version 4\n writer.u32le(0); // RedirectedSessionID\n return userDataBlock(CS_CLUSTER, writer.take());\n}\n\nfunction clientNetworkData(channels) {\n if (channels.length === 0) return new Uint8Array(0);\n\n const writer = new Writer(4 + channels.length * 12);\n writer.u32le(channels.length);\n for (const channel of channels) {\n const name = new Uint8Array(8);\n for (let i = 0; i < Math.min(7, channel.name.length); i++) name[i] = channel.name.charCodeAt(i);\n writer.raw(name);\n writer.u32le(channel.options >>> 0);\n }\n return userDataBlock(CS_NET, writer.take());\n}\n\nexport function clientData(options) {\n return concatBytes(\n clientCoreData(options),\n clientClusterData(),\n clientSecurityData(options.encryptionMethods),\n clientNetworkData(options.channels || [])\n );\n}\n\n/**\n * Walk the host's answer. Only the security and network blocks carry anything\n * the client must act on; the core block is kept for logging.\n */\nexport function parseServerData(blocks) {\n const reader = new Reader(blocks);\n const result = {\n version: null,\n encryptionMethod: 0,\n encryptionLevel: ENCRYPTION_LEVEL.NONE,\n serverRandom: null,\n publicKey: null,\n ioChannelId: 1003,\n channelIds: [],\n };\n\n while (reader.remaining >= 4) {\n const type = reader.u16le();\n const length = reader.u16le();\n if (length < 4 || length - 4 > reader.remaining) break;\n const body = new Reader(reader.raw(length - 4));\n\n if (type === SC_CORE) {\n result.version = body.remaining >= 4 ? body.u32le() : null;\n continue;\n }\n\n if (type === SC_NET) {\n result.ioChannelId = body.u16le();\n const channelCount = body.u16le();\n for (let i = 0; i < channelCount && body.remaining >= 2; i++) {\n result.channelIds.push(body.u16le());\n }\n continue;\n }\n\n if (type === SC_SECURITY) {\n result.encryptionMethod = body.u32le();\n result.encryptionLevel = body.u32le();\n\n // With TLS in play the host reports no RDP-level encryption and stops.\n if (result.encryptionMethod === 0 && result.encryptionLevel === 0) continue;\n if (body.remaining < 8) continue;\n\n const serverRandomLength = body.u32le();\n const serverCertLength = body.u32le();\n result.serverRandom = body.raw(serverRandomLength).slice();\n result.publicKey = parseServerCertificate(body.raw(serverCertLength));\n continue;\n }\n }\n\n return result;\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/protocols/rdp/keymap.ts"],
4
- "sourcesContent": ["// KeyboardEvent.code -> PC/AT set 1 scancode, which is what RDP carries.\n// Keys marked extended need KBDFLAGS_EXTENDED so the host tells, for example,\n// the numeric keypad Enter from the main one.\n\nconst SCANCODES = {\n Escape: 0x01,\n Digit1: 0x02, Digit2: 0x03, Digit3: 0x04, Digit4: 0x05, Digit5: 0x06,\n Digit6: 0x07, Digit7: 0x08, Digit8: 0x09, Digit9: 0x0a, Digit0: 0x0b,\n Minus: 0x0c, Equal: 0x0d, Backspace: 0x0e, Tab: 0x0f,\n KeyQ: 0x10, KeyW: 0x11, KeyE: 0x12, KeyR: 0x13, KeyT: 0x14,\n KeyY: 0x15, KeyU: 0x16, KeyI: 0x17, KeyO: 0x18, KeyP: 0x19,\n BracketLeft: 0x1a, BracketRight: 0x1b, Enter: 0x1c, ControlLeft: 0x1d,\n KeyA: 0x1e, KeyS: 0x1f, KeyD: 0x20, KeyF: 0x21, KeyG: 0x22,\n KeyH: 0x23, KeyJ: 0x24, KeyK: 0x25, KeyL: 0x26,\n Semicolon: 0x27, Quote: 0x28, Backquote: 0x29, ShiftLeft: 0x2a, Backslash: 0x2b,\n KeyZ: 0x2c, KeyX: 0x2d, KeyC: 0x2e, KeyV: 0x2f, KeyB: 0x30,\n KeyN: 0x31, KeyM: 0x32, Comma: 0x33, Period: 0x34, Slash: 0x35,\n ShiftRight: 0x36, NumpadMultiply: 0x37, AltLeft: 0x38, Space: 0x39, CapsLock: 0x3a,\n F1: 0x3b, F2: 0x3c, F3: 0x3d, F4: 0x3e, F5: 0x3f,\n F6: 0x40, F7: 0x41, F8: 0x42, F9: 0x43, F10: 0x44,\n NumLock: 0x45, ScrollLock: 0x46,\n Numpad7: 0x47, Numpad8: 0x48, Numpad9: 0x49, NumpadSubtract: 0x4a,\n Numpad4: 0x4b, Numpad5: 0x4c, Numpad6: 0x4d, NumpadAdd: 0x4e,\n Numpad1: 0x4f, Numpad2: 0x50, Numpad3: 0x51, Numpad0: 0x52, NumpadDecimal: 0x53,\n IntlBackslash: 0x56, F11: 0x57, F12: 0x58,\n IntlRo: 0x73, IntlYen: 0x7d,\n};\n\nconst EXTENDED_SCANCODES = {\n NumpadEnter: 0x1c,\n ControlRight: 0x1d,\n NumpadDivide: 0x35,\n PrintScreen: 0x37,\n AltRight: 0x38,\n Home: 0x47,\n ArrowUp: 0x48,\n PageUp: 0x49,\n ArrowLeft: 0x4b,\n ArrowRight: 0x4d,\n End: 0x4f,\n ArrowDown: 0x50,\n PageDown: 0x51,\n Insert: 0x52,\n Delete: 0x53,\n MetaLeft: 0x5b,\n MetaRight: 0x5c,\n ContextMenu: 0x5d,\n};\n\n/** Returns { scancode, extended } or null when the key has no RDP equivalent. */\nexport function lookupScancode(code: string) {\n if (Object.prototype.hasOwnProperty.call(SCANCODES, code)) {\n return { scancode: SCANCODES[code], extended: false };\n }\n if (Object.prototype.hasOwnProperty.call(EXTENDED_SCANCODES, code)) {\n return { scancode: EXTENDED_SCANCODES[code], extended: true };\n }\n return null;\n}\n\nexport const CTRL_ALT_DEL = [\n { code: 'ControlLeft', pressed: true },\n { code: 'AltLeft', pressed: true },\n { code: 'Delete', pressed: true },\n { code: 'Delete', pressed: false },\n { code: 'AltLeft', pressed: false },\n { code: 'ControlLeft', pressed: false },\n];\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
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": "AAGA,SAAS,QAAQ,QAAQ,mBAAmB;AAC5C,SAAS,WAAW,mBAAmB;AAEhC,MAAM,sBAAsB;AAC5B,MAAM,wBAAwB;AAErC,MAAM,gBAAgB;AAAA,EACpB,sBAAsB;AAAA,EACtB,+BAA+B;AAAA,EAC/B,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,sBAAsB;AACxB;AAEA,MAAM,qBAAqB;AAAA,EACzB,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAIA,SAAS,UAAU,QAAgB;AACjC,MAAI,SAAS,IAAM,QAAO,IAAI,WAAW,CAAC,KAAO,UAAU,IAAK,KAAM,SAAS,GAAI,CAAC;AACpF,MAAI,SAAS,IAAM,QAAO,IAAI,WAAW,CAAC,KAAM,MAAM,CAAC;AACvD,SAAO,IAAI,WAAW,CAAC,MAAM,CAAC;AAChC;AAEA,SAAS,OAAO,KAAa,SAAqB;AAChD,SAAO,YAAY,IAAI,WAAW,GAAG,GAAG,UAAU,QAAQ,MAAM,GAAG,OAAO;AAC5E;AAEA,SAAS,WAAW,OAAe;AACjC,MAAI;AACJ,MAAI,QAAQ,IAAM,QAAO,IAAI,WAAW,CAAC,KAAK,CAAC;AAAA,WACtC,QAAQ,MAAQ,QAAO,IAAI,WAAW,CAAC,SAAS,GAAG,QAAQ,GAAI,CAAC;AAAA,WAChE,QAAQ,QAAU,QAAO,IAAI,WAAW,CAAC,SAAS,IAAK,SAAS,IAAK,KAAM,QAAQ,GAAI,CAAC;AAAA,MAC5F,QAAO,IAAI,WAAW,CAAC,UAAU,IAAK,SAAS,KAAM,KAAO,SAAS,IAAK,KAAM,QAAQ,GAAI,CAAC;AAClG,SAAO,OAAO,CAAC,CAAI,GAAG,IAAI;AAC5B;AAEA,MAAM,iBAAiB,CAAC,UAAsB,OAAO,CAAC,CAAI,GAAG,KAAK;AAClE,MAAM,aAAa,CAAC,UAAkB,OAAO,CAAC,CAAI,GAAG,IAAI,WAAW,CAAC,QAAQ,MAAO,CAAI,CAAC,CAAC;AAG1F,SAAS,oBAAoB,QAA2B;AACtD,SAAO,OAAO,CAAC,EAAI,GAAG,YAAY,GAAG,OAAO,IAAI,UAAU,CAAC,CAAC;AAC9D;AAIA,SAAS,UAAU,QAAgB,QAAgB;AACjD,MAAI,SAAS,IAAM,QAAO,MAAM,QAAS,MAAM;AAAA,MAC1C,QAAO,GAAG,MAAM;AACrB,SAAO;AACT;AAEA,SAAS,cAAc,QAAgB;AACrC,QAAM,QAAQ,OAAO,GAAG;AACxB,SAAO,QAAQ,OAAS,QAAQ,QAAS,IAAK,OAAO,GAAG,IAAI;AAC9D;AAIA,MAAM,yBAAyB,IAAI,WAAW,CAAC,GAAM,GAAM,IAAM,KAAM,GAAM,CAAI,CAAC;AAClF,MAAM,kBAAkB,IAAI,WAAW,CAAC,IAAM,KAAM,IAAM,EAAI,CAAC;AAC/D,MAAM,kBAAkB,IAAI,WAAW,CAAC,IAAM,IAAM,IAAM,GAAI,CAAC;AAE/D,SAAS,2BAA2B,YAAwB;AAC1D,QAAM,SAAS,IAAI,OAAO,WAAW,SAAS,EAAE;AAEhD,SAAO,GAAG,CAAC;AACX,SAAO,IAAI,sBAAsB;AACjC,YAAU,QAAQ,WAAW,SAAS,EAAE;AAExC,SAAO,GAAG,CAAC;AACX,SAAO,GAAG,CAAI;AACd,SAAO,GAAG,CAAI;AACd,SAAO,GAAG,EAAI;AACd,SAAO,GAAG,CAAI;AACd,SAAO,GAAG,CAAI;AACd,SAAO,GAAG,GAAI;AACd,SAAO,GAAG,CAAI;AACd,SAAO,IAAI,eAAe;AAC1B,YAAU,QAAQ,WAAW,MAAM;AACnC,SAAO,IAAI,UAAU;AAErB,SAAO,OAAO,KAAK;AACrB;AASA,SAAS,oBAAoB,UAAsB;AACjD,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,QACE,SAAS,CAAC,MAAM,gBAAgB,CAAC,KACjC,SAAS,IAAI,CAAC,MAAM,gBAAgB,CAAC,KACrC,SAAS,IAAI,CAAC,MAAM,gBAAgB,CAAC,KACrC,SAAS,IAAI,CAAC,MAAM,gBAAgB,CAAC,GACrC;AACA,YAAM,SAAS,IAAI,OAAO,UAAU,IAAI,CAAC;AACzC,YAAM,SAAS,cAAc,MAAM;AACnC,YAAM,SAAS,OAAO,KAAK;AAC3B,aAAO,OAAO,SAAS,GAAG,KAAK,IAAI,QAAQ,OAAO,MAAM,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,QAAM,IAAI,MAAM,qDAAqD;AACvE;AAIA,MAAM,gBAAgB,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,OAAQ,CAAC;AACnD,MAAM,iBAAiB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,MAAO,CAAC;AAClD,MAAM,iBAAiB,CAAC,OAAQ,OAAQ,OAAQ,GAAG,GAAG,GAAG,OAAQ,CAAC;AAE3D,SAAS,eAAe,YAAwB;AACrD,QAAM,WAAW,2BAA2B,UAAU;AACtD,QAAM,UAAU;AAAA,IACd,eAAe,IAAI,WAAW,CAAC,CAAI,CAAC,CAAC;AAAA;AAAA,IACrC,eAAe,IAAI,WAAW,CAAC,CAAI,CAAC,CAAC;AAAA;AAAA,IACrC,WAAW,IAAI;AAAA;AAAA,IACf,oBAAoB,aAAa;AAAA,IACjC,oBAAoB,cAAc;AAAA,IAClC,oBAAoB,cAAc;AAAA,IAClC,eAAe,QAAQ;AAAA,EACzB;AAGA,SAAO,UAAU,OAAO,CAAC,KAAM,GAAI,GAAG,OAAO,CAAC;AAChD;AAGA,SAAS,WAAW,QAAgB;AAClC,MAAI,MAAM,OAAO,GAAG;AACpB,OAAK,MAAM,QAAU,GAAM,OAAO,OAAO,IAAK,OAAO,GAAG;AAExD,MAAI,SAAS,OAAO,GAAG;AACvB,MAAI,SAAS,KAAM;AACjB,UAAM,YAAY,SAAS;AAC3B,aAAS;AACT,aAAS,IAAI,GAAG,IAAI,WAAW,IAAK,UAAU,UAAU,IAAK,OAAO,GAAG;AAAA,EACzE;AAEA,SAAO,EAAE,KAAK,OAAO,OAAO,IAAI,MAAM,EAAE;AAC1C;AAEO,SAAS,qBAAqB,OAAmB;AACtD,QAAM,SAAS,IAAI,OAAO,YAAY,KAAK,CAAC;AAC5C,QAAM,QAAQ,WAAW,MAAM;AAC/B,MAAI,MAAM,QAAQ,OAAQ;AACxB,UAAM,IAAI,MAAM,wDAAwD,MAAM,IAAI,SAAS,EAAE,CAAC,EAAE;AAAA,EAClG;AAEA,QAAM,QAAQ,IAAI,OAAO,MAAM,KAAK;AACpC,QAAM,SAAS,WAAW,KAAK;AAC/B,aAAW,KAAK;AAChB,aAAW,KAAK;AAChB,QAAM,WAAW,WAAW,KAAK;AAEjC,MAAI,OAAO,MAAM,CAAC,MAAM,GAAG;AACzB,UAAM,IAAI,MAAM,qDAAqD,OAAO,MAAM,CAAC,CAAC,GAAG;AAAA,EACzF;AAEA,SAAO,oBAAoB,SAAS,KAAK;AAC3C;AAIA,MAAM,eAAe,CAAC,QAAoB,OAAO;AAE1C,SAAS,qBAAqB;AACnC,QAAM,SAAS,IAAI,OAAO,CAAC;AAC3B,SAAO,GAAG,aAAa,cAAc,oBAAoB,CAAC;AAC1D,SAAO,GAAG,CAAC,EAAE,GAAG,CAAC;AACjB,SAAO,GAAG,CAAC,EAAE,GAAG,CAAC;AACjB,SAAO,UAAU,OAAO,KAAK,CAAC;AAChC;AAEO,SAAS,oBAAoB;AAClC,SAAO,UAAU,IAAI,WAAW,CAAC,aAAa,cAAc,mBAAmB,CAAC,CAAC,CAAC;AACpF;AAEO,SAAS,uBAAuB,OAAmB;AACxD,QAAM,SAAS,IAAI,OAAO,YAAY,KAAK,CAAC;AAC5C,QAAM,SAAS,OAAO,GAAG;AACzB,MAAI,UAAU,MAAM,cAAc,qBAAqB;AACrD,UAAM,IAAI,MAAM,qDAAqD,UAAU,CAAC,EAAE;AAAA,EACpF;AAEA,QAAM,SAAS,OAAO,GAAG;AACzB,MAAI,WAAW,EAAG,OAAM,IAAI,MAAM,kDAAkD,MAAM,GAAG;AAG7F,QAAM,SAAS,SAAS,IAAO,OAAO,MAAM,IAAI,sBAAsB;AACtE,SAAO,EAAE,OAAO;AAClB;AAEO,SAAS,mBAAmB,QAAgB,WAAmB;AACpE,QAAM,SAAS,IAAI,OAAO,CAAC;AAC3B,SAAO,GAAG,aAAa,cAAc,oBAAoB,CAAC;AAC1D,SAAO,MAAM,SAAS,mBAAmB;AACzC,SAAO,MAAM,SAAS;AACtB,SAAO,UAAU,OAAO,KAAK,CAAC;AAChC;AAEO,SAAS,wBAAwB,OAAmB;AACzD,QAAM,SAAS,IAAI,OAAO,YAAY,KAAK,CAAC;AAC5C,QAAM,SAAS,OAAO,GAAG;AACzB,MAAI,UAAU,MAAM,cAAc,sBAAsB;AACtD,UAAM,IAAI,MAAM,sDAAsD,UAAU,CAAC,EAAE;AAAA,EACrF;AAEA,QAAM,SAAS,OAAO,GAAG;AACzB,SAAO,MAAM;AACb,QAAM,YAAY,OAAO,MAAM;AAC/B,MAAI,WAAW,GAAG;AAChB,UAAM,IAAI,MAAM,yCAAyC,SAAS,YAAY,MAAM,GAAG;AAAA,EACzF;AAGA,QAAM,YAAY,OAAO,aAAa,IAAI,OAAO,MAAM,IAAI;AAC3D,SAAO,EAAE,WAAW,aAAa,UAAU;AAC7C;AAEO,SAAS,gBAAgB,QAAgB,WAAmB,SAAqB;AACtF,QAAM,SAAS,IAAI,OAAO,QAAQ,SAAS,EAAE;AAC7C,SAAO,GAAG,aAAa,cAAc,iBAAiB,CAAC;AACvD,SAAO,MAAM,SAAS,mBAAmB;AACzC,SAAO,MAAM,SAAS;AACtB,SAAO,GAAG,GAAI;AACd,YAAU,QAAQ,QAAQ,MAAM;AAChC,SAAO,IAAI,OAAO;AAClB,SAAO,UAAU,OAAO,KAAK,CAAC;AAChC;AAMO,SAAS,eAAe,OAAmB;AAChD,QAAM,SAAS,IAAI,OAAO,YAAY,KAAK,CAAC;AAC5C,QAAM,SAAS,OAAO,GAAG;AACzB,QAAM,OAAO,UAAU;AAEvB,MAAI,SAAS,cAAc,sBAAsB;AAC/C,WAAO,MAAM;AACb,UAAM,YAAY,OAAO,MAAM;AAC/B,WAAO,GAAG;AACV,UAAM,SAAS,cAAc,MAAM;AACnC,UAAM,UAAU,OAAO,KAAK;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,SAAS,QAAQ,SAAS,GAAG,KAAK,IAAI,QAAQ,QAAQ,MAAM,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,MAAI,SAAS,cAAc,+BAA+B;AAGxD,UAAM,UAAW,SAAS,MAAS,KAAM,OAAO,YAAY,IAAI,OAAO,GAAG,KAAK,IAAI;AACnF,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,SAAS,mBAAmB,MAAM,KAAK,2CAA2C,MAAM;AAAA,IAC1F;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,SAAS,YAAY,KAAK;AAC3C;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
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": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/protocols/rdp/pdu.ts"],
4
- "sourcesContent": ["// The share layer: PDU headers, the client info PDU, input events, and the\n// server update PDUs this client understands (MS-RDPBCGR 2.2.8, 2.2.9, 2.2.1.13).\n\nimport { Reader, Writer } from './buffer';\n\nexport const PDU_TYPE = {\n DEMAND_ACTIVE: 1,\n CONFIRM_ACTIVE: 3,\n DEACTIVATE_ALL: 6,\n DATA: 7,\n SERVER_REDIRECT: 10,\n};\n\nexport const PDU_TYPE2 = {\n UPDATE: 2,\n CONTROL: 20,\n POINTER: 27,\n INPUT: 28,\n SYNCHRONIZE: 31,\n REFRESH_RECT: 33,\n PLAY_SOUND: 34,\n SUPPRESS_OUTPUT: 35,\n SHUTDOWN_REQUEST: 36,\n SHUTDOWN_DENIED: 37,\n SAVE_SESSION_INFO: 38,\n FONT_LIST: 39,\n FONT_MAP: 40,\n SET_ERROR_INFO: 47,\n MONITOR_LAYOUT: 55,\n};\n\nexport const UPDATE_TYPE = {\n ORDERS: 0,\n BITMAP: 1,\n PALETTE: 2,\n SYNCHRONIZE: 3,\n};\n\nexport const CONTROL_ACTION = {\n REQUEST_CONTROL: 1,\n GRANTED_CONTROL: 2,\n DETACH: 3,\n COOPERATE: 4,\n};\n\nexport const INPUT_EVENT = {\n SYNC: 0x0000,\n SCANCODE: 0x0004,\n UNICODE: 0x0005,\n MOUSE: 0x8001,\n MOUSEX: 0x8002,\n};\n\nexport const KEYBOARD_FLAG = {\n EXTENDED: 0x0100,\n DOWN: 0x4000,\n RELEASE: 0x8000,\n};\n\nexport const POINTER_FLAG = {\n WHEEL: 0x0200,\n HWHEEL: 0x0400,\n WHEEL_NEGATIVE: 0x0100,\n MOVE: 0x0800,\n DOWN: 0x8000,\n BUTTON1: 0x1000,\n BUTTON2: 0x2000,\n BUTTON3: 0x4000,\n};\n\n/** Translate browser-style wheel direction to the signed RDP rotation flags. */\nexport function pointerWheelFlags(delta: number, horizontal = false): number {\n const steps = horizontal ? Math.sign(delta) : -Math.sign(delta);\n if (steps === 0) return 0;\n const wheelFlag = horizontal ? POINTER_FLAG.HWHEEL : POINTER_FLAG.WHEEL;\n const rotation = 120;\n return steps > 0\n ? wheelFlag | rotation\n : wheelFlag | POINTER_FLAG.WHEEL_NEGATIVE | ((-rotation) & 0xff);\n}\n\nexport const TOGGLE_FLAG = {\n SCROLL_LOCK: 0x0001,\n NUM_LOCK: 0x0002,\n CAPS_LOCK: 0x0004,\n KANA_LOCK: 0x0008,\n};\n\nconst POINTER_MESSAGE = {\n SYSTEM: 0x0001,\n POSITION: 0x0003,\n COLOR: 0x0006,\n CACHED: 0x0007,\n POINTER: 0x0008,\n LARGE: 0x0009,\n};\n\nconst INFO_FLAG =\n 0x00000001 | // INFO_MOUSE\n 0x00000002 | // INFO_DISABLECTRLALTDEL\n 0x00000010 | // INFO_UNICODE\n 0x00000020 | // INFO_MAXIMIZESHELL\n 0x00000040 | // INFO_LOGONNOTIFY\n 0x00000100 | // INFO_ENABLEWINDOWSKEY\n 0x00010000 | // INFO_LOGONERRORS\n 0x00020000 | // INFO_MOUSE_HAS_WHEEL\n 0x00080000; // INFO_NOAUDIOPLAYBACK\n\nconst INFO_AUTOLOGON = 0x00000008;\nconst INFO_RAIL = 0x00008000;\n\nconst ERROR_INFO_MESSAGES = {\n 0x00000001: 'The host disconnected the session (an administrative API call ended it).',\n 0x00000002: 'The host logged the session off.',\n 0x00000003: 'The session was disconnected after being idle too long.',\n 0x00000004: 'The session was disconnected because sign-in took too long.',\n 0x00000005: 'The session was taken over by another connection.',\n 0x00000006: 'The host ran out of memory.',\n 0x00000007: 'The host denied the connection.',\n 0x00000009: 'This account does not have permission to sign in remotely.',\n 0x0000000a: 'The host requires fresh credentials.',\n 0x0000000b: 'A user on the host ended the session.',\n 0x0000000c: 'The remote user signed out.',\n 0x00000100: 'Remote Desktop licensing failed on the host (internal error).',\n 0x00000101: 'The host could not reach a Remote Desktop licensing server.',\n 0x00000102: 'The host has no Remote Desktop licence available for this client.',\n 0x00000103: 'The host rejected this client during licensing.',\n 0x00000104: 'The stored Remote Desktop licence does not match this client.',\n 0x00000105: 'The host rejected the client licence.',\n 0x00000106: 'Remote Desktop licensing could not be completed.',\n 0x00000107: 'The client ended the licensing exchange.',\n 0x00000108: 'The host rejected the client licence encryption.',\n 0x00000109: 'The host could not upgrade the client licence.',\n 0x0000010a: 'The host does not accept remote connections.',\n 0x000010f9: 'The host rejected a malformed capability set from this client.',\n 0x000010fa: 'The host rejected the client capability exchange.',\n};\n\nexport function errorInfoMessage(errorInfo) {\n return (\n ERROR_INFO_MESSAGES[errorInfo] ||\n `The host ended the session with error info 0x${errorInfo.toString(16).padStart(8, '0')}.`\n );\n}\n\n// --- Outbound PDUs ----------------------------------------------------------\n\n/** TS_SHARECONTROLHEADER + payload. */\nexport function shareControlPdu(pduType, userId: number, payload: Uint8Array) {\n const writer = new Writer(payload.length + 6);\n writer.u16le(payload.length + 6);\n writer.u16le(pduType | 0x10); // low nibble is the type, high nibble the version\n writer.u16le(userId);\n writer.raw(payload);\n return writer.take();\n}\n\n/** TS_SHAREDATAHEADER inside a share control PDU of type DATA. */\nexport function shareDataPdu(shareId: number, userId: number, pduType2, payload: Uint8Array) {\n const writer = new Writer(payload.length + 12);\n writer.u32le(shareId);\n writer.u8(0); // pad\n writer.u8(1); // streamId: low priority\n writer.u16le(payload.length + 18); // uncompressedLength, headers included\n writer.u8(pduType2);\n writer.u8(0); // compressedType: none\n writer.u16le(0); // compressedLength\n writer.raw(payload);\n return shareControlPdu(PDU_TYPE.DATA, userId, writer.take());\n}\n\n/** Write a UTF-16LE field with its terminator, returning the length without it. */\nfunction unicodeField(writer: Writer, text: string) {\n const start = writer.length;\n writer.utf16le(text);\n const byteLength = writer.length - start;\n writer.u16le(0); // terminator\n return byteLength;\n}\n\n/**\n * Client Info PDU (MS-RDPBCGR 2.2.1.11). The credential lengths sit in front of\n * the strings, so the strings are written to a scratch buffer first.\n */\nexport function clientInfoPdu({ domain, username, password, performanceFlags, autoLogon, remoteApp = false }) {\n const strings = new Writer(512);\n const cbDomain = unicodeField(strings, domain || '');\n const cbUsername = unicodeField(strings, username || '');\n const cbPassword = unicodeField(strings, password || '');\n const cbAlternateShell = unicodeField(strings, '');\n const cbWorkingDir = unicodeField(strings, '');\n\n const writer = new Writer(768);\n writer.u32le(0); // codePage\n writer.u32le((INFO_FLAG | (autoLogon ? INFO_AUTOLOGON : 0) | (remoteApp ? INFO_RAIL : 0)) >>> 0);\n writer.u16le(cbDomain);\n writer.u16le(cbUsername);\n writer.u16le(cbPassword);\n writer.u16le(cbAlternateShell);\n writer.u16le(cbWorkingDir);\n writer.raw(strings.take());\n\n // TS_EXTENDED_INFO_PACKET\n writer.u16le(2); // clientAddressFamily: AF_INET\n writer.u16le(2); // cbClientAddress: just the terminator\n writer.u16le(0);\n writer.u16le(2); // cbClientDir\n writer.u16le(0);\n writer.zeros(172); // clientTimeZone\n writer.u32le(0); // clientSessionId\n writer.u32le(performanceFlags >>> 0);\n writer.u16le(0); // cbAutoReconnectCookie\n\n return writer.take();\n}\n\nexport function synchronizePdu(targetUser) {\n const writer = new Writer(4);\n writer.u16le(1); // SYNCMSGTYPE_SYNC\n writer.u16le(targetUser);\n return writer.take();\n}\n\nexport function controlPdu(action) {\n const writer = new Writer(8);\n writer.u16le(action);\n writer.u16le(0); // grantId\n writer.u32le(0); // controlId\n return writer.take();\n}\n\nexport function fontListPdu() {\n const writer = new Writer(8);\n writer.u16le(0); // numberFonts\n writer.u16le(0); // totalNumberFonts\n writer.u16le(0x0003); // listFlags: first and last\n writer.u16le(0x0032); // entrySize\n return writer.take();\n}\n\nexport function confirmActivePdu(shareId: number, capabilities, capabilityCount) {\n const sourceDescriptor = new TextEncoder().encode('MSTSC\\0');\n const writer = new Writer(capabilities.length + 32);\n\n writer.u32le(shareId);\n writer.u16le(0x03ea); // originatorId: the server channel\n writer.u16le(sourceDescriptor.length);\n writer.u16le(capabilities.length + 4); // lengthCombinedCapabilities\n writer.raw(sourceDescriptor);\n writer.u16le(capabilityCount);\n writer.u16le(0); // pad\n writer.raw(capabilities);\n\n return writer.take();\n}\n\n/** TS_INPUT_PDU_DATA: a batch of input events sharing one header. */\nexport function inputEventsPdu(events) {\n const writer = new Writer(events.length * 12 + 4);\n writer.u16le(events.length);\n writer.u16le(0); // pad\n for (const event of events) writer.raw(event);\n return writer.take();\n}\n\nfunction inputEvent(messageType, write) {\n const writer = new Writer(12);\n writer.u32le(0); // eventTime, ignored by every host\n writer.u16le(messageType);\n write(writer);\n return writer.take();\n}\n\nexport function scancodeEvent(scancode, pressed: boolean, extended) {\n return inputEvent(INPUT_EVENT.SCANCODE, (writer: Writer) => {\n writer.u16le(\n (pressed ? KEYBOARD_FLAG.DOWN : KEYBOARD_FLAG.RELEASE) |\n (extended ? KEYBOARD_FLAG.EXTENDED : 0)\n );\n writer.u16le(scancode);\n writer.u16le(0);\n });\n}\n\nexport function unicodeEvent(codeUnit, pressed: boolean) {\n return inputEvent(INPUT_EVENT.UNICODE, (writer: Writer) => {\n writer.u16le(pressed ? KEYBOARD_FLAG.DOWN : KEYBOARD_FLAG.RELEASE);\n writer.u16le(codeUnit);\n writer.u16le(0);\n });\n}\n\nexport function mouseEvent(flags: number, x: number, y: number) {\n return inputEvent(INPUT_EVENT.MOUSE, (writer: Writer) => {\n writer.u16le(flags);\n writer.u16le(Math.max(0, Math.min(0xffff, Math.round(x))));\n writer.u16le(Math.max(0, Math.min(0xffff, Math.round(y))));\n });\n}\n\nexport function extendedMouseEvent(flags: number, x: number, y: number) {\n return inputEvent(INPUT_EVENT.MOUSEX, (writer: Writer) => {\n writer.u16le(flags);\n writer.u16le(Math.max(0, Math.min(0xffff, Math.round(x))));\n writer.u16le(Math.max(0, Math.min(0xffff, Math.round(y))));\n });\n}\n\nexport function syncEvent(toggleFlags: number) {\n return inputEvent(INPUT_EVENT.SYNC, (writer: Writer) => {\n writer.u16le(0);\n writer.u32le(toggleFlags >>> 0);\n });\n}\n\nexport function refreshRectPdu(rects) {\n const writer = new Writer(4 + rects.length * 8);\n writer.u8(rects.length);\n writer.zeros(3); // pad\n for (const rect of rects) {\n writer.u16le(rect.left);\n writer.u16le(rect.top);\n writer.u16le(rect.right);\n writer.u16le(rect.bottom);\n }\n return writer.take();\n}\n\nexport function suppressOutputPdu(allowDisplayUpdates, rect) {\n const writer = new Writer(12);\n writer.u8(allowDisplayUpdates ? 1 : 0);\n writer.zeros(3); // pad\n if (allowDisplayUpdates && rect) {\n writer.u16le(rect.left);\n writer.u16le(rect.top);\n writer.u16le(rect.right);\n writer.u16le(rect.bottom);\n }\n return writer.take();\n}\n\n// --- Inbound PDUs -----------------------------------------------------------\n\nexport function parseShareControlHeader(bytes: Uint8Array) {\n const reader = new Reader(bytes);\n const totalLength = reader.u16le();\n const typeAndVersion = reader.u16le();\n const pduSource = reader.u16le();\n\n return {\n totalLength,\n pduType: typeAndVersion & 0x0f,\n pduSource,\n payload: reader.rest().subarray(0, Math.max(0, totalLength - 6)),\n };\n}\n\nexport function parseShareDataHeader(bytes: Uint8Array) {\n const reader = new Reader(bytes);\n const shareId = reader.u32le();\n reader.u8(); // pad\n reader.u8(); // streamId\n reader.u16le(); // uncompressedLength\n const pduType2 = reader.u8();\n const compressedType = reader.u8();\n const compressedLength = reader.u16le();\n\n return { shareId, pduType2, compressedType, compressedLength, payload: reader.rest() };\n}\n\nexport function parseDemandActive(bytes: Uint8Array) {\n const reader = new Reader(bytes);\n const shareId = reader.u32le();\n const lengthSourceDescriptor = reader.u16le();\n const lengthCombinedCapabilities = reader.u16le();\n reader.skip(lengthSourceDescriptor);\n\n const capabilities = reader.raw(Math.min(lengthCombinedCapabilities, reader.remaining));\n return { shareId, capabilities };\n}\n\nconst BITMAP_COMPRESSION = 0x0001;\nconst NO_BITMAP_COMPRESSION_HDR = 0x0400;\n\nexport function parseBitmapUpdate(reader: Reader) {\n const count = reader.u16le();\n const rects = [];\n\n for (let i = 0; i < count && reader.remaining >= 18; i++) {\n const left = reader.u16le();\n const top = reader.u16le();\n const right = reader.u16le();\n const bottom = reader.u16le();\n const width = reader.u16le();\n const height = reader.u16le();\n const bitsPerPixel = reader.u16le();\n const flags = reader.u16le();\n let bitmapLength = reader.u16le();\n\n const compressed = Boolean(flags & BITMAP_COMPRESSION);\n if (compressed && !(flags & NO_BITMAP_COMPRESSION_HDR)) {\n // TS_CD_HEADER: the main body size is authoritative, and the eight header\n // bytes are counted in bitmapLength.\n reader.u16le(); // cbCompFirstRowSize, always zero\n const mainBodySize = reader.u16le();\n reader.u16le(); // cbScanWidth\n reader.u16le(); // cbUncompressedSize\n bitmapLength = mainBodySize;\n }\n\n rects.push({\n left,\n top,\n right,\n bottom,\n width,\n height,\n bitsPerPixel,\n compressed,\n data: reader.raw(Math.min(bitmapLength, reader.remaining)),\n });\n }\n\n return rects;\n}\n\nexport function parsePaletteUpdate(reader: Reader) {\n reader.u16le(); // updateType, repeated\n reader.u16le(); // pad\n const count = reader.u32le();\n const palette = new Uint8Array(256 * 3);\n\n for (let i = 0; i < count && i < 256 && reader.remaining >= 3; i++) {\n palette[i * 3] = reader.u8();\n palette[i * 3 + 1] = reader.u8();\n palette[i * 3 + 2] = reader.u8();\n }\n return palette;\n}\n\nfunction parseColorPointer(reader: Reader, xorBpp) {\n const cacheIndex = reader.u16le();\n const hotSpotX = reader.u16le();\n const hotSpotY = reader.u16le();\n const width = reader.u16le();\n const height = reader.u16le();\n const andMaskLength = reader.u16le();\n const xorMaskLength = reader.u16le();\n const xorMask = reader.raw(Math.min(xorMaskLength, reader.remaining)).slice();\n const andMask = reader.raw(Math.min(andMaskLength, reader.remaining)).slice();\n\n return {\n kind: 'bitmap',\n cacheIndex,\n hotSpotX,\n hotSpotY,\n width,\n height,\n xorBpp: xorBpp || 24,\n xorMask,\n andMask,\n };\n}\n\nexport function parsePointerUpdate(reader: Reader) {\n const messageType = reader.u16le();\n reader.u16le(); // pad\n\n if (messageType === POINTER_MESSAGE.POSITION) {\n return { kind: 'position', x: reader.u16le(), y: reader.u16le() };\n }\n\n if (messageType === POINTER_MESSAGE.SYSTEM) {\n const systemPointerType = reader.u32le();\n return { kind: 'system', hidden: systemPointerType === 0x00000000 };\n }\n\n if (messageType === POINTER_MESSAGE.CACHED) {\n return { kind: 'cached', cacheIndex: reader.u16le() };\n }\n\n if (messageType === POINTER_MESSAGE.COLOR) {\n return parseColorPointer(reader, 24);\n }\n\n if (messageType === POINTER_MESSAGE.POINTER) {\n const xorBpp = reader.u16le();\n return parseColorPointer(reader, xorBpp);\n }\n\n if (messageType === POINTER_MESSAGE.LARGE) {\n // Large pointers are only sent when advertised; treat as unsupported.\n return { kind: 'unsupported', messageType };\n }\n\n return { kind: 'unsupported', messageType };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
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
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/protocols/rdp/rle.ts"],
4
- "sourcesContent": ["// Interleaved RLE bitmap decompression (MS-RDPEGDI 3.1.9) plus the pixel\n// conversion that turns decoded pixels into something a canvas can accept.\n//\n// Pixels are decoded into a Uint32Array of raw values first, so one copy of the\n// algorithm serves every colour depth; only the final conversion to RGBA knows\n// how a pixel is laid out.\n\nconst REGULAR_BG_RUN = 0x00;\nconst REGULAR_FG_RUN = 0x01;\nconst REGULAR_FGBG_IMAGE = 0x02;\nconst REGULAR_COLOR_RUN = 0x03;\nconst REGULAR_COLOR_IMAGE = 0x04;\nconst LITE_SET_FG_FG_RUN = 0x0c;\nconst LITE_SET_FG_FGBG_IMAGE = 0x0d;\nconst LITE_DITHERED_RUN = 0x0e;\nconst MEGA_MEGA_BG_RUN = 0xf0;\nconst MEGA_MEGA_FG_RUN = 0xf1;\nconst MEGA_MEGA_FGBG_IMAGE = 0xf2;\nconst MEGA_MEGA_COLOR_RUN = 0xf3;\nconst MEGA_MEGA_COLOR_IMAGE = 0xf4;\nconst MEGA_MEGA_SET_FG_RUN = 0xf6;\nconst MEGA_MEGA_SET_FGBG_IMAGE = 0xf7;\nconst MEGA_MEGA_DITHERED_RUN = 0xf8;\nconst SPECIAL_FGBG_1 = 0xf9;\nconst SPECIAL_FGBG_2 = 0xfa;\nconst SPECIAL_WHITE = 0xfd;\nconst SPECIAL_BLACK = 0xfe;\n\nconst MASK_SPECIAL_FGBG_1 = 0x03;\nconst MASK_SPECIAL_FGBG_2 = 0x05;\n\n/** Regular orders pack the code in the top bits; LITE and MEGA use a nibble. */\nfunction extractCodeId(header: number) {\n if ((header & 0xc0) !== 0xc0) return header >> 5;\n if ((header & 0xf0) === 0xf0) return header;\n return header >> 4;\n}\n\nexport function rleDecompress(src: Uint8Array, width: number, height: number, bytesPerPixel: number) {\n const pixels = new Uint32Array(width * height);\n const white = bytesPerPixel >= 4 ? 0xffffffff : (1 << (bytesPerPixel * 8)) - 1;\n\n let srcOffset = 0;\n let dest = 0;\n let foreground = white;\n let insertForegroundPixel = false;\n let firstLine = true;\n\n const readPixel = () => {\n let value = 0;\n for (let i = 0; i < bytesPerPixel; i++) value |= src[srcOffset + i] << (i * 8);\n srcOffset += bytesPerPixel;\n return value >>> 0;\n };\n\n const runLengthOf = (code: number) => {\n const header = src[srcOffset];\n\n if (code === REGULAR_FGBG_IMAGE) {\n const packed = header & 0x1f;\n if (packed === 0) {\n srcOffset += 2;\n return src[srcOffset - 1] + 1;\n }\n srcOffset += 1;\n return packed * 8;\n }\n\n if (code === LITE_SET_FG_FGBG_IMAGE) {\n const packed = header & 0x0f;\n if (packed === 0) {\n srcOffset += 2;\n return src[srcOffset - 1] + 1;\n }\n srcOffset += 1;\n return packed * 8;\n }\n\n if (\n code === REGULAR_BG_RUN ||\n code === REGULAR_FG_RUN ||\n code === REGULAR_COLOR_RUN ||\n code === REGULAR_COLOR_IMAGE\n ) {\n const packed = header & 0x1f;\n if (packed === 0) {\n srcOffset += 2;\n return src[srcOffset - 1] + 32;\n }\n srcOffset += 1;\n return packed;\n }\n\n if (code === LITE_SET_FG_FG_RUN || code === LITE_DITHERED_RUN) {\n const packed = header & 0x0f;\n if (packed === 0) {\n srcOffset += 2;\n return src[srcOffset - 1] + 16;\n }\n srcOffset += 1;\n return packed;\n }\n\n // Every MEGA_MEGA order carries a 16-bit run length.\n const length = src[srcOffset + 1] | (src[srcOffset + 2] << 8);\n srcOffset += 3;\n return length;\n };\n\n /** Foreground/background image: one bit per pixel, least significant first. */\n const writeFgBgImage = (bitmask: number, count: number) => {\n let mask = 0x01;\n for (let i = 0; i < count; i++) {\n if (firstLine) {\n pixels[dest] = bitmask & mask ? foreground : 0;\n } else {\n const above = pixels[dest - width];\n pixels[dest] = bitmask & mask ? (above ^ foreground) >>> 0 : above;\n }\n dest++;\n mask = (mask << 1) & 0xff;\n }\n };\n\n while (srcOffset < src.length && dest < pixels.length) {\n // The first scanline has no row above it to delta against. The switch\n // happens between orders, so a run that crosses the boundary keeps\n // first-line semantics throughout.\n if (firstLine && dest >= width) firstLine = false;\n\n const code = extractCodeId(src[srcOffset]);\n\n if (code === REGULAR_BG_RUN || code === MEGA_MEGA_BG_RUN) {\n let runLength = runLengthOf(code);\n\n if (firstLine) {\n if (insertForegroundPixel) {\n pixels[dest++] = foreground;\n runLength--;\n }\n while (runLength-- > 0 && dest < pixels.length) pixels[dest++] = 0;\n } else {\n if (insertForegroundPixel) {\n pixels[dest] = (pixels[dest - width] ^ foreground) >>> 0;\n dest++;\n runLength--;\n }\n while (runLength-- > 0 && dest < pixels.length) {\n pixels[dest] = pixels[dest - width];\n dest++;\n }\n }\n\n // Two background runs in a row mean a single foreground pixel between them.\n insertForegroundPixel = true;\n continue;\n }\n\n insertForegroundPixel = false;\n\n switch (code) {\n case REGULAR_FG_RUN:\n case MEGA_MEGA_FG_RUN:\n case LITE_SET_FG_FG_RUN:\n case MEGA_MEGA_SET_FG_RUN: {\n let runLength = runLengthOf(code);\n if (code === LITE_SET_FG_FG_RUN || code === MEGA_MEGA_SET_FG_RUN) foreground = readPixel();\n\n if (firstLine) {\n while (runLength-- > 0 && dest < pixels.length) pixels[dest++] = foreground;\n } else {\n while (runLength-- > 0 && dest < pixels.length) {\n pixels[dest] = (pixels[dest - width] ^ foreground) >>> 0;\n dest++;\n }\n }\n break;\n }\n\n case LITE_DITHERED_RUN:\n case MEGA_MEGA_DITHERED_RUN: {\n let runLength = runLengthOf(code);\n const pixelA = readPixel();\n const pixelB = readPixel();\n while (runLength-- > 0 && dest < pixels.length - 1) {\n pixels[dest++] = pixelA;\n pixels[dest++] = pixelB;\n }\n break;\n }\n\n case REGULAR_COLOR_RUN:\n case MEGA_MEGA_COLOR_RUN: {\n let runLength = runLengthOf(code);\n const color = readPixel();\n while (runLength-- > 0 && dest < pixels.length) pixels[dest++] = color;\n break;\n }\n\n case REGULAR_FGBG_IMAGE:\n case MEGA_MEGA_FGBG_IMAGE:\n case LITE_SET_FG_FGBG_IMAGE:\n case MEGA_MEGA_SET_FGBG_IMAGE: {\n let runLength = runLengthOf(code);\n if (code === LITE_SET_FG_FGBG_IMAGE || code === MEGA_MEGA_SET_FGBG_IMAGE) {\n foreground = readPixel();\n }\n\n while (runLength > 8) {\n writeFgBgImage(src[srcOffset++], 8);\n runLength -= 8;\n }\n if (runLength > 0) writeFgBgImage(src[srcOffset++], runLength);\n break;\n }\n\n case REGULAR_COLOR_IMAGE:\n case MEGA_MEGA_COLOR_IMAGE: {\n let runLength = runLengthOf(code);\n while (runLength-- > 0 && dest < pixels.length) pixels[dest++] = readPixel();\n break;\n }\n\n case SPECIAL_FGBG_1:\n srcOffset++;\n writeFgBgImage(MASK_SPECIAL_FGBG_1, 8);\n break;\n\n case SPECIAL_FGBG_2:\n srcOffset++;\n writeFgBgImage(MASK_SPECIAL_FGBG_2, 8);\n break;\n\n case SPECIAL_WHITE:\n srcOffset++;\n pixels[dest++] = white;\n break;\n\n case SPECIAL_BLACK:\n srcOffset++;\n pixels[dest++] = 0;\n break;\n\n default:\n throw new Error(`RDP: unsupported bitmap compression order 0x${code.toString(16)}`);\n }\n }\n\n return pixels;\n}\n\n/**\n * Reverse the row order of a decoded rectangle. RDP stores bitmaps bottom-up\n * and a canvas expects top-down, so without this every rectangle is painted\n * upside down.\n */\nexport function flipRows(pixels: Uint8Array, width: number) {\n if (width <= 0) return pixels;\n const height = Math.floor(pixels.length / width);\n if (height < 2) return pixels;\n\n const flipped = new Uint32Array(pixels.length);\n for (let y = 0; y < height; y++) {\n flipped.set(pixels.subarray(y * width, (y + 1) * width), (height - 1 - y) * width);\n }\n return flipped;\n}\n\n/** Read uncompressed bitmap data, which RDP stores bottom-up. */\nexport function readUncompressed(src: Uint8Array, width: number, height: number, bytesPerPixel: number) {\n const pixels = new Uint32Array(width * height);\n\n for (let y = 0; y < height; y++) {\n // Source row 0 is the bottom row of the rectangle.\n const destRow = (height - 1 - y) * width;\n let offset = y * width * bytesPerPixel;\n for (let x = 0; x < width; x++) {\n let value = 0;\n for (let i = 0; i < bytesPerPixel; i++) value |= src[offset + i] << (i * 8);\n pixels[destRow + x] = value >>> 0;\n offset += bytesPerPixel;\n }\n }\n\n return pixels;\n}\n\n/** Expand raw pixel values into RGBA for putImageData. */\nexport function pixelsToRgba(pixels: Uint8Array, bitsPerPixel: number, palette: Uint32Array) {\n const rgba = new Uint8ClampedArray(pixels.length * 4);\n\n for (let i = 0; i < pixels.length; i++) {\n const value = pixels[i];\n let r;\n let g;\n let b;\n\n switch (bitsPerPixel) {\n case 15:\n r = ((value >> 10) & 0x1f) * 255 / 31;\n g = ((value >> 5) & 0x1f) * 255 / 31;\n b = (value & 0x1f) * 255 / 31;\n break;\n case 16:\n r = ((value >> 11) & 0x1f) * 255 / 31;\n g = ((value >> 5) & 0x3f) * 255 / 63;\n b = (value & 0x1f) * 255 / 31;\n break;\n case 8: {\n const index = (value & 0xff) * 3;\n r = palette ? palette[index] : value;\n g = palette ? palette[index + 1] : value;\n b = palette ? palette[index + 2] : value;\n break;\n }\n default: // 24 and 32 bits per pixel are both BGR in the low three bytes\n r = (value >> 16) & 0xff;\n g = (value >> 8) & 0xff;\n b = value & 0xff;\n break;\n }\n\n const offset = i * 4;\n rgba[offset] = r;\n rgba[offset + 1] = g;\n rgba[offset + 2] = b;\n rgba[offset + 3] = 255;\n }\n\n return rgba;\n}\n\n/** Decode one TS_BITMAP_DATA rectangle to RGBA. */\nexport function decodeBitmapRect(rect: BitmapRect, palette: Uint32Array) {\n const bytesPerPixel = Math.max(1, Math.ceil(rect.bitsPerPixel / 8));\n const pixels = rect.compressed\n // Compressed data has to be expanded in wire order, because its runs delta\n // against the row above, so the flip to top-down happens afterwards.\n ? flipRows(rleDecompress(rect.data, rect.width, rect.height, bytesPerPixel), rect.width)\n : readUncompressed(rect.data, rect.width, rect.height, bytesPerPixel);\n\n return pixelsToRgba(pixels, rect.bitsPerPixel, palette);\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }