@ai-ecoverse/slicc-kernel 1.124.12 → 1.124.13
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/README.md +29 -8
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +304 -53
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +4419 -4337
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +309 -58
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +7087 -7005
- package/dist/process-worker.js.map +4 -4
- package/dist/types/fs/unlinked.d.ts +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/kernel/net/tls-ciphers.d.ts +6 -0
- package/dist/types/kernel/net/tls-client.d.ts +13 -1
- package/dist/types/kernel/net/tls-engine.d.ts +10 -0
- package/dist/types/kernel/net/tls-uplink.d.ts +14 -1
- package/dist/types/kernel/net/uplink-socket.d.ts +1 -1
- package/dist/types/kernel/socket-syscalls.d.ts +7 -0
- package/dist/types/kernel/vfs-file.d.ts +2 -0
- package/dist/types/process/js/js-dev.d.ts +1 -0
- package/dist/types/process/js/js-net.d.ts +16 -0
- package/dist/types/process/process-fds.d.ts +1 -1
- package/dist/types/process/wasi/wasi-host.d.ts +1 -0
- package/package.json +3 -3
package/dist/kernel-worker.js
CHANGED
|
@@ -4655,8 +4655,8 @@ function uplinkLink(conn, onReset) {
|
|
|
4655
4655
|
open = false;
|
|
4656
4656
|
conn.close();
|
|
4657
4657
|
};
|
|
4658
|
-
void inbound(conn, rx).catch(() => {
|
|
4659
|
-
onReset();
|
|
4658
|
+
void inbound(conn, rx).catch((err) => {
|
|
4659
|
+
onReset(err);
|
|
4660
4660
|
close();
|
|
4661
4661
|
tx.closeRead();
|
|
4662
4662
|
}).finally(() => rx.closeWrite());
|
|
@@ -4747,7 +4747,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
4747
4747
|
state = "open";
|
|
4748
4748
|
dialing;
|
|
4749
4749
|
failed;
|
|
4750
|
-
reset
|
|
4750
|
+
reset;
|
|
4751
4751
|
local;
|
|
4752
4752
|
peer;
|
|
4753
4753
|
peerCred;
|
|
@@ -4786,19 +4786,20 @@ var KernelSocket = class _KernelSocket {
|
|
|
4786
4786
|
const { rx } = this.connection();
|
|
4787
4787
|
if (this.readShut || max <= 0) return new Uint8Array(0);
|
|
4788
4788
|
const bytes = await pipeCall(() => rx.read(max, signal));
|
|
4789
|
-
if (bytes.length === 0 && this.reset) throw
|
|
4789
|
+
if (bytes.length === 0 && this.reset) throw this.reset;
|
|
4790
4790
|
return bytes;
|
|
4791
4791
|
}
|
|
4792
4792
|
async peek(max, signal) {
|
|
4793
4793
|
const { rx } = this.connection();
|
|
4794
4794
|
if (this.readShut || max <= 0) return new Uint8Array(0);
|
|
4795
4795
|
const bytes = await pipeCall(() => rx.peek(max, signal));
|
|
4796
|
-
if (bytes.length === 0 && this.reset) throw
|
|
4796
|
+
if (bytes.length === 0 && this.reset) throw this.reset;
|
|
4797
4797
|
return bytes;
|
|
4798
4798
|
}
|
|
4799
4799
|
async write(bytes, signal) {
|
|
4800
4800
|
const { tx } = this.connection();
|
|
4801
4801
|
if (this.writeShut) throw new KernelError("EPIPE");
|
|
4802
|
+
if (this.reset?.code === "EPROTO") throw this.reset;
|
|
4802
4803
|
return pipeCall(() => tx.write(bytes, signal));
|
|
4803
4804
|
}
|
|
4804
4805
|
poll() {
|
|
@@ -4983,8 +4984,8 @@ var KernelSocket = class _KernelSocket {
|
|
|
4983
4984
|
this.dialing = void 0;
|
|
4984
4985
|
this.switch = conn;
|
|
4985
4986
|
this.attach(
|
|
4986
|
-
uplinkLink(conn, () => {
|
|
4987
|
-
this.reset =
|
|
4987
|
+
uplinkLink(conn, (err) => {
|
|
4988
|
+
this.reset = err instanceof KernelError && err.code === "EPROTO" ? err : new KernelError("ECONNRESET");
|
|
4988
4989
|
this.changes.wake();
|
|
4989
4990
|
})
|
|
4990
4991
|
);
|
|
@@ -6625,7 +6626,7 @@ function satisfies(version, range2) {
|
|
|
6625
6626
|
}
|
|
6626
6627
|
|
|
6627
6628
|
// src/version.ts
|
|
6628
|
-
var KERNEL_VERSION = true ? "1.124.
|
|
6629
|
+
var KERNEL_VERSION = true ? "1.124.13" : "0.0.0-dev";
|
|
6629
6630
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6630
6631
|
function procVersion() {
|
|
6631
6632
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -7682,16 +7683,24 @@ var UnlinkedKeeper = class {
|
|
|
7682
7683
|
gated();
|
|
7683
7684
|
const held = /* @__PURE__ */ new Map();
|
|
7684
7685
|
const hidden = /* @__PURE__ */ new Map();
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
const
|
|
7693
|
-
|
|
7686
|
+
const moved2 = [];
|
|
7687
|
+
try {
|
|
7688
|
+
for (; ; ) {
|
|
7689
|
+
await take();
|
|
7690
|
+
const now = this.heldWithin(target);
|
|
7691
|
+
const next3 = paths.filter((path) => now.has(path) && !held.has(path));
|
|
7692
|
+
if (next3.length === 0) break;
|
|
7693
|
+
for (const path of next3) {
|
|
7694
|
+
const holders = now.get(path);
|
|
7695
|
+
held.set(path, holders);
|
|
7696
|
+
for (const holder of holders) moved2.push(holder.moving?.(path) ?? (() => void 0));
|
|
7697
|
+
const at = await this.hide(path);
|
|
7698
|
+
if (at !== void 0) hidden.set(path, at);
|
|
7699
|
+
}
|
|
7694
7700
|
}
|
|
7701
|
+
} catch (err) {
|
|
7702
|
+
for (const settle3 of moved2) settle3();
|
|
7703
|
+
throw err;
|
|
7695
7704
|
}
|
|
7696
7705
|
sealed();
|
|
7697
7706
|
const done4 = () => {
|
|
@@ -7704,6 +7713,7 @@ var UnlinkedKeeper = class {
|
|
|
7704
7713
|
files.set(path, file);
|
|
7705
7714
|
for (const holder of holders) holder.keep(path, file);
|
|
7706
7715
|
}
|
|
7716
|
+
for (const settle3 of moved2) settle3();
|
|
7707
7717
|
return {
|
|
7708
7718
|
moved: new Set(hidden.keys()),
|
|
7709
7719
|
commit: () => {
|
|
@@ -14773,6 +14783,8 @@ function realmCa(owner, store) {
|
|
|
14773
14783
|
|
|
14774
14784
|
// src/kernel/net/tls-engine.ts
|
|
14775
14785
|
var TLS_CLIENT_INSECURE_SKIP_VERIFY = 1;
|
|
14786
|
+
var TLS_CLIENT_NO_SNI = 2;
|
|
14787
|
+
var TLS_CLIENT_VERIFY_CHAIN_ONLY = 4;
|
|
14776
14788
|
var SCRATCH = 64 * 1024;
|
|
14777
14789
|
var EOF = -1;
|
|
14778
14790
|
var TlsError = class extends Error {
|
|
@@ -14829,10 +14841,22 @@ var TlsEngine = class {
|
|
|
14829
14841
|
this.m._free(ptr);
|
|
14830
14842
|
}
|
|
14831
14843
|
}
|
|
14844
|
+
withSecret(bytes, fn) {
|
|
14845
|
+
const ptr = this.put(bytes);
|
|
14846
|
+
try {
|
|
14847
|
+
return fn(ptr);
|
|
14848
|
+
} finally {
|
|
14849
|
+
this.m.HEAPU8.fill(0, ptr, ptr + bytes.length + 1);
|
|
14850
|
+
this.m._free(ptr);
|
|
14851
|
+
}
|
|
14852
|
+
}
|
|
14832
14853
|
intoScratch(fn) {
|
|
14833
14854
|
const n = fn(this.scratch, SCRATCH);
|
|
14834
14855
|
return n > 0 ? this.taken(n) : n;
|
|
14835
14856
|
}
|
|
14857
|
+
get sessionControls() {
|
|
14858
|
+
return typeof this.m._tls_client_cert === "function";
|
|
14859
|
+
}
|
|
14836
14860
|
get client() {
|
|
14837
14861
|
return typeof this.m._tls_client_new === "function" ? this.m : void 0;
|
|
14838
14862
|
}
|
|
@@ -14985,6 +15009,27 @@ var TlsSession = class {
|
|
|
14985
15009
|
const out = this.engine.intoScratch((p, max) => this.c._tls_alpn(this.ptr, p, max));
|
|
14986
15010
|
return out instanceof Uint8Array ? new TextDecoder().decode(out) : void 0;
|
|
14987
15011
|
}
|
|
15012
|
+
ownCert(chain2, key, pass2) {
|
|
15013
|
+
const set3 = this.m._tls_client_cert;
|
|
15014
|
+
const keyLen = key[0] === 45 ? key.length + 1 : key.length;
|
|
15015
|
+
const ret = this.engine.withBytes(
|
|
15016
|
+
chain2,
|
|
15017
|
+
(c) => this.engine.withSecret(
|
|
15018
|
+
key,
|
|
15019
|
+
(k) => this.engine.withSecret(
|
|
15020
|
+
pass2,
|
|
15021
|
+
(p) => set3(this.ptr, c, chain2.length, k, keyLen, pass2.length > 0 ? p : 0, pass2.length)
|
|
15022
|
+
)
|
|
15023
|
+
)
|
|
15024
|
+
);
|
|
15025
|
+
if (ret !== 0) throw this.engine.error(ret, "client certificate");
|
|
15026
|
+
}
|
|
15027
|
+
get ciphersuite() {
|
|
15028
|
+
return this.m._tls_ciphersuite(this.ptr);
|
|
15029
|
+
}
|
|
15030
|
+
get nameMismatch() {
|
|
15031
|
+
return this.m._tls_name_mismatch(this.ptr) === 1;
|
|
15032
|
+
}
|
|
14988
15033
|
peerChain() {
|
|
14989
15034
|
const chain2 = [];
|
|
14990
15035
|
const count2 = this.c._tls_peer_count(this.ptr);
|
|
@@ -16403,11 +16448,11 @@ async function runChild(req, deps) {
|
|
|
16403
16448
|
if (pid !== 0) kill();
|
|
16404
16449
|
decided.resolve();
|
|
16405
16450
|
};
|
|
16406
|
-
const
|
|
16451
|
+
const controls2 = [];
|
|
16407
16452
|
const capture = () => {
|
|
16408
16453
|
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
16409
16454
|
const control = { shut: false, ended: resolve2, eof: promise };
|
|
16410
|
-
|
|
16455
|
+
controls2.push(control);
|
|
16411
16456
|
return { capture: true, max, overflow: () => stop("ENOBUFS"), control };
|
|
16412
16457
|
};
|
|
16413
16458
|
const decided = Promise.withResolvers();
|
|
@@ -16441,11 +16486,11 @@ async function runChild(req, deps) {
|
|
|
16441
16486
|
let status;
|
|
16442
16487
|
try {
|
|
16443
16488
|
status = await reaped(deps, pid);
|
|
16444
|
-
const open =
|
|
16489
|
+
const open = controls2.filter((c) => c.opened);
|
|
16445
16490
|
await Promise.race([Promise.all(open.map((c) => c.eof)), decided.promise]);
|
|
16446
16491
|
} finally {
|
|
16447
16492
|
cancel?.();
|
|
16448
|
-
for (const control of
|
|
16493
|
+
for (const control of controls2) control.shut = true;
|
|
16449
16494
|
}
|
|
16450
16495
|
const out = deps.children.captured(pid, 1);
|
|
16451
16496
|
const err = deps.children.captured(pid, 2);
|
|
@@ -17027,6 +17072,47 @@ function encodeReceived(got) {
|
|
|
17027
17072
|
return out;
|
|
17028
17073
|
}
|
|
17029
17074
|
|
|
17075
|
+
// src/kernel/net/tls-ciphers.ts
|
|
17076
|
+
var SUITES = [
|
|
17077
|
+
[4865, "TLS_AES_128_GCM_SHA256", "TLS_AES_128_GCM_SHA256", "TLSv1.3"],
|
|
17078
|
+
[4866, "TLS_AES_256_GCM_SHA384", "TLS_AES_256_GCM_SHA384", "TLSv1.3"],
|
|
17079
|
+
[4867, "TLS_CHACHA20_POLY1305_SHA256", "TLS_CHACHA20_POLY1305_SHA256", "TLSv1.3"],
|
|
17080
|
+
[4868, "TLS_AES_128_CCM_SHA256", "TLS_AES_128_CCM_SHA256", "TLSv1.3"],
|
|
17081
|
+
[4869, "TLS_AES_128_CCM_8_SHA256", "TLS_AES_128_CCM_8_SHA256", "TLSv1.3"],
|
|
17082
|
+
[49195, "ECDHE-ECDSA-AES128-GCM-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
|
|
17083
|
+
[49196, "ECDHE-ECDSA-AES256-GCM-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
|
|
17084
|
+
[49199, "ECDHE-RSA-AES128-GCM-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
|
|
17085
|
+
[49200, "ECDHE-RSA-AES256-GCM-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
|
|
17086
|
+
[52392, "ECDHE-RSA-CHACHA20-POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLSv1.2"],
|
|
17087
|
+
[
|
|
17088
|
+
52393,
|
|
17089
|
+
"ECDHE-ECDSA-CHACHA20-POLY1305",
|
|
17090
|
+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
17091
|
+
"TLSv1.2"
|
|
17092
|
+
],
|
|
17093
|
+
[49187, "ECDHE-ECDSA-AES128-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLSv1.2"],
|
|
17094
|
+
[49188, "ECDHE-ECDSA-AES256-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLSv1.2"],
|
|
17095
|
+
[49191, "ECDHE-RSA-AES128-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLSv1.2"],
|
|
17096
|
+
[49192, "ECDHE-RSA-AES256-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLSv1.2"],
|
|
17097
|
+
[49161, "ECDHE-ECDSA-AES128-SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLSv1.0"],
|
|
17098
|
+
[49162, "ECDHE-ECDSA-AES256-SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLSv1.0"],
|
|
17099
|
+
[49171, "ECDHE-RSA-AES128-SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLSv1.0"],
|
|
17100
|
+
[49172, "ECDHE-RSA-AES256-SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLSv1.0"],
|
|
17101
|
+
[156, "AES128-GCM-SHA256", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
|
|
17102
|
+
[157, "AES256-GCM-SHA384", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
|
|
17103
|
+
[158, "DHE-RSA-AES128-GCM-SHA256", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
|
|
17104
|
+
[159, "DHE-RSA-AES256-GCM-SHA384", "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"]
|
|
17105
|
+
];
|
|
17106
|
+
function cipherOf(id2, protocol) {
|
|
17107
|
+
const known = SUITES.find(([n]) => n === id2);
|
|
17108
|
+
const hex3 = `0x${id2.toString(16).padStart(4, "0").toUpperCase()}`;
|
|
17109
|
+
return {
|
|
17110
|
+
name: known?.[1] ?? hex3,
|
|
17111
|
+
standardName: known?.[2] ?? hex3,
|
|
17112
|
+
version: known?.[3] ?? protocol
|
|
17113
|
+
};
|
|
17114
|
+
}
|
|
17115
|
+
|
|
17030
17116
|
// src/kernel/net/tls-client.ts
|
|
17031
17117
|
var WRITE_CHUNK = 16 * 1024;
|
|
17032
17118
|
var BADCERT = [
|
|
@@ -17043,6 +17129,15 @@ function verifyCode(flags2) {
|
|
|
17043
17129
|
if (flags2 === -1) return "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
|
|
17044
17130
|
return BADCERT.find(([bit]) => (flags2 & bit) !== 0)?.[1] ?? "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
|
|
17045
17131
|
}
|
|
17132
|
+
function isIP(name2) {
|
|
17133
|
+
return ipv4Bytes(name2) !== void 0 || name2.includes(":") && ipv6Groups(name2) !== void 0;
|
|
17134
|
+
}
|
|
17135
|
+
function clientFlags(o) {
|
|
17136
|
+
return (o.insecure ? TLS_CLIENT_INSECURE_SKIP_VERIFY : 0) | (o.sni === false ? TLS_CLIENT_NO_SNI : 0) | (o.checkHostname === false ? TLS_CLIENT_VERIFY_CHAIN_ONLY : 0);
|
|
17137
|
+
}
|
|
17138
|
+
function openSession(o) {
|
|
17139
|
+
return o.engine.clientSession(o.store, o.servername, o.alpn, clientFlags(o));
|
|
17140
|
+
}
|
|
17046
17141
|
var Ciphertext = class {
|
|
17047
17142
|
queue = [];
|
|
17048
17143
|
ended = false;
|
|
@@ -17115,17 +17210,39 @@ async function handshake(conn, o, session, inbox) {
|
|
|
17115
17210
|
}
|
|
17116
17211
|
}
|
|
17117
17212
|
}
|
|
17213
|
+
function controlsOf(o, session, protocol) {
|
|
17214
|
+
if (!o.engine.sessionControls) return {};
|
|
17215
|
+
const checked = o.checkHostname !== false && !o.insecure;
|
|
17216
|
+
return {
|
|
17217
|
+
cipher: cipherOf(session.ciphersuite, protocol),
|
|
17218
|
+
clientCertificate: o.clientCertificate === true,
|
|
17219
|
+
sni: o.sni !== false && !isIP(o.servername),
|
|
17220
|
+
hostnameChecked: checked,
|
|
17221
|
+
...o.insecure ? {} : { hostnameMatches: checked || !session.nameMismatch }
|
|
17222
|
+
};
|
|
17223
|
+
}
|
|
17118
17224
|
function infoOf(o, session) {
|
|
17119
17225
|
const flags2 = session.verifyResult;
|
|
17120
17226
|
const code = verifyCode(flags2);
|
|
17227
|
+
const protocol = session.version === 772 ? "TLSv1.3" : "TLSv1.2";
|
|
17121
17228
|
return {
|
|
17122
|
-
protocol
|
|
17229
|
+
protocol,
|
|
17123
17230
|
alpnProtocol: session.alpn ?? false,
|
|
17124
17231
|
authorized: code === void 0,
|
|
17125
17232
|
...code ? { authorizationError: code, authorizationText: o.engine.verifyInfo(flags2).trim() } : {},
|
|
17126
|
-
peerCertificates: session.peerChain()
|
|
17233
|
+
peerCertificates: session.peerChain(),
|
|
17234
|
+
...controlsOf(o, session, protocol)
|
|
17127
17235
|
};
|
|
17128
17236
|
}
|
|
17237
|
+
var FATAL_ALERT = -30592;
|
|
17238
|
+
function alerted(err) {
|
|
17239
|
+
if (err.code === FATAL_ALERT)
|
|
17240
|
+
return new KernelError(
|
|
17241
|
+
"EPROTO",
|
|
17242
|
+
`ERR_SSL_FATAL_ALERT: the server ended the session: ${err.message}`
|
|
17243
|
+
);
|
|
17244
|
+
return new KernelError("EPROTO", `ERR_SSL_PROTOCOL_ERROR: ${err.message}`);
|
|
17245
|
+
}
|
|
17129
17246
|
function plaintext(conn, session, inbox) {
|
|
17130
17247
|
let freed = false;
|
|
17131
17248
|
let writeClosed = false;
|
|
@@ -17140,7 +17257,12 @@ function plaintext(conn, session, inbox) {
|
|
|
17140
17257
|
async read() {
|
|
17141
17258
|
for (; ; ) {
|
|
17142
17259
|
if (freed) return null;
|
|
17143
|
-
|
|
17260
|
+
let got;
|
|
17261
|
+
try {
|
|
17262
|
+
got = session.read();
|
|
17263
|
+
} catch (err) {
|
|
17264
|
+
throw alerted(err);
|
|
17265
|
+
}
|
|
17144
17266
|
await send(conn, session);
|
|
17145
17267
|
if (got instanceof Uint8Array) return got;
|
|
17146
17268
|
if (got === "eof") return null;
|
|
@@ -17168,8 +17290,7 @@ function plaintext(conn, session, inbox) {
|
|
|
17168
17290
|
};
|
|
17169
17291
|
}
|
|
17170
17292
|
async function tlsClient(conn, o, taken = new Uint8Array(0)) {
|
|
17171
|
-
const
|
|
17172
|
-
const session = o.engine.clientSession(o.store, o.servername, o.alpn, flags2);
|
|
17293
|
+
const session = o.session ?? openSession(o);
|
|
17173
17294
|
const inbox = new Ciphertext(conn, session);
|
|
17174
17295
|
inbox.hand(taken);
|
|
17175
17296
|
try {
|
|
@@ -17182,10 +17303,10 @@ async function tlsClient(conn, o, taken = new Uint8Array(0)) {
|
|
|
17182
17303
|
}
|
|
17183
17304
|
|
|
17184
17305
|
// src/kernel/net/tls-uplink.ts
|
|
17185
|
-
var
|
|
17306
|
+
var isIP2 = (text) => ipv4Bytes(text) !== void 0 || text.includes(":") && ipv6Groups(text) !== void 0;
|
|
17186
17307
|
var LABEL2 = /^(?!-)[A-Za-z0-9-]{1,63}(?<!-)$/;
|
|
17187
17308
|
function serverName(name2) {
|
|
17188
|
-
if (
|
|
17309
|
+
if (isIP2(name2.replace(/^\[|\]$/g, ""))) return name2.replace(/^\[|\]$/g, "");
|
|
17189
17310
|
const bare = name2.endsWith(".") ? name2.slice(0, -1) : name2;
|
|
17190
17311
|
if (bare.length === 0 || bare.length > 253 || !bare.split(".").every((l) => LABEL2.test(l))) {
|
|
17191
17312
|
throw new KernelError(
|
|
@@ -17235,9 +17356,66 @@ function sessionOf(info, servername) {
|
|
|
17235
17356
|
authorizationText: info.authorizationText
|
|
17236
17357
|
} : {},
|
|
17237
17358
|
servername,
|
|
17238
|
-
peerCertificates: info.peerCertificates.map(encode)
|
|
17359
|
+
peerCertificates: info.peerCertificates.map(encode),
|
|
17360
|
+
...controls(info)
|
|
17239
17361
|
};
|
|
17240
17362
|
}
|
|
17363
|
+
function controls(info) {
|
|
17364
|
+
if (!info.cipher) return {};
|
|
17365
|
+
return {
|
|
17366
|
+
cipher: info.cipher,
|
|
17367
|
+
clientCertificate: info.clientCertificate === true,
|
|
17368
|
+
sni: info.sni !== false,
|
|
17369
|
+
hostnameChecked: info.hostnameChecked === true,
|
|
17370
|
+
...info.hostnameMatches === void 0 ? {} : { hostnameMatches: info.hostnameMatches }
|
|
17371
|
+
};
|
|
17372
|
+
}
|
|
17373
|
+
var KEY_ERRORS = [
|
|
17374
|
+
[-3, "ERR_OSSL_X509_KEY_VALUES_MISMATCH"],
|
|
17375
|
+
[-15232, "ERR_OSSL_BAD_DECRYPT"],
|
|
17376
|
+
[-15360, "ERR_OSSL_CRYPTO_INTERRUPTED_OR_CANCELLED"]
|
|
17377
|
+
];
|
|
17378
|
+
function keyRefused(err) {
|
|
17379
|
+
const code = err instanceof TlsError ? err.code : 0;
|
|
17380
|
+
const name2 = KEY_ERRORS.find(([n]) => n === code)?.[1] ?? "ERR_OSSL_UNSUPPORTED";
|
|
17381
|
+
const text = code === -3 ? "the key does not match the certificate" : err.message;
|
|
17382
|
+
return new KernelError("EPROTO", `${name2}: ${text}`);
|
|
17383
|
+
}
|
|
17384
|
+
function takeCert(req) {
|
|
17385
|
+
const cert = req.clientCert;
|
|
17386
|
+
if (!cert) return void 0;
|
|
17387
|
+
delete req.clientCert;
|
|
17388
|
+
if (!Array.isArray(cert.chain) || cert.chain.length === 0 || typeof cert.key !== "string")
|
|
17389
|
+
throw new KernelError("EINVAL", "ERR_INVALID_ARG_VALUE: cert and key go together");
|
|
17390
|
+
let ders;
|
|
17391
|
+
let key;
|
|
17392
|
+
try {
|
|
17393
|
+
ders = cert.chain.map(base64Der);
|
|
17394
|
+
key = base64Der(cert.key);
|
|
17395
|
+
} catch {
|
|
17396
|
+
throw new KernelError("EINVAL", "ERR_INVALID_ARG_VALUE: cert or key is not base64");
|
|
17397
|
+
}
|
|
17398
|
+
const chain2 = new Uint8Array(ders.reduce((n, d) => n + d.length, 0));
|
|
17399
|
+
let at = 0;
|
|
17400
|
+
for (const der of ders) {
|
|
17401
|
+
chain2.set(der, at);
|
|
17402
|
+
at += der.length;
|
|
17403
|
+
}
|
|
17404
|
+
const pass2 = new TextEncoder().encode(cert.passphrase ?? "");
|
|
17405
|
+
return { chain: chain2, key, pass: pass2 };
|
|
17406
|
+
}
|
|
17407
|
+
function withCert(session, cert) {
|
|
17408
|
+
if (!cert) return;
|
|
17409
|
+
try {
|
|
17410
|
+
session.ownCert(cert.chain, cert.key, cert.pass);
|
|
17411
|
+
} catch (err) {
|
|
17412
|
+
throw keyRefused(err);
|
|
17413
|
+
}
|
|
17414
|
+
}
|
|
17415
|
+
function wipe(cert) {
|
|
17416
|
+
cert?.key.fill(0);
|
|
17417
|
+
cert?.pass.fill(0);
|
|
17418
|
+
}
|
|
17241
17419
|
async function setUp(support, req) {
|
|
17242
17420
|
const engine = await support.engine();
|
|
17243
17421
|
if (!engine.client)
|
|
@@ -17255,21 +17433,66 @@ async function setUp(support, req) {
|
|
|
17255
17433
|
}
|
|
17256
17434
|
return { engine, store: own, own };
|
|
17257
17435
|
}
|
|
17258
|
-
function
|
|
17259
|
-
|
|
17260
|
-
|
|
17436
|
+
async function prepare(support, req, servername) {
|
|
17437
|
+
const cert = takeCert(req);
|
|
17438
|
+
try {
|
|
17439
|
+
return await prepareWith(support, req, servername, cert);
|
|
17440
|
+
} catch (err) {
|
|
17441
|
+
if (err instanceof KernelError) throw err;
|
|
17442
|
+
throw new KernelError("ENOTSUP", err instanceof Error ? err.message : String(err));
|
|
17443
|
+
} finally {
|
|
17444
|
+
wipe(cert);
|
|
17445
|
+
}
|
|
17446
|
+
}
|
|
17447
|
+
async function prepareWith(support, req, servername, cert) {
|
|
17448
|
+
if (req.checkHostname === false && req.insecure === true) {
|
|
17449
|
+
throw new KernelError(
|
|
17450
|
+
"EINVAL",
|
|
17451
|
+
"ERR_INVALID_ARG_VALUE: checkHostname: false needs rejectUnauthorized"
|
|
17452
|
+
);
|
|
17453
|
+
}
|
|
17454
|
+
const { engine, store, own } = await setUp(support, req);
|
|
17455
|
+
const options = {
|
|
17456
|
+
engine,
|
|
17457
|
+
store,
|
|
17458
|
+
servername,
|
|
17459
|
+
alpn: req.alpn ?? [],
|
|
17460
|
+
insecure: req.insecure === true,
|
|
17461
|
+
...req.sni === false ? { sni: false } : {},
|
|
17462
|
+
...req.checkHostname === false ? { checkHostname: false } : {},
|
|
17463
|
+
clientCertificate: cert !== void 0
|
|
17464
|
+
};
|
|
17465
|
+
let session;
|
|
17466
|
+
try {
|
|
17467
|
+
const controls2 = req.sni === false || req.checkHostname === false || cert !== void 0;
|
|
17468
|
+
if (controls2 && !engine.sessionControls) {
|
|
17469
|
+
throw new KernelError("ENOTSUP", "the installed tls engine has no client certificates");
|
|
17470
|
+
}
|
|
17471
|
+
session = openSession(options);
|
|
17472
|
+
withCert(session, cert);
|
|
17473
|
+
return { options: { ...options, session }, own };
|
|
17474
|
+
} catch (err) {
|
|
17475
|
+
session?.free();
|
|
17476
|
+
own?.release();
|
|
17477
|
+
throw err;
|
|
17478
|
+
}
|
|
17479
|
+
}
|
|
17480
|
+
function secure(prepared) {
|
|
17481
|
+
let ran = false;
|
|
17482
|
+
const make = async (raw) => {
|
|
17483
|
+
ran = true;
|
|
17261
17484
|
try {
|
|
17262
|
-
return await tlsClient(raw,
|
|
17263
|
-
engine,
|
|
17264
|
-
store,
|
|
17265
|
-
servername,
|
|
17266
|
-
alpn: req.alpn ?? [],
|
|
17267
|
-
insecure: req.insecure === true
|
|
17268
|
-
});
|
|
17485
|
+
return await tlsClient(raw, prepared.options);
|
|
17269
17486
|
} finally {
|
|
17270
|
-
own?.release();
|
|
17487
|
+
prepared.own?.release();
|
|
17271
17488
|
}
|
|
17272
17489
|
};
|
|
17490
|
+
const abandon = () => {
|
|
17491
|
+
if (ran) return;
|
|
17492
|
+
prepared.options.session.free();
|
|
17493
|
+
prepared.own?.release();
|
|
17494
|
+
};
|
|
17495
|
+
return { make, abandon };
|
|
17273
17496
|
}
|
|
17274
17497
|
function supportOf(net) {
|
|
17275
17498
|
const support = net.tlsClient;
|
|
@@ -17278,7 +17501,7 @@ function supportOf(net) {
|
|
|
17278
17501
|
}
|
|
17279
17502
|
async function uplinkAddress(proc, host) {
|
|
17280
17503
|
const bare = host.replace(/^\[|\]$/g, "");
|
|
17281
|
-
if (
|
|
17504
|
+
if (isIP2(bare)) return bare;
|
|
17282
17505
|
const [first] = await proc.resolve(host, 0, () => proc.blocking());
|
|
17283
17506
|
if (!first) throw new KernelError("ENOENT", `ENOTFOUND: ${host}`);
|
|
17284
17507
|
return first;
|
|
@@ -17292,18 +17515,26 @@ async function connectSecure(proc, socket, host, port, req) {
|
|
|
17292
17515
|
throw new KernelError("ENOTSUP", "TLS in the kernel needs a destination the uplink routes");
|
|
17293
17516
|
const support = supportOf(proc.net);
|
|
17294
17517
|
let info;
|
|
17295
|
-
const make = secure(support, req, servername);
|
|
17296
|
-
|
|
17297
|
-
|
|
17298
|
-
|
|
17518
|
+
const { make, abandon } = secure(await prepare(support, req, servername));
|
|
17519
|
+
try {
|
|
17520
|
+
await socket.connectSecure({ family: "inet", host: address, port }, route, async (conn) => {
|
|
17521
|
+
info = await conn.upgrade(make);
|
|
17522
|
+
});
|
|
17523
|
+
} finally {
|
|
17524
|
+
abandon();
|
|
17525
|
+
}
|
|
17299
17526
|
return sessionOf(info, servername);
|
|
17300
17527
|
}
|
|
17301
17528
|
async function upgradeSecure(proc, socket, req) {
|
|
17302
17529
|
const peer = socket.peer;
|
|
17303
17530
|
const host = req.servername || (peer?.family === "inet" ? peer.host : "");
|
|
17304
17531
|
const servername = serverName(host);
|
|
17305
|
-
const
|
|
17306
|
-
|
|
17532
|
+
const { make, abandon } = secure(await prepare(supportOf(proc.net), req, servername));
|
|
17533
|
+
try {
|
|
17534
|
+
return sessionOf(await socket.upgradeSecure(make), servername);
|
|
17535
|
+
} finally {
|
|
17536
|
+
abandon();
|
|
17537
|
+
}
|
|
17307
17538
|
}
|
|
17308
17539
|
|
|
17309
17540
|
// src/kernel/unix-dgram.ts
|
|
@@ -17665,17 +17896,23 @@ var NOT_HTTP_PORTS = /* @__PURE__ */ new Set([
|
|
|
17665
17896
|
8883
|
|
17666
17897
|
]);
|
|
17667
17898
|
var HOST_NAME = /^[A-Za-z0-9.-]+$|^\[?[0-9A-Fa-f:.]+\]?$/;
|
|
17899
|
+
function sessionControls(req) {
|
|
17900
|
+
return req.sni === false || req.checkHostname === false || req.clientCert !== void 0;
|
|
17901
|
+
}
|
|
17668
17902
|
function wantsKernel(req) {
|
|
17669
17903
|
if (req.path === "kernel") return true;
|
|
17670
17904
|
if (req.path === "transport") return false;
|
|
17671
|
-
return Array.isArray(req.ca) || req.alpn !== void 0 && req.alpn.length > 0 && !req.alpn.includes("http/1.1") || NOT_HTTP_PORTS.has(req.port);
|
|
17905
|
+
return Array.isArray(req.ca) || sessionControls(req) || req.alpn !== void 0 && req.alpn.length > 0 && !req.alpn.includes("http/1.1") || NOT_HTTP_PORTS.has(req.port);
|
|
17672
17906
|
}
|
|
17673
17907
|
async function secureConnect(req, proc) {
|
|
17674
17908
|
if (!Number.isInteger(req.port) || req.port < 1 || req.port > 65535)
|
|
17675
17909
|
throw new KernelError("EINVAL");
|
|
17676
17910
|
const kernelPath = wantsKernel(req) && await uplinked(proc, req.host);
|
|
17677
17911
|
if (!kernelPath) {
|
|
17678
|
-
if (req.path === "kernel" || Array.isArray(req.ca)
|
|
17912
|
+
if (req.path === "kernel" || Array.isArray(req.ca) || sessionControls(req)) {
|
|
17913
|
+
delete req.clientCert;
|
|
17914
|
+
throw new KernelError("ENOTSUP");
|
|
17915
|
+
}
|
|
17679
17916
|
return { ...tlsOverTransport(req, proc), path: "transport", substitutes: true };
|
|
17680
17917
|
}
|
|
17681
17918
|
const socket = proc.net.socket("inet");
|
|
@@ -17809,13 +18046,17 @@ var VfsNode = class {
|
|
|
17809
18046
|
const ranged2 = await this.prepare();
|
|
17810
18047
|
await ranged2?.pin();
|
|
17811
18048
|
}
|
|
18049
|
+
moving = /* @__PURE__ */ new Set();
|
|
17812
18050
|
async load() {
|
|
17813
18051
|
if (this.revoked) throw new KernelError("EIO");
|
|
17814
|
-
|
|
18052
|
+
while (!this.data) {
|
|
18053
|
+
const at = this.path;
|
|
17815
18054
|
try {
|
|
17816
|
-
this.data = await this.fs.readFileBuffer(
|
|
18055
|
+
this.data = await this.fs.readFileBuffer(at);
|
|
17817
18056
|
} catch (err) {
|
|
17818
18057
|
if (!isMissing(err)) throw err;
|
|
18058
|
+
while (this.moving.size > 0) await Promise.all(this.moving);
|
|
18059
|
+
if (this.path !== at) continue;
|
|
17819
18060
|
this.data = new Uint8Array(0);
|
|
17820
18061
|
this.missing = true;
|
|
17821
18062
|
}
|
|
@@ -18169,6 +18410,16 @@ var VfsNodes = class {
|
|
|
18169
18410
|
this.byPath.set(file.hidden, node);
|
|
18170
18411
|
this.kept.set(node, file);
|
|
18171
18412
|
}
|
|
18413
|
+
moving(path) {
|
|
18414
|
+
const node = this.byPath.get(path);
|
|
18415
|
+
if (!node) return () => void 0;
|
|
18416
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
18417
|
+
node.moving.add(promise);
|
|
18418
|
+
return () => {
|
|
18419
|
+
node.moving.delete(promise);
|
|
18420
|
+
resolve2();
|
|
18421
|
+
};
|
|
18422
|
+
}
|
|
18172
18423
|
unkeep(path, file) {
|
|
18173
18424
|
const node = this.byPath.get(file.hidden);
|
|
18174
18425
|
if (!node) return;
|
|
@@ -21456,7 +21707,7 @@ function register(automaton, sources, ids, bytes, source) {
|
|
|
21456
21707
|
}
|
|
21457
21708
|
sources[id2].push(source);
|
|
21458
21709
|
}
|
|
21459
|
-
function
|
|
21710
|
+
function prepare2(secrets) {
|
|
21460
21711
|
const main = new Automaton();
|
|
21461
21712
|
const wrap = new Automaton();
|
|
21462
21713
|
const sources = [];
|
|
@@ -21607,7 +21858,7 @@ function merge(into, from) {
|
|
|
21607
21858
|
}
|
|
21608
21859
|
}
|
|
21609
21860
|
function compile(secrets, options = {}) {
|
|
21610
|
-
const c =
|
|
21861
|
+
const c = prepare2(secrets.map((secret) => ({ ...secret })));
|
|
21611
21862
|
const decoder4 = new TextDecoder();
|
|
21612
21863
|
const idleMs = options.idleMs ?? 250;
|
|
21613
21864
|
const scrubBytes = (input) => {
|