node-opcua-pki 6.22.0 → 6.22.1
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/dist/bin/pki.mjs +44 -7
- package/dist/bin/pki.mjs.map +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +49 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/bin/pki.mjs
CHANGED
|
@@ -430,17 +430,30 @@ function makeFingerprint(certificate) {
|
|
|
430
430
|
function short(stringToShorten) {
|
|
431
431
|
return stringToShorten.substring(0, 10);
|
|
432
432
|
}
|
|
433
|
+
function toFilenameLabel(commonName) {
|
|
434
|
+
const label = (commonName || "").normalize("NFKC").replace(disallowedInLabel, "_").replace(/[^\x20-\x7E]/g, "").slice(0, 64).trim();
|
|
435
|
+
return label || "certificate";
|
|
436
|
+
}
|
|
433
437
|
function buildIdealCertificateName(certificate) {
|
|
434
438
|
const chain = coerceCertificateChain(certificate);
|
|
435
439
|
const fingerprint2 = makeFingerprint(chain);
|
|
436
440
|
try {
|
|
437
441
|
const commonName = exploreCertificate(chain[0]).tbsCertificate.subject.commonName || "";
|
|
438
|
-
const sanitizedCommonName = commonName
|
|
442
|
+
const sanitizedCommonName = toFilenameLabel(commonName);
|
|
439
443
|
return `${sanitizedCommonName}[${fingerprint2}]`;
|
|
440
444
|
} catch (_err) {
|
|
441
445
|
return `invalid_certificate_[${fingerprint2}]`;
|
|
442
446
|
}
|
|
443
447
|
}
|
|
448
|
+
function safeStoreJoin(folder, filename) {
|
|
449
|
+
const full = path2.resolve(folder, filename);
|
|
450
|
+
const base = path2.resolve(folder);
|
|
451
|
+
if (full !== base && !full.startsWith(base + path2.sep)) {
|
|
452
|
+
warningLog("refusing to write certificate outside its store folder:", filename);
|
|
453
|
+
throw new Error(`certificate filename escapes its store folder: ${filename}`);
|
|
454
|
+
}
|
|
455
|
+
return full;
|
|
456
|
+
}
|
|
444
457
|
function findMatchingIssuerKey(entries, wantedIssuerKey) {
|
|
445
458
|
return entries.filter((entry) => {
|
|
446
459
|
const info = getOrComputeInfo(entry);
|
|
@@ -502,7 +515,7 @@ function findIssuerCertificateInChain(certificate, chain) {
|
|
|
502
515
|
}
|
|
503
516
|
return null;
|
|
504
517
|
}
|
|
505
|
-
var configurationFileSimpleTemplate, fsWriteFile,
|
|
518
|
+
var configurationFileSimpleTemplate, fsWriteFile, disallowedInLabel, ChainCompletionStatus, CertificateManager;
|
|
506
519
|
var init_certificate_manager = __esm({
|
|
507
520
|
"packages/node-opcua-pki/lib/pki/certificate_manager.ts"() {
|
|
508
521
|
"use strict";
|
|
@@ -514,7 +527,7 @@ var init_certificate_manager = __esm({
|
|
|
514
527
|
init_simple_config_template_cnf();
|
|
515
528
|
configurationFileSimpleTemplate = simple_config_template_cnf_default;
|
|
516
529
|
fsWriteFile = fs4.promises.writeFile;
|
|
517
|
-
|
|
530
|
+
disallowedInLabel = /[^A-Za-z0-9._ -]/g;
|
|
518
531
|
ChainCompletionStatus = /* @__PURE__ */ ((ChainCompletionStatus2) => {
|
|
519
532
|
ChainCompletionStatus2["AlreadyComplete"] = "AlreadyComplete";
|
|
520
533
|
ChainCompletionStatus2["ChainCompleted"] = "ChainCompleted";
|
|
@@ -999,7 +1012,7 @@ var init_certificate_manager = __esm({
|
|
|
999
1012
|
} catch (_err) {
|
|
1000
1013
|
return "BadCertificateInvalid";
|
|
1001
1014
|
}
|
|
1002
|
-
const filename =
|
|
1015
|
+
const filename = safeStoreJoin(this.rejectedFolder, `${buildIdealCertificateName(leafCertificate)}.pem`);
|
|
1003
1016
|
debugLog("certificate has never been seen before and is now rejected (untrusted) ", filename);
|
|
1004
1017
|
await fsWriteFile(filename, toPem(chain, "CERTIFICATE"));
|
|
1005
1018
|
this.#thumbs.rejected.set(fingerprint2, { certificate: leafCertificate, filename });
|
|
@@ -1407,7 +1420,7 @@ var init_certificate_manager = __esm({
|
|
|
1407
1420
|
if (this.#thumbs.issuers.certs.has(fingerprint2)) {
|
|
1408
1421
|
return "Good" /* Good */;
|
|
1409
1422
|
}
|
|
1410
|
-
const filename =
|
|
1423
|
+
const filename = safeStoreJoin(this.issuersCertFolder, `issuer_${buildIdealCertificateName(certificate)}.pem`);
|
|
1411
1424
|
await fs4.promises.writeFile(filename, pemCertificate, "ascii");
|
|
1412
1425
|
this.#thumbs.issuers.certs.set(fingerprint2, { certificate, filename });
|
|
1413
1426
|
if (addInTrustList) {
|
|
@@ -1866,7 +1879,7 @@ var init_certificate_manager = __esm({
|
|
|
1866
1879
|
let status = await this.#checkRejectedOrTrusted(certificate);
|
|
1867
1880
|
if (status === "unknown") {
|
|
1868
1881
|
const pem = toPem(chain, "CERTIFICATE");
|
|
1869
|
-
const filename =
|
|
1882
|
+
const filename = safeStoreJoin(this.rejectedFolder, `${buildIdealCertificateName(certificate)}.pem`);
|
|
1870
1883
|
await fs4.promises.writeFile(filename, pem);
|
|
1871
1884
|
this.#thumbs.rejected.set(fingerprint2, { certificate, filename });
|
|
1872
1885
|
status = "rejected";
|
|
@@ -1883,7 +1896,7 @@ var init_certificate_manager = __esm({
|
|
|
1883
1896
|
throw new Error(`#moveCertificate: certificate ${fingerprint2.substring(0, 10)} not found in ${status} index`);
|
|
1884
1897
|
}
|
|
1885
1898
|
const destFolder = newStatus === "trusted" ? this.trustedFolder : this.rejectedFolder;
|
|
1886
|
-
const certificateDest =
|
|
1899
|
+
const certificateDest = safeStoreJoin(destFolder, path2.basename(srcEntry.filename));
|
|
1887
1900
|
debugLog("#moveCertificate", fingerprint2.substring(0, 10), "old name", srcEntry.filename);
|
|
1888
1901
|
debugLog("#moveCertificate", fingerprint2.substring(0, 10), "new name", certificateDest);
|
|
1889
1902
|
await fs4.promises.rename(srcEntry.filename, certificateDest);
|
|
@@ -2640,8 +2653,32 @@ function passinArg(passphrase = "") {
|
|
|
2640
2653
|
function renderForDisplay(file, args) {
|
|
2641
2654
|
return [file, ...args].map((a) => a === "" || /[\s"'`$\\]/.test(a) ? JSON.stringify(a) : a).join(" ");
|
|
2642
2655
|
}
|
|
2656
|
+
function hasUnsafeArgChar(value) {
|
|
2657
|
+
for (const ch of value) {
|
|
2658
|
+
const code = ch.codePointAt(0);
|
|
2659
|
+
if (code < 32 || code === 127) {
|
|
2660
|
+
return true;
|
|
2661
|
+
}
|
|
2662
|
+
if (code < 128) {
|
|
2663
|
+
continue;
|
|
2664
|
+
}
|
|
2665
|
+
if (/[\p{L}\p{N}\p{M}]/u.test(ch)) {
|
|
2666
|
+
continue;
|
|
2667
|
+
}
|
|
2668
|
+
return true;
|
|
2669
|
+
}
|
|
2670
|
+
return false;
|
|
2671
|
+
}
|
|
2672
|
+
function checkArgs(file, args) {
|
|
2673
|
+
for (const value of [file, ...args]) {
|
|
2674
|
+
if (typeof value === "string" && hasUnsafeArgChar(value)) {
|
|
2675
|
+
throw new Error(`execute_openssl: refusing argument with an unexpected character: ${JSON.stringify(value)}`);
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2643
2679
|
async function execute2(file, args, options) {
|
|
2644
2680
|
const from = new Error();
|
|
2681
|
+
checkArgs(file, args);
|
|
2645
2682
|
options.cwd = options.cwd || process.cwd();
|
|
2646
2683
|
if (!g_config.silent) {
|
|
2647
2684
|
warningLog(chalk5.cyan(" CWD "), options.cwd);
|