appium-ios-remotexpc 0.0.3 → 0.0.4

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 (192) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/src/base-plist-service.d.ts +51 -0
  3. package/build/src/base-plist-service.d.ts.map +1 -0
  4. package/build/src/base-plist-service.js +61 -0
  5. package/build/src/base-socket-service.d.ts +15 -0
  6. package/build/src/base-socket-service.d.ts.map +1 -0
  7. package/build/src/base-socket-service.js +46 -0
  8. package/build/src/index.d.ts +9 -0
  9. package/build/src/index.d.ts.map +1 -0
  10. package/build/src/index.js +7 -0
  11. package/build/src/lib/apple-tv/constants.d.ts +49 -0
  12. package/build/src/lib/apple-tv/constants.d.ts.map +1 -0
  13. package/build/src/lib/apple-tv/constants.js +71 -0
  14. package/build/src/lib/apple-tv/errors.d.ts +17 -0
  15. package/build/src/lib/apple-tv/errors.d.ts.map +1 -0
  16. package/build/src/lib/apple-tv/errors.js +30 -0
  17. package/build/src/lib/apple-tv/tlv/decoder.d.ts +19 -0
  18. package/build/src/lib/apple-tv/tlv/decoder.d.ts.map +1 -0
  19. package/build/src/lib/apple-tv/tlv/decoder.js +49 -0
  20. package/build/src/lib/apple-tv/tlv/encoder.d.ts +10 -0
  21. package/build/src/lib/apple-tv/tlv/encoder.d.ts.map +1 -0
  22. package/build/src/lib/apple-tv/tlv/encoder.js +20 -0
  23. package/build/src/lib/apple-tv/tlv/index.d.ts +4 -0
  24. package/build/src/lib/apple-tv/tlv/index.d.ts.map +1 -0
  25. package/build/src/lib/apple-tv/tlv/index.js +3 -0
  26. package/build/src/lib/apple-tv/tlv/pairing-tlv.d.ts +14 -0
  27. package/build/src/lib/apple-tv/tlv/pairing-tlv.d.ts.map +1 -0
  28. package/build/src/lib/apple-tv/tlv/pairing-tlv.js +27 -0
  29. package/build/src/lib/apple-tv/types.d.ts +36 -0
  30. package/build/src/lib/apple-tv/types.d.ts.map +1 -0
  31. package/build/src/lib/apple-tv/types.js +1 -0
  32. package/build/src/lib/apple-tv/utils/buffer-utils.d.ts +40 -0
  33. package/build/src/lib/apple-tv/utils/buffer-utils.d.ts.map +1 -0
  34. package/build/src/lib/apple-tv/utils/buffer-utils.js +76 -0
  35. package/build/src/lib/apple-tv/utils/index.d.ts +3 -0
  36. package/build/src/lib/apple-tv/utils/index.d.ts.map +1 -0
  37. package/build/src/lib/apple-tv/utils/index.js +2 -0
  38. package/build/src/lib/apple-tv/utils/uuid-generator.d.ts +9 -0
  39. package/build/src/lib/apple-tv/utils/uuid-generator.d.ts.map +1 -0
  40. package/build/src/lib/apple-tv/utils/uuid-generator.js +36 -0
  41. package/build/src/lib/lockdown/index.d.ts +87 -0
  42. package/build/src/lib/lockdown/index.d.ts.map +1 -0
  43. package/build/src/lib/lockdown/index.js +324 -0
  44. package/build/src/lib/pair-record/index.d.ts +3 -0
  45. package/build/src/lib/pair-record/index.d.ts.map +1 -0
  46. package/build/src/lib/pair-record/index.js +2 -0
  47. package/build/src/lib/pair-record/pair-record.d.ts +48 -0
  48. package/build/src/lib/pair-record/pair-record.d.ts.map +1 -0
  49. package/build/src/lib/pair-record/pair-record.js +85 -0
  50. package/build/src/lib/plist/binary-plist-creator.d.ts +14 -0
  51. package/build/src/lib/plist/binary-plist-creator.d.ts.map +1 -0
  52. package/build/src/lib/plist/binary-plist-creator.js +475 -0
  53. package/build/src/lib/plist/binary-plist-parser.d.ts +14 -0
  54. package/build/src/lib/plist/binary-plist-parser.d.ts.map +1 -0
  55. package/build/src/lib/plist/binary-plist-parser.js +449 -0
  56. package/build/src/lib/plist/constants.d.ts +36 -0
  57. package/build/src/lib/plist/constants.d.ts.map +1 -0
  58. package/build/src/lib/plist/constants.js +43 -0
  59. package/build/src/lib/plist/index.d.ts +14 -0
  60. package/build/src/lib/plist/index.d.ts.map +1 -0
  61. package/build/src/lib/plist/index.js +16 -0
  62. package/build/src/lib/plist/length-based-splitter.d.ts +43 -0
  63. package/build/src/lib/plist/length-based-splitter.d.ts.map +1 -0
  64. package/build/src/lib/plist/length-based-splitter.js +228 -0
  65. package/build/src/lib/plist/plist-creator.d.ts +8 -0
  66. package/build/src/lib/plist/plist-creator.d.ts.map +1 -0
  67. package/build/src/lib/plist/plist-creator.js +33 -0
  68. package/build/src/lib/plist/plist-decoder.d.ts +25 -0
  69. package/build/src/lib/plist/plist-decoder.d.ts.map +1 -0
  70. package/build/src/lib/plist/plist-decoder.js +103 -0
  71. package/build/src/lib/plist/plist-encoder.d.ts +10 -0
  72. package/build/src/lib/plist/plist-encoder.d.ts.map +1 -0
  73. package/build/src/lib/plist/plist-encoder.js +27 -0
  74. package/build/src/lib/plist/plist-parser.d.ts +9 -0
  75. package/build/src/lib/plist/plist-parser.d.ts.map +1 -0
  76. package/build/src/lib/plist/plist-parser.js +109 -0
  77. package/build/src/lib/plist/plist-service.d.ts +86 -0
  78. package/build/src/lib/plist/plist-service.d.ts.map +1 -0
  79. package/build/src/lib/plist/plist-service.js +180 -0
  80. package/build/src/lib/plist/unified-plist-creator.d.ts +9 -0
  81. package/build/src/lib/plist/unified-plist-creator.d.ts.map +1 -0
  82. package/build/src/lib/plist/unified-plist-creator.js +14 -0
  83. package/build/src/lib/plist/unified-plist-parser.d.ts +8 -0
  84. package/build/src/lib/plist/unified-plist-parser.d.ts.map +1 -0
  85. package/build/src/lib/plist/unified-plist-parser.js +23 -0
  86. package/build/src/lib/plist/utils.d.ts +97 -0
  87. package/build/src/lib/plist/utils.d.ts.map +1 -0
  88. package/build/src/lib/plist/utils.js +287 -0
  89. package/build/src/lib/remote-xpc/constants.d.ts +20 -0
  90. package/build/src/lib/remote-xpc/constants.d.ts.map +1 -0
  91. package/build/src/lib/remote-xpc/constants.js +21 -0
  92. package/build/src/lib/remote-xpc/handshake-frames.d.ts +74 -0
  93. package/build/src/lib/remote-xpc/handshake-frames.d.ts.map +1 -0
  94. package/build/src/lib/remote-xpc/handshake-frames.js +285 -0
  95. package/build/src/lib/remote-xpc/handshake.d.ts +14 -0
  96. package/build/src/lib/remote-xpc/handshake.d.ts.map +1 -0
  97. package/build/src/lib/remote-xpc/handshake.js +95 -0
  98. package/build/src/lib/remote-xpc/remote-xpc-connection.d.ts +55 -0
  99. package/build/src/lib/remote-xpc/remote-xpc-connection.d.ts.map +1 -0
  100. package/build/src/lib/remote-xpc/remote-xpc-connection.js +365 -0
  101. package/build/src/lib/remote-xpc/xpc-protocol.d.ts +22 -0
  102. package/build/src/lib/remote-xpc/xpc-protocol.d.ts.map +1 -0
  103. package/build/src/lib/remote-xpc/xpc-protocol.js +368 -0
  104. package/build/src/lib/tunnel/index.d.ts +69 -0
  105. package/build/src/lib/tunnel/index.d.ts.map +1 -0
  106. package/build/src/lib/tunnel/index.js +205 -0
  107. package/build/src/lib/tunnel/packet-stream-client.d.ts +46 -0
  108. package/build/src/lib/tunnel/packet-stream-client.d.ts.map +1 -0
  109. package/build/src/lib/tunnel/packet-stream-client.js +152 -0
  110. package/build/src/lib/tunnel/packet-stream-server.d.ts +37 -0
  111. package/build/src/lib/tunnel/packet-stream-server.d.ts.map +1 -0
  112. package/build/src/lib/tunnel/packet-stream-server.js +109 -0
  113. package/build/src/lib/tunnel/tunnel-api-client.d.ts +85 -0
  114. package/build/src/lib/tunnel/tunnel-api-client.d.ts.map +1 -0
  115. package/build/src/lib/tunnel/tunnel-api-client.js +207 -0
  116. package/build/src/lib/tunnel/tunnel-registry-server.d.ts +68 -0
  117. package/build/src/lib/tunnel/tunnel-registry-server.d.ts.map +1 -0
  118. package/build/src/lib/tunnel/tunnel-registry-server.js +351 -0
  119. package/build/src/lib/types.d.ts +238 -0
  120. package/build/src/lib/types.d.ts.map +1 -0
  121. package/build/src/lib/types.js +4 -0
  122. package/build/src/lib/usbmux/index.d.ts +177 -0
  123. package/build/src/lib/usbmux/index.d.ts.map +1 -0
  124. package/build/src/lib/usbmux/index.js +490 -0
  125. package/build/src/lib/usbmux/usbmux-decoder.d.ts +19 -0
  126. package/build/src/lib/usbmux/usbmux-decoder.d.ts.map +1 -0
  127. package/build/src/lib/usbmux/usbmux-decoder.js +38 -0
  128. package/build/src/lib/usbmux/usbmux-encoder.d.ts +12 -0
  129. package/build/src/lib/usbmux/usbmux-encoder.d.ts.map +1 -0
  130. package/build/src/lib/usbmux/usbmux-encoder.js +32 -0
  131. package/build/src/service-connection.d.ts +34 -0
  132. package/build/src/service-connection.d.ts.map +1 -0
  133. package/build/src/service-connection.js +51 -0
  134. package/build/src/services/index.d.ts +6 -0
  135. package/build/src/services/index.d.ts.map +1 -0
  136. package/build/src/services/index.js +5 -0
  137. package/build/src/services/ios/base-service.d.ts +35 -0
  138. package/build/src/services/ios/base-service.d.ts.map +1 -0
  139. package/build/src/services/ios/base-service.js +55 -0
  140. package/build/src/services/ios/diagnostic-service/index.d.ts +46 -0
  141. package/build/src/services/ios/diagnostic-service/index.d.ts.map +1 -0
  142. package/build/src/services/ios/diagnostic-service/index.js +169 -0
  143. package/build/src/services/ios/diagnostic-service/keys.d.ts +5 -0
  144. package/build/src/services/ios/diagnostic-service/keys.d.ts.map +1 -0
  145. package/build/src/services/ios/diagnostic-service/keys.js +770 -0
  146. package/build/src/services/ios/syslog-service/index.d.ts +91 -0
  147. package/build/src/services/ios/syslog-service/index.d.ts.map +1 -0
  148. package/build/src/services/ios/syslog-service/index.js +323 -0
  149. package/build/src/services/ios/tunnel-service/index.d.ts +17 -0
  150. package/build/src/services/ios/tunnel-service/index.d.ts.map +1 -0
  151. package/build/src/services/ios/tunnel-service/index.js +57 -0
  152. package/build/src/services.d.ts +14 -0
  153. package/build/src/services.d.ts.map +1 -0
  154. package/build/src/services.js +48 -0
  155. package/package.json +12 -3
  156. package/.github/dependabot.yml +0 -38
  157. package/.github/workflows/format-check.yml +0 -43
  158. package/.github/workflows/lint-and-build.yml +0 -40
  159. package/.github/workflows/pr-title.yml +0 -16
  160. package/.github/workflows/publish.js.yml +0 -43
  161. package/.github/workflows/test-validation.yml +0 -40
  162. package/.mocharc.json +0 -8
  163. package/.prettierignore +0 -3
  164. package/.prettierrc +0 -17
  165. package/.releaserc +0 -48
  166. package/assets/images/ios-arch.png +0 -0
  167. package/eslint.config.js +0 -45
  168. package/npm-shrinkwrap.json +0 -2711
  169. package/test/integration/diagnostics-test.ts +0 -44
  170. package/test/integration/read-pair-record-test.ts +0 -39
  171. package/test/integration/tunnel-test.ts +0 -104
  172. package/test/unit/apple-tv/tlv/decoder.spec.ts +0 -144
  173. package/test/unit/apple-tv/tlv/encoder.spec.ts +0 -91
  174. package/test/unit/apple-tv/tlv/pairing-tlv.spec.ts +0 -101
  175. package/test/unit/apple-tv/tlv/tlv-integration.spec.ts +0 -146
  176. package/test/unit/apple-tv/utils/buffer-utils.spec.ts +0 -74
  177. package/test/unit/apple-tv/utils/uuid-generator.spec.ts +0 -39
  178. package/test/unit/fixtures/index.ts +0 -88
  179. package/test/unit/fixtures/usbmuxconnectmessage.bin +0 -0
  180. package/test/unit/fixtures/usbmuxlistdevicemessage.bin +0 -0
  181. package/test/unit/plist/error-handling.spec.ts +0 -101
  182. package/test/unit/plist/fixtures/sample.binary.plist +0 -0
  183. package/test/unit/plist/fixtures/sample.xml.plist +0 -38
  184. package/test/unit/plist/plist-parser.spec.ts +0 -283
  185. package/test/unit/plist/plist.spec.ts +0 -205
  186. package/test/unit/plist/tag-position-handling.spec.ts +0 -90
  187. package/test/unit/plist/unified-plist-parser.spec.ts +0 -227
  188. package/test/unit/plist/utils.spec.ts +0 -249
  189. package/test/unit/plist/xml-cleaning.spec.ts +0 -60
  190. package/test/unit/tunnel/tunnel-registry-server.spec.ts +0 -194
  191. package/test/unit/usbmux/usbmux-specs.ts +0 -71
  192. package/tsconfig.json +0 -36
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer-utils.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/utils/buffer-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAepE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,MAAM,CAoBR"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Converts a non-negative bigint to a fixed-length Buffer in big-endian format.
3
+ *
4
+ * @param value - The bigint value to convert (must be non-negative).
5
+ * @param length - The target buffer length in bytes.
6
+ * @returns A Buffer representing the bigint, padded to the specified length.
7
+ *
8
+ * @throws {RangeError} If the value is negative or doesn't fit in the specified length.
9
+ */
10
+ export function bigIntToBuffer(value, length) {
11
+ if (value < 0n) {
12
+ throw new RangeError('Negative values not supported');
13
+ }
14
+ const hex = value.toString(16);
15
+ const byteLength = Math.ceil(hex.length / 2);
16
+ if (byteLength > length) {
17
+ throw new RangeError(`Value 0x${hex} is too large to fit in ${length} bytes`);
18
+ }
19
+ const paddedHex = hex.padStart(length * 2, '0');
20
+ return Buffer.from(paddedHex, 'hex');
21
+ }
22
+ /**
23
+ * Converts a Buffer into a bigint by interpreting it as a big-endian hexadecimal number.
24
+ *
25
+ * @param buffer - The input Buffer.
26
+ * @returns A bigint representing the numeric value of the buffer.
27
+ */
28
+ export function bufferToBigInt(buffer) {
29
+ return BigInt('0x' + buffer.toString('hex'));
30
+ }
31
+ /**
32
+ * Converts a non-negative bigint into a minimal-length Buffer in big-endian format.
33
+ * No unnecessary leading zero bytes will be included.
34
+ *
35
+ * @param value - The bigint value to convert (must be non-negative).
36
+ * @returns A Buffer representing the bigint with minimal byte length.
37
+ *
38
+ * @throws {RangeError} If the value is negative.
39
+ */
40
+ export function bigIntToMinimalBuffer(value) {
41
+ if (value < 0n) {
42
+ throw new RangeError('Negative values not supported');
43
+ }
44
+ const hex = value.toString(16);
45
+ const paddedHex = hex.length % 2 === 0 ? hex : '0' + hex;
46
+ return Buffer.from(paddedHex, 'hex');
47
+ }
48
+ /**
49
+ * Computes modular exponentiation: (base ^ exponent) % modulus.
50
+ * Efficiently handles large numbers using the binary exponentiation method.
51
+ *
52
+ * @param base - The base number.
53
+ * @param exponent - The exponent (must be non-negative).
54
+ * @param modulus - The modulus (must be non-zero).
55
+ * @returns The result of (base ** exponent) modulo modulus.
56
+ *
57
+ * @throws {RangeError} If the exponent is negative or the modulus is zero.
58
+ */
59
+ export function modPow(base, exponent, modulus) {
60
+ if (modulus === 0n) {
61
+ throw new RangeError('Modulus must be non-zero');
62
+ }
63
+ if (exponent < 0n) {
64
+ throw new RangeError('Negative exponents not supported');
65
+ }
66
+ let result = 1n;
67
+ base = base % modulus;
68
+ while (exponent > 0n) {
69
+ if (exponent % 2n === 1n) {
70
+ result = (result * base) % modulus;
71
+ }
72
+ exponent = exponent / 2n;
73
+ base = (base * base) % modulus;
74
+ }
75
+ return result;
76
+ }
@@ -0,0 +1,3 @@
1
+ export * from './buffer-utils.js';
2
+ export * from './uuid-generator.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './buffer-utils.js';
2
+ export * from './uuid-generator.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generates a deterministic UUIDv3 (MD5-based) from a hostname string.
3
+ * This mimics DNS-based UUID generation using the standard DNS namespace UUID.
4
+ *
5
+ * @param hostname - The host string to be converted to a UUID
6
+ * @returns A UUIDv3 string in uppercase
7
+ */
8
+ export declare function generateHostId(hostname: string): string;
9
+ //# sourceMappingURL=uuid-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid-generator.d.ts","sourceRoot":"","sources":["../../../../../src/lib/apple-tv/utils/uuid-generator.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA8BvD"}
@@ -0,0 +1,36 @@
1
+ import { createHash } from 'node:crypto';
2
+ // UUID namespace for DNS, per RFC 4122
3
+ const NAMESPACE_DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
4
+ /**
5
+ * Generates a deterministic UUIDv3 (MD5-based) from a hostname string.
6
+ * This mimics DNS-based UUID generation using the standard DNS namespace UUID.
7
+ *
8
+ * @param hostname - The host string to be converted to a UUID
9
+ * @returns A UUIDv3 string in uppercase
10
+ */
11
+ export function generateHostId(hostname) {
12
+ if (typeof hostname !== 'string' || hostname.length === 0) {
13
+ throw new TypeError('Hostname must be a non-empty string');
14
+ }
15
+ const namespaceBytes = Buffer.from(NAMESPACE_DNS.replace(/-/g, ''), 'hex');
16
+ // Hash the namespace and the hostname using MD5
17
+ const hash = createHash('md5');
18
+ hash.update(namespaceBytes);
19
+ hash.update(hostname, 'utf8');
20
+ const hashBytes = hash.digest();
21
+ // Set UUID version to 3 (MD5)
22
+ hashBytes[6] = (hashBytes[6] & 0x0f) | 0x30;
23
+ // Set UUID variant to RFC 4122
24
+ hashBytes[8] = (hashBytes[8] & 0x3f) | 0x80;
25
+ // Convert to UUID string format
26
+ const uuid = [
27
+ hashBytes.subarray(0, 4).toString('hex'),
28
+ hashBytes.subarray(4, 6).toString('hex'),
29
+ hashBytes.subarray(6, 8).toString('hex'),
30
+ hashBytes.subarray(8, 10).toString('hex'),
31
+ hashBytes.subarray(10, 16).toString('hex'),
32
+ ]
33
+ .join('-')
34
+ .toUpperCase();
35
+ return uuid;
36
+ }
@@ -0,0 +1,87 @@
1
+ import { Socket } from 'node:net';
2
+ import { type ConnectionOptions, TLSSocket } from 'tls';
3
+ import { BasePlistService } from '../../base-plist-service.js';
4
+ import type { PlistMessage, PlistValue } from '../types.js';
5
+ import { RelayService } from '../usbmux/index.js';
6
+ interface DeviceProperties {
7
+ ConnectionSpeed: number;
8
+ ConnectionType: string;
9
+ DeviceID: number;
10
+ LocationID: number;
11
+ ProductID: number;
12
+ SerialNumber: string;
13
+ USBSerialNumber: string;
14
+ }
15
+ interface Device {
16
+ DeviceID: number;
17
+ MessageType: string;
18
+ Properties: DeviceProperties;
19
+ }
20
+ interface LockdownServiceInfo {
21
+ lockdownService: LockdownService;
22
+ device: Device;
23
+ }
24
+ interface SessionInfo {
25
+ sessionID: string;
26
+ enableSessionSSL: boolean;
27
+ }
28
+ export declare class LockdownService extends BasePlistService {
29
+ private readonly udid;
30
+ private tlsService?;
31
+ private isTLS;
32
+ private tlsUpgradePromise?;
33
+ private _relayService?;
34
+ private readonly tlsManager;
35
+ private readonly deviceManager;
36
+ constructor(socket: Socket, udid: string, autoSecure?: boolean);
37
+ /**
38
+ * Starts a lockdown session
39
+ */
40
+ startSession(hostID: string, systemBUID: string, timeout?: number): Promise<SessionInfo>;
41
+ /**
42
+ * Attempts to upgrade the connection to TLS
43
+ */
44
+ tryUpgradeToTLS(): Promise<void>;
45
+ /**
46
+ * Gets the current socket (TLS or regular)
47
+ */
48
+ getSocket(): Socket | TLSSocket;
49
+ /**
50
+ * Sends a message and receives a response
51
+ */
52
+ sendAndReceive(msg: Record<string, PlistValue>, timeout?: number): Promise<PlistMessage>;
53
+ /**
54
+ * Closes the service and associated resources
55
+ */
56
+ close(): void;
57
+ /**
58
+ * Sets the relay service for this lockdown instance
59
+ */
60
+ set relayService(relay: RelayService);
61
+ /**
62
+ * Gets the relay service for this lockdown instance
63
+ */
64
+ get relayService(): RelayService | undefined;
65
+ /**
66
+ * Waits for TLS upgrade to complete if in progress
67
+ */
68
+ waitForTLSUpgrade(): Promise<void>;
69
+ /**
70
+ * Stops the relay service with an optional custom message
71
+ */
72
+ stopRelayService(message?: string): void;
73
+ private validatePairRecord;
74
+ private performTLSUpgrade;
75
+ private closeSocket;
76
+ }
77
+ export declare class LockdownServiceFactory {
78
+ private readonly deviceManager;
79
+ /**
80
+ * Creates a LockdownService for a specific device UDID
81
+ */
82
+ createByUDID(udid: string, port?: number, autoSecure?: boolean): Promise<LockdownServiceInfo>;
83
+ }
84
+ export declare function createLockdownServiceByUDID(udid: string, port?: number, autoSecure?: boolean): Promise<LockdownServiceInfo>;
85
+ export declare function upgradeSocketToTLS(socket: Socket, tlsOptions?: Partial<ConnectionOptions>): Promise<TLSSocket>;
86
+ export {};
87
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/lockdown/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,324 @@
1
+ import { logger } from '@appium/support';
2
+ import { Socket } from 'node:net';
3
+ import tls, { TLSSocket } from 'tls';
4
+ import { BasePlistService } from '../../base-plist-service.js';
5
+ import {} from '../pair-record/index.js';
6
+ import { PlistService } from '../plist/plist-service.js';
7
+ import { RelayService, createUsbmux } from '../usbmux/index.js';
8
+ const log = logger.getLogger('Lockdown');
9
+ // Constants
10
+ const LABEL = 'appium-internal';
11
+ const DEFAULT_TIMEOUT = 5000;
12
+ const DEFAULT_LOCKDOWN_PORT = 62078;
13
+ const DEFAULT_RELAY_PORT = 2222;
14
+ // Error classes for better error handling
15
+ class LockdownError extends Error {
16
+ constructor(message) {
17
+ super(message);
18
+ this.name = 'LockdownError';
19
+ }
20
+ }
21
+ class TLSUpgradeError extends Error {
22
+ constructor(message) {
23
+ super(message);
24
+ this.name = 'TLSUpgradeError';
25
+ }
26
+ }
27
+ class DeviceNotFoundError extends Error {
28
+ constructor(udid) {
29
+ super(`Device with UDID ${udid} not found`);
30
+ this.name = 'DeviceNotFoundError';
31
+ }
32
+ }
33
+ // TLS Manager for handling TLS operations
34
+ class TLSManager {
35
+ log = logger.getLogger('TLSManager');
36
+ /**
37
+ * Upgrades a socket to TLS
38
+ */
39
+ async upgradeSocketToTLS(socket, tlsOptions = {}) {
40
+ return new Promise((resolve, reject) => {
41
+ socket.pause();
42
+ this.log.debug('Upgrading socket to TLS...');
43
+ const secure = tls.connect({
44
+ socket,
45
+ rejectUnauthorized: false,
46
+ minVersion: 'TLSv1.2',
47
+ ...tlsOptions,
48
+ }, () => {
49
+ this.log.info('TLS handshake completed');
50
+ resolve(secure);
51
+ });
52
+ secure.on('error', (err) => {
53
+ this.log.error(`TLS socket error: ${err}`);
54
+ reject(new TLSUpgradeError(`TLS socket error: ${err.message}`));
55
+ });
56
+ socket.on('error', (err) => {
57
+ this.log.error(`Underlying socket error during TLS: ${err}`);
58
+ reject(new TLSUpgradeError(`Socket error during TLS: ${err.message}`));
59
+ });
60
+ });
61
+ }
62
+ }
63
+ // Device Manager for handling device operations
64
+ class DeviceManager {
65
+ log = logger.getLogger('DeviceManager');
66
+ /**
67
+ * Lists all connected devices
68
+ */
69
+ async listDevices() {
70
+ const usbmux = await createUsbmux();
71
+ try {
72
+ this.log.debug('Listing connected devices...');
73
+ const devices = await usbmux.listDevices();
74
+ this.log.debug(`Found ${devices.length} devices: ${devices.map((d) => d.Properties.SerialNumber).join(', ')}`);
75
+ return devices;
76
+ }
77
+ finally {
78
+ await this.closeUsbmux(usbmux);
79
+ }
80
+ }
81
+ /**
82
+ * Finds a device by UDID
83
+ */
84
+ async findDeviceByUDID(udid) {
85
+ const devices = await this.listDevices();
86
+ if (!devices || devices.length === 0) {
87
+ throw new LockdownError('No devices connected');
88
+ }
89
+ const device = devices.find((d) => d.Properties.SerialNumber === udid);
90
+ if (!device) {
91
+ throw new DeviceNotFoundError(udid);
92
+ }
93
+ this.log.info(`Found device: DeviceID=${device.DeviceID}, SerialNumber=${device.Properties.SerialNumber}, ConnectionType=${device.Properties.ConnectionType}`);
94
+ return device;
95
+ }
96
+ /**
97
+ * Reads pair record for a device
98
+ */
99
+ async readPairRecord(udid) {
100
+ this.log.debug(`Retrieving pair record for UDID: ${udid}`);
101
+ const usbmux = await createUsbmux();
102
+ try {
103
+ const record = await usbmux.readPairRecord(udid);
104
+ if (!record?.HostCertificate || !record.HostPrivateKey) {
105
+ throw new LockdownError('Pair record missing certificate or key');
106
+ }
107
+ this.log.info('Pair record retrieved successfully');
108
+ return record;
109
+ }
110
+ catch (err) {
111
+ this.log.error(`Error getting pair record: ${err}`);
112
+ throw err;
113
+ }
114
+ finally {
115
+ await this.closeUsbmux(usbmux);
116
+ }
117
+ }
118
+ async closeUsbmux(usbmux) {
119
+ try {
120
+ await usbmux.close();
121
+ }
122
+ catch (err) {
123
+ this.log.error(`Error closing usbmux: ${err}`);
124
+ }
125
+ }
126
+ }
127
+ // Main LockdownService class
128
+ export class LockdownService extends BasePlistService {
129
+ udid;
130
+ tlsService;
131
+ isTLS = false;
132
+ tlsUpgradePromise;
133
+ _relayService;
134
+ tlsManager = new TLSManager();
135
+ deviceManager = new DeviceManager();
136
+ constructor(socket, udid, autoSecure = true) {
137
+ super(socket);
138
+ this.udid = udid;
139
+ log.info(`LockdownService initialized for UDID: ${udid}`);
140
+ if (autoSecure) {
141
+ this.tlsUpgradePromise = this.tryUpgradeToTLS().catch((err) => log.warn(`Auto TLS upgrade failed: ${err.message}`));
142
+ }
143
+ }
144
+ /**
145
+ * Starts a lockdown session
146
+ */
147
+ async startSession(hostID, systemBUID, timeout = DEFAULT_TIMEOUT) {
148
+ log.debug(`Starting lockdown session with HostID: ${hostID}`);
149
+ const request = {
150
+ Label: LABEL,
151
+ Request: 'StartSession',
152
+ HostID: hostID,
153
+ SystemBUID: systemBUID,
154
+ };
155
+ const response = (await this.sendAndReceive(request, timeout));
156
+ if (response.Request === 'StartSession' && response.SessionID) {
157
+ const sessionInfo = {
158
+ sessionID: String(response.SessionID),
159
+ enableSessionSSL: Boolean(response.EnableSessionSSL),
160
+ };
161
+ log.info(`Lockdown session started, SessionID: ${sessionInfo.sessionID}`);
162
+ return sessionInfo;
163
+ }
164
+ throw new LockdownError(`Unexpected session data: ${JSON.stringify(response)}`);
165
+ }
166
+ /**
167
+ * Attempts to upgrade the connection to TLS
168
+ */
169
+ async tryUpgradeToTLS() {
170
+ try {
171
+ const pairRecord = await this.deviceManager.readPairRecord(this.udid);
172
+ if (!this.validatePairRecord(pairRecord)) {
173
+ log.warn('Invalid pair record for TLS upgrade');
174
+ return;
175
+ }
176
+ const sessionInfo = await this.startSession(pairRecord.HostID, pairRecord.SystemBUID);
177
+ if (!sessionInfo.enableSessionSSL) {
178
+ log.info('Device did not request TLS upgrade. Continuing unencrypted.');
179
+ return;
180
+ }
181
+ await this.performTLSUpgrade(pairRecord);
182
+ }
183
+ catch (err) {
184
+ log.error(`TLS upgrade failed: ${err}`);
185
+ throw err;
186
+ }
187
+ }
188
+ /**
189
+ * Gets the current socket (TLS or regular)
190
+ */
191
+ getSocket() {
192
+ return this.isTLS && this.tlsService
193
+ ? this.tlsService.getSocket()
194
+ : this.getPlistService().getSocket();
195
+ }
196
+ /**
197
+ * Sends a message and receives a response
198
+ */
199
+ async sendAndReceive(msg, timeout = DEFAULT_TIMEOUT) {
200
+ const service = this.isTLS && this.tlsService ? this.tlsService : this._plistService;
201
+ return service.sendPlistAndReceive(msg, timeout);
202
+ }
203
+ /**
204
+ * Closes the service and associated resources
205
+ */
206
+ close() {
207
+ log.info('Closing LockdownService connections');
208
+ try {
209
+ this.closeSocket();
210
+ this.stopRelayService();
211
+ }
212
+ catch (err) {
213
+ log.error(`Error during close: ${err}`);
214
+ throw err;
215
+ }
216
+ }
217
+ /**
218
+ * Sets the relay service for this lockdown instance
219
+ */
220
+ set relayService(relay) {
221
+ this._relayService = relay;
222
+ }
223
+ /**
224
+ * Gets the relay service for this lockdown instance
225
+ */
226
+ get relayService() {
227
+ return this._relayService;
228
+ }
229
+ /**
230
+ * Waits for TLS upgrade to complete if in progress
231
+ */
232
+ async waitForTLSUpgrade() {
233
+ if (this.tlsUpgradePromise) {
234
+ await this.tlsUpgradePromise;
235
+ }
236
+ }
237
+ /**
238
+ * Stops the relay service with an optional custom message
239
+ */
240
+ stopRelayService(message = 'Stopping relay server associated with LockdownService') {
241
+ const relay = this.relayService;
242
+ if (relay) {
243
+ log.info(message);
244
+ (async () => {
245
+ try {
246
+ await relay.stop();
247
+ log.info('Relay server stopped successfully');
248
+ }
249
+ catch (err) {
250
+ log.error(`Error stopping relay server: ${err}`);
251
+ }
252
+ })();
253
+ }
254
+ }
255
+ validatePairRecord(record) {
256
+ return Boolean(record?.HostCertificate &&
257
+ record.HostPrivateKey &&
258
+ record.HostID &&
259
+ record.SystemBUID);
260
+ }
261
+ async performTLSUpgrade(pairRecord) {
262
+ const tlsConfig = {
263
+ cert: pairRecord.HostCertificate,
264
+ key: pairRecord.HostPrivateKey,
265
+ };
266
+ const tlsSocket = await this.tlsManager.upgradeSocketToTLS(this.getSocket(), tlsConfig);
267
+ this.tlsService = new PlistService(tlsSocket);
268
+ this.isTLS = true;
269
+ log.info('Successfully upgraded connection to TLS');
270
+ }
271
+ closeSocket() {
272
+ if (this.isTLS && this.tlsService) {
273
+ this.tlsService.close();
274
+ }
275
+ else {
276
+ super.close();
277
+ }
278
+ }
279
+ }
280
+ // Factory class for creating LockdownService instances
281
+ export class LockdownServiceFactory {
282
+ deviceManager = new DeviceManager();
283
+ /**
284
+ * Creates a LockdownService for a specific device UDID
285
+ */
286
+ async createByUDID(udid, port = DEFAULT_LOCKDOWN_PORT, autoSecure = true) {
287
+ log.info(`Creating LockdownService for UDID: ${udid}`);
288
+ // Find the device
289
+ const device = await this.deviceManager.findDeviceByUDID(udid);
290
+ // Create relay service
291
+ const relay = new RelayService(device.DeviceID, port, DEFAULT_RELAY_PORT);
292
+ await relay.start();
293
+ let service;
294
+ try {
295
+ // Connect through the relay
296
+ const socket = await relay.connect();
297
+ log.debug('Socket connected, creating LockdownService');
298
+ // Create the lockdown service
299
+ service = new LockdownService(socket, udid, autoSecure);
300
+ service.relayService = relay;
301
+ // Wait for TLS upgrade if enabled
302
+ if (autoSecure) {
303
+ log.debug('Waiting for TLS upgrade to complete...');
304
+ await service.waitForTLSUpgrade();
305
+ }
306
+ return { lockdownService: service, device };
307
+ }
308
+ catch (err) {
309
+ // Clean up relay on error
310
+ service?.stopRelayService('Stopping relay after failure');
311
+ throw err;
312
+ }
313
+ }
314
+ }
315
+ // Export factory function for backward compatibility
316
+ export async function createLockdownServiceByUDID(udid, port = DEFAULT_LOCKDOWN_PORT, autoSecure = true) {
317
+ const factory = new LockdownServiceFactory();
318
+ return factory.createByUDID(udid, port, autoSecure);
319
+ }
320
+ // Export the TLS upgrade function for external use
321
+ export function upgradeSocketToTLS(socket, tlsOptions = {}) {
322
+ const tlsManager = new TLSManager();
323
+ return tlsManager.upgradeSocketToTLS(socket, tlsOptions);
324
+ }
@@ -0,0 +1,3 @@
1
+ import { type PairRecord, getPairRecord, processPlistResponse, savePairRecord } from './pair-record.js';
2
+ export { getPairRecord, processPlistResponse, savePairRecord, type PairRecord };
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/pair-record/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EACf,aAAa,EACb,oBAAoB,EACpB,cAAc,EACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { getPairRecord, processPlistResponse, savePairRecord, } from './pair-record.js';
2
+ export { getPairRecord, processPlistResponse, savePairRecord };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Interface defining the structure of a pair record.
3
+ */
4
+ export interface PairRecord {
5
+ HostID: string | null;
6
+ SystemBUID: string | null;
7
+ HostCertificate: string | null;
8
+ HostPrivateKey: string | null;
9
+ DeviceCertificate: string | null;
10
+ RootCertificate: string | null;
11
+ RootPrivateKey: string | null;
12
+ WiFiMACAddress: string | null;
13
+ EscrowBag: string | null;
14
+ }
15
+ /**
16
+ * Interface for the raw response from plist.parsePlist
17
+ */
18
+ export interface RawPairRecordResponse {
19
+ HostID: string;
20
+ SystemBUID: string;
21
+ HostCertificate: Buffer;
22
+ HostPrivateKey: Buffer;
23
+ DeviceCertificate: Buffer;
24
+ RootCertificate: Buffer;
25
+ RootPrivateKey: Buffer;
26
+ WiFiMACAddress: string;
27
+ EscrowBag: Buffer;
28
+ }
29
+ /**
30
+ * Processes raw response from plist.parsePlist and formats it into a proper pair-record
31
+ * @param response - Response from plist.parsePlist(data.payload.PairRecordData)
32
+ * @returns Formatted pair-record object with properly structured data
33
+ */
34
+ export declare function processPlistResponse(response: RawPairRecordResponse): PairRecord;
35
+ /**
36
+ * Saves a pair record to the filesystem.
37
+ * @param udid - Device UDID.
38
+ * @param pairRecord - Pair record to save.
39
+ * @returns Promise that resolves when record is saved.
40
+ */
41
+ export declare function savePairRecord(udid: string, pairRecord: PairRecord): Promise<void>;
42
+ /**
43
+ * Gets a saved pair record from the filesystem.
44
+ * @param udid - Device UDID.
45
+ * @returns Promise that resolves with the pair record or null if not found.
46
+ */
47
+ export declare function getPairRecord(udid: string): Promise<PairRecord | null>;
48
+ //# sourceMappingURL=pair-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pair-record.d.ts","sourceRoot":"","sources":["../../../../src/lib/pair-record/pair-record.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAWD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,qBAAqB,GAC9B,UAAU,CAyBZ;AAUD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAc5E"}