sliftutils 1.7.133 → 1.7.134

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 (58) hide show
  1. package/bin/addmachine.js +1 -5
  2. package/bin/derivekey.js +2 -7
  3. package/bin/portsecuredaemon.js +1 -8
  4. package/bin/securessh.js +2 -7
  5. package/bin/setupnotify.js +2 -6
  6. package/bin/signfiles.js +2 -7
  7. package/bin/testnotify.js +2 -6
  8. package/bin/unrevoke.js +1 -5
  9. package/misc/dist/ownIPs.ts.cache +2 -2
  10. package/misc/https/dist/certs.ts.cache +12 -9
  11. package/misc/https/dist/persistentLocalStorage.ts.cache +10 -4
  12. package/package.json +1 -1
  13. package/security/authorizedKeys/daemon/daemon.ts +142 -7
  14. package/security/authorizedKeys/daemon/dist/changes.ts.cache +2 -2
  15. package/security/authorizedKeys/daemon/dist/git.ts.cache +26 -8
  16. package/security/authorizedKeys/daemon/dist/notify.ts.cache +2 -2
  17. package/security/authorizedKeys/daemon/dist/paths.ts.cache +2 -2
  18. package/security/authorizedKeys/daemon/dist/repoFiles.ts.cache +4 -6
  19. package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
  20. package/security/authorizedKeys/daemon/dist/sessions.ts.cache +2 -2
  21. package/security/authorizedKeys/daemon/dist/state.ts.cache +2 -2
  22. package/security/authorizedKeys/daemon/dist/trust.ts.cache +85 -265
  23. package/security/authorizedKeys/daemon/git.d.ts +8 -0
  24. package/security/authorizedKeys/daemon/git.ts +22 -4
  25. package/security/authorizedKeys/daemon/repoFiles.ts +2 -4
  26. package/security/authorizedKeys/daemon/trust.d.ts +25 -19
  27. package/security/authorizedKeys/daemon/trust.ts +91 -278
  28. package/security/authorizedKeys/dist/authorizedKeys.ts.cache +2 -2
  29. package/security/authorizedKeys/dist/keysRepo.ts.cache +2 -2
  30. package/security/authorizedKeys/dist/revokeSource.ts.cache +2 -2
  31. package/security/authorizedKeys/dist/sources.ts.cache +2 -2
  32. package/security/authorizedKeys/secureSSH.ts +6 -1
  33. package/security/authorizedKeys/unrevoke.ts +2 -198
  34. package/security/authorizedKeys/unrevokeCli.ts +204 -0
  35. package/security/helpers/dist/paths.ts.cache +2 -2
  36. package/security/helpers/dist/remoteSSH.ts.cache +2 -2
  37. package/security/helpers/dist/spawn.ts.cache +2 -2
  38. package/security/helpers/remoteSSH.d.ts +35 -0
  39. package/security/keys/deriveKey.d.ts +0 -1
  40. package/security/keys/deriveKey.ts +1 -56
  41. package/security/keys/deriveKeyCli.ts +62 -0
  42. package/security/keys/dist/deriveKey.ts.cache +4 -51
  43. package/security/keys/dist/sshKeyFile.ts.cache +5 -3
  44. package/security/machines/addMachine.ts +31 -61
  45. package/security/machines/dist/addMachine.ts.cache +72 -57
  46. package/security/machines/dist/machines.ts.cache +134 -55
  47. package/security/machines/machines.d.ts +11 -0
  48. package/security/machines/machines.ts +134 -57
  49. package/security/notifications/dist/discord.ts.cache +2 -2
  50. package/security/notifications/setupNotify.ts +6 -1
  51. package/security/notifications/testNotify.ts +6 -1
  52. package/security/signedFiles/dist/manifest.ts.cache +2 -2
  53. package/security/signedFiles/dist/sshsig.ts.cache +138 -0
  54. package/security/signedFiles/signFiles.ts +11 -52
  55. package/security/signedFiles/signFilesCli.ts +54 -0
  56. package/security/signedFiles/sshsig.d.ts +13 -0
  57. package/security/signedFiles/sshsig.ts +141 -0
  58. package/storage/dist/backblaze.ts.cache +10 -2
@@ -7,11 +7,12 @@ import { listRepoDir, readRepoFile } from "../authorizedKeys/daemon/repoFiles";
7
7
  import { newRevocationId, pairKey, readRevocationFiles, readUnrevokes } from "../authorizedKeys/daemon/revocation";
8
8
  import { runGit } from "../authorizedKeys/daemon/git";
9
9
  import { ensureRevokeKey } from "../authorizedKeys/daemon/repoFiles";
10
- import { verifyCheckout } from "../authorizedKeys/daemon/trust";
10
+ import { readSignedRepo } from "../authorizedKeys/daemon/trust";
11
11
  import { revokeRepoPath, revokeRepoURL } from "../authorizedKeys/revokeSource";
12
12
  import { notify } from "../authorizedKeys/daemon/notify";
13
13
  import { areDiscordNotificationsConfigured, configureDiscordNotifications, DEFAULT_WEBHOOK_FILE_PATH } from "../notifications/discord";
14
- import { getOwnMachineId } from "../../misc/https/certs";
14
+ import { DEV_getIdentityFilePath, generateCA, getMachineId, getOwnMachineId, IdentityStorageType } from "../../misc/https/certs";
15
+ import { describeHost, runOverSSH, writeRemoteFile } from "../helpers/remoteSSH";
15
16
  import { lazy } from "socket-function/src/caching";
16
17
  import { runInfinitePoll } from "socket-function/src/batching";
17
18
  import { spawnPromise } from "../helpers/spawn";
@@ -34,6 +35,10 @@ const MACHINES_REFRESH_INTERVAL = 60 * 1000;
34
35
  // not pay for resolving the repo on every request either.
35
36
  const REPO_RETRY_DELAY = 15 * 1000;
36
37
  const LOOPBACK = ["127.0.0.1", "::1", "::ffff:127.0.0.1"];
38
+ // The trusted machine list is re-read at most this often when a check rejects, so a caller that
39
+ // was just added is picked up quickly without letting a flood of rejections re-read every time.
40
+ const MACHINES_INVALIDATION_INTERVAL = 60 * 1000;
41
+ let lastMachinesInvalidation = 0;
37
42
 
38
43
  /** One machine we are willing to talk to, and the addresses it may talk to us from. */
39
44
  export type MachineState = {
@@ -72,13 +77,24 @@ export async function getMachines(repoPath?: string): Promise<MachineState[]> {
72
77
  return [...(await readMachines(repoPath || (await keysRepo()).repoPath)).values()];
73
78
  }
74
79
 
75
- /** Reads the machine list, once its signature has been checked. An unsigned machine list, or one
76
- signed over different contents, is not evidence of anything, so this throws rather than
77
- quietly trusting nobody. */
80
+ /** The machines the signed files vouch for. Only the machine files covered by the signature are
81
+ read - an unsigned machines/*.json is not evidence of anything, so readSignedRepo has already
82
+ left it out. */
78
83
  async function readTrustedMachines() {
79
84
  let { repoPath } = await keysRepo();
80
- await verifyCheckout(repoPath);
81
- return await getMachines(repoPath);
85
+ let { files } = await readSignedRepo(repoPath);
86
+ let machines: MachineState[] = [];
87
+ for (let [filePath, contents] of files) {
88
+ let name = filePath.startsWith(`${MACHINES_DIR}/`) && filePath.slice(MACHINES_DIR.length + 1) || "";
89
+ if (!name.endsWith(".json") || name.includes("/")) {
90
+ continue;
91
+ }
92
+ let machine = parseMachineFile(name, contents.toString("utf8"));
93
+ if (machine) {
94
+ machines.push(machine);
95
+ }
96
+ }
97
+ return machines;
82
98
  }
83
99
 
84
100
  const trustedMachines = lazy(async () => {
@@ -108,6 +124,36 @@ export async function getTrustedMachines(): Promise<MachineState[]> {
108
124
  return await trustedMachines();
109
125
  }
110
126
 
127
+ /** The machine id of a machine reached over ssh, generating and installing an identity for it if
128
+ it has none under this domain. The private key ends up on that machine and nowhere else. */
129
+ export async function getOrCreateRemoteMachineId(host: string, domain: string): Promise<string> {
130
+ let fileName = path.basename(DEV_getIdentityFilePath(domain));
131
+ let home = (await runOverSSH({ host, script: `echo $HOME` })).stdout.trim();
132
+ if (!home) {
133
+ throw new Error(`Expected ${host} to report a home directory, it reported nothing`);
134
+ }
135
+ let contents = await runOverSSH({ host, script: `cat ${home}/${fileName} 2>/dev/null || true` });
136
+ if (contents.stdout.trim()) {
137
+ let stored = JSON.parse(contents.stdout) as IdentityStorageType;
138
+ return getMachineId(stored.domain, domain);
139
+ }
140
+ console.log(`${describeHost(host)} has no identity for ${domain}, generating one`);
141
+ let generated = generateCA(domain);
142
+ let stored: IdentityStorageType = {
143
+ domain: generated.domain,
144
+ certB64: generated.cert.toString("base64"),
145
+ keyB64: generated.key.toString("base64"),
146
+ };
147
+ await writeRemoteFile({
148
+ host,
149
+ filePath: `${home}/${fileName}`,
150
+ contents: JSON.stringify(stored),
151
+ fileMode: "600",
152
+ directoryMode: "700",
153
+ });
154
+ return getMachineId(generated.domain, domain);
155
+ }
156
+
111
157
  /** Makes a checkout list exactly these machines: those named are written with the addresses given,
112
158
  and anything not named is removed. So read them, change what you want, and write the result.
113
159
 
@@ -160,7 +206,19 @@ export async function setMachines(config: {
160
206
  return written;
161
207
  }
162
208
 
163
- /** Every machine the repo lists. */
209
+ function parseMachineFile(name: string, contents: string): MachineState | undefined {
210
+ try {
211
+ let parsed = JSON.parse(contents);
212
+ let machineId = parsed.machineId || name.replace(/\.json$/, "");
213
+ return { machineId, ips: parsed.ips || [], addedAt: parsed.addedAt || "" };
214
+ } catch (e) {
215
+ console.log(`Ignoring unreadable machine file ${name}. ${e}`);
216
+ return undefined;
217
+ }
218
+ }
219
+
220
+ /** Every machine file on disk. For editing the repo, not for deciding trust - trust reads the
221
+ signed files through readTrustedMachines. */
164
222
  async function readMachines(repoPath: string) {
165
223
  let machines = new Map<string, MachineState>();
166
224
  let directory = path.join(repoPath, MACHINES_DIR);
@@ -169,12 +227,9 @@ async function readMachines(repoPath: string) {
169
227
  if (!name.endsWith(".json")) {
170
228
  continue;
171
229
  }
172
- try {
173
- let parsed = JSON.parse(await fs.readFile(path.join(directory, name), "utf8"));
174
- let machineId = parsed.machineId || name.replace(/\.json$/, "");
175
- machines.set(machineId, { machineId, ips: parsed.ips || [], addedAt: parsed.addedAt || "" });
176
- } catch (e) {
177
- console.log(`Ignoring unreadable machine file ${name}. ${e}`);
230
+ let machine = parseMachineFile(name, await fs.readFile(path.join(directory, name), "utf8").catch(() => ""));
231
+ if (machine) {
232
+ machines.set(machine.machineId, machine);
178
233
  }
179
234
  }
180
235
  return machines;
@@ -331,53 +386,75 @@ export async function isMachineAccepted(config: {
331
386
  if (!machineId || !ip) {
332
387
  throw new Error(`Expected a machineId and an ip, was ${JSON.stringify(machineId)} and ${JSON.stringify(ip)}`);
333
388
  }
334
- if (LOOPBACK.includes(ip) && !!domain && machineId === getOwnMachineId(domain)) {
335
- return { accepted: true, reason: "" };
336
- }
337
- let { sourceURL } = await keysRepo();
338
- // Verified before it is believed, and cached, since this is asked once per request.
339
- let machine = (await getTrustedMachines()).find(entry => entry.machineId === machineId);
340
- if (!machine) {
341
- return { accepted: false, reason: `that machine is not trusted. ${addMachineCommand({ machineId, ip, domain })}` };
342
- }
343
389
 
344
- await syncRevocations(sourceURL);
345
- let unrevokes = await readUnrevokes(sourceURL).catch(() => ({ pairs: new Map(), legacyIds: new Map() }));
346
- // An unrevoke counts as soon as it is seen. It is signed, so writing one already takes the
347
- // hardware key, and anyone holding that can sign anything at all - a wait before honouring it
348
- // guards against an attacker who has no need of it.
349
- let allowedAgain = (pair: string) => !!unrevokes.pairs.get(pair)?.length;
350
- let revocations = await readMachineRevocations(sourceURL);
351
- // Any revocation nothing has undone keeps the machine out, from everywhere, the way a revoked
352
- // ssh key is out everywhere rather than only from the address it was misused from.
353
- let frozenFrom = "";
354
- for (let revocation of revocations) {
355
- if (revocation.machineId !== machineId) {
356
- continue;
390
+ // The whole check, plus whether it froze the machine. A rejection that froze it is final, so
391
+ // there is nothing to gain from looking again. Any other rejection might just be a stale view -
392
+ // a machine added seconds ago that our cached list has not caught up to - so it is worth one
393
+ // fresh look, which is what the retry below does.
394
+ let evaluate = async (): Promise<{ verdict: MachineVerdict; froze: boolean }> => {
395
+ if (LOOPBACK.includes(ip) && !!domain && machineId === getOwnMachineId(domain)) {
396
+ return { verdict: { accepted: true, reason: "" }, froze: false };
357
397
  }
358
- if (!allowedAgain(pairKey({ fingerprint: revocation.machineId, ip: revocation.ip }))) {
359
- frozenFrom = revocation.ip;
398
+ let { sourceURL } = await keysRepo();
399
+ // Verified before it is believed, and cached, since this is asked once per request.
400
+ let machine = (await getTrustedMachines()).find(entry => entry.machineId === machineId);
401
+ if (!machine) {
402
+ return { verdict: { accepted: false, reason: `that machine is not trusted. ${addMachineCommand({ machineId, ip, domain })}` }, froze: false };
360
403
  }
361
- }
362
- if (frozenFrom) {
363
- return {
364
- accepted: false,
365
- reason: `that machine is frozen, it was used from ${frozenFrom} which it is not allowed from`,
366
- };
367
- }
368
404
 
369
- if (machine.ips.includes(ip)) {
370
- return { accepted: true, reason: "" };
371
- }
405
+ await syncRevocations(sourceURL);
406
+ let unrevokes = await readUnrevokes(sourceURL).catch(() => ({ pairs: new Map(), legacyIds: new Map() }));
407
+ // An unrevoke counts as soon as it is seen. It is signed, so writing one already takes the
408
+ // hardware key, and anyone holding that can sign anything at all - a wait before honouring it
409
+ // guards against an attacker who has no need of it.
410
+ let allowedAgain = (pair: string) => !!unrevokes.pairs.get(pair)?.length;
411
+ let revocations = await readMachineRevocations(sourceURL);
412
+ // Any revocation nothing has undone keeps the machine out, from everywhere, the way a revoked
413
+ // ssh key is out everywhere rather than only from the address it was misused from.
414
+ let frozenFrom = "";
415
+ for (let revocation of revocations) {
416
+ if (revocation.machineId !== machineId) {
417
+ continue;
418
+ }
419
+ if (!allowedAgain(pairKey({ fingerprint: revocation.machineId, ip: revocation.ip }))) {
420
+ frozenFrom = revocation.ip;
421
+ }
422
+ }
423
+ if (frozenFrom) {
424
+ return {
425
+ verdict: { accepted: false, reason: `that machine is frozen, it was used from ${frozenFrom} which it is not allowed from` },
426
+ froze: false,
427
+ };
428
+ }
372
429
 
373
- // Listed, but talking to us from somewhere it should not be. Recorded once for this machine
374
- // and address, so being talked to repeatedly does not write repeatedly.
375
- let pair = pairKey({ fingerprint: machineId, ip });
376
- let alreadyRecorded = revocations.some(revocation =>
377
- pairKey({ fingerprint: revocation.machineId, ip: revocation.ip }) === pair);
378
- if (!alreadyRecorded && !allowedAgain(pair)) {
379
- await recordMachineRevocation({ sourceURL, machineId, ip, hostLabel: os.hostname() });
380
- return { accepted: false, reason: `that machine is not allowed from ${ip}, so it is now frozen everywhere` };
430
+ if (machine.ips.includes(ip)) {
431
+ return { verdict: { accepted: true, reason: "" }, froze: false };
432
+ }
433
+
434
+ // Listed, but talking to us from somewhere it should not be. Recorded once for this machine
435
+ // and address, so being talked to repeatedly does not write repeatedly.
436
+ let pair = pairKey({ fingerprint: machineId, ip });
437
+ let alreadyRecorded = revocations.some(revocation =>
438
+ pairKey({ fingerprint: revocation.machineId, ip: revocation.ip }) === pair);
439
+ if (!alreadyRecorded && !allowedAgain(pair)) {
440
+ await recordMachineRevocation({ sourceURL, machineId, ip, hostLabel: os.hostname() });
441
+ return { verdict: { accepted: false, reason: `that machine is not allowed from ${ip}, so it is now frozen everywhere` }, froze: true };
442
+ }
443
+ return { verdict: { accepted: false, reason: `that machine is not allowed from ${ip}` }, froze: false };
444
+ };
445
+
446
+ let { verdict, froze } = await evaluate();
447
+ // An accept, or a rejection that just froze the machine, is the final word. Any other rejection
448
+ // might just be a stale list - a machine added seconds ago we have not caught up to - so it is
449
+ // worth one fresh look.
450
+ if (verdict.accepted || froze) {
451
+ return verdict;
452
+ }
453
+ // Re-read the list at most once a minute, so a burst of bad callers cannot make us re-read on
454
+ // every one of them, then take whatever the fresh look says as final.
455
+ if (Date.now() - lastMachinesInvalidation > MACHINES_INVALIDATION_INTERVAL) {
456
+ lastMachinesInvalidation = Date.now();
457
+ trustedMachines.reset();
381
458
  }
382
- return { accepted: false, reason: `that machine is not allowed from ${ip}` };
459
+ return (await evaluate()).verdict;
383
460
  }
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
4
  };
@@ -203,4 +203,4 @@ function stopDiscordNotifications() {
203
203
  }
204
204
  exports.stopDiscordNotifications = stopDiscordNotifications;
205
205
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzY29yZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRpc2NvcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMkRBQTZCO0FBRTdCLHNIQUFzSDtBQUN0SCxrR0FBa0c7QUFDbEcsOENBQThDO0FBRWpDLFFBQUEseUJBQXlCLEdBQUcsaUNBQWlDLENBQUM7QUFDM0UsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUM3QyxNQUFNLHNCQUFzQixHQUFHO0lBQzNCLG1DQUFtQztJQUNuQyxzQ0FBc0M7SUFDdEMsMENBQTBDO0NBQzdDLENBQUM7QUFDRixNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQztBQUNuQyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQztBQUNsQyxNQUFNLGlCQUFpQixHQUFHLENBQUMsQ0FBQztBQUM1QixNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLHVCQUF1QixHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7QUFFekMsSUFBSSxpQkFJUyxDQUFDO0FBRWQsc0ZBQXNGO0FBQ3RGLDRDQUE0QztBQUM1QyxJQUFJLFNBQVMsR0FBcUIsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBRXBEO3NDQUNzQztBQUN0QyxTQUFnQixnQkFBZ0IsQ0FBQyxNQUFnRDtJQUM3RSxJQUFJLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUN0QyxJQUFJLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN4RyxJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2QsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsVUFBVSxnQ0FBZ0MsQ0FBQyxDQUFDO0lBQ3JHLENBQUM7SUFDRCxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDeEUsTUFBTSxJQUFJLEtBQUssQ0FDWCx1REFBdUQsc0JBQXNCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJO2NBQzFGLE9BQU8sVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUscUJBQXFCLENBQUMsUUFBUSxVQUFVLEdBQUcsQ0FDM0UsQ0FBQztJQUNOLENBQUM7SUFDRCxPQUFPLFVBQVUsQ0FBQztBQUN0QixDQUFDO0FBZEQsNENBY0M7QUFFRDtnREFDZ0Q7QUFDaEQsU0FBZ0IsZ0JBQWdCLENBQUMsVUFBa0I7SUFDL0MsSUFBSSxjQUFjLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRCxJQUFJLElBQUksR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxjQUFjLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDbkQsSUFBSSxLQUFLLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDakQsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLHNCQUFzQixHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzdDLG1FQUFtRTtRQUNuRSxPQUFPLEdBQUcsSUFBSSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLHNCQUFzQixDQUFDLEtBQUssQ0FBQztJQUNqRSxDQUFDO0lBQ0QsT0FBTyxHQUFHLElBQUksR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxzQkFBc0IsQ0FBQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLENBQUM7QUFDeEcsQ0FBQztBQVRELDRDQVNDO0FBRUQsU0FBZ0IsaUJBQWlCLENBQUMsVUFBa0I7SUFDaEQsT0FBTyxrRUFBa0UsVUFBVSxJQUFJLENBQUM7QUFDNUYsQ0FBQztBQUZELDhDQUVDO0FBRUQsS0FBSyxVQUFVLGVBQWUsQ0FBQyxRQUFnQjtJQUMzQyxJQUFJLFFBQVEsQ0FBQztJQUNiLElBQUksQ0FBQztRQUNELFFBQVEsR0FBRyxNQUFNLGtCQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNULE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFDRCxPQUFPLGdCQUFnQixDQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFFRDs7cUZBRXFGO0FBQ3JGLFNBQWdCLGdCQUFnQixDQUFDLEdBQVM7SUFDdEMsSUFBSSxJQUFJLEdBQUcsR0FBRyxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNDLElBQUksSUFBSSxHQUFHLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUU7UUFDdkMsSUFBSSxFQUFFLFNBQVM7UUFDZixNQUFNLEVBQUUsU0FBUztRQUNqQixNQUFNLEVBQUUsU0FBUztRQUNqQixNQUFNLEVBQUUsSUFBSTtRQUNaLFlBQVksRUFBRSxPQUFPO0tBQ3hCLENBQUMsQ0FBQztJQUNILE9BQU8sR0FBRyxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7QUFDN0IsQ0FBQztBQVZELDRDQVVDO0FBRUQsS0FBSyxVQUFVLGFBQWEsQ0FBQyxVQUFrQixFQUFFLE9BQWU7SUFDNUQsNEZBQTRGO0lBQzVGLDZGQUE2RjtJQUM3Riw0RUFBNEU7SUFDNUUsSUFBSSxPQUFPLEdBQUcsR0FBRyxPQUFPLFFBQVEsZ0JBQWdCLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUM7SUFDakUsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLHFCQUFxQixFQUFFLENBQUM7UUFDekMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLHFCQUFxQixHQUFHLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUNsRSxDQUFDO0lBQ0QsS0FBSyxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsT0FBTyxJQUFJLGlCQUFpQixFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUM7UUFDNUQsSUFBSSxRQUFRLEdBQUcsTUFBTSxLQUFLLENBQUMsVUFBVSxFQUFFO1lBQ25DLE1BQU0sRUFBRSxNQUFNO1lBQ2QsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFO1lBQy9DLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUM7U0FDcEMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxRQUFRLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDZCxPQUFPO1FBQ1gsQ0FBQztRQUNELElBQUksSUFBSSxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLHFCQUFxQixDQUFDLENBQUM7UUFDbkUsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEdBQUcsSUFBSSxPQUFPLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQztZQUN6RCxJQUFJLFVBQVUsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztZQUM3RCxJQUFJLFFBQVEsR0FBRyxVQUFVLElBQUksVUFBVSxHQUFHLElBQUksSUFBSSx1QkFBdUIsQ0FBQztZQUMxRSxNQUFNLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQzVELFNBQVM7UUFDYixDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FDWCx5REFBeUQsUUFBUSxDQUFDLE1BQU0sSUFBSSxRQUFRLENBQUMsVUFBVSxVQUFVLElBQUksRUFBRSxDQUNsSCxDQUFDO0lBQ04sQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxVQUFrQixFQUFFLE9BQWU7SUFDbEQsSUFBSSxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwRCxJQUFJLE1BQU0sR0FBRyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN4QyxTQUFTLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMxQyxPQUFPLE1BQU0sQ0FBQztBQUNsQixDQUFDO0FBRUQ7OEVBQzhFO0FBQzlFLFNBQWdCLGdCQUFnQixDQUFDLE1BQStDO0lBQzVFLE9BQU8sU0FBUyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ3hELENBQUM7QUFGRCw0Q0FFQztBQUVELEtBQUssVUFBVSx1QkFBdUI7SUFDbEMsSUFBSSxLQUFLLEdBQUcsaUJBQWlCLENBQUM7SUFDOUIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ1QsT0FBTztJQUNYLENBQUM7SUFDRCxJQUFJLGFBQWEsQ0FBQztJQUNsQixJQUFJLENBQUM7UUFDRCxhQUFhLEdBQUcsTUFBTSxlQUFlLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzFELENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1QsT0FBTyxDQUFDLEtBQUssQ0FBQywyRkFBMkYsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM5RyxPQUFPO0lBQ1gsQ0FBQztJQUNELElBQUksYUFBYSxLQUFLLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNyQyxPQUFPO0lBQ1gsQ0FBQztJQUNELDhGQUE4RjtJQUM5RixzQ0FBc0M7SUFDdEMsSUFBSSxDQUFDO1FBQ0QsTUFBTSxTQUFTLENBQ1gsS0FBSyxDQUFDLFVBQVUsRUFDaEIsaUVBQWlFO2NBQy9ELHNGQUFzRjtjQUN0Riw4Q0FBOEM7Y0FDOUMsc0JBQXNCLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxJQUFJO2NBQ3pELGVBQWUsS0FBSyxDQUFDLFFBQVEsSUFBSSxDQUN0QyxDQUFDO0lBQ04sQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDVCxPQUFPLENBQUMsS0FBSyxDQUFDLHdFQUF3RSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQy9GLENBQUM7SUFDRCxLQUFLLENBQUMsVUFBVSxHQUFHLGFBQWEsQ0FBQztBQUNyQyxDQUFDO0FBRUQ7O21DQUVtQztBQUM1QixLQUFLLFVBQVUsNkJBQTZCLENBQUMsTUFHbkQ7SUFDRyxJQUFJLGlCQUFpQixFQUFFLENBQUM7UUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQyw2RkFBNkYsaUJBQWlCLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztJQUNoSixDQUFDO0lBQ0QsSUFBSSxRQUFRLEdBQUcsQ0FBQSxNQUFNLGFBQU4sTUFBTSx1QkFBTixNQUFNLENBQUUsUUFBUSxLQUFJLGlDQUF5QixDQUFDO0lBQzdELElBQUksYUFBYSxHQUFHLENBQUEsTUFBTSxhQUFOLE1BQU0sdUJBQU4sTUFBTSxDQUFFLGFBQWEsS0FBSSxzQkFBc0IsQ0FBQztJQUNwRSxJQUFJLFVBQVUsQ0FBQztJQUNmLElBQUksQ0FBQztRQUNELFVBQVUsR0FBRyxNQUFNLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNULE9BQU8sQ0FBQyxLQUFLLENBQUMsd0VBQXdFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDM0YsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwQixDQUFDO0lBQ0QsSUFBSSxVQUFVLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtRQUM5Qix1QkFBdUIsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsa0RBQWtELENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvRyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDbEIsZ0VBQWdFO0lBQ2hFLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNuQixpQkFBaUIsR0FBRyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLENBQUM7SUFDekQsT0FBTyxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsQ0FBQztBQUN2QyxDQUFDO0FBdkJELHNFQXVCQztBQUVELGdHQUFnRztBQUNoRyxpR0FBaUc7QUFDakcsdUVBQXVFO0FBQ2hFLEtBQUssVUFBVSx1QkFBdUIsQ0FBQyxPQUFlO0lBQ3pELElBQUksS0FBSyxHQUFHLGlCQUFpQixDQUFDO0lBQzlCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNULE1BQU0sSUFBSSxLQUFLLENBQUMsK0ZBQStGLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLHFCQUFxQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzlKLENBQUM7SUFDRCxNQUFNLFNBQVMsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFORCwwREFNQztBQUVEO3lGQUN5RjtBQUN6RixTQUFnQixpQ0FBaUM7SUFDN0MsT0FBTyxDQUFDLENBQUMsaUJBQWlCLENBQUM7QUFDL0IsQ0FBQztBQUZELDhFQUVDO0FBRUQsU0FBZ0Isd0JBQXdCO0lBQ3BDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3JCLE9BQU87SUFDWCxDQUFDO0lBQ0QsYUFBYSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzVDLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztBQUNsQyxDQUFDO0FBTkQsNERBTUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzL3Byb21pc2VzXCI7XG5cbi8vIFBPUlRFRCBDT0RFOiBzZWN1cml0eS9hdXRob3JpemVkS2V5cy9kYWVtb24vcG9ydHNlY3VyZURhZW1vbi5qcyBlbWJlZHMgYSBoYW5kIHBvcnQgb2YgdGhpcyBmaWxlIGluIHBsYWluIEpTLCBzbyB0aGVcbi8vIGRhZW1vbiBjYW4gcnVuIHdpdGggbm8gZGVwZW5kZW5jaWVzLiBUaGUgdHdvIGFyZSBleHBlY3RlZCB0byBiZWhhdmUgaWRlbnRpY2FsbHkgLSBpZiB5b3UgY2hhbmdlXG4vLyBvbmUsIG1ha2UgdGhlIG1hdGNoaW5nIGNoYW5nZSBpbiB0aGUgb3RoZXIuXG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1dFQkhPT0tfRklMRV9QQVRIID0gXCIvZXRjL3BvcnRzZWN1cmUvZGlzY29yZC13ZWJob29rXCI7XG5jb25zdCBERUZBVUxUX0NIRUNLX0lOVEVSVkFMID0gNSAqIDYwICogMTAwMDtcbmNvbnN0IFZBTElEX1dFQkhPT0tfUFJFRklYRVMgPSBbXG4gICAgXCJodHRwczovL2Rpc2NvcmQuY29tL2FwaS93ZWJob29rcy9cIixcbiAgICBcImh0dHBzOi8vZGlzY29yZGFwcC5jb20vYXBpL3dlYmhvb2tzL1wiLFxuICAgIFwiaHR0cHM6Ly9jYW5hcnkuZGlzY29yZC5jb20vYXBpL3dlYmhvb2tzL1wiLFxuXTtcbmNvbnN0IERJU0NPUkRfTUVTU0FHRV9MSU1JVCA9IDIwMDA7XG5jb25zdCBNQVhfRVJST1JfQk9EWV9MRU5HVEggPSA1MDA7XG5jb25zdCBNQVhfU0VORF9BVFRFTVBUUyA9IDM7XG5jb25zdCBSRURBQ1RFRF9UT0tFTl9WSVNJQkxFID0gODtcbmNvbnN0IERFRkFVTFRfUkFURV9MSU1JVF9XQUlUID0gMiAqIDEwMDA7XG5cbmxldCBub3RpZmljYXRpb25TdGF0ZToge1xuICAgIGZpbGVQYXRoOiBzdHJpbmc7XG4gICAgd2ViaG9va1VSTDogc3RyaW5nO1xuICAgIGNoZWNrVGltZXI6IE5vZGVKUy5UaW1lb3V0O1xufSB8IHVuZGVmaW5lZDtcblxuLy8gRGlzY29yZCB3ZWJob29rcyBhcmUgcmF0ZSBsaW1pdGVkIChyb3VnaGx5IDUgcmVxdWVzdHMgcGVyIDIgc2Vjb25kcyksIHNvIGV2ZXJ5IHNlbmRcbi8vIGdvZXMgdGhyb3VnaCBvbmUgY2hhaW4gaW5zdGVhZCBvZiByYWNpbmcuXG5sZXQgc2VuZENoYWluOiBQcm9taXNlPHVua25vd24+ID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbi8qKiBQdWxscyB0aGUgd2ViaG9vayBVUkwgb3V0IG9mIHdlYmhvb2sgZmlsZSBjb250ZW50cy4gYHNvdXJjZU5hbWVgIG9ubHkgYXBwZWFycyBpbiBlcnJvcnMsIHNvXG4gICAgY2FsbGVycyBjYW4gbmFtZSBhIHJlbW90ZSBwYXRoLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlV2ViaG9va0ZpbGUoY29uZmlnOiB7IGNvbnRlbnRzOiBzdHJpbmc7IHNvdXJjZU5hbWU6IHN0cmluZyB9KSB7XG4gICAgbGV0IHsgY29udGVudHMsIHNvdXJjZU5hbWUgfSA9IGNvbmZpZztcbiAgICBsZXQgbGluZXMgPSBjb250ZW50cy5zcGxpdChcIlxcblwiKS5tYXAobGluZSA9PiBsaW5lLnRyaW0oKSkuZmlsdGVyKGxpbmUgPT4gbGluZSAmJiAhbGluZS5zdGFydHNXaXRoKFwiI1wiKSk7XG4gICAgbGV0IHdlYmhvb2tVUkwgPSBsaW5lc1swXTtcbiAgICBpZiAoIXdlYmhvb2tVUkwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhIERpc2NvcmQgd2ViaG9vayBVUkwgaW4gJHtzb3VyY2VOYW1lfSwgdGhlIGZpbGUgaGFzIG5vIHVzYWJsZSBsaW5lc2ApO1xuICAgIH1cbiAgICBpZiAoIVZBTElEX1dFQkhPT0tfUFJFRklYRVMuc29tZShwcmVmaXggPT4gd2ViaG9va1VSTC5zdGFydHNXaXRoKHByZWZpeCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCBhIERpc2NvcmQgd2ViaG9vayBVUkwgc3RhcnRpbmcgd2l0aCBvbmUgb2YgJHtWQUxJRF9XRUJIT09LX1BSRUZJWEVTLmpvaW4oXCIsIFwiKX0sIGBcbiAgICAgICAgICAgICsgYHdhcyAke3dlYmhvb2tVUkwuc2xpY2UoMCwgTUFYX0VSUk9SX0JPRFlfTEVOR1RIKX0gKGluICR7c291cmNlTmFtZX0pYFxuICAgICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gd2ViaG9va1VSTDtcbn1cblxuLyoqIEtlZXBzIHRoZSBpZCBhbmQgYm90aCBlbmRzIG9mIHRoZSB0b2tlbiwgc28gYSByZWFkZXIgY2FuIGNvbmZpcm0gd2hpY2ggd2ViaG9vayByZXBsYWNlZCB0aGVpcnNcbiAgICB3aXRob3V0IHJlY2VpdmluZyBvbmUgdGhleSBjb3VsZCBwb3N0IHRvLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZGFjdFdlYmhvb2tVUkwod2ViaG9va1VSTDogc3RyaW5nKSB7XG4gICAgbGV0IHNlcGFyYXRvckluZGV4ID0gd2ViaG9va1VSTC5sYXN0SW5kZXhPZihcIi9cIik7XG4gICAgbGV0IGJhc2UgPSB3ZWJob29rVVJMLnNsaWNlKDAsIHNlcGFyYXRvckluZGV4ICsgMSk7XG4gICAgbGV0IHRva2VuID0gd2ViaG9va1VSTC5zbGljZShzZXBhcmF0b3JJbmRleCArIDEpO1xuICAgIGlmICh0b2tlbi5sZW5ndGggPD0gUkVEQUNURURfVE9LRU5fVklTSUJMRSAqIDIpIHtcbiAgICAgICAgLy8gVG9vIHNob3J0IHRvIHNob3cgYm90aCBlbmRzIHdpdGhvdXQgZ2l2aW5nIGF3YXkgdGhlIHdob2xlIHRva2VuLlxuICAgICAgICByZXR1cm4gYCR7YmFzZX0ke3Rva2VuLnNsaWNlKDAsIFJFREFDVEVEX1RPS0VOX1ZJU0lCTEUpfS4uLmA7XG4gICAgfVxuICAgIHJldHVybiBgJHtiYXNlfSR7dG9rZW4uc2xpY2UoMCwgUkVEQUNURURfVE9LRU5fVklTSUJMRSl9Li4uJHt0b2tlbi5zbGljZSgtUkVEQUNURURfVE9LRU5fVklTSUJMRSl9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFdlYmhvb2tGaWxlKHdlYmhvb2tVUkw6IHN0cmluZykge1xuICAgIHJldHVybiBgIyBwb3J0c2VjdXJlIERpc2NvcmQgd2ViaG9vay4gRmlyc3Qgbm9uLWNvbW1lbnQgbGluZSBpcyB1c2VkLlxcbiR7d2ViaG9va1VSTH1cXG5gO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkV2ViaG9va0ZpbGUoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIGxldCBjb250ZW50cztcbiAgICB0cnkge1xuICAgICAgICBjb250ZW50cyA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoLCBcInV0ZjhcIik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEgcmVhZGFibGUgRGlzY29yZCB3ZWJob29rIGZpbGUgYXQgJHtmaWxlUGF0aH0sICR7ZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlV2ViaG9va0ZpbGUoeyBjb250ZW50cywgc291cmNlTmFtZTogZmlsZVBhdGggfSk7XG59XG5cbi8qKiBXaGVuIHRoZSBtZXNzYWdlIHdhcyBzZW50LCBpbiB0aGUgc2VuZGluZyBtYWNoaW5lJ3Mgb3duIHRpbWUgem9uZS4gRGlzY29yZCBzaG93cyB3aGVuIGl0XG4gICAgcmVjZWl2ZWQgc29tZXRoaW5nLCB3aGljaCBpcyBub3QgdGhlIHNhbWUgdGhpbmcgd2hlbiBhIG1hY2hpbmUgaGFzIGJlZW4gb2ZmbGluZSBvciBhIHNlbmQgaGFzXG4gICAgYmVlbiByZXRyaWVkLCBhbmQgdGhlIHpvbmUgbWF0dGVycyB3aGVuIHRoZSBtYWNoaW5lcyBhcmUgbm90IGFsbCBpbiBvbmUgcGxhY2UuICovXG5leHBvcnQgZnVuY3Rpb24gbWVzc2FnZVRpbWVzdGFtcChub3c6IERhdGUpIHtcbiAgICBsZXQgZGF0ZSA9IG5vdy50b0xvY2FsZURhdGVTdHJpbmcoXCJlbi1DQVwiKTtcbiAgICBsZXQgdGltZSA9IG5vdy50b0xvY2FsZVRpbWVTdHJpbmcoXCJlbi1VU1wiLCB7XG4gICAgICAgIGhvdXI6IFwiMi1kaWdpdFwiLFxuICAgICAgICBtaW51dGU6IFwiMi1kaWdpdFwiLFxuICAgICAgICBzZWNvbmQ6IFwiMi1kaWdpdFwiLFxuICAgICAgICBob3VyMTI6IHRydWUsXG4gICAgICAgIHRpbWVab25lTmFtZTogXCJzaG9ydFwiLFxuICAgIH0pO1xuICAgIHJldHVybiBgJHtkYXRlfSAke3RpbWV9YDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcG9zdFRvV2ViaG9vayh3ZWJob29rVVJMOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgIC8vIFN0YW1wZWQgb25jZSByYXRoZXIgdGhhbiBwZXIgYXR0ZW1wdCwgc28gYSByZXRyeSBzYXlzIHdoZW4gdGhlIHRoaW5nIGhhcHBlbmVkIHJhdGhlciB0aGFuXG4gICAgLy8gd2hlbiB3ZSBsYXN0IG1hbmFnZWQgdG8gZ2V0IGl0IG91dC4gQXQgdGhlIGVuZCwgYmVjYXVzZSB0aGUgZmlyc3QgbGluZSBvZiBhIG1lc3NhZ2UgaXMgdGhlXG4gICAgLy8gbm90aWZpY2F0aW9uIHByZXZpZXcgYW5kIGEgdGltZXN0YW1wIHRoZXJlIHdvdWxkIHNwZW5kIGl0IHNheWluZyBub3RoaW5nLlxuICAgIGxldCBjb250ZW50ID0gYCR7bWVzc2FnZX0gwrcgXFxgJHttZXNzYWdlVGltZXN0YW1wKG5ldyBEYXRlKCkpfVxcYGA7XG4gICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gRElTQ09SRF9NRVNTQUdFX0xJTUlUKSB7XG4gICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnNsaWNlKDAsIERJU0NPUkRfTUVTU0FHRV9MSU1JVCAtIDMpICsgXCIuLi5cIjtcbiAgICB9XG4gICAgZm9yIChsZXQgYXR0ZW1wdCA9IDE7IGF0dGVtcHQgPD0gTUFYX1NFTkRfQVRURU1QVFM7IGF0dGVtcHQrKykge1xuICAgICAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh3ZWJob29rVVJMLCB7XG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgaGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBjb250ZW50IH0pLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGJvZHkgPSAoYXdhaXQgcmVzcG9uc2UudGV4dCgpKS5zbGljZSgwLCBNQVhfRVJST1JfQk9EWV9MRU5HVEgpO1xuICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MjkgJiYgYXR0ZW1wdCA8IE1BWF9TRU5EX0FUVEVNUFRTKSB7XG4gICAgICAgICAgICBsZXQgcmV0cnlBZnRlciA9IE51bWJlcihyZXNwb25zZS5oZWFkZXJzLmdldChcInJldHJ5LWFmdGVyXCIpKTtcbiAgICAgICAgICAgIGxldCB3YWl0VGltZSA9IHJldHJ5QWZ0ZXIgJiYgcmV0cnlBZnRlciAqIDEwMDAgfHwgREVGQVVMVF9SQVRFX0xJTUlUX1dBSVQ7XG4gICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgd2FpdFRpbWUpKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCBhIDJ4eCByZXNwb25zZSBmcm9tIHRoZSBEaXNjb3JkIHdlYmhvb2ssIHdhcyAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fSwgYm9keSAke2JvZHl9YFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcXVldWVTZW5kKHdlYmhvb2tVUkw6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgbGV0IHNlbmQgPSAoKSA9PiBwb3N0VG9XZWJob29rKHdlYmhvb2tVUkwsIG1lc3NhZ2UpO1xuICAgIGxldCByZXN1bHQgPSBzZW5kQ2hhaW4udGhlbihzZW5kLCBzZW5kKTtcbiAgICBzZW5kQ2hhaW4gPSByZXN1bHQuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKiogU2VuZHMgdG8gYW4gZXhwbGljaXQgd2ViaG9vayBVUkwsIGZvciB0b29saW5nIHRoYXQgYWN0cyBvbiBhIHdlYmhvb2sgYmVmb3JlIChvciBpbnN0ZWFkIG9mKVxuICAgIGNvbmZpZ3VyZURpc2NvcmROb3RpZmljYXRpb25zIC0gc2V0dXAsIG1pZ3JhdGlvbnMsIGNvbm5lY3Rpdml0eSBjaGVja3MuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZFRvV2ViaG9va1VSTChjb25maWc6IHsgd2ViaG9va1VSTDogc3RyaW5nOyBtZXNzYWdlOiBzdHJpbmcgfSkge1xuICAgIHJldHVybiBxdWV1ZVNlbmQoY29uZmlnLndlYmhvb2tVUkwsIGNvbmZpZy5tZXNzYWdlKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2hlY2tXZWJob29rRmlsZUNoYW5nZWQoKSB7XG4gICAgbGV0IHN0YXRlID0gbm90aWZpY2F0aW9uU3RhdGU7XG4gICAgaWYgKCFzdGF0ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBuZXdXZWJob29rVVJMO1xuICAgIHRyeSB7XG4gICAgICAgIG5ld1dlYmhvb2tVUkwgPSBhd2FpdCByZWFkV2ViaG9va0ZpbGUoc3RhdGUuZmlsZVBhdGgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgcG9ydHNlY3VyZTogRGlzY29yZCB3ZWJob29rIGZpbGUgaXMgbm8gbG9uZ2VyIHJlYWRhYmxlLCBzdGlsbCB1c2luZyB0aGUgbG9hZGVkIHdlYmhvb2suICR7ZX1gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobmV3V2ViaG9va1VSTCA9PT0gc3RhdGUud2ViaG9va1VSTCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIFdhcm4gdGhlIG9sZCBjaGFubmVsIGZpcnN0LCB3aXRoIHRoZSBuZXcgd2ViaG9vayByZWRhY3RlZCwgc28gYSBzdG9sZW4gb2xkIHdlYmhvb2sgZG9lcyBub3RcbiAgICAvLyBoYW5kIHRoZSBhdHRhY2tlciBhIHVzYWJsZSBuZXcgb25lLlxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHF1ZXVlU2VuZChcbiAgICAgICAgICAgIHN0YXRlLndlYmhvb2tVUkwsXG4gICAgICAgICAgICBgKipwb3J0c2VjdXJlKio6ICoqTk9USUZJQ0FUSU9OUyBBUkUgTU9WSU5HIFRPIEFOT1RIRVIgQ0hBTk5FTCoqYFxuICAgICAgICAgICAgKyBgXFxuXFxuVGhpcyBjaGFubmVsIHN0b3BzIHJlY2VpdmluZyB0aGVtIG5vdy4gSWYgdGhhdCB3YXMgbm90IHlvdSwgc29tZWJvZHkgd2l0aCBhY2Nlc3NgXG4gICAgICAgICAgICArIGAgdG8gdGhpcyBtYWNoaW5lIGp1c3QgcmVkaXJlY3RlZCBpdHMgYWxlcnRzLmBcbiAgICAgICAgICAgICsgYFxcblxcbm5ldyB3ZWJob29rOiBcXGAke3JlZGFjdFdlYmhvb2tVUkwobmV3V2ViaG9va1VSTCl9XFxgYFxuICAgICAgICAgICAgKyBgXFxuc2V0IGluOiBcXGAke3N0YXRlLmZpbGVQYXRofVxcYGBcbiAgICAgICAgKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYHBvcnRzZWN1cmU6IGZhaWxlZCB0byB3YXJuIHRoZSBvbGQgRGlzY29yZCB3ZWJob29rIGFib3V0IHRoZSBjaGFuZ2UuICR7ZX1gKTtcbiAgICB9XG4gICAgc3RhdGUud2ViaG9va1VSTCA9IG5ld1dlYmhvb2tVUkw7XG59XG5cbi8qKiBNdXN0IGJlIGNhbGxlZCBvbmNlIG9uIHN0YXJ0dXAsIGJlZm9yZSBhbnkgbm90aWZpY2F0aW9uIGlzIHNlbnQuIEFib3J0cyB0aGUgcHJvY2VzcyBpZiB0aGVcbiAgICB3ZWJob29rIGZpbGUgaXMgbWlzc2luZyBvciBpbnZhbGlkLCB0aGVuIHJlLWNoZWNrcyB0aGUgZmlsZSBvbiBhbiBpbnRlcnZhbCBhbmQgd2FybnMgdGhlIG9sZFxuICAgIHdlYmhvb2sgd2hlbmV2ZXIgaXQgY2hhbmdlcy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyhjb25maWc/OiB7XG4gICAgZmlsZVBhdGg/OiBzdHJpbmc7XG4gICAgY2hlY2tJbnRlcnZhbD86IG51bWJlcjtcbn0pIHtcbiAgICBpZiAobm90aWZpY2F0aW9uU3RhdGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyB0byBiZSBjYWxsZWQgb25jZSwgd2FzIGNhbGxlZCBhZ2FpbiAoYWxyZWFkeSB1c2luZyAke25vdGlmaWNhdGlvblN0YXRlLmZpbGVQYXRofSlgKTtcbiAgICB9XG4gICAgbGV0IGZpbGVQYXRoID0gY29uZmlnPy5maWxlUGF0aCB8fCBERUZBVUxUX1dFQkhPT0tfRklMRV9QQVRIO1xuICAgIGxldCBjaGVja0ludGVydmFsID0gY29uZmlnPy5jaGVja0ludGVydmFsIHx8IERFRkFVTFRfQ0hFQ0tfSU5URVJWQUw7XG4gICAgbGV0IHdlYmhvb2tVUkw7XG4gICAgdHJ5IHtcbiAgICAgICAgd2ViaG9va1VSTCA9IGF3YWl0IHJlYWRXZWJob29rRmlsZShmaWxlUGF0aCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBwb3J0c2VjdXJlOiByZWZ1c2luZyB0byBzdGFydCB3aXRob3V0IGEgdmFsaWQgRGlzY29yZCB3ZWJob29rIGZpbGUuXFxuJHtlfWApO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICAgIGxldCBjaGVja1RpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBjaGVja1dlYmhvb2tGaWxlQ2hhbmdlZCgpLmNhdGNoKGUgPT4gY29uc29sZS5lcnJvcihgcG9ydHNlY3VyZTogRGlzY29yZCB3ZWJob29rIGZpbGUgY2hlY2sgZmFpbGVkLiAke2V9YCkpO1xuICAgIH0sIGNoZWNrSW50ZXJ2YWwpO1xuICAgIC8vIFRoZSBjaGVjayBzaG91bGQgbmV2ZXIgYmUgdGhlIHJlYXNvbiB0aGUgcHJvY2VzcyBzdGF5cyBhbGl2ZS5cbiAgICBjaGVja1RpbWVyLnVucmVmKCk7XG4gICAgbm90aWZpY2F0aW9uU3RhdGUgPSB7IGZpbGVQYXRoLCB3ZWJob29rVVJMLCBjaGVja1RpbWVyIH07XG4gICAgcmV0dXJuIHsgZmlsZVBhdGgsIGNoZWNrSW50ZXJ2YWwgfTtcbn1cblxuLy8gRE8gTk9UIGFkZCBuZXcgY2FsbHMgdG8gdGhpcy4gRXZlcnkgbWVzc2FnZSBnb2VzIHRvIGEgcmVhbCBEaXNjb3JkIHNlcnZlciBzb21lb25lIHJlYWRzLCBzbyBhXG4vLyBub3RpZmljYXRpb24gaXMgb25seSBldmVyIGFkZGVkIHdoZW4gdGhlIHVzZXIgZXhwbGljaXRseSBhc2tzIGZvciB0aGF0IHNwZWNpZmljIGNhc2UuIFN0YXJ0dXAsXG4vLyBzdWNjZXNzLCBlcnJvcnMsIHJldHJpZXMgYW5kIHJlY292ZXJpZXMgYWxsIGJlbG9uZyBpbiBhIGxvZyBpbnN0ZWFkLlxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmREaXNjb3JkTm90aWZpY2F0aW9uKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIGxldCBzdGF0ZSA9IG5vdGlmaWNhdGlvblN0YXRlO1xuICAgIGlmICghc3RhdGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyB0byBiZSBjYWxsZWQgYmVmb3JlIHNlbmRpbmcsIHdhcyBjYWxsZWQgd2l0aCBtZXNzYWdlICR7bWVzc2FnZS5zbGljZSgwLCBNQVhfRVJST1JfQk9EWV9MRU5HVEgpfWApO1xuICAgIH1cbiAgICBhd2FpdCBxdWV1ZVNlbmQoc3RhdGUud2ViaG9va1VSTCwgbWVzc2FnZSk7XG59XG5cbi8qKiBXaGV0aGVyIG5vdGlmaWNhdGlvbnMgYXJlIHNldCB1cCBpbiB0aGlzIHByb2Nlc3MuIEZvciBjb2RlIHRoYXQgbWF5IHJ1biBvdXRzaWRlIHRoZSBkYWVtb24sXG4gICAgd2hlcmUgc2VuZGluZyBpcyB3b3J0aCBkb2luZyBpZiBpdCBjYW4gYmUgYW5kIG5vdCB3b3J0aCBmYWlsaW5nIG92ZXIgaWYgaXQgY2Fubm90LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFyZURpc2NvcmROb3RpZmljYXRpb25zQ29uZmlndXJlZCgpIHtcbiAgICByZXR1cm4gISFub3RpZmljYXRpb25TdGF0ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BEaXNjb3JkTm90aWZpY2F0aW9ucygpIHtcbiAgICBpZiAoIW5vdGlmaWNhdGlvblN0YXRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2xlYXJJbnRlcnZhbChub3RpZmljYXRpb25TdGF0ZS5jaGVja1RpbWVyKTtcbiAgICBub3RpZmljYXRpb25TdGF0ZSA9IHVuZGVmaW5lZDtcbn1cbiJdfQ==
206
- /* _JS_SOURCE_HASH = "abb6e0b243d1d85cb4a3599020263d0b3164ce4bf2aef2aa81489e304cd43b4c"; */
206
+ /* _JS_SOURCE_HASH = "a4fe18f537fa6da028d1607b16331b146697f9fabb96c6de058f0b41c5553b17"; */
@@ -24,7 +24,7 @@ function parseArgs(argv: string[]) {
24
24
  return { host, webhookURL, replace };
25
25
  }
26
26
 
27
- export async function main() {
27
+ async function main() {
28
28
  let { host, webhookURL, replace } = parseArgs(process.argv.slice(2));
29
29
  let { outcome, filePath } = await ensureRemoteWebhook({ host, webhookURL, replace });
30
30
  if (outcome === "unchanged") {
@@ -36,3 +36,8 @@ export async function main() {
36
36
  }
37
37
  console.log(`Wrote ${filePath} on ${describeHost(host)} (mode 600), and confirmed on the new webhook.`);
38
38
  }
39
+
40
+ main().catch(e => {
41
+ console.error(`${e}`);
42
+ process.exitCode = 1;
43
+ }).finally(() => process.exit());
@@ -9,7 +9,7 @@ Sends one message to a webhook, to prove it works. With no host it uses this mac
9
9
  ${DEFAULT_WEBHOOK_FILE_PATH}. With a host it reads that host's webhook and sends to that instead,
10
10
  which is how you check a machine you have just set up.`;
11
11
 
12
- export async function main() {
12
+ async function main() {
13
13
  let argv = process.argv.slice(2);
14
14
  if (argv.length > 1) {
15
15
  throw new Error(`Expected at most a host, was ${argv.length} argument(s)\n${USAGE}`);
@@ -46,3 +46,8 @@ export async function main() {
46
46
  });
47
47
  console.log(`Sent a test message to the webhook ${source} uses.`);
48
48
  }
49
+
50
+ main().catch(e => {
51
+ console.error(`${e}`);
52
+ process.exitCode = 1;
53
+ }).finally(() => process.exit());
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
4
  };
@@ -82,4 +82,4 @@ function formatManifest(manifest) {
82
82
  }
83
83
  exports.formatManifest = formatManifest;
84
84
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuaWZlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtYW5pZmVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsMkRBQTZCO0FBQzdCLGdEQUF3QjtBQUN4Qiw0Q0FBZ0Q7QUFFaEQsa0dBQWtHO0FBQ2xHLGlHQUFpRztBQUNqRyxrR0FBa0c7QUFDbEcsdUJBQXVCO0FBRVYsUUFBQSxhQUFhLEdBQUcsa0JBQWtCLENBQUM7QUFDbkMsUUFBQSxjQUFjLEdBQUcsc0JBQXNCLENBQUM7QUFDckQsb0dBQW9HO0FBQ3ZGLFFBQUEsY0FBYyxHQUFHLFdBQVcsQ0FBQztBQUM3QixRQUFBLGdCQUFnQixHQUFHLENBQUMsQ0FBQztBQU9sQzs7Ozs7OzswRkFPMEY7QUFDbkYsS0FBSyxVQUFVLGFBQWEsQ0FBQyxRQUFnQjtJQUNoRCxJQUFJLE1BQU0sR0FBRyxNQUFNLElBQUEsb0JBQVksRUFBQztRQUM1QixPQUFPLEVBQUUsS0FBSztRQUNkLElBQUksRUFBRSxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLG9CQUFvQixDQUFDO1FBQ2hFLEdBQUcsRUFBRSxRQUFRO0tBQ2hCLENBQUMsQ0FBQztJQUNILElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN0QixNQUFNLElBQUksS0FBSyxDQUNYLGlDQUFpQyxRQUFRLHlCQUF5QixNQUFNLENBQUMsTUFBTSxJQUFJO2NBQ2pGLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNoRCxDQUFDO0lBQ04sQ0FBQztJQUNELElBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztTQUNqQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxJQUFJLElBQUksS0FBSyxxQkFBYSxJQUFJLElBQUksS0FBSyxzQkFBYyxDQUFDO1NBQ3pFLElBQUksRUFBRSxDQUFDO0lBRVosSUFBSSxPQUFPLEdBQWEsRUFBRSxDQUFDO0lBQzNCLEtBQUssSUFBSSxZQUFZLElBQUksTUFBTSxFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDO1lBQ0QsTUFBTSxrQkFBRSxDQUFDLE1BQU0sQ0FBQyxjQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQ25ELE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDL0IsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDVCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsWUFBWSx3REFBd0QsQ0FBQyxDQUFDO1FBQ2pHLENBQUM7SUFDTCxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDbkIsQ0FBQztBQTNCRCxzQ0EyQkM7QUFFRDs7OytCQUcrQjtBQUMvQixTQUFnQixnQkFBZ0IsQ0FBQyxRQUFnQjtJQUM3QyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQ3JGLENBQUM7QUFGRCw0Q0FFQztBQUVEOytGQUMrRjtBQUN4RixLQUFLLFVBQVUsVUFBVSxDQUFDLFFBQWdCO0lBQzdDLElBQUksUUFBUSxHQUFHLGdCQUFnQixDQUFDLE1BQU0sa0JBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUM3RCxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLGdCQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUN6RyxDQUFDO0FBSEQsZ0NBR0M7QUFFTSxLQUFLLFVBQVUsYUFBYSxDQUFDLFFBQWdCO0lBQ2hELElBQUksS0FBSyxHQUFzQixFQUFFLENBQUM7SUFDbEMsS0FBSyxJQUFJLFlBQVksSUFBSSxNQUFNLGFBQWEsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQ3JELElBQUksTUFBTSxHQUFHLE1BQU0sVUFBVSxDQUFDLGNBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFDakUsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ2pGLENBQUM7SUFDRCxPQUFPLEVBQUUsT0FBTyxFQUFFLHdCQUFnQixFQUFFLEtBQUssRUFBRSxDQUFDO0FBQ2hELENBQUM7QUFQRCxzQ0FPQztBQUVELG1HQUFtRztBQUNuRyxTQUFnQixjQUFjLENBQUMsUUFBa0I7SUFDN0MsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO0FBQ3pELENBQUM7QUFGRCx3Q0FFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjcnlwdG8gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0IGZzIGZyb20gXCJmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHNwYXduUHJvbWlzZSB9IGZyb20gXCIuLi9oZWxwZXJzL3NwYXduXCI7XG5cbi8vIFBPUlRFRCBDT0RFOiBzZWN1cml0eS9hdXRob3JpemVkS2V5cy9kYWVtb24vcG9ydHNlY3VyZURhZW1vbi5qcyBjb250YWlucyBhIHBsYWluIEpTIHBvcnQgb2YgdGhlXG4vLyB2ZXJpZnlpbmcgaGFsZiBvZiB0aGlzIGZpbGUsIHNvIGl0IGNhbiBjaGVjayBhIHNpZ25hdHVyZSB3aXRoIG5vIGRlcGVuZGVuY2llcy4gQm90aCBzaWRlcyBtdXN0XG4vLyBhZ3JlZSBvbiB0aGUgbWFuaWZlc3Qgc2hhcGUgYW5kIG9uIHdoaWNoIGZpbGVzIGl0IGNvdmVycyAtIGlmIHlvdSBjaGFuZ2Ugb25lLCBtYWtlIHRoZSBtYXRjaGluZ1xuLy8gY2hhbmdlIGluIHRoZSBvdGhlci5cblxuZXhwb3J0IGNvbnN0IE1BTklGRVNUX05BTUUgPSBcInNpZ25lZGZpbGVzLmpzb25cIjtcbmV4cG9ydCBjb25zdCBTSUdOQVRVUkVfTkFNRSA9IFwic2lnbmVkZmlsZXMuanNvbi5zaWdcIjtcbi8vIHNzaCBzaWduYXR1cmVzIGFyZSBuYW1lc3BhY2VkLCBzbyBhIHNpZ25hdHVyZSBtYWRlIGZvciBvbmUgcHVycG9zZSBjYW5ub3QgYmUgcmVwbGF5ZWQgYXMgYW5vdGhlci5cbmV4cG9ydCBjb25zdCBTSUdOX05BTUVTUEFDRSA9IFwic2lnbmZpbGVzXCI7XG5leHBvcnQgY29uc3QgTUFOSUZFU1RfVkVSU0lPTiA9IDE7XG5cbmV4cG9ydCB0eXBlIE1hbmlmZXN0ID0ge1xuICAgIHZlcnNpb246IG51bWJlcjtcbiAgICBmaWxlczogeyBwYXRoOiBzdHJpbmc7IHNpemU6IG51bWJlcjsgc2hhMjU2OiBzdHJpbmcgfVtdO1xufTtcblxuLyoqIEV2ZXJ5dGhpbmcgaW4gdGhlIHJlcG8gdGhhdCBpcyBub3QgaWdub3JlZDogd2hhdCBpcyBpbiB0aGUgaW5kZXgsIHBsdXMgd2hhdCBpcyBub3Qgc3RhZ2VkIHlldC5cbiAgICBHaXQgaXMgYXNrZWQgYmVjYXVzZSBnaXQgaXMgd2hhdCBrbm93cyBob3cgdG8gYXBwbHkgdGhlIGlnbm9yZSBydWxlcy5cblxuICAgIFdoYXQgY29tZXMgYmFjayBpcyBhIGhpbnQgdGhhdCBhIGZpbGUgbWlnaHQgYmUgdGhlcmUsIG5vdCB0aGF0IGl0IGlzLiBBIGZpbGUgZGVsZXRlZCBmcm9tIHRoZVxuICAgIHdvcmtpbmcgdHJlZSBzdGF5cyBpbiB0aGUgaW5kZXggdW50aWwgdGhhdCBkZWxldGlvbiBpcyBzdGFnZWQsIHNvIGdpdCBuYW1lcyBpdCBhbmQgdGhlcmUgaXNcbiAgICBub3RoaW5nIHRvIHJlYWQsIHdoaWNoIGlzIHdoeSBlYWNoIG9uZSBpcyBjaGVja2VkIGJlZm9yZSBpdCBnb2VzIGluLlxuXG4gICAgVGhlIG1hbmlmZXN0IGFuZCBpdHMgc2lnbmF0dXJlIGFyZSBsZWZ0IG91dCwgc2luY2UgdGhleSBjYW5ub3QgZGVzY3JpYmUgdGhlbXNlbHZlcy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0UmVwb0ZpbGVzKHJlcG9QYXRoOiBzdHJpbmcpIHtcbiAgICBsZXQgcmVzdWx0ID0gYXdhaXQgc3Bhd25Qcm9taXNlKHtcbiAgICAgICAgY29tbWFuZDogXCJnaXRcIixcbiAgICAgICAgYXJnczogW1wibHMtZmlsZXNcIiwgXCItLWNhY2hlZFwiLCBcIi0tb3RoZXJzXCIsIFwiLS1leGNsdWRlLXN0YW5kYXJkXCJdLFxuICAgICAgICBjd2Q6IHJlcG9QYXRoLFxuICAgIH0pO1xuICAgIGlmIChyZXN1bHQuc3RhdHVzICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCB0byBsaXN0IHRoZSBmaWxlcyBpbiAke3JlcG9QYXRofSwgZ2l0IGxzLWZpbGVzIGV4aXRlZCAke3Jlc3VsdC5zdGF0dXN9LiBgXG4gICAgICAgICAgICArIGAkeyhyZXN1bHQuc3Rkb3V0ICsgcmVzdWx0LnN0ZGVycikudHJpbSgpfWBcbiAgICAgICAgKTtcbiAgICB9XG4gICAgbGV0IGxpc3RlZCA9IHJlc3VsdC5zdGRvdXQuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgLm1hcChsaW5lID0+IGxpbmUudHJpbSgpKVxuICAgICAgICAuZmlsdGVyKGxpbmUgPT4gbGluZSAmJiBsaW5lICE9PSBNQU5JRkVTVF9OQU1FICYmIGxpbmUgIT09IFNJR05BVFVSRV9OQU1FKVxuICAgICAgICAuc29ydCgpO1xuXG4gICAgbGV0IHByZXNlbnQ6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChsZXQgcmVsYXRpdmVQYXRoIG9mIGxpc3RlZCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgZnMuYWNjZXNzKHBhdGguam9pbihyZXBvUGF0aCwgcmVsYXRpdmVQYXRoKSk7XG4gICAgICAgICAgICBwcmVzZW50LnB1c2gocmVsYXRpdmVQYXRoKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYExlYXZpbmcgJHtyZWxhdGl2ZVBhdGh9IG91dCBvZiB0aGUgbWFuaWZlc3QsIGl0IGlzIGdvbmUgZnJvbSB0aGUgd29ya2luZyB0cmVlYCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHByZXNlbnQ7XG59XG5cbi8qKiBBIFdpbmRvd3MgY2hlY2tvdXQgdHVybnMgTEYgaW50byBDUkxGLCBzbyB0aGUgc2FtZSBjb21taXQgaGFzaGVzIGRpZmZlcmVudGx5IHRoZXJlIHRoYW4gaXRcbiAgICBkb2VzIG9uIHRoZSBtYWNoaW5lIHRoYXQgcHVsbHMgaXQuIE5vcm1hbGlzaW5nIGZpcnN0IG1ha2VzIHRoZSBkaWdlc3QgZGVzY3JpYmUgdGhlIGNvbnRlbnRcbiAgICByYXRoZXIgdGhhbiB3aGljaGV2ZXIgY2hlY2tvdXQgcHJvZHVjZWQgaXQuIGxhdGluMSByb3VuZCB0cmlwcyBldmVyeSBieXRlLCBzbyB0aGlzIGlzIHNhZmUgb25cbiAgICBmaWxlcyB0aGF0IGFyZSBub3QgdGV4dC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVDb250ZW50KGNvbnRlbnRzOiBCdWZmZXIpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oY29udGVudHMudG9TdHJpbmcoXCJsYXRpbjFcIikucmVwbGFjZSgvXFxyXFxuL2csIFwiXFxuXCIpLCBcImxhdGluMVwiKTtcbn1cblxuLyoqIFRoZSBzaXplIGFuZCBoYXNoIG9mIGEgZmlsZSdzIG5vcm1hbGlzZWQgY29udGVudC4gVGhlIHNpemUgaXMgdGhlIG5vcm1hbGlzZWQgb25lIG9uIHB1cnBvc2UsXG4gICAgc28gaXQgYWdyZWVzIHdpdGggdGhlIGhhc2ggcmF0aGVyIHRoYW4gd2l0aCB3aGF0ZXZlciB0aGUgbG9jYWwgY2hlY2tvdXQgaGFwcGVucyB0byBob2xkLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRpZ2VzdEZpbGUoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIGxldCBjb250ZW50cyA9IG5vcm1hbGl6ZUNvbnRlbnQoYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgpKTtcbiAgICByZXR1cm4geyBzaXplOiBjb250ZW50cy5sZW5ndGgsIHNoYTI1NjogY3J5cHRvLmNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKGNvbnRlbnRzKS5kaWdlc3QoXCJoZXhcIikgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1aWxkTWFuaWZlc3QocmVwb1BhdGg6IHN0cmluZykge1xuICAgIGxldCBmaWxlczogTWFuaWZlc3RbXCJmaWxlc1wiXSA9IFtdO1xuICAgIGZvciAobGV0IHJlbGF0aXZlUGF0aCBvZiBhd2FpdCBsaXN0UmVwb0ZpbGVzKHJlcG9QYXRoKSkge1xuICAgICAgICBsZXQgZGlnZXN0ID0gYXdhaXQgZGlnZXN0RmlsZShwYXRoLmpvaW4ocmVwb1BhdGgsIHJlbGF0aXZlUGF0aCkpO1xuICAgICAgICBmaWxlcy5wdXNoKHsgcGF0aDogcmVsYXRpdmVQYXRoLCBzaXplOiBkaWdlc3Quc2l6ZSwgc2hhMjU2OiBkaWdlc3Quc2hhMjU2IH0pO1xuICAgIH1cbiAgICByZXR1cm4geyB2ZXJzaW9uOiBNQU5JRkVTVF9WRVJTSU9OLCBmaWxlcyB9O1xufVxuXG4vKiogU29ydGVkIGtleXMgYW5kIGEgdHJhaWxpbmcgbmV3bGluZSwgc28gdGhlIHNhbWUgdHJlZSBhbHdheXMgcHJvZHVjZXMgdGhlIHNhbWUgYnl0ZXMgdG8gc2lnbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRNYW5pZmVzdChtYW5pZmVzdDogTWFuaWZlc3QpIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWFuaWZlc3QsIHVuZGVmaW5lZCwgNCkgKyBcIlxcblwiO1xufVxuIl19
85
- /* _JS_SOURCE_HASH = "e58787cb53d84ba9647f11c90c737f7303e120b8e02ca37cc9f38202fce1929d"; */
85
+ /* _JS_SOURCE_HASH = "201e773734f1a3a4a276457669646f936d46b81026afab845e5b8161d1b4310d"; */
@@ -0,0 +1,138 @@
1
+ "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
+ //exports.verifySSHSIG = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ // Verifies an SSHSIG signature (the format ssh-keygen -Y sign produces) in process, so nothing has
9
+ // to shell out to ssh-keygen to check one. The wire format is PROTOCOL.sshsig, and the actual
10
+ // check is one ed25519 verification.
11
+ //
12
+ // Both ed25519 and the hardware sk-ed25519 variant are handled, since signfiles signs with a
13
+ // hardware ed25519-sk key. The sk variant signs a little more than the message - the authenticator
14
+ // flags and counter go in too - but it is still ed25519 underneath.
15
+ const MAGIC = "SSHSIG";
16
+ // An ed25519 public key as a DER SPKI is this fixed 12 byte header followed by the 32 byte key.
17
+ const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
18
+ /** Reads the length prefixed fields SSH wire format is made of. */
19
+ class Reader {
20
+ constructor(buffer) {
21
+ this.buffer = buffer;
22
+ this.offset = 0;
23
+ }
24
+ u8() {
25
+ return this.buffer.readUInt8(this.offset++);
26
+ }
27
+ u32() {
28
+ let value = this.buffer.readUInt32BE(this.offset);
29
+ this.offset += 4;
30
+ return value;
31
+ }
32
+ string() {
33
+ let length = this.u32();
34
+ let value = this.buffer.subarray(this.offset, this.offset + length);
35
+ this.offset += length;
36
+ return value;
37
+ }
38
+ remaining() {
39
+ return this.buffer.length - this.offset;
40
+ }
41
+ }
42
+ /** One length prefixed field, the way SSH writes them. */
43
+ function sshString(bytes) {
44
+ let length = Buffer.alloc(4);
45
+ length.writeUInt32BE(bytes.length);
46
+ return Buffer.concat([length, bytes]);
47
+ }
48
+ function hash(algorithm, data) {
49
+ // SSHSIG names sha256 or sha512; node uses the same names.
50
+ if (algorithm !== "sha256" && algorithm !== "sha512") {
51
+ throw new Error(`Unsupported SSHSIG hash algorithm ${JSON.stringify(algorithm)}`);
52
+ }
53
+ return crypto_1.default.createHash(algorithm).update(data).digest();
54
+ }
55
+ function ed25519PublicKey(rawKey) {
56
+ if (rawKey.length !== 32) {
57
+ throw new Error(`Expected a 32 byte ed25519 key, was ${rawKey.length}`);
58
+ }
59
+ return crypto_1.default.createPublicKey({
60
+ key: Buffer.concat([ED25519_SPKI_PREFIX, rawKey]),
61
+ format: "der",
62
+ type: "spki",
63
+ });
64
+ }
65
+ /** Verifies an SSHSIG signature over a message, and that it was made for the given namespace.
66
+ Returns the signing public key and its fingerprint, in the forms ssh-keygen reports them.
67
+ Throws if it does not verify, or is not for this namespace. */
68
+ function verifySSHSIG(config) {
69
+ let { signature, message, namespace } = config;
70
+ let body = signature.split("\n").filter(line => line && !line.startsWith("-----")).join("");
71
+ let blob = Buffer.from(body, "base64");
72
+ if (blob.subarray(0, MAGIC.length).toString() !== MAGIC) {
73
+ throw new Error(`Expected an ${MAGIC} signature, started with ${JSON.stringify(blob.subarray(0, MAGIC.length).toString())}`);
74
+ }
75
+ let reader = new Reader(blob.subarray(MAGIC.length));
76
+ let version = reader.u32();
77
+ if (version !== 1) {
78
+ throw new Error(`Expected SSHSIG version 1, was ${version}`);
79
+ }
80
+ let publicKeyBlob = reader.string();
81
+ let signatureNamespace = reader.string().toString();
82
+ reader.string(); // reserved
83
+ let hashAlgorithm = reader.string().toString();
84
+ let signatureBlob = reader.string();
85
+ if (signatureNamespace !== namespace) {
86
+ throw new Error(`Signature is for namespace ${JSON.stringify(signatureNamespace)}, expected ${JSON.stringify(namespace)}`);
87
+ }
88
+ let publicKeyReader = new Reader(publicKeyBlob);
89
+ let keyType = publicKeyReader.string().toString();
90
+ let rawKey = publicKeyReader.string();
91
+ let application = publicKeyReader.remaining() ? publicKeyReader.string() : Buffer.alloc(0);
92
+ let signatureReader = new Reader(signatureBlob);
93
+ let signatureType = signatureReader.string().toString();
94
+ let rawSignature = signatureReader.string();
95
+ if (signatureType !== keyType) {
96
+ throw new Error(`Signature type ${signatureType} does not match key type ${keyType}`);
97
+ }
98
+ // The bytes the signature is over: the magic, the namespace, the reserved field, the hash
99
+ // algorithm, and the hash of the message. Never the message itself, so a huge file still signs
100
+ // a fixed size blob.
101
+ let signed = Buffer.concat([
102
+ Buffer.from(MAGIC),
103
+ sshString(Buffer.from(signatureNamespace)),
104
+ sshString(Buffer.alloc(0)),
105
+ sshString(Buffer.from(hashAlgorithm)),
106
+ sshString(hash(hashAlgorithm, message)),
107
+ ]);
108
+ let toVerify;
109
+ if (keyType === "ssh-ed25519") {
110
+ toVerify = signed;
111
+ }
112
+ else if (keyType === "sk-ssh-ed25519@openssh.com") {
113
+ // A hardware key signs over what the authenticator saw, not the blob directly: the hash of
114
+ // the application it is scoped to, the flags and counter it returned, and the hash of the
115
+ // blob. Reconstructing that is the whole difference from a plain ed25519 signature.
116
+ let flags = signatureReader.u8();
117
+ let counter = signatureReader.u32();
118
+ let counterBytes = Buffer.alloc(4);
119
+ counterBytes.writeUInt32BE(counter);
120
+ toVerify = Buffer.concat([
121
+ hash("sha256", application),
122
+ Buffer.from([flags]),
123
+ counterBytes,
124
+ hash("sha256", signed),
125
+ ]);
126
+ }
127
+ else {
128
+ throw new Error(`Unsupported SSHSIG key type ${JSON.stringify(keyType)}`);
129
+ }
130
+ if (!crypto_1.default.verify(null, toVerify, ed25519PublicKey(rawKey), rawSignature)) {
131
+ throw new Error(`The SSHSIG signature does not verify`);
132
+ }
133
+ let fingerprint = "SHA256:" + crypto_1.default.createHash("sha256").update(publicKeyBlob).digest("base64").replace(/=+$/, "");
134
+ return { publicKey: `${keyType} ${publicKeyBlob.toString("base64")}`, fingerprint };
135
+ }
136
+ exports.verifySSHSIG = verifySSHSIG;
137
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Noc2lnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3Noc2lnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG9EQUE0QjtBQUU1QixtR0FBbUc7QUFDbkcsOEZBQThGO0FBQzlGLHFDQUFxQztBQUNyQyxFQUFFO0FBQ0YsNkZBQTZGO0FBQzdGLG1HQUFtRztBQUNuRyxvRUFBb0U7QUFFcEUsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDO0FBQ3ZCLGdHQUFnRztBQUNoRyxNQUFNLG1CQUFtQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsMEJBQTBCLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFFM0UsbUVBQW1FO0FBQ25FLE1BQU0sTUFBTTtJQUVSLFlBQW9CLE1BQWM7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBRDFCLFdBQU0sR0FBRyxDQUFDLENBQUM7SUFDbUIsQ0FBQztJQUN2QyxFQUFFO1FBQ0UsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBQ0QsR0FBRztRQUNDLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQztRQUNqQixPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBQ0QsTUFBTTtRQUNGLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN4QixJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLENBQUM7UUFDcEUsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUM7UUFDdEIsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUNELFNBQVM7UUFDTCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDNUMsQ0FBQztDQUNKO0FBRUQsMERBQTBEO0FBQzFELFNBQVMsU0FBUyxDQUFDLEtBQWE7SUFDNUIsSUFBSSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QixNQUFNLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuQyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUMxQyxDQUFDO0FBRUQsU0FBUyxJQUFJLENBQUMsU0FBaUIsRUFBRSxJQUFZO0lBQ3pDLDJEQUEyRDtJQUMzRCxJQUFJLFNBQVMsS0FBSyxRQUFRLElBQUksU0FBUyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ25ELE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFDRCxPQUFPLGdCQUFNLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztBQUM5RCxDQUFDO0FBRUQsU0FBUyxnQkFBZ0IsQ0FBQyxNQUFjO0lBQ3BDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBQ0QsT0FBTyxnQkFBTSxDQUFDLGVBQWUsQ0FBQztRQUMxQixHQUFHLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2pELE1BQU0sRUFBRSxLQUFLO1FBQ2IsSUFBSSxFQUFFLE1BQU07S0FDZixDQUFDLENBQUM7QUFDUCxDQUFDO0FBRUQ7O2tFQUVrRTtBQUNsRSxTQUFnQixZQUFZLENBQUMsTUFBaUU7SUFDMUYsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBRS9DLElBQUksSUFBSSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM1RixJQUFJLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN2QyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLEVBQUUsS0FBSyxLQUFLLEVBQUUsQ0FBQztRQUN0RCxNQUFNLElBQUksS0FBSyxDQUFDLGVBQWUsS0FBSyw0QkFBNEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakksQ0FBQztJQUVELElBQUksTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDckQsSUFBSSxPQUFPLEdBQUcsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQzNCLElBQUksT0FBTyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDakUsQ0FBQztJQUNELElBQUksYUFBYSxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNwQyxJQUFJLGtCQUFrQixHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNwRCxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxXQUFXO0lBQzVCLElBQUksYUFBYSxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMvQyxJQUFJLGFBQWEsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7SUFFcEMsSUFBSSxrQkFBa0IsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNuQyxNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixJQUFJLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLGNBQWMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0gsQ0FBQztJQUVELElBQUksZUFBZSxHQUFHLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ2hELElBQUksT0FBTyxHQUFHLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNsRCxJQUFJLE1BQU0sR0FBRyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDdEMsSUFBSSxXQUFXLEdBQUcsZUFBZSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0YsSUFBSSxlQUFlLEdBQUcsSUFBSSxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDaEQsSUFBSSxhQUFhLEdBQUcsZUFBZSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3hELElBQUksWUFBWSxHQUFHLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUM1QyxJQUFJLGFBQWEsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLGtCQUFrQixhQUFhLDRCQUE0QixPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFFRCwwRkFBMEY7SUFDMUYsK0ZBQStGO0lBQy9GLHFCQUFxQjtJQUNyQixJQUFJLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQ3ZCLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ2xCLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDMUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUIsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDckMsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDMUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxRQUFnQixDQUFDO0lBQ3JCLElBQUksT0FBTyxLQUFLLGFBQWEsRUFBRSxDQUFDO1FBQzVCLFFBQVEsR0FBRyxNQUFNLENBQUM7SUFDdEIsQ0FBQztTQUFNLElBQUksT0FBTyxLQUFLLDRCQUE0QixFQUFFLENBQUM7UUFDbEQsMkZBQTJGO1FBQzNGLDBGQUEwRjtRQUMxRixvRkFBb0Y7UUFDcEYsSUFBSSxLQUFLLEdBQUcsZUFBZSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ2pDLElBQUksT0FBTyxHQUFHLGVBQWUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNwQyxJQUFJLFlBQVksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25DLFlBQVksQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDckIsSUFBSSxDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUM7WUFDM0IsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BCLFlBQVk7WUFDWixJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQztTQUN6QixDQUFDLENBQUM7SUFDUCxDQUFDO1NBQU0sQ0FBQztRQUNKLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFFRCxJQUFJLENBQUMsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsRUFBRSxZQUFZLENBQUMsRUFBRSxDQUFDO1FBQ3pFLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQsSUFBSSxXQUFXLEdBQUcsU0FBUyxHQUFHLGdCQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNwSCxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsT0FBTyxJQUFJLGFBQWEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUN4RixDQUFDO0FBMUVELG9DQTBFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjcnlwdG8gZnJvbSBcImNyeXB0b1wiO1xuXG4vLyBWZXJpZmllcyBhbiBTU0hTSUcgc2lnbmF0dXJlICh0aGUgZm9ybWF0IHNzaC1rZXlnZW4gLVkgc2lnbiBwcm9kdWNlcykgaW4gcHJvY2Vzcywgc28gbm90aGluZyBoYXNcbi8vIHRvIHNoZWxsIG91dCB0byBzc2gta2V5Z2VuIHRvIGNoZWNrIG9uZS4gVGhlIHdpcmUgZm9ybWF0IGlzIFBST1RPQ09MLnNzaHNpZywgYW5kIHRoZSBhY3R1YWxcbi8vIGNoZWNrIGlzIG9uZSBlZDI1NTE5IHZlcmlmaWNhdGlvbi5cbi8vXG4vLyBCb3RoIGVkMjU1MTkgYW5kIHRoZSBoYXJkd2FyZSBzay1lZDI1NTE5IHZhcmlhbnQgYXJlIGhhbmRsZWQsIHNpbmNlIHNpZ25maWxlcyBzaWducyB3aXRoIGFcbi8vIGhhcmR3YXJlIGVkMjU1MTktc2sga2V5LiBUaGUgc2sgdmFyaWFudCBzaWducyBhIGxpdHRsZSBtb3JlIHRoYW4gdGhlIG1lc3NhZ2UgLSB0aGUgYXV0aGVudGljYXRvclxuLy8gZmxhZ3MgYW5kIGNvdW50ZXIgZ28gaW4gdG9vIC0gYnV0IGl0IGlzIHN0aWxsIGVkMjU1MTkgdW5kZXJuZWF0aC5cblxuY29uc3QgTUFHSUMgPSBcIlNTSFNJR1wiO1xuLy8gQW4gZWQyNTUxOSBwdWJsaWMga2V5IGFzIGEgREVSIFNQS0kgaXMgdGhpcyBmaXhlZCAxMiBieXRlIGhlYWRlciBmb2xsb3dlZCBieSB0aGUgMzIgYnl0ZSBrZXkuXG5jb25zdCBFRDI1NTE5X1NQS0lfUFJFRklYID0gQnVmZmVyLmZyb20oXCIzMDJhMzAwNTA2MDMyYjY1NzAwMzIxMDBcIiwgXCJoZXhcIik7XG5cbi8qKiBSZWFkcyB0aGUgbGVuZ3RoIHByZWZpeGVkIGZpZWxkcyBTU0ggd2lyZSBmb3JtYXQgaXMgbWFkZSBvZi4gKi9cbmNsYXNzIFJlYWRlciB7XG4gICAgcHJpdmF0ZSBvZmZzZXQgPSAwO1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgYnVmZmVyOiBCdWZmZXIpIHsgfVxuICAgIHU4KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5idWZmZXIucmVhZFVJbnQ4KHRoaXMub2Zmc2V0KyspO1xuICAgIH1cbiAgICB1MzIoKSB7XG4gICAgICAgIGxldCB2YWx1ZSA9IHRoaXMuYnVmZmVyLnJlYWRVSW50MzJCRSh0aGlzLm9mZnNldCk7XG4gICAgICAgIHRoaXMub2Zmc2V0ICs9IDQ7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgc3RyaW5nKCkge1xuICAgICAgICBsZXQgbGVuZ3RoID0gdGhpcy51MzIoKTtcbiAgICAgICAgbGV0IHZhbHVlID0gdGhpcy5idWZmZXIuc3ViYXJyYXkodGhpcy5vZmZzZXQsIHRoaXMub2Zmc2V0ICsgbGVuZ3RoKTtcbiAgICAgICAgdGhpcy5vZmZzZXQgKz0gbGVuZ3RoO1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICAgIHJlbWFpbmluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVmZmVyLmxlbmd0aCAtIHRoaXMub2Zmc2V0O1xuICAgIH1cbn1cblxuLyoqIE9uZSBsZW5ndGggcHJlZml4ZWQgZmllbGQsIHRoZSB3YXkgU1NIIHdyaXRlcyB0aGVtLiAqL1xuZnVuY3Rpb24gc3NoU3RyaW5nKGJ5dGVzOiBCdWZmZXIpIHtcbiAgICBsZXQgbGVuZ3RoID0gQnVmZmVyLmFsbG9jKDQpO1xuICAgIGxlbmd0aC53cml0ZVVJbnQzMkJFKGJ5dGVzLmxlbmd0aCk7XG4gICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoW2xlbmd0aCwgYnl0ZXNdKTtcbn1cblxuZnVuY3Rpb24gaGFzaChhbGdvcml0aG06IHN0cmluZywgZGF0YTogQnVmZmVyKSB7XG4gICAgLy8gU1NIU0lHIG5hbWVzIHNoYTI1NiBvciBzaGE1MTI7IG5vZGUgdXNlcyB0aGUgc2FtZSBuYW1lcy5cbiAgICBpZiAoYWxnb3JpdGhtICE9PSBcInNoYTI1NlwiICYmIGFsZ29yaXRobSAhPT0gXCJzaGE1MTJcIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIFNTSFNJRyBoYXNoIGFsZ29yaXRobSAke0pTT04uc3RyaW5naWZ5KGFsZ29yaXRobSl9YCk7XG4gICAgfVxuICAgIHJldHVybiBjcnlwdG8uY3JlYXRlSGFzaChhbGdvcml0aG0pLnVwZGF0ZShkYXRhKS5kaWdlc3QoKTtcbn1cblxuZnVuY3Rpb24gZWQyNTUxOVB1YmxpY0tleShyYXdLZXk6IEJ1ZmZlcikge1xuICAgIGlmIChyYXdLZXkubGVuZ3RoICE9PSAzMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEgMzIgYnl0ZSBlZDI1NTE5IGtleSwgd2FzICR7cmF3S2V5Lmxlbmd0aH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGNyeXB0by5jcmVhdGVQdWJsaWNLZXkoe1xuICAgICAgICBrZXk6IEJ1ZmZlci5jb25jYXQoW0VEMjU1MTlfU1BLSV9QUkVGSVgsIHJhd0tleV0pLFxuICAgICAgICBmb3JtYXQ6IFwiZGVyXCIsXG4gICAgICAgIHR5cGU6IFwic3BraVwiLFxuICAgIH0pO1xufVxuXG4vKiogVmVyaWZpZXMgYW4gU1NIU0lHIHNpZ25hdHVyZSBvdmVyIGEgbWVzc2FnZSwgYW5kIHRoYXQgaXQgd2FzIG1hZGUgZm9yIHRoZSBnaXZlbiBuYW1lc3BhY2UuXG4gICAgUmV0dXJucyB0aGUgc2lnbmluZyBwdWJsaWMga2V5IGFuZCBpdHMgZmluZ2VycHJpbnQsIGluIHRoZSBmb3JtcyBzc2gta2V5Z2VuIHJlcG9ydHMgdGhlbS5cbiAgICBUaHJvd3MgaWYgaXQgZG9lcyBub3QgdmVyaWZ5LCBvciBpcyBub3QgZm9yIHRoaXMgbmFtZXNwYWNlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcmlmeVNTSFNJRyhjb25maWc6IHsgc2lnbmF0dXJlOiBzdHJpbmc7IG1lc3NhZ2U6IEJ1ZmZlcjsgbmFtZXNwYWNlOiBzdHJpbmcgfSkge1xuICAgIGxldCB7IHNpZ25hdHVyZSwgbWVzc2FnZSwgbmFtZXNwYWNlIH0gPSBjb25maWc7XG5cbiAgICBsZXQgYm9keSA9IHNpZ25hdHVyZS5zcGxpdChcIlxcblwiKS5maWx0ZXIobGluZSA9PiBsaW5lICYmICFsaW5lLnN0YXJ0c1dpdGgoXCItLS0tLVwiKSkuam9pbihcIlwiKTtcbiAgICBsZXQgYmxvYiA9IEJ1ZmZlci5mcm9tKGJvZHksIFwiYmFzZTY0XCIpO1xuICAgIGlmIChibG9iLnN1YmFycmF5KDAsIE1BR0lDLmxlbmd0aCkudG9TdHJpbmcoKSAhPT0gTUFHSUMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhbiAke01BR0lDfSBzaWduYXR1cmUsIHN0YXJ0ZWQgd2l0aCAke0pTT04uc3RyaW5naWZ5KGJsb2Iuc3ViYXJyYXkoMCwgTUFHSUMubGVuZ3RoKS50b1N0cmluZygpKX1gKTtcbiAgICB9XG5cbiAgICBsZXQgcmVhZGVyID0gbmV3IFJlYWRlcihibG9iLnN1YmFycmF5KE1BR0lDLmxlbmd0aCkpO1xuICAgIGxldCB2ZXJzaW9uID0gcmVhZGVyLnUzMigpO1xuICAgIGlmICh2ZXJzaW9uICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgU1NIU0lHIHZlcnNpb24gMSwgd2FzICR7dmVyc2lvbn1gKTtcbiAgICB9XG4gICAgbGV0IHB1YmxpY0tleUJsb2IgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgbGV0IHNpZ25hdHVyZU5hbWVzcGFjZSA9IHJlYWRlci5zdHJpbmcoKS50b1N0cmluZygpO1xuICAgIHJlYWRlci5zdHJpbmcoKTsgLy8gcmVzZXJ2ZWRcbiAgICBsZXQgaGFzaEFsZ29yaXRobSA9IHJlYWRlci5zdHJpbmcoKS50b1N0cmluZygpO1xuICAgIGxldCBzaWduYXR1cmVCbG9iID0gcmVhZGVyLnN0cmluZygpO1xuXG4gICAgaWYgKHNpZ25hdHVyZU5hbWVzcGFjZSAhPT0gbmFtZXNwYWNlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgU2lnbmF0dXJlIGlzIGZvciBuYW1lc3BhY2UgJHtKU09OLnN0cmluZ2lmeShzaWduYXR1cmVOYW1lc3BhY2UpfSwgZXhwZWN0ZWQgJHtKU09OLnN0cmluZ2lmeShuYW1lc3BhY2UpfWApO1xuICAgIH1cblxuICAgIGxldCBwdWJsaWNLZXlSZWFkZXIgPSBuZXcgUmVhZGVyKHB1YmxpY0tleUJsb2IpO1xuICAgIGxldCBrZXlUeXBlID0gcHVibGljS2V5UmVhZGVyLnN0cmluZygpLnRvU3RyaW5nKCk7XG4gICAgbGV0IHJhd0tleSA9IHB1YmxpY0tleVJlYWRlci5zdHJpbmcoKTtcbiAgICBsZXQgYXBwbGljYXRpb24gPSBwdWJsaWNLZXlSZWFkZXIucmVtYWluaW5nKCkgPyBwdWJsaWNLZXlSZWFkZXIuc3RyaW5nKCkgOiBCdWZmZXIuYWxsb2MoMCk7XG5cbiAgICBsZXQgc2lnbmF0dXJlUmVhZGVyID0gbmV3IFJlYWRlcihzaWduYXR1cmVCbG9iKTtcbiAgICBsZXQgc2lnbmF0dXJlVHlwZSA9IHNpZ25hdHVyZVJlYWRlci5zdHJpbmcoKS50b1N0cmluZygpO1xuICAgIGxldCByYXdTaWduYXR1cmUgPSBzaWduYXR1cmVSZWFkZXIuc3RyaW5nKCk7XG4gICAgaWYgKHNpZ25hdHVyZVR5cGUgIT09IGtleVR5cGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTaWduYXR1cmUgdHlwZSAke3NpZ25hdHVyZVR5cGV9IGRvZXMgbm90IG1hdGNoIGtleSB0eXBlICR7a2V5VHlwZX1gKTtcbiAgICB9XG5cbiAgICAvLyBUaGUgYnl0ZXMgdGhlIHNpZ25hdHVyZSBpcyBvdmVyOiB0aGUgbWFnaWMsIHRoZSBuYW1lc3BhY2UsIHRoZSByZXNlcnZlZCBmaWVsZCwgdGhlIGhhc2hcbiAgICAvLyBhbGdvcml0aG0sIGFuZCB0aGUgaGFzaCBvZiB0aGUgbWVzc2FnZS4gTmV2ZXIgdGhlIG1lc3NhZ2UgaXRzZWxmLCBzbyBhIGh1Z2UgZmlsZSBzdGlsbCBzaWduc1xuICAgIC8vIGEgZml4ZWQgc2l6ZSBibG9iLlxuICAgIGxldCBzaWduZWQgPSBCdWZmZXIuY29uY2F0KFtcbiAgICAgICAgQnVmZmVyLmZyb20oTUFHSUMpLFxuICAgICAgICBzc2hTdHJpbmcoQnVmZmVyLmZyb20oc2lnbmF0dXJlTmFtZXNwYWNlKSksXG4gICAgICAgIHNzaFN0cmluZyhCdWZmZXIuYWxsb2MoMCkpLFxuICAgICAgICBzc2hTdHJpbmcoQnVmZmVyLmZyb20oaGFzaEFsZ29yaXRobSkpLFxuICAgICAgICBzc2hTdHJpbmcoaGFzaChoYXNoQWxnb3JpdGhtLCBtZXNzYWdlKSksXG4gICAgXSk7XG5cbiAgICBsZXQgdG9WZXJpZnk6IEJ1ZmZlcjtcbiAgICBpZiAoa2V5VHlwZSA9PT0gXCJzc2gtZWQyNTUxOVwiKSB7XG4gICAgICAgIHRvVmVyaWZ5ID0gc2lnbmVkO1xuICAgIH0gZWxzZSBpZiAoa2V5VHlwZSA9PT0gXCJzay1zc2gtZWQyNTUxOUBvcGVuc3NoLmNvbVwiKSB7XG4gICAgICAgIC8vIEEgaGFyZHdhcmUga2V5IHNpZ25zIG92ZXIgd2hhdCB0aGUgYXV0aGVudGljYXRvciBzYXcsIG5vdCB0aGUgYmxvYiBkaXJlY3RseTogdGhlIGhhc2ggb2ZcbiAgICAgICAgLy8gdGhlIGFwcGxpY2F0aW9uIGl0IGlzIHNjb3BlZCB0bywgdGhlIGZsYWdzIGFuZCBjb3VudGVyIGl0IHJldHVybmVkLCBhbmQgdGhlIGhhc2ggb2YgdGhlXG4gICAgICAgIC8vIGJsb2IuIFJlY29uc3RydWN0aW5nIHRoYXQgaXMgdGhlIHdob2xlIGRpZmZlcmVuY2UgZnJvbSBhIHBsYWluIGVkMjU1MTkgc2lnbmF0dXJlLlxuICAgICAgICBsZXQgZmxhZ3MgPSBzaWduYXR1cmVSZWFkZXIudTgoKTtcbiAgICAgICAgbGV0IGNvdW50ZXIgPSBzaWduYXR1cmVSZWFkZXIudTMyKCk7XG4gICAgICAgIGxldCBjb3VudGVyQnl0ZXMgPSBCdWZmZXIuYWxsb2MoNCk7XG4gICAgICAgIGNvdW50ZXJCeXRlcy53cml0ZVVJbnQzMkJFKGNvdW50ZXIpO1xuICAgICAgICB0b1ZlcmlmeSA9IEJ1ZmZlci5jb25jYXQoW1xuICAgICAgICAgICAgaGFzaChcInNoYTI1NlwiLCBhcHBsaWNhdGlvbiksXG4gICAgICAgICAgICBCdWZmZXIuZnJvbShbZmxhZ3NdKSxcbiAgICAgICAgICAgIGNvdW50ZXJCeXRlcyxcbiAgICAgICAgICAgIGhhc2goXCJzaGEyNTZcIiwgc2lnbmVkKSxcbiAgICAgICAgXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBTU0hTSUcga2V5IHR5cGUgJHtKU09OLnN0cmluZ2lmeShrZXlUeXBlKX1gKTtcbiAgICB9XG5cbiAgICBpZiAoIWNyeXB0by52ZXJpZnkobnVsbCwgdG9WZXJpZnksIGVkMjU1MTlQdWJsaWNLZXkocmF3S2V5KSwgcmF3U2lnbmF0dXJlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBTU0hTSUcgc2lnbmF0dXJlIGRvZXMgbm90IHZlcmlmeWApO1xuICAgIH1cblxuICAgIGxldCBmaW5nZXJwcmludCA9IFwiU0hBMjU2OlwiICsgY3J5cHRvLmNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHB1YmxpY0tleUJsb2IpLmRpZ2VzdChcImJhc2U2NFwiKS5yZXBsYWNlKC89KyQvLCBcIlwiKTtcbiAgICByZXR1cm4geyBwdWJsaWNLZXk6IGAke2tleVR5cGV9ICR7cHVibGljS2V5QmxvYi50b1N0cmluZyhcImJhc2U2NFwiKX1gLCBmaW5nZXJwcmludCB9O1xufVxuIl19
138
+ /* _JS_SOURCE_HASH = "7806dd475f184dc11a03815e46fb4e4e3f975c3a65ac16bd167b7b6936c9149b"; */