node-opcua-pki 6.22.0 → 7.0.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.
- package/bin/install_prerequisite.ts +1 -1
- package/bin/pki.ts +1 -1
- package/dist/bin/install_prerequisite.d.ts +2 -0
- package/dist/bin/install_prerequisite.js +6 -0
- package/dist/bin/install_prerequisite.js.map +1 -0
- package/dist/bin/pki.d.ts +2 -0
- package/dist/bin/pki.js +4 -0
- package/dist/bin/pki.js.map +1 -0
- package/dist/lib/ca/backends/native_ca_backend.d.ts +49 -0
- package/dist/lib/ca/backends/native_ca_backend.js +365 -0
- package/dist/lib/ca/backends/native_ca_backend.js.map +1 -0
- package/dist/lib/ca/backends/openssl_ca_backend.d.ts +47 -0
- package/dist/lib/ca/backends/openssl_ca_backend.js +398 -0
- package/dist/lib/ca/backends/openssl_ca_backend.js.map +1 -0
- package/dist/lib/ca/certificate_authority.d.ts +62 -0
- package/dist/lib/ca/certificate_authority.js +91 -0
- package/dist/lib/ca/certificate_authority.js.map +1 -0
- package/dist/lib/ca/core/ca_backend.d.ts +89 -0
- package/dist/lib/ca/core/ca_backend.js +24 -0
- package/dist/lib/ca/core/ca_backend.js.map +1 -0
- package/dist/lib/ca/core/ca_database.d.ts +91 -0
- package/dist/lib/ca/core/ca_database.js +267 -0
- package/dist/lib/ca/core/ca_database.js.map +1 -0
- package/dist/{core-BwqSJPHc.d.mts → lib/ca/core/certificate_authority_core.d.ts} +45 -394
- package/dist/lib/ca/core/certificate_authority_core.js +1300 -0
- package/dist/lib/ca/core/certificate_authority_core.js.map +1 -0
- package/dist/lib/ca/core/index.d.ts +17 -0
- package/dist/lib/ca/core/index.js +25 -0
- package/dist/lib/ca/core/index.js.map +1 -0
- package/dist/lib/ca/crypto_create_CA.d.ts +1 -0
- package/dist/lib/ca/crypto_create_CA.js +821 -0
- package/dist/lib/ca/crypto_create_CA.js.map +1 -0
- package/dist/lib/ca/index.d.ts +1 -0
- package/dist/lib/ca/index.js +2 -0
- package/dist/lib/ca/index.js.map +1 -0
- package/dist/lib/ca/templates/ca_config_template.cnf.d.ts +2 -0
- package/dist/lib/ca/templates/ca_config_template.cnf.js +170 -0
- package/dist/lib/ca/templates/ca_config_template.cnf.js.map +1 -0
- package/dist/lib/core.d.ts +33 -0
- package/dist/lib/core.js +56 -0
- package/dist/lib/core.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.js +37 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/misc/applicationurn.d.ts +1 -0
- package/dist/lib/misc/applicationurn.js +40 -0
- package/dist/lib/misc/applicationurn.js.map +1 -0
- package/dist/lib/misc/hostname.d.ts +8 -0
- package/dist/lib/misc/hostname.js +82 -0
- package/dist/lib/misc/hostname.js.map +1 -0
- package/dist/lib/misc/subject.d.ts +2 -0
- package/dist/lib/misc/subject.js +2 -0
- package/dist/lib/misc/subject.js.map +1 -0
- package/dist/{index.d.ts → lib/pki/certificate_manager.d.ts} +24 -246
- package/dist/lib/pki/certificate_manager.js +2302 -0
- package/dist/lib/pki/certificate_manager.js.map +1 -0
- package/dist/lib/pki/templates/simple_config_template.cnf.d.ts +2 -0
- package/dist/lib/pki/templates/simple_config_template.cnf.js +74 -0
- package/dist/lib/pki/templates/simple_config_template.cnf.js.map +1 -0
- package/dist/lib/pki/toolbox_pfx.d.ts +127 -0
- package/dist/lib/pki/toolbox_pfx.js +248 -0
- package/dist/lib/pki/toolbox_pfx.js.map +1 -0
- package/dist/lib/toolbox/common.d.ts +150 -0
- package/dist/lib/toolbox/common.js +82 -0
- package/dist/lib/toolbox/common.js.map +1 -0
- package/dist/lib/toolbox/common2.d.ts +25 -0
- package/dist/lib/toolbox/common2.js +97 -0
- package/dist/lib/toolbox/common2.js.map +1 -0
- package/dist/lib/toolbox/config.d.ts +5 -0
- package/dist/lib/toolbox/config.js +28 -0
- package/dist/lib/toolbox/config.js.map +1 -0
- package/dist/lib/toolbox/debug.d.ts +5 -0
- package/dist/lib/toolbox/debug.js +35 -0
- package/dist/lib/toolbox/debug.js.map +1 -0
- package/dist/lib/toolbox/display.d.ts +4 -0
- package/dist/lib/toolbox/display.js +56 -0
- package/dist/lib/toolbox/display.js.map +1 -0
- package/dist/lib/toolbox/index.d.ts +5 -0
- package/dist/lib/toolbox/index.js +28 -0
- package/dist/lib/toolbox/index.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/_create_random_file.d.ts +4 -0
- package/dist/lib/toolbox/with_openssl/_create_random_file.js +50 -0
- package/dist/lib/toolbox/with_openssl/_create_random_file.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/_env.d.ts +58 -0
- package/dist/lib/toolbox/with_openssl/_env.js +126 -0
- package/dist/lib/toolbox/with_openssl/_env.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/create_certificate_signing_request.d.ts +5 -0
- package/dist/lib/toolbox/with_openssl/create_certificate_signing_request.js +72 -0
- package/dist/lib/toolbox/with_openssl/create_certificate_signing_request.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/create_private_key.d.ts +5 -0
- package/dist/lib/toolbox/with_openssl/create_private_key.js +92 -0
- package/dist/lib/toolbox/with_openssl/create_private_key.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/create_self_signed_certificate.d.ts +5 -0
- package/dist/lib/toolbox/with_openssl/create_self_signed_certificate.js +135 -0
- package/dist/lib/toolbox/with_openssl/create_self_signed_certificate.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/execute_openssl.d.ts +67 -0
- package/dist/lib/toolbox/with_openssl/execute_openssl.js +246 -0
- package/dist/lib/toolbox/with_openssl/execute_openssl.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/index.d.ts +5 -0
- package/dist/lib/toolbox/with_openssl/index.js +30 -0
- package/dist/lib/toolbox/with_openssl/index.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/install_prerequisite.d.ts +7 -0
- package/dist/lib/toolbox/with_openssl/install_prerequisite.js +358 -0
- package/dist/lib/toolbox/with_openssl/install_prerequisite.js.map +1 -0
- package/dist/lib/toolbox/with_openssl/toolbox.d.ts +53 -0
- package/dist/lib/toolbox/with_openssl/toolbox.js +190 -0
- package/dist/lib/toolbox/with_openssl/toolbox.js.map +1 -0
- package/dist/lib/toolbox/without_openssl/create_certificate_signing_request.d.ts +5 -0
- package/dist/lib/toolbox/without_openssl/create_certificate_signing_request.js +69 -0
- package/dist/lib/toolbox/without_openssl/create_certificate_signing_request.js.map +1 -0
- package/dist/lib/toolbox/without_openssl/create_self_signed_certificate.d.ts +3 -0
- package/dist/lib/toolbox/without_openssl/create_self_signed_certificate.js +78 -0
- package/dist/lib/toolbox/without_openssl/create_self_signed_certificate.js.map +1 -0
- package/dist/lib/toolbox/without_openssl/index.d.ts +2 -0
- package/dist/lib/toolbox/without_openssl/index.js +25 -0
- package/dist/lib/toolbox/without_openssl/index.js.map +1 -0
- package/package.json +11 -30
- package/dist/bin/install_prerequisite.mjs +0 -18
- package/dist/bin/install_prerequisite.mjs.map +0 -1
- package/dist/bin/pki.mjs +0 -5895
- package/dist/bin/pki.mjs.map +0 -1
- package/dist/chunk-EQ4DGI4M.mjs +0 -1917
- package/dist/chunk-EQ4DGI4M.mjs.map +0 -1
- package/dist/chunk-GCHH54PS.mjs +0 -30
- package/dist/chunk-GCHH54PS.mjs.map +0 -1
- package/dist/core-BwqSJPHc.d.ts +0 -1041
- package/dist/core.d.mts +0 -2
- package/dist/core.d.ts +0 -2
- package/dist/core.js +0 -1902
- package/dist/core.js.map +0 -1
- package/dist/core.mjs +0 -21
- package/dist/core.mjs.map +0 -1
- package/dist/index.d.mts +0 -1001
- package/dist/index.js +0 -4968
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -3106
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// node-opcua-pki
|
|
3
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org
|
|
5
|
+
// Copyright (c) 2022-2026 - Sterfive.com
|
|
6
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
//
|
|
8
|
+
// This project is licensed under the terms of the MIT license.
|
|
9
|
+
//
|
|
10
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
11
|
+
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
12
|
+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
13
|
+
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
14
|
+
//
|
|
15
|
+
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
16
|
+
// Software.
|
|
17
|
+
//
|
|
18
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
19
|
+
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
20
|
+
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
21
|
+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
23
|
+
import fs from "node:fs";
|
|
24
|
+
import path from "node:path";
|
|
25
|
+
import { Subject } from "node-opcua-crypto";
|
|
26
|
+
import { displaySubtitle, displayTitle, makePath } from "../../toolbox/index.js";
|
|
27
|
+
import { buildSubjectAltNameString, cleanupStaticConfig, ensure_openssl_installed, execute_openssl, execute_openssl_no_failure, generateStaticConfig, passinArg, setEnv, x509Date } from "../../toolbox/with_openssl/index.js";
|
|
28
|
+
const n = makePath;
|
|
29
|
+
/** The ALTNAME openssl embeds as `subjectAltName` on the CA's own certificate/CSR — see `[v3_ca]` / `[v3_ca_req]`. */
|
|
30
|
+
function caAltName(ca) {
|
|
31
|
+
// OPC UA validators (UaExpert, compliance tools) require every
|
|
32
|
+
// certificate — including the root/intermediate CA — to carry a
|
|
33
|
+
// SubjectAltName extension. RFC 5280 does not strictly mandate it
|
|
34
|
+
// on CA certificates but the OPC UA Profile does. Build a stable
|
|
35
|
+
// URI SAN derived from the CA CommonName so the resulting CA cert
|
|
36
|
+
// passes the spec check.
|
|
37
|
+
return `URI:urn:${ca.subject.commonName || "NodeOPCUA-CA"}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Every render of `conf/caconfig.cnf` needs `ALTNAME` / `CDP_URL` /
|
|
41
|
+
* `AIA_VALUE` resolved, **even for an `openssl` subcommand that only reads
|
|
42
|
+
* a different section** (`ca -gencrl` only needs `[crl_ext]`, `ca -revoke`
|
|
43
|
+
* only needs `[ca]`): openssl's config loader (`NCONF_load`) expands every
|
|
44
|
+
* `$ENV::NAME` reference in the file line by line as it parses it, not
|
|
45
|
+
* lazily per queried section, and every section in this template — not
|
|
46
|
+
* just the two gated behind `{{#CDP_URL}}` / `{{#AIA_VALUE}}` — references
|
|
47
|
+
* `$ENV::ALTNAME` unconditionally. Leaving any of the three unresolved
|
|
48
|
+
* makes openssl fall through to its own native `$ENV::` resolution (a real
|
|
49
|
+
* OS environment variable, which is never set) and fail with "variable has
|
|
50
|
+
* no value".
|
|
51
|
+
*
|
|
52
|
+
* Passed explicitly rather than relying on whatever `setEnv()` last wrote
|
|
53
|
+
* to the shared registry (see {@link generateStaticConfig}'s
|
|
54
|
+
* `envOverrides`) — empty string means "omit the extension" for the two
|
|
55
|
+
* gated keys (the template's `{{#KEY}}` block strips itself on an empty
|
|
56
|
+
* value), never "fall back to the registry".
|
|
57
|
+
*
|
|
58
|
+
* Exported as the single implementation of the CDP/AIA value format:
|
|
59
|
+
* `CertificateAuthority._wireRevocationEnvVars` (the legacy registry shim)
|
|
60
|
+
* delegates here so the format cannot drift between the two mechanisms.
|
|
61
|
+
*/
|
|
62
|
+
export function caConfigEnvOverrides(ca, altName = caAltName(ca)) {
|
|
63
|
+
const aiaLegs = [];
|
|
64
|
+
if (ca.ocspResponderUrl) {
|
|
65
|
+
aiaLegs.push(`OCSP;URI:${ca.ocspResponderUrl}`);
|
|
66
|
+
}
|
|
67
|
+
if (ca.caIssuersUrl) {
|
|
68
|
+
aiaLegs.push(`caIssuers;URI:${ca.caIssuersUrl}`);
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
ALTNAME: altName,
|
|
72
|
+
CDP_URL: ca.crlDistributionUrl ?? "",
|
|
73
|
+
AIA_VALUE: aiaLegs.join(",")
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The default {@link CaBackend}: shells out to the `openssl` CLI, exactly as
|
|
78
|
+
* `CertificateAuthority` always has — this is a pure code move (plus a lock
|
|
79
|
+
* around every database-mutating operation, temp-config cleanup, and
|
|
80
|
+
* explicit `envOverrides` on every config render) with no change in the
|
|
81
|
+
* openssl commands issued or the files produced.
|
|
82
|
+
*/
|
|
83
|
+
export class OpenSslCaBackend {
|
|
84
|
+
/** This backend is the `openssl` executable, so it has to be there. */
|
|
85
|
+
/**
|
|
86
|
+
* `-passin env:` argv and env for an openssl call that has to load this
|
|
87
|
+
* CA's key. Built here rather than on the CA: the passphrase is the
|
|
88
|
+
* CA's business, but expressing it as an openssl argument is this
|
|
89
|
+
* backend's, and the core has no reason to know the flag exists.
|
|
90
|
+
*/
|
|
91
|
+
async #passin(ca) {
|
|
92
|
+
return passinArg(await ca._privateKeyPassphrase());
|
|
93
|
+
}
|
|
94
|
+
/** The openssl CLI loads its key from a file, so it cannot call out to an HSM. */
|
|
95
|
+
supportsExternalSigner = false;
|
|
96
|
+
async preflight() {
|
|
97
|
+
await ensure_openssl_installed();
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Render `conf/caconfig.cnf` once with explicit overrides, run `fn`
|
|
101
|
+
* with the rendered path, and always remove the temp file. Structural
|
|
102
|
+
* guarantee that (a) every render carries the three required env
|
|
103
|
+
* values and (b) no rendered `<name>.<pid>-<n>.tmp` file is ever left
|
|
104
|
+
* behind — each was previously a per-method discipline.
|
|
105
|
+
*/
|
|
106
|
+
async #withConfig(ca, altName, fn) {
|
|
107
|
+
const caRootDir = path.resolve(ca.rootDir);
|
|
108
|
+
const options = { cwd: caRootDir };
|
|
109
|
+
const configFile = generateStaticConfig("conf/caconfig.cnf", options, caConfigEnvOverrides(ca, altName));
|
|
110
|
+
try {
|
|
111
|
+
return await fn(configFile, options);
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
await cleanupStaticConfig(configFile, options);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async #generateCaCsrWith(ca, configFile, options, privateKeyFile, csrFile) {
|
|
118
|
+
const passin = await this.#passin(ca);
|
|
119
|
+
displayTitle("Generate a certificate request for the CA key");
|
|
120
|
+
await execute_openssl([
|
|
121
|
+
"req",
|
|
122
|
+
"-new",
|
|
123
|
+
"-sha256",
|
|
124
|
+
"-extensions",
|
|
125
|
+
"v3_ca_req",
|
|
126
|
+
"-config",
|
|
127
|
+
n(configFile),
|
|
128
|
+
"-key",
|
|
129
|
+
n(privateKeyFile),
|
|
130
|
+
"-out",
|
|
131
|
+
n(csrFile),
|
|
132
|
+
"-subj",
|
|
133
|
+
ca.subject.toString(),
|
|
134
|
+
...passin.args
|
|
135
|
+
], { ...options, env: passin.env });
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* `openssl ca -gencrl` signs the CRL with the CA key it finds through the
|
|
139
|
+
* config file (`private_key = $dir/private/cakey.pem`), so it needs the
|
|
140
|
+
* CA passphrase like every other `openssl ca` invocation.
|
|
141
|
+
*/
|
|
142
|
+
async #regenerateCrlWith(ca, configFile, options) {
|
|
143
|
+
const passin = await this.#passin(ca);
|
|
144
|
+
// produce a CRL in PEM format
|
|
145
|
+
displaySubtitle("regenerate CRL (Certificate Revocation List)");
|
|
146
|
+
await execute_openssl(["ca", "-gencrl", "-config", n(configFile), "-out", "crl/revocation_list.crl", ...passin.args], {
|
|
147
|
+
...options,
|
|
148
|
+
env: passin.env
|
|
149
|
+
});
|
|
150
|
+
await execute_openssl(["crl", "-in", "crl/revocation_list.crl", "-out", "crl/revocation_list.der", "-outform", "der"], options);
|
|
151
|
+
displaySubtitle("Display (Certificate Revocation List)");
|
|
152
|
+
await execute_openssl(["crl", "-in", n(ca.revocationList), "-text", "-noout"], options);
|
|
153
|
+
}
|
|
154
|
+
async generateCaCsr(ca, _caRootDir, privateKeyFile, csrFile) {
|
|
155
|
+
await this.#withConfig(ca, caAltName(ca), (configFile, options) => this.#generateCaCsrWith(ca, configFile, options, privateKeyFile, csrFile));
|
|
156
|
+
}
|
|
157
|
+
async bootstrap(ca) {
|
|
158
|
+
const caRootDir = path.resolve(ca.rootDir);
|
|
159
|
+
const privateKeyFilename = path.join(caRootDir, "private/cakey.pem");
|
|
160
|
+
const csrFilename = path.join(caRootDir, "private/cakey.csr");
|
|
161
|
+
// one render serves the CSR, the CA-certificate signature, and the
|
|
162
|
+
// initial CRL (the overrides are identical for all three)
|
|
163
|
+
await this.#withConfig(ca, caAltName(ca), async (configFile, options) => {
|
|
164
|
+
await this.#generateCaCsrWith(ca, configFile, options, privateKeyFilename, csrFilename);
|
|
165
|
+
const issuerCA = ca._issuerCA;
|
|
166
|
+
if (issuerCA) {
|
|
167
|
+
// Subordinate (intermediate) CA — signed by the parent CA
|
|
168
|
+
displayTitle("Generate CA Certificate (signed by issuer CA)");
|
|
169
|
+
const issuerCert = path.resolve(issuerCA.caCertificate);
|
|
170
|
+
const issuerKey = path.resolve(issuerCA.rootDir, "private/cakey.pem");
|
|
171
|
+
const issuerSerial = path.resolve(issuerCA.rootDir, "serial");
|
|
172
|
+
// the -CAkey is the *issuer's* key: its passphrase, not this CA's
|
|
173
|
+
const issuerPassin = await this.#passin(issuerCA);
|
|
174
|
+
const signWithIssuer = async () => {
|
|
175
|
+
await execute_openssl([
|
|
176
|
+
"x509",
|
|
177
|
+
"-sha256",
|
|
178
|
+
"-req",
|
|
179
|
+
"-days",
|
|
180
|
+
"3650",
|
|
181
|
+
"-extensions",
|
|
182
|
+
"v3_ca",
|
|
183
|
+
"-extfile",
|
|
184
|
+
n(configFile),
|
|
185
|
+
"-in",
|
|
186
|
+
"private/cakey.csr",
|
|
187
|
+
"-CA",
|
|
188
|
+
n(issuerCert),
|
|
189
|
+
"-CAkey",
|
|
190
|
+
n(issuerKey),
|
|
191
|
+
"-CAserial",
|
|
192
|
+
n(issuerSerial),
|
|
193
|
+
"-out",
|
|
194
|
+
"public/cacert.pem",
|
|
195
|
+
...issuerPassin.args
|
|
196
|
+
], { ...options, env: issuerPassin.env });
|
|
197
|
+
};
|
|
198
|
+
// `-CAserial` read-increment-writes the ISSUER's serial file,
|
|
199
|
+
// so this must hold the issuer's directory lock, not just the
|
|
200
|
+
// subordinate's (which the caller already holds). The only
|
|
201
|
+
// cross-CA lock ordering in the codebase is subordinate ->
|
|
202
|
+
// issuer, so this cannot deadlock — unless both CAs share one
|
|
203
|
+
// rootDir (a degenerate configuration), where the lock is
|
|
204
|
+
// already held and re-acquiring the non-reentrant file lock
|
|
205
|
+
// would self-deadlock: skip it there.
|
|
206
|
+
if (path.resolve(issuerCA.rootDir) === caRootDir) {
|
|
207
|
+
await signWithIssuer();
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
await issuerCA._withCaDirectoryLock(signWithIssuer);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// Root CA — self-signed
|
|
215
|
+
displayTitle("Generate CA Certificate (self-signed)");
|
|
216
|
+
const passin = await this.#passin(ca);
|
|
217
|
+
await execute_openssl([
|
|
218
|
+
"x509",
|
|
219
|
+
"-sha256",
|
|
220
|
+
"-req",
|
|
221
|
+
"-days",
|
|
222
|
+
"3650",
|
|
223
|
+
"-extensions",
|
|
224
|
+
"v3_ca",
|
|
225
|
+
"-extfile",
|
|
226
|
+
n(configFile),
|
|
227
|
+
"-in",
|
|
228
|
+
"private/cakey.csr",
|
|
229
|
+
"-signkey",
|
|
230
|
+
n(privateKeyFilename),
|
|
231
|
+
"-out",
|
|
232
|
+
"public/cacert.pem",
|
|
233
|
+
...passin.args
|
|
234
|
+
], { ...options, env: passin.env });
|
|
235
|
+
}
|
|
236
|
+
displaySubtitle("generate initial CRL (Certificate Revocation List)");
|
|
237
|
+
await this.#regenerateCrlWith(ca, configFile, options);
|
|
238
|
+
});
|
|
239
|
+
displayTitle("Create Certificate Authority (CA) ---> DONE");
|
|
240
|
+
}
|
|
241
|
+
async regenerateCrl(ca) {
|
|
242
|
+
await this.#withConfig(ca, caAltName(ca), (configFile, options) => this.#regenerateCrlWith(ca, configFile, options));
|
|
243
|
+
}
|
|
244
|
+
async signSubordinateCsr(ca, csrFile, certFile, validityDays) {
|
|
245
|
+
// `[v3_ca]`'s subjectAltName should describe the *subordinate* being
|
|
246
|
+
// certified, not `ca` (the issuer doing the signing) — but nothing
|
|
247
|
+
// here parses `csrFile`'s own subject, so this reuses the issuer's
|
|
248
|
+
// identity as a well-formed placeholder. This is a pre-existing gap,
|
|
249
|
+
// not a regression: the original code left this value to whatever a
|
|
250
|
+
// prior, unrelated operation had last set in the shared env
|
|
251
|
+
// registry (an accidental "URI:undefined" or a stale value from a
|
|
252
|
+
// different CA entirely), so this is deterministic where the
|
|
253
|
+
// original was not, even though neither describes the subordinate.
|
|
254
|
+
await this.#withConfig(ca, caAltName(ca), async (configFile, options) => {
|
|
255
|
+
const caRootDir = options.cwd;
|
|
256
|
+
const passin = await this.#passin(ca);
|
|
257
|
+
await execute_openssl([
|
|
258
|
+
"x509",
|
|
259
|
+
"-sha256",
|
|
260
|
+
"-req",
|
|
261
|
+
"-days",
|
|
262
|
+
String(validityDays),
|
|
263
|
+
"-extensions",
|
|
264
|
+
"v3_ca",
|
|
265
|
+
"-extfile",
|
|
266
|
+
n(configFile),
|
|
267
|
+
"-in",
|
|
268
|
+
n(csrFile),
|
|
269
|
+
"-CA",
|
|
270
|
+
n(ca.caCertificate),
|
|
271
|
+
"-CAkey",
|
|
272
|
+
n(path.join(caRootDir, "private/cakey.pem")),
|
|
273
|
+
"-CAserial",
|
|
274
|
+
n(path.join(caRootDir, "serial")),
|
|
275
|
+
"-out",
|
|
276
|
+
n(certFile),
|
|
277
|
+
...passin.args
|
|
278
|
+
], { ...options, env: passin.env });
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async signEndEntityCsr(ca, certificate, csr, params1, sanOverride) {
|
|
282
|
+
await this.#withConfig(ca, buildSubjectAltNameString(sanOverride), async (configFile, options) => {
|
|
283
|
+
displaySubtitle("- then we ask the authority to sign the certificate signing request");
|
|
284
|
+
const passin = await this.#passin(ca);
|
|
285
|
+
await execute_openssl([
|
|
286
|
+
"ca",
|
|
287
|
+
"-config",
|
|
288
|
+
configFile,
|
|
289
|
+
"-startdate",
|
|
290
|
+
x509Date(params1.startDate),
|
|
291
|
+
"-enddate",
|
|
292
|
+
x509Date(params1.endDate),
|
|
293
|
+
"-batch",
|
|
294
|
+
"-out",
|
|
295
|
+
n(certificate),
|
|
296
|
+
"-in",
|
|
297
|
+
n(csr),
|
|
298
|
+
...passin.args
|
|
299
|
+
], { ...options, env: passin.env });
|
|
300
|
+
displaySubtitle("- dump the certificate for a check");
|
|
301
|
+
await execute_openssl(["x509", "-in", n(certificate), "-dates", "-fingerprint", "-purpose", "-noout"], options);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
async revoke(ca, certificate, reason) {
|
|
305
|
+
// one render serves the revocation and the CRL regeneration
|
|
306
|
+
// openssl writes its entropy file here; the native backend has no such notion
|
|
307
|
+
setEnv("RANDFILE", path.join(ca.rootDir, "random.rnd"));
|
|
308
|
+
await this.#withConfig(ca, caAltName(ca), async (configFile, options) => {
|
|
309
|
+
displaySubtitle("Revoke certificate");
|
|
310
|
+
const passin = await this.#passin(ca);
|
|
311
|
+
await execute_openssl_no_failure(["ca", "-verbose", "-config", n(configFile), "-revoke", certificate, "-crl_reason", reason, ...passin.args], { ...options, env: passin.env });
|
|
312
|
+
// regenerate CRL (Certificate Revocation List)
|
|
313
|
+
await this.#regenerateCrlWith(ca, configFile, options);
|
|
314
|
+
displaySubtitle("Verify that certificate is revoked");
|
|
315
|
+
await execute_openssl_no_failure([
|
|
316
|
+
"verify",
|
|
317
|
+
"-verbose",
|
|
318
|
+
"-CRLfile",
|
|
319
|
+
n(ca.revocationList),
|
|
320
|
+
"-CAfile",
|
|
321
|
+
n(ca.caCertificate),
|
|
322
|
+
"-crl_check",
|
|
323
|
+
n(certificate)
|
|
324
|
+
], options);
|
|
325
|
+
// produce CRL in DER format
|
|
326
|
+
displaySubtitle("Produce CRL in DER form ");
|
|
327
|
+
await execute_openssl(["crl", "-in", n(ca.revocationList), "-out", "crl/revocation_list.der", "-outform", "der"], options);
|
|
328
|
+
// produce CRL in PEM format with text
|
|
329
|
+
displaySubtitle("Produce CRL in PEM form ");
|
|
330
|
+
await execute_openssl(["crl", "-in", n(ca.revocationList), "-out", "crl/revocation_list.pem", "-outform", "pem", "-text"], options);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
async createSelfSignedCertificate(ca, certificateFile, privateKeyFile, params) {
|
|
334
|
+
// Explicit overrides like every other method: `$ENV::ALTNAME` in the
|
|
335
|
+
// rendered config comes from THIS call's params, never from whatever
|
|
336
|
+
// the shared env registry happened to hold — the registry-based
|
|
337
|
+
// render made a concurrent operation's SANs (or an empty ALTNAME
|
|
338
|
+
// from a concurrent revoke) leak into this certificate. CDP/AIA now
|
|
339
|
+
// deterministically follow this CA's configured URLs as well.
|
|
340
|
+
const envOverrides = caConfigEnvOverrides(ca, buildSubjectAltNameString(params));
|
|
341
|
+
const configFile = generateStaticConfig(ca.configFile, { cwd: ca.rootDir }, envOverrides);
|
|
342
|
+
const options = {
|
|
343
|
+
cwd: ca.rootDir,
|
|
344
|
+
openssl_conf: makePath(configFile)
|
|
345
|
+
};
|
|
346
|
+
try {
|
|
347
|
+
const subject = params.subject ? new Subject(params.subject).toString() : "";
|
|
348
|
+
const subjectOptions = subject && subject.length > 1 ? ["-subj", subject] : [];
|
|
349
|
+
const csrFile = `${certificateFile}_csr`;
|
|
350
|
+
// `req -new -key` reads (and, for an encrypted key, must decrypt)
|
|
351
|
+
// privateKeyFile too: without -passin it hangs indefinitely
|
|
352
|
+
// waiting on a passphrase prompt that never comes, even with
|
|
353
|
+
// stdin redirected to /dev/null — unlike e.g. `pkcs12`/`rsa
|
|
354
|
+
// -pubout`, which fail fast instead. Reproduced directly against
|
|
355
|
+
// OpenSSL 3.5.4. Empty passin is a no-op against a plaintext key.
|
|
356
|
+
const passin = await this.#passin(ca);
|
|
357
|
+
displaySubtitle("- the certificate signing request");
|
|
358
|
+
await execute_openssl([
|
|
359
|
+
"req",
|
|
360
|
+
"-new",
|
|
361
|
+
"-sha256",
|
|
362
|
+
...subjectOptions,
|
|
363
|
+
"-batch",
|
|
364
|
+
"-key",
|
|
365
|
+
n(privateKeyFile),
|
|
366
|
+
"-out",
|
|
367
|
+
n(csrFile),
|
|
368
|
+
...passin.args
|
|
369
|
+
], { ...options, env: passin.env });
|
|
370
|
+
displaySubtitle("- creating the self-signed certificate");
|
|
371
|
+
await execute_openssl([
|
|
372
|
+
"ca",
|
|
373
|
+
"-selfsign",
|
|
374
|
+
"-keyfile",
|
|
375
|
+
n(privateKeyFile),
|
|
376
|
+
"-startdate",
|
|
377
|
+
x509Date(params.startDate),
|
|
378
|
+
"-enddate",
|
|
379
|
+
x509Date(params.endDate),
|
|
380
|
+
"-batch",
|
|
381
|
+
"-out",
|
|
382
|
+
n(certificateFile),
|
|
383
|
+
"-in",
|
|
384
|
+
n(csrFile),
|
|
385
|
+
...passin.args
|
|
386
|
+
], { ...options, env: passin.env });
|
|
387
|
+
displaySubtitle("- dump the certificate for a check");
|
|
388
|
+
await execute_openssl(["x509", "-in", n(certificateFile), "-dates", "-fingerprint", "-purpose", "-noout"], {});
|
|
389
|
+
displaySubtitle("- verify self-signed certificate");
|
|
390
|
+
await execute_openssl_no_failure(["verify", "-verbose", "-CAfile", n(certificateFile), n(certificateFile)], options);
|
|
391
|
+
await fs.promises.unlink(csrFile);
|
|
392
|
+
}
|
|
393
|
+
finally {
|
|
394
|
+
await cleanupStaticConfig(configFile, { cwd: ca.rootDir });
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=openssl_ca_backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openssl_ca_backend.js","sourceRoot":"","sources":["../../../../lib/ca/backends/openssl_ca_backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type OpensslPassArg } from "../toolbox/with_openssl/index.js";
|
|
2
|
+
import { CertificateAuthorityCore, type CertificateAuthorityCoreOptions } from "./core/certificate_authority_core.js";
|
|
3
|
+
export * from "./core/certificate_authority_core.js";
|
|
4
|
+
/**
|
|
5
|
+
* Options for {@link CertificateAuthority}: the core's, except that the
|
|
6
|
+
* backend is named rather than supplied.
|
|
7
|
+
*/
|
|
8
|
+
export interface CertificateAuthorityOptions extends Omit<CertificateAuthorityCoreOptions, "backend"> {
|
|
9
|
+
/**
|
|
10
|
+
* Signing backend to use.
|
|
11
|
+
*
|
|
12
|
+
* - `"openssl"` (default): shells out to the `openssl` CLI, as this
|
|
13
|
+
* class always has.
|
|
14
|
+
* - `"native"`: signs in pure JS via `node-opcua-crypto`, writing the
|
|
15
|
+
* same on-disk database format, and needs no `openssl` executable.
|
|
16
|
+
*
|
|
17
|
+
* Setting `signer` implies `"native"`, since the openssl CLI can only
|
|
18
|
+
* load a key from a file.
|
|
19
|
+
*
|
|
20
|
+
* To supply a backend instance directly - including one of your own -
|
|
21
|
+
* use {@link CertificateAuthorityCore}, which is also the class to
|
|
22
|
+
* build against when you do not want the openssl backend in your
|
|
23
|
+
* bundle at all.
|
|
24
|
+
*/
|
|
25
|
+
backend?: "openssl" | "native";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A Certificate Authority with a backend chosen for you.
|
|
29
|
+
*
|
|
30
|
+
* This is {@link CertificateAuthorityCore} plus the convenience that made
|
|
31
|
+
* it the historical API: name a backend, or name nothing and get openssl.
|
|
32
|
+
* Because it resolves the name, it necessarily references both backends,
|
|
33
|
+
* which is why the core exists separately - a program that never imports
|
|
34
|
+
* this class never pulls the openssl backend into its bundle.
|
|
35
|
+
*/
|
|
36
|
+
export declare class CertificateAuthority extends CertificateAuthorityCore {
|
|
37
|
+
constructor(options: CertificateAuthorityOptions);
|
|
38
|
+
/**
|
|
39
|
+
* @internal `-passin env:` argv + env for an openssl call that loads
|
|
40
|
+
* this CA's key (always emitted, empty when none).
|
|
41
|
+
*
|
|
42
|
+
* The openssl backend builds its own now; this remains so that external
|
|
43
|
+
* code calling it keeps working, and lives here rather than on the core
|
|
44
|
+
* because the flag means nothing to a backend that spawns nothing.
|
|
45
|
+
*/
|
|
46
|
+
_opensslPassin(): Promise<OpensslPassArg>;
|
|
47
|
+
/**
|
|
48
|
+
* @internal
|
|
49
|
+
* Legacy shim: publish the `CDP_URL` / `AIA_VALUE` config substitution
|
|
50
|
+
* values to the shared env registry, or unset them so the matching
|
|
51
|
+
* `{{#KEY}}...{{/KEY}}` blocks are stripped. Nothing in this package
|
|
52
|
+
* reads the registry any more - every openssl config render receives
|
|
53
|
+
* these values explicitly, from the same {@link caConfigEnvOverrides}
|
|
54
|
+
* builder this delegates to, so the two cannot drift - kept only for
|
|
55
|
+
* external code that renders openssl config templates against the
|
|
56
|
+
* registry directly.
|
|
57
|
+
*
|
|
58
|
+
* It lives on this class rather than the core because it is meaningful
|
|
59
|
+
* only to the openssl backend.
|
|
60
|
+
*/
|
|
61
|
+
_wireRevocationEnvVars(): void;
|
|
62
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// node-opcua-pki
|
|
3
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
// Copyright (c) 2014-2026 - Etienne Rossignon - etienne.rossignon (at) gadz.org
|
|
5
|
+
// Copyright (c) 2022-2026 - Sterfive.com
|
|
6
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
//
|
|
8
|
+
// This project is licensed under the terms of the MIT license.
|
|
9
|
+
//
|
|
10
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
11
|
+
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
12
|
+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
13
|
+
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
14
|
+
//
|
|
15
|
+
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
16
|
+
// Software.
|
|
17
|
+
//
|
|
18
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
19
|
+
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
20
|
+
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
21
|
+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
23
|
+
import { passinArg, setEnv, unsetEnv } from "../toolbox/with_openssl/index.js";
|
|
24
|
+
import { NativeCaBackend } from "./backends/native_ca_backend.js";
|
|
25
|
+
import { caConfigEnvOverrides, OpenSslCaBackend } from "./backends/openssl_ca_backend.js";
|
|
26
|
+
import { CertificateAuthorityCore } from "./core/certificate_authority_core.js";
|
|
27
|
+
// Everything the CA exposes lives in the core module; re-exported here so
|
|
28
|
+
// that `import { ... } from "./ca/certificate_authority"` keeps resolving
|
|
29
|
+
// exactly as it did before the split.
|
|
30
|
+
export * from "./core/certificate_authority_core.js";
|
|
31
|
+
/**
|
|
32
|
+
* A Certificate Authority with a backend chosen for you.
|
|
33
|
+
*
|
|
34
|
+
* This is {@link CertificateAuthorityCore} plus the convenience that made
|
|
35
|
+
* it the historical API: name a backend, or name nothing and get openssl.
|
|
36
|
+
* Because it resolves the name, it necessarily references both backends,
|
|
37
|
+
* which is why the core exists separately - a program that never imports
|
|
38
|
+
* this class never pulls the openssl backend into its bundle.
|
|
39
|
+
*/
|
|
40
|
+
export class CertificateAuthority extends CertificateAuthorityCore {
|
|
41
|
+
constructor(options) {
|
|
42
|
+
if (options.signer && options.backend === "openssl") {
|
|
43
|
+
throw new Error("CertificateAuthority: backend 'openssl' cannot be combined with 'signer' - " +
|
|
44
|
+
"the openssl CLI loads its key from a file and cannot call an external signer. " +
|
|
45
|
+
"Drop the backend option (a signer implies 'native') or drop the signer.");
|
|
46
|
+
}
|
|
47
|
+
const backend = options.signer || options.backend === "native" ? new NativeCaBackend() : new OpenSslCaBackend();
|
|
48
|
+
super({ ...options, backend });
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @internal `-passin env:` argv + env for an openssl call that loads
|
|
52
|
+
* this CA's key (always emitted, empty when none).
|
|
53
|
+
*
|
|
54
|
+
* The openssl backend builds its own now; this remains so that external
|
|
55
|
+
* code calling it keeps working, and lives here rather than on the core
|
|
56
|
+
* because the flag means nothing to a backend that spawns nothing.
|
|
57
|
+
*/
|
|
58
|
+
async _opensslPassin() {
|
|
59
|
+
return passinArg(await this._privateKeyPassphrase());
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* @internal
|
|
63
|
+
* Legacy shim: publish the `CDP_URL` / `AIA_VALUE` config substitution
|
|
64
|
+
* values to the shared env registry, or unset them so the matching
|
|
65
|
+
* `{{#KEY}}...{{/KEY}}` blocks are stripped. Nothing in this package
|
|
66
|
+
* reads the registry any more - every openssl config render receives
|
|
67
|
+
* these values explicitly, from the same {@link caConfigEnvOverrides}
|
|
68
|
+
* builder this delegates to, so the two cannot drift - kept only for
|
|
69
|
+
* external code that renders openssl config templates against the
|
|
70
|
+
* registry directly.
|
|
71
|
+
*
|
|
72
|
+
* It lives on this class rather than the core because it is meaningful
|
|
73
|
+
* only to the openssl backend.
|
|
74
|
+
*/
|
|
75
|
+
_wireRevocationEnvVars() {
|
|
76
|
+
const overrides = caConfigEnvOverrides(this);
|
|
77
|
+
if (overrides.CDP_URL) {
|
|
78
|
+
setEnv("CDP_URL", overrides.CDP_URL);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
unsetEnv("CDP_URL");
|
|
82
|
+
}
|
|
83
|
+
if (overrides.AIA_VALUE) {
|
|
84
|
+
setEnv("AIA_VALUE", overrides.AIA_VALUE);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
unsetEnv("AIA_VALUE");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=certificate_authority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certificate_authority.js","sourceRoot":"","sources":["../../../lib/ca/certificate_authority.ts"],"names":[],"mappings":"AAAA,wHAAwH;AACxH,iBAAiB;AACjB,wHAAwH;AACxH,gFAAgF;AAChF,yCAAyC;AACzC,wHAAwH;AACxH,EAAE;AACF,gEAAgE;AAChE,EAAE;AACF,+GAA+G;AAC/G,sHAAsH;AACtH,kHAAkH;AAClH,mGAAmG;AACnG,EAAE;AACF,uHAAuH;AACvH,YAAY;AACZ,EAAE;AACF,uHAAuH;AACvH,wHAAwH;AACxH,mHAAmH;AACnH,mHAAmH;AACnH,wHAAwH;AAExH,OAAO,EAAuB,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACpG,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAC1F,OAAO,EAAE,wBAAwB,EAAwC,MAAM,sCAAsC,CAAC;AAEtH,0EAA0E;AAC1E,0EAA0E;AAC1E,sCAAsC;AACtC,cAAc,sCAAsC,CAAC;AA0BrD;;;;;;;;GAQG;AACH,MAAM,OAAO,oBAAqB,SAAQ,wBAAwB;IAC9D,YAAY,OAAoC;QAC5C,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CACX,6EAA6E;gBACzE,gFAAgF;gBAChF,yEAAyE,CAChF,CAAC;QACN,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAChH,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,cAAc;QACvB,OAAO,SAAS,CAAC,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;;;;;;;OAaG;IACI,sBAAsB;QACzB,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACJ,QAAQ,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;QACD,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACJ,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;IACL,CAAC;CACJ"}
|