@intentic/keyring 0.0.1-bootstrap.0 → 1.338.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -1
  3. package/dist/address.d.ts +14 -0
  4. package/dist/address.d.ts.map +1 -0
  5. package/dist/address.js +17 -0
  6. package/dist/address.js.map +1 -0
  7. package/dist/app.d.ts +3 -0
  8. package/dist/app.d.ts.map +1 -0
  9. package/dist/app.js +100 -0
  10. package/dist/app.js.map +1 -0
  11. package/dist/askpass/askpass-run.d.ts +7 -0
  12. package/dist/askpass/askpass-run.d.ts.map +1 -0
  13. package/dist/askpass/askpass-run.js +25 -0
  14. package/dist/askpass/askpass-run.js.map +1 -0
  15. package/dist/askpass/askpass.d.ts +9 -0
  16. package/dist/askpass/askpass.d.ts.map +1 -0
  17. package/dist/askpass/askpass.js +70 -0
  18. package/dist/askpass/askpass.js.map +1 -0
  19. package/dist/askpass-cli.d.ts +3 -0
  20. package/dist/askpass-cli.d.ts.map +1 -0
  21. package/dist/askpass-cli.js +4 -0
  22. package/dist/askpass-cli.js.map +1 -0
  23. package/dist/audit.d.ts +18 -0
  24. package/dist/audit.d.ts.map +1 -0
  25. package/dist/audit.js +14 -0
  26. package/dist/audit.js.map +1 -0
  27. package/dist/backends.d.ts +19 -0
  28. package/dist/backends.d.ts.map +1 -0
  29. package/dist/backends.js +97 -0
  30. package/dist/backends.js.map +1 -0
  31. package/dist/cli.d.ts +3 -0
  32. package/dist/cli.d.ts.map +1 -0
  33. package/dist/cli.js +11 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/client.d.ts +10 -0
  36. package/dist/client.d.ts.map +1 -0
  37. package/dist/client.js +59 -0
  38. package/dist/client.js.map +1 -0
  39. package/dist/consent/consent-posix.d.ts +6 -0
  40. package/dist/consent/consent-posix.d.ts.map +1 -0
  41. package/dist/consent/consent-posix.js +57 -0
  42. package/dist/consent/consent-posix.js.map +1 -0
  43. package/dist/consent/consent-windows.d.ts +5 -0
  44. package/dist/consent/consent-windows.d.ts.map +1 -0
  45. package/dist/consent/consent-windows.js +244 -0
  46. package/dist/consent/consent-windows.js.map +1 -0
  47. package/dist/consent/consent.d.ts +67 -0
  48. package/dist/consent/consent.d.ts.map +1 -0
  49. package/dist/consent/consent.js +89 -0
  50. package/dist/consent/consent.js.map +1 -0
  51. package/dist/core.d.ts +61 -0
  52. package/dist/core.d.ts.map +1 -0
  53. package/dist/core.js +882 -0
  54. package/dist/core.js.map +1 -0
  55. package/dist/index.d.ts +8 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +8 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/keyring-fetch.d.ts +4 -0
  60. package/dist/keyring-fetch.d.ts.map +1 -0
  61. package/dist/keyring-fetch.js +20 -0
  62. package/dist/keyring-fetch.js.map +1 -0
  63. package/dist/keys.d.ts +27 -0
  64. package/dist/keys.d.ts.map +1 -0
  65. package/dist/keys.js +55 -0
  66. package/dist/keys.js.map +1 -0
  67. package/dist/policy.d.ts +71 -0
  68. package/dist/policy.d.ts.map +1 -0
  69. package/dist/policy.js +170 -0
  70. package/dist/policy.js.map +1 -0
  71. package/dist/powershell.d.ts +22 -0
  72. package/dist/powershell.d.ts.map +1 -0
  73. package/dist/powershell.js +53 -0
  74. package/dist/powershell.js.map +1 -0
  75. package/dist/protocol.d.ts +923 -0
  76. package/dist/protocol.d.ts.map +1 -0
  77. package/dist/protocol.js +125 -0
  78. package/dist/protocol.js.map +1 -0
  79. package/dist/run.d.ts +20 -0
  80. package/dist/run.d.ts.map +1 -0
  81. package/dist/run.js +34 -0
  82. package/dist/run.js.map +1 -0
  83. package/dist/seal.d.ts +3 -0
  84. package/dist/seal.d.ts.map +1 -0
  85. package/dist/seal.js +3 -0
  86. package/dist/seal.js.map +1 -0
  87. package/dist/serve.d.ts +17 -0
  88. package/dist/serve.d.ts.map +1 -0
  89. package/dist/serve.js +65 -0
  90. package/dist/serve.js.map +1 -0
  91. package/dist/server.d.ts +9 -0
  92. package/dist/server.d.ts.map +1 -0
  93. package/dist/server.js +77 -0
  94. package/dist/server.js.map +1 -0
  95. package/dist/service/acl.d.ts +9 -0
  96. package/dist/service/acl.d.ts.map +1 -0
  97. package/dist/service/acl.js +25 -0
  98. package/dist/service/acl.js.map +1 -0
  99. package/dist/service/channel.d.ts +17 -0
  100. package/dist/service/channel.d.ts.map +1 -0
  101. package/dist/service/channel.js +64 -0
  102. package/dist/service/channel.js.map +1 -0
  103. package/dist/service/door.d.ts +89 -0
  104. package/dist/service/door.d.ts.map +1 -0
  105. package/dist/service/door.js +28 -0
  106. package/dist/service/door.js.map +1 -0
  107. package/dist/service/hello-verify.d.ts +2 -0
  108. package/dist/service/hello-verify.d.ts.map +1 -0
  109. package/dist/service/hello-verify.js +10 -0
  110. package/dist/service/hello-verify.js.map +1 -0
  111. package/dist/service/helper.d.ts +3 -0
  112. package/dist/service/helper.d.ts.map +1 -0
  113. package/dist/service/helper.js +117 -0
  114. package/dist/service/helper.js.map +1 -0
  115. package/dist/service/install.d.ts +10 -0
  116. package/dist/service/install.d.ts.map +1 -0
  117. package/dist/service/install.js +77 -0
  118. package/dist/service/install.js.map +1 -0
  119. package/dist/service/lines.d.ts +13 -0
  120. package/dist/service/lines.d.ts.map +1 -0
  121. package/dist/service/lines.js +89 -0
  122. package/dist/service/lines.js.map +1 -0
  123. package/dist/service/paths.d.ts +19 -0
  124. package/dist/service/paths.d.ts.map +1 -0
  125. package/dist/service/paths.js +27 -0
  126. package/dist/service/paths.js.map +1 -0
  127. package/dist/service/remote.d.ts +21 -0
  128. package/dist/service/remote.d.ts.map +1 -0
  129. package/dist/service/remote.js +83 -0
  130. package/dist/service/remote.js.map +1 -0
  131. package/dist/service/service-run.d.ts +3 -0
  132. package/dist/service/service-run.d.ts.map +1 -0
  133. package/dist/service/service-run.js +77 -0
  134. package/dist/service/service-run.js.map +1 -0
  135. package/dist/service/sid.d.ts +3 -0
  136. package/dist/service/sid.d.ts.map +1 -0
  137. package/dist/service/sid.js +10 -0
  138. package/dist/service/sid.js.map +1 -0
  139. package/dist/service/task.d.ts +11 -0
  140. package/dist/service/task.d.ts.map +1 -0
  141. package/dist/service/task.js +38 -0
  142. package/dist/service/task.js.map +1 -0
  143. package/dist/service/wire.d.ts +53 -0
  144. package/dist/service/wire.d.ts.map +1 -0
  145. package/dist/service/wire.js +17 -0
  146. package/dist/service/wire.js.map +1 -0
  147. package/dist/typing/android.d.ts +14 -0
  148. package/dist/typing/android.d.ts.map +1 -0
  149. package/dist/typing/android.js +117 -0
  150. package/dist/typing/android.js.map +1 -0
  151. package/dist/typing/index.d.ts +9 -0
  152. package/dist/typing/index.d.ts.map +1 -0
  153. package/dist/typing/index.js +21 -0
  154. package/dist/typing/index.js.map +1 -0
  155. package/dist/typing/linux.d.ts +6 -0
  156. package/dist/typing/linux.d.ts.map +1 -0
  157. package/dist/typing/linux.js +72 -0
  158. package/dist/typing/linux.js.map +1 -0
  159. package/dist/typing/mac.d.ts +5 -0
  160. package/dist/typing/mac.d.ts.map +1 -0
  161. package/dist/typing/mac.js +40 -0
  162. package/dist/typing/mac.js.map +1 -0
  163. package/dist/typing/typist.d.ts +32 -0
  164. package/dist/typing/typist.d.ts.map +1 -0
  165. package/dist/typing/typist.js +9 -0
  166. package/dist/typing/typist.js.map +1 -0
  167. package/dist/typing/windows.d.ts +4 -0
  168. package/dist/typing/windows.d.ts.map +1 -0
  169. package/dist/typing/windows.js +200 -0
  170. package/dist/typing/windows.js.map +1 -0
  171. package/dist/vault.d.ts +530 -0
  172. package/dist/vault.d.ts.map +1 -0
  173. package/dist/vault.js +188 -0
  174. package/dist/vault.js.map +1 -0
  175. package/dist/version.d.ts +2 -0
  176. package/dist/version.d.ts.map +1 -0
  177. package/dist/version.js +10 -0
  178. package/dist/version.js.map +1 -0
  179. package/package.json +56 -5
@@ -0,0 +1,97 @@
1
+ import { firstLineScrubbed, succeeded } from "./run.js";
2
+ const TIMEOUT_MS = 20_000;
3
+ const valueOf = (answer) => answer.stdout.replace(/\r?\n$/u, "");
4
+ const unavailable = (reason) => ({ ok: false, code: "unavailable", reason });
5
+ const failure = (manager, cli, answer, secrets) => {
6
+ if (answer.missing) {
7
+ return unavailable(`${manager}'s CLI (${cli}) is not installed, or not on this keyring's PATH.`);
8
+ }
9
+ if (answer.timedOut) {
10
+ return unavailable(`${manager} did not answer within ${String(TIMEOUT_MS / 1000)} s.`);
11
+ }
12
+ const said = firstLineScrubbed(answer.stderr, secrets);
13
+ return unavailable(`${manager} did not answer${said === "" ? "" : `: ${said}`}`);
14
+ };
15
+ export class BackendReader {
16
+ runner;
17
+ #bitwardenSession;
18
+ constructor(runner) {
19
+ this.runner = runner;
20
+ }
21
+ forget() {
22
+ this.#bitwardenSession = undefined;
23
+ }
24
+ async read(ref, configs, secretOf) {
25
+ switch (ref.backend) {
26
+ case "1password":
27
+ return await this.#onePassword(ref.ref, configs.find((config) => config.backend === "1password"), secretOf);
28
+ case "bitwarden": {
29
+ const config = configs.find((candidate) => candidate.backend === "bitwarden");
30
+ return config?.backend === "bitwarden"
31
+ ? await this.#bitwarden(ref.ref, ref.field, config, secretOf)
32
+ : unavailable("Bitwarden is not set up in this keyring: `intentic-machine keyring backend bitwarden` names the entry holding its master password.");
33
+ }
34
+ case "keepassxc": {
35
+ const config = configs.find((candidate) => candidate.backend === "keepassxc");
36
+ return config?.backend === "keepassxc"
37
+ ? await this.#keepass(ref.ref, ref.attribute, config, secretOf)
38
+ : unavailable("KeePassXC is not set up in this keyring: `intentic-machine keyring backend keepassxc` names its database and the entry holding its password.");
39
+ }
40
+ }
41
+ }
42
+ async #onePassword(ref, config, secretOf) {
43
+ const settings = config?.backend === "1password" ? config : undefined;
44
+ const cli = settings?.cli ?? "op";
45
+ let token;
46
+ if (settings?.tokenEntry !== undefined) {
47
+ token = await secretOf(settings.tokenEntry);
48
+ if (token === undefined) {
49
+ return unavailable(`The entry ${settings.tokenEntry}, which holds the 1Password token, is not in this keyring.`);
50
+ }
51
+ }
52
+ const args = [...(settings?.account === undefined ? [] : ["--account", settings.account]), "read", "--no-newline", ref];
53
+ const request = token === undefined ? { command: cli, args, timeoutMs: TIMEOUT_MS } : { command: cli, args, env: { OP_SERVICE_ACCOUNT_TOKEN: token }, timeoutMs: TIMEOUT_MS };
54
+ const answer = await this.runner(request);
55
+ return succeeded(answer) ? { ok: true, value: valueOf(answer) } : failure("1Password", cli, answer, token === undefined ? [] : [token]);
56
+ }
57
+ async #bitwarden(ref, field, config, secretOf) {
58
+ const password = await secretOf(config.passwordEntry);
59
+ if (password === undefined) {
60
+ return unavailable(`The entry ${config.passwordEntry}, which holds the Bitwarden master password, is not in this keyring.`);
61
+ }
62
+ for (const fresh of [false, true]) {
63
+ if (fresh || this.#bitwardenSession === undefined) {
64
+ const unlocked = await this.runner({
65
+ command: config.cli,
66
+ args: ["unlock", "--passwordenv", "INTENTIC_BW_PASSWORD", "--raw"],
67
+ env: { INTENTIC_BW_PASSWORD: password },
68
+ timeoutMs: TIMEOUT_MS,
69
+ });
70
+ const session = unlocked.stdout.trim();
71
+ if (!succeeded(unlocked) || session === "") {
72
+ return failure("Bitwarden", config.cli, unlocked, [password, session]);
73
+ }
74
+ this.#bitwardenSession = session;
75
+ }
76
+ const session = this.#bitwardenSession;
77
+ const answer = await this.runner({ command: config.cli, args: ["get", field, ref], env: { BW_SESSION: session }, timeoutMs: TIMEOUT_MS });
78
+ if (succeeded(answer)) {
79
+ return { ok: true, value: valueOf(answer) };
80
+ }
81
+ if (fresh || answer.missing || answer.timedOut || !/session|locked|unlock/iu.test(answer.stderr)) {
82
+ return failure("Bitwarden", config.cli, answer, [password, session]);
83
+ }
84
+ }
85
+ return unavailable("Bitwarden did not answer.");
86
+ }
87
+ async #keepass(ref, attribute, config, secretOf) {
88
+ const password = await secretOf(config.passwordEntry);
89
+ if (password === undefined) {
90
+ return unavailable(`The entry ${config.passwordEntry}, which holds the KeePassXC database password, is not in this keyring.`);
91
+ }
92
+ const args = ["show", "-q", "-s", "-a", attribute, ...(config.keyFile === undefined ? [] : ["-k", config.keyFile]), config.database, ref];
93
+ const answer = await this.runner({ command: config.cli, args, input: `${password}\n`, timeoutMs: TIMEOUT_MS });
94
+ return succeeded(answer) ? { ok: true, value: valueOf(answer) } : failure("KeePassXC", config.cli, answer, [password]);
95
+ }
96
+ }
97
+ //# sourceMappingURL=backends.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backends.js","sourceRoot":"","sources":["../src/backends.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "@stricli/core";
3
+ import { app } from "./app.js";
4
+ import { askpass, startedAsAskpass } from "./askpass/askpass-run.js";
5
+ if (startedAsAskpass()) {
6
+ process.exitCode = await askpass(process.argv.slice(2).join(" "), process.stdout, process.stderr);
7
+ }
8
+ else {
9
+ await run(app, process.argv.slice(2), { process: process });
10
+ }
11
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGrE,IAAI,gBAAgB,EAAE,EAAE,CAAC;IACrB,OAAO,CAAC,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;AACtG,CAAC;KAAM,CAAC;IAEJ,MAAM,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,OAAyB,EAAE,CAAC,CAAC;AAClF,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type KeyringRequest, type KeyringResponse } from "./protocol.js";
2
+ export declare class KeyringUnavailable extends Error {
3
+ constructor(message: string, options?: ErrorOptions);
4
+ }
5
+ export interface KeyringClientOptions {
6
+ readonly address: string;
7
+ readonly timeoutMs?: number;
8
+ }
9
+ export declare const askKeyring: <R extends KeyringRequest>(options: KeyringClientOptions, request: R) => Promise<KeyringResponse<R["op"]>>;
10
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAuC,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAM/G,qBAAa,kBAAmB,SAAQ,KAAK;IACzC,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACJ;AAED,MAAM,WAAW,oBAAoB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC/B;AAKD,eAAO,MAAM,UAAU,GAAU,CAAC,SAAS,cAAc,WAAW,oBAAoB,WAAW,CAAC,KAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CA6DjI,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,59 @@
1
+ import { connect } from "node:net";
2
+ import { KEYRING_LINE_MAX, KEYRING_RESPONSES } from "./protocol.js";
3
+ export class KeyringUnavailable extends Error {
4
+ constructor(message, options) {
5
+ super(message, options);
6
+ this.name = "KeyringUnavailable";
7
+ }
8
+ }
9
+ const DEFAULT_TIMEOUT_MS = 130_000;
10
+ export const askKeyring = async (options, request) => new Promise((resolve, reject) => {
11
+ const socket = connect(options.address);
12
+ let buffered = "";
13
+ let settled = false;
14
+ const finish = (outcome) => {
15
+ if (!settled) {
16
+ settled = true;
17
+ clearTimeout(timer);
18
+ socket.destroy();
19
+ outcome();
20
+ }
21
+ };
22
+ const timer = setTimeout(() => finish(() => reject(new KeyringUnavailable(`the keyring did not answer within ${String(Math.round((options.timeoutMs ?? DEFAULT_TIMEOUT_MS) / 1000))} s`))), options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
23
+ socket.setEncoding("utf8");
24
+ socket.on("connect", () => socket.write(`${JSON.stringify(request)}\n`));
25
+ socket.on("data", (chunk) => {
26
+ buffered += chunk;
27
+ if (buffered.length > KEYRING_LINE_MAX) {
28
+ finish(() => reject(new KeyringUnavailable("the keyring answered with more than any answer holds")));
29
+ return;
30
+ }
31
+ const end = buffered.indexOf("\n");
32
+ if (end === -1) {
33
+ return;
34
+ }
35
+ const line = buffered.slice(0, end);
36
+ finish(() => {
37
+ const schema = KEYRING_RESPONSES[request.op];
38
+ let parsed;
39
+ try {
40
+ parsed = JSON.parse(line);
41
+ }
42
+ catch (error) {
43
+ reject(new KeyringUnavailable("the keyring answered with something that is not JSON", { cause: error }));
44
+ return;
45
+ }
46
+ const answer = schema.safeParse(parsed);
47
+ if (!answer.success) {
48
+ reject(new KeyringUnavailable(`the keyring's answer to ${request.op} is not one this build reads: is it a different version?`));
49
+ return;
50
+ }
51
+ resolve(answer.data);
52
+ });
53
+ });
54
+ socket.on("error", (error) => finish(() => reject(new KeyringUnavailable(error.code === "ENOENT" || error.code === "ECONNREFUSED"
55
+ ? "no keyring is running on this computer: `intentic-machine keyring setup` installs one"
56
+ : `the keyring could not be reached: ${error.message}`, { cause: error }))));
57
+ socket.on("end", () => finish(() => reject(new KeyringUnavailable("the keyring closed the connection without an answer"))));
58
+ });
59
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { Notice, PassphrasePrompt } from "./consent.js";
2
+ import type { Runner } from "../run.js";
3
+ export declare const linuxPassphrasePrompt: (runner: Runner, env?: NodeJS.ProcessEnv) => PassphrasePrompt;
4
+ export declare const macDialogScript: (notice: Notice) => string;
5
+ export declare const macPassphrasePrompt: (runner: Runner) => PassphrasePrompt;
6
+ //# sourceMappingURL=consent-posix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent-posix.d.ts","sourceRoot":"","sources":["../../src/consent/consent-posix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAgB,MAAM,cAAc,CAAC;AAC3E,OAAO,KAAK,EAAa,MAAM,EAAE,MAAM,WAAW,CAAC;AAuCnD,eAAO,MAAM,qBAAqB,WACrB,MAAM,QAAO,MAAM,CAAC,UAAU,KAAiB,gBAwBvD,CAAC;AAKN,eAAO,MAAM,eAAe,WAAY,MAAM,KAAG,MAKjC,CAAC;AAEjB,eAAO,MAAM,mBAAmB,WACnB,MAAM,KAAG,gBAWjB,CAAC"}
@@ -0,0 +1,57 @@
1
+ const PROMPT_SECONDS = 120;
2
+ const PROMPT_TIMEOUT_MS = (PROMPT_SECONDS + 5) * 1000;
3
+ const typed = (answer) => answer.stdout.replace(/\r?\n$/u, "");
4
+ const markupText = (text) => text.replace(/&/gu, "&amp;").replace(/</gu, "&lt;").replace(/>/gu, "&gt;");
5
+ const DIALOGS = [
6
+ {
7
+ command: "zenity",
8
+ args: (notice) => ["--entry", "--hide-text", `--title=${notice.title}`, `--text=${markupText(notice.message)}`, `--timeout=${String(PROMPT_SECONDS)}`],
9
+ cancelled: [1, 5],
10
+ },
11
+ { command: "kdialog", args: (notice) => ["--title", notice.title, "--password", notice.message], cancelled: [1] },
12
+ ];
13
+ const ASK_PASSWORD = {
14
+ command: "systemd-ask-password",
15
+ args: (notice) => [`--timeout=${String(PROMPT_SECONDS)}`, `${notice.title} ${notice.message}`],
16
+ cancelled: [1],
17
+ };
18
+ export const linuxPassphrasePrompt = (runner, env = process.env) => async (notice) => {
19
+ const graphical = (env["DISPLAY"] ?? "") !== "" || (env["WAYLAND_DISPLAY"] ?? "") !== "";
20
+ const dialogs = graphical ? [...DIALOGS, ASK_PASSWORD] : [ASK_PASSWORD];
21
+ const tried = [];
22
+ for (const dialog of dialogs) {
23
+ const answer = await runner({ command: dialog.command, args: dialog.args(notice), timeoutMs: PROMPT_TIMEOUT_MS });
24
+ if (answer.missing) {
25
+ tried.push(`no ${dialog.command}`);
26
+ continue;
27
+ }
28
+ if (answer.exitCode === 0 && !answer.timedOut) {
29
+ return { kind: "answered", passphrase: typed(answer) };
30
+ }
31
+ if (answer.exitCode !== null && dialog.cancelled.includes(answer.exitCode)) {
32
+ return { kind: "cancelled" };
33
+ }
34
+ tried.push(`${dialog.command} could not ask (exit ${String(answer.exitCode ?? "none")})`);
35
+ }
36
+ return {
37
+ kind: "unavailable",
38
+ reason: `${tried.join(", ")}${graphical ? "" : ", and no display to show a dialog on"}: install zenity or kdialog, or unlock from a desktop session`,
39
+ };
40
+ };
41
+ const appleScriptText = (text) => `"${text.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"')}"`;
42
+ export const macDialogScript = (notice) => [
43
+ `set answer to display dialog ${appleScriptText(`${notice.message}\n\nThe keyring's passphrase:`)} with title ${appleScriptText(notice.title)} default answer "" with hidden answer buttons {"Cancel", "OK"} default button "OK" giving up after ${String(PROMPT_SECONDS)}`,
44
+ `if gave up of answer then error number -128`,
45
+ `return text returned of answer`,
46
+ ].join("\n");
47
+ export const macPassphrasePrompt = (runner) => async (notice) => {
48
+ const answer = await runner({ command: "osascript", args: ["-"], input: macDialogScript(notice), timeoutMs: PROMPT_TIMEOUT_MS });
49
+ if (answer.missing) {
50
+ return { kind: "unavailable", reason: "osascript was not found" };
51
+ }
52
+ if (answer.exitCode === 0 && !answer.timedOut) {
53
+ return { kind: "answered", passphrase: typed(answer) };
54
+ }
55
+ return /-128/u.test(answer.stderr) ? { kind: "cancelled" } : { kind: "unavailable", reason: "the dialog could not be shown (no desktop session?)" };
56
+ };
57
+ //# sourceMappingURL=consent-posix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent-posix.js","sourceRoot":"","sources":["../../src/consent/consent-posix.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { HelloDriver, PassphrasePrompt } from "./consent.js";
2
+ import type { Runner } from "../run.js";
3
+ export declare const windowsHello: (runner: Runner, now?: () => number) => HelloDriver;
4
+ export declare const windowsPassphrasePrompt: (runner: Runner) => PassphrasePrompt;
5
+ //# sourceMappingURL=consent-windows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent-windows.d.ts","sourceRoot":"","sources":["../../src/consent/consent-windows.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAuB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAqNxC,eAAO,MAAM,YAAY,WAAY,MAAM,QAAO,MAAM,MAAM,KAAc,WAyC3E,CAAC;AAEF,eAAO,MAAM,uBAAuB,WACvB,MAAM,KAAG,gBAejB,CAAC"}
@@ -0,0 +1,244 @@
1
+ import { z } from "zod";
2
+ import { runPowerShell, WINRT_AWAIT } from "../powershell.js";
3
+ const PROMPT_TIMEOUT_MS = 125_000;
4
+ const AVAILABLE_FOR_MS = 5 * 60_000;
5
+ const FORMS = String.raw `
6
+ using System;
7
+ using System.Drawing;
8
+ using System.Threading;
9
+ using System.Windows.Forms;
10
+
11
+ namespace IntenticKeyring {
12
+ public class Notice {
13
+ Form form;
14
+ readonly ManualResetEvent shown = new ManualResetEvent(false);
15
+
16
+ public static Notice Show(string title, string message) {
17
+ Notice notice = new Notice();
18
+ Thread thread = new Thread(delegate() { notice.Run(title, message); });
19
+ thread.SetApartmentState(ApartmentState.STA);
20
+ thread.IsBackground = true;
21
+ thread.Start();
22
+ notice.shown.WaitOne(5000);
23
+ return notice;
24
+ }
25
+
26
+ void Run(string title, string message) {
27
+ form = new Form();
28
+ form.Text = "intentic keyring";
29
+ form.FormBorderStyle = FormBorderStyle.FixedToolWindow;
30
+ form.TopMost = true;
31
+ form.ShowInTaskbar = false;
32
+ form.StartPosition = FormStartPosition.Manual;
33
+ form.AutoSize = true;
34
+ form.AutoSizeMode = AutoSizeMode.GrowAndShrink;
35
+ form.Padding = new Padding(16);
36
+ FlowLayoutPanel panel = new FlowLayoutPanel();
37
+ panel.FlowDirection = FlowDirection.TopDown;
38
+ panel.AutoSize = true;
39
+ Label heading = new Label();
40
+ heading.Text = title;
41
+ heading.AutoSize = true;
42
+ heading.MaximumSize = new Size(480, 0);
43
+ heading.Font = new Font("Segoe UI Semibold", 11f);
44
+ Label body = new Label();
45
+ body.Text = message + "\r\n\r\nWindows Hello asks for your gesture to answer it.";
46
+ body.AutoSize = true;
47
+ body.MaximumSize = new Size(480, 0);
48
+ body.Font = new Font("Segoe UI", 9.5f);
49
+ panel.Controls.Add(heading);
50
+ panel.Controls.Add(body);
51
+ form.Controls.Add(panel);
52
+ form.Shown += delegate(object sender, EventArgs e) {
53
+ Rectangle area = Screen.PrimaryScreen.WorkingArea;
54
+ form.Location = new Point(area.X + (area.Width - form.Width) / 2, area.Y + 24);
55
+ shown.Set();
56
+ };
57
+ Application.Run(form);
58
+ }
59
+
60
+ public void Close() {
61
+ try { if (form != null && form.IsHandleCreated) form.BeginInvoke(new MethodInvoker(form.Close)); } catch (Exception) { } // allow(silent-catch): a notice already gone has nothing left to close
62
+ }
63
+ }
64
+
65
+ public static class Passphrase {
66
+ public static string Ask(string title, string message, int seconds) {
67
+ Application.EnableVisualStyles();
68
+ Form form = new Form();
69
+ form.Text = title;
70
+ form.FormBorderStyle = FormBorderStyle.FixedDialog;
71
+ form.MinimizeBox = false;
72
+ form.MaximizeBox = false;
73
+ form.TopMost = true;
74
+ form.StartPosition = FormStartPosition.CenterScreen;
75
+ form.AutoSize = true;
76
+ form.AutoSizeMode = AutoSizeMode.GrowAndShrink;
77
+ form.Padding = new Padding(16);
78
+ FlowLayoutPanel panel = new FlowLayoutPanel();
79
+ panel.FlowDirection = FlowDirection.TopDown;
80
+ panel.AutoSize = true;
81
+ Label body = new Label();
82
+ body.Text = message + "\r\n\r\nThe keyring's passphrase:";
83
+ body.AutoSize = true;
84
+ body.MaximumSize = new Size(480, 0);
85
+ TextBox box = new TextBox();
86
+ box.UseSystemPasswordChar = true;
87
+ box.Width = 320;
88
+ FlowLayoutPanel buttons = new FlowLayoutPanel();
89
+ buttons.AutoSize = true;
90
+ Button ok = new Button();
91
+ ok.Text = "OK";
92
+ ok.DialogResult = DialogResult.OK;
93
+ Button cancel = new Button();
94
+ cancel.Text = "Cancel";
95
+ cancel.DialogResult = DialogResult.Cancel;
96
+ buttons.Controls.Add(ok);
97
+ buttons.Controls.Add(cancel);
98
+ panel.Controls.Add(body);
99
+ panel.Controls.Add(box);
100
+ panel.Controls.Add(buttons);
101
+ form.Controls.Add(panel);
102
+ form.AcceptButton = ok;
103
+ form.CancelButton = cancel;
104
+ System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
105
+ timer.Interval = seconds * 1000;
106
+ timer.Tick += delegate(object sender, EventArgs e) { form.DialogResult = DialogResult.Cancel; form.Close(); };
107
+ form.Shown += delegate(object sender, EventArgs e) { form.Activate(); box.Focus(); timer.Start(); };
108
+ DialogResult result = form.ShowDialog();
109
+ timer.Stop();
110
+ return result == DialogResult.OK ? box.Text : null;
111
+ }
112
+ }
113
+ }
114
+ `;
115
+ const PREAMBLE = `
116
+ $ErrorActionPreference = 'Stop'
117
+ function Answer($o) { [Console]::Out.WriteLine('intentic-keyring>' + ($o | ConvertTo-Json -Compress)) }
118
+ Add-Type -AssemblyName System.Windows.Forms, System.Drawing
119
+ Add-Type -ReferencedAssemblies System.Windows.Forms, System.Drawing -TypeDefinition @'
120
+ ${FORMS}
121
+ '@
122
+ `;
123
+ const HELLO_SCRIPT = `${PREAMBLE}
124
+ ${WINRT_AWAIT}
125
+ [Windows.Security.Credentials.KeyCredentialManager,Windows.Security.Credentials,ContentType=WindowsRuntime] | Out-Null
126
+ [Windows.Security.Credentials.UI.UserConsentVerifier,Windows.Security.Credentials.UI,ContentType=WindowsRuntime] | Out-Null
127
+ [Windows.Security.Cryptography.Core.CryptographicPublicKeyBlobType,Windows.Security.Cryptography.Core,ContentType=WindowsRuntime] | Out-Null
128
+ $buffers = [System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions]
129
+ function SignWith($credential) {
130
+ $challenge = $buffers::AsBuffer([Convert]::FromBase64String($KeyringInput.challenge))
131
+ $signed = Await ($credential.RequestSignAsync($challenge)) ([Windows.Security.Credentials.KeyCredentialOperationResult])
132
+ if ([string]$signed.Status -ne 'Success') { return @{ ok = $false; status = [string]$signed.Status } }
133
+ return @{ ok = $true; signature = [Convert]::ToBase64String($buffers::ToArray($signed.Result)) }
134
+ }
135
+ try {
136
+ $op = $KeyringInput.op
137
+ if ($op -eq 'available') {
138
+ $supported = Await ([Windows.Security.Credentials.KeyCredentialManager]::IsSupportedAsync()) ([bool])
139
+ $verifier = Await ([Windows.Security.Credentials.UI.UserConsentVerifier]::CheckAvailabilityAsync()) ([Windows.Security.Credentials.UI.UserConsentVerifierAvailability])
140
+ Answer @{ ok = $true; supported = [bool]$supported; status = [string]$verifier }
141
+ } elseif ($op -eq 'verify') {
142
+ $result = Await ([Windows.Security.Credentials.UI.UserConsentVerifier]::RequestVerificationAsync($KeyringInput.message)) ([Windows.Security.Credentials.UI.UserConsentVerificationResult])
143
+ Answer @{ ok = ([string]$result -eq 'Verified'); status = [string]$result }
144
+ } else {
145
+ $notice = [IntenticKeyring.Notice]::Show($KeyringInput.title, $KeyringInput.message)
146
+ try {
147
+ if ($op -eq 'enrol') {
148
+ $made = Await ([Windows.Security.Credentials.KeyCredentialManager]::RequestCreateAsync($KeyringInput.credential, [Windows.Security.Credentials.KeyCredentialCreationOption]::ReplaceExisting)) ([Windows.Security.Credentials.KeyCredentialRetrievalResult])
149
+ if ([string]$made.Status -ne 'Success') { Answer @{ ok = $false; status = [string]$made.Status } } else {
150
+ $answer = SignWith $made.Credential
151
+ # X.509 SubjectPublicKeyInfo, which hardened mode's service reads with node:crypto to check later signatures.
152
+ $answer.publicKey = [Convert]::ToBase64String($buffers::ToArray($made.Credential.RetrievePublicKey([Windows.Security.Cryptography.Core.CryptographicPublicKeyBlobType]::X509SubjectPublicKeyInfo)))
153
+ Answer $answer
154
+ }
155
+ } else {
156
+ $opened = Await ([Windows.Security.Credentials.KeyCredentialManager]::OpenAsync($KeyringInput.credential)) ([Windows.Security.Credentials.KeyCredentialRetrievalResult])
157
+ if ([string]$opened.Status -ne 'Success') { Answer @{ ok = $false; status = [string]$opened.Status } } else { Answer (SignWith $opened.Credential) }
158
+ }
159
+ } finally { $notice.Close() }
160
+ }
161
+ } catch {
162
+ Answer @{ ok = $false; error = $_.Exception.Message }
163
+ }
164
+ `;
165
+ const PASSPHRASE_SCRIPT = `${PREAMBLE}
166
+ try {
167
+ $typed = [IntenticKeyring.Passphrase]::Ask($KeyringInput.title, $KeyringInput.message, [int]$KeyringInput.seconds)
168
+ if ($typed -eq $null) { Answer @{ ok = $false; cancelled = $true } } else { Answer @{ ok = $true; passphrase = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($typed)) } }
169
+ } catch {
170
+ Answer @{ ok = $false; error = $_.Exception.Message }
171
+ }
172
+ `;
173
+ const AnswerSchema = z.object({
174
+ ok: z.boolean(),
175
+ supported: z.boolean().optional(),
176
+ status: z.string().optional(),
177
+ error: z.string().optional(),
178
+ signature: z.string().optional(),
179
+ publicKey: z.string().optional(),
180
+ passphrase: z.string().optional(),
181
+ cancelled: z.boolean().optional(),
182
+ });
183
+ const CANCELLED = new Set(["UserCanceled", "Canceled"]);
184
+ const failed = (answer) => ({
185
+ ok: false,
186
+ cancelled: answer.status !== undefined && CANCELLED.has(answer.status),
187
+ reason: answer.error ?? `Windows Hello answered ${answer.status ?? "without a status"}`,
188
+ });
189
+ const base64 = (text) => (text === undefined || !/^[A-Za-z0-9+/=]+$/u.test(text) ? undefined : Buffer.from(text, "base64"));
190
+ const standardBase64 = (challenge) => Buffer.from(challenge, "base64url").toString("base64");
191
+ export const windowsHello = (runner, now = Date.now) => {
192
+ let known;
193
+ const hello = async (input) => {
194
+ const ran = await runPowerShell(runner, { script: HELLO_SCRIPT, input, timeoutMs: PROMPT_TIMEOUT_MS }, AnswerSchema);
195
+ return ran.ok ? { ok: true, value: ran.answer } : { ok: false, cancelled: false, reason: ran.reason };
196
+ };
197
+ return {
198
+ available: async () => {
199
+ if (known !== undefined && now() - known.at < AVAILABLE_FOR_MS) {
200
+ return known.available;
201
+ }
202
+ const asked = await hello({ op: "available" });
203
+ const available = asked.ok && asked.value.ok && asked.value.supported === true;
204
+ known = { at: now(), available };
205
+ return available;
206
+ },
207
+ enrol: async (credential, challenge, notice) => {
208
+ const asked = await hello({ op: "enrol", credential, challenge: standardBase64(challenge), title: notice.title, message: notice.message });
209
+ if (!asked.ok) {
210
+ return asked;
211
+ }
212
+ const signature = base64(asked.value.signature);
213
+ const publicKey = asked.value.publicKey;
214
+ return asked.value.ok && signature !== undefined && publicKey !== undefined ? { ok: true, value: { signature, publicKey } } : failed(asked.value);
215
+ },
216
+ sign: async (credential, challenge, notice) => {
217
+ const asked = await hello({ op: "sign", credential, challenge: standardBase64(challenge), title: notice.title, message: notice.message });
218
+ if (!asked.ok) {
219
+ return asked;
220
+ }
221
+ const signature = base64(asked.value.signature);
222
+ return asked.value.ok && signature !== undefined ? { ok: true, value: signature } : failed(asked.value);
223
+ },
224
+ verify: async (notice) => {
225
+ const asked = await hello({ op: "verify", message: `${notice.title}\n\n${notice.message}` });
226
+ if (!asked.ok) {
227
+ return asked;
228
+ }
229
+ return asked.value.ok ? { ok: true, value: true } : failed(asked.value);
230
+ },
231
+ };
232
+ };
233
+ export const windowsPassphrasePrompt = (runner) => async (notice) => {
234
+ const ran = await runPowerShell(runner, { script: PASSPHRASE_SCRIPT, input: { title: notice.title, message: notice.message, seconds: String(Math.floor(PROMPT_TIMEOUT_MS / 1000) - 5) }, timeoutMs: PROMPT_TIMEOUT_MS }, AnswerSchema);
235
+ if (!ran.ok) {
236
+ return { kind: "unavailable", reason: ran.reason };
237
+ }
238
+ if (ran.answer.ok) {
239
+ const typed = base64(ran.answer.passphrase);
240
+ return typed === undefined ? { kind: "unavailable", reason: "the passphrase dialog answered with nothing" } : { kind: "answered", passphrase: typed.toString("utf8") };
241
+ }
242
+ return ran.answer.cancelled === true ? { kind: "cancelled" } : { kind: "unavailable", reason: ran.answer.error ?? "the passphrase dialog failed" };
243
+ };
244
+ //# sourceMappingURL=consent-windows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent-windows.js","sourceRoot":"","sources":["../../src/consent/consent-windows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ export interface VaultOpener {
2
+ readonly withPassphrase: (passphrase: string) => Promise<Buffer | undefined>;
3
+ readonly hello?: HelloOpener;
4
+ }
5
+ export interface HelloOpener {
6
+ readonly credential: string;
7
+ readonly challenge: string;
8
+ readonly withSignature: (signature: Buffer) => Buffer | undefined;
9
+ }
10
+ export interface ConsentRequest {
11
+ readonly title: string;
12
+ readonly message: string;
13
+ readonly unlock: boolean;
14
+ readonly opener: VaultOpener | undefined;
15
+ readonly waitMs?: number;
16
+ }
17
+ export type ConsentRefusal = {
18
+ readonly ok: false;
19
+ readonly code: "declined" | "busy" | "locked";
20
+ readonly reason: string;
21
+ };
22
+ export type ConsentAnswer = {
23
+ readonly ok: true;
24
+ readonly vaultKey: Buffer | undefined;
25
+ readonly how: "hello" | "passphrase" | "verified";
26
+ } | ConsentRefusal;
27
+ export type HelloResult<T> = {
28
+ readonly ok: true;
29
+ readonly value: T;
30
+ } | {
31
+ readonly ok: false;
32
+ readonly cancelled: boolean;
33
+ readonly reason: string;
34
+ };
35
+ export interface HelloEnrolment {
36
+ readonly signature: Buffer;
37
+ readonly publicKey: string;
38
+ }
39
+ export interface HelloDriver {
40
+ readonly available: () => Promise<boolean>;
41
+ readonly enrol: (credential: string, challenge: string, notice: Notice) => Promise<HelloResult<HelloEnrolment>>;
42
+ readonly sign: (credential: string, challenge: string, notice: Notice) => Promise<HelloResult<Buffer>>;
43
+ readonly verify: (notice: Notice) => Promise<HelloResult<true>>;
44
+ }
45
+ export interface Notice {
46
+ readonly title: string;
47
+ readonly message: string;
48
+ }
49
+ export type PromptAnswer = {
50
+ readonly kind: "answered";
51
+ readonly passphrase: string;
52
+ } | {
53
+ readonly kind: "cancelled";
54
+ } | {
55
+ readonly kind: "unavailable";
56
+ readonly reason: string;
57
+ };
58
+ export type PassphrasePrompt = (notice: Notice) => Promise<PromptAnswer>;
59
+ export interface Consent {
60
+ readonly ask: (request: ConsentRequest) => Promise<ConsentAnswer>;
61
+ readonly hello: HelloDriver | undefined;
62
+ }
63
+ export declare const refusingConsent: (why: string) => Consent;
64
+ export declare const passphraseConsent: (prompt: PassphrasePrompt) => Consent;
65
+ export declare const helloConsent: (hello: HelloDriver, fallback: Consent) => Consent;
66
+ export declare const serialConsent: (inner: Consent, defaultWaitMs?: number) => Consent;
67
+ //# sourceMappingURL=consent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/consent/consent.ts"],"names":[],"mappings":"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"}