@ai-ecoverse/slicc-kernel 1.123.1 → 1.124.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/README.md +29 -6
- package/dist/kernel-worker.js +680 -85
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +88 -18
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +710 -115
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +88 -18
- package/dist/process-worker.js.map +3 -3
- package/dist/types/kernel/fd-table.d.ts +1 -1
- package/dist/types/kernel/host-ops.d.ts +1 -0
- package/dist/types/kernel/lock-service.d.ts +4 -0
- package/dist/types/kernel/locks.d.ts +3 -0
- package/dist/types/kernel/net/network.d.ts +2 -0
- package/dist/types/kernel/net/switch-conn.d.ts +28 -0
- package/dist/types/kernel/net/tls-client.d.ts +22 -0
- package/dist/types/kernel/net/tls-engine.d.ts +27 -0
- package/dist/types/kernel/net/tls-uplink.d.ts +35 -0
- package/dist/types/kernel/socket-syscalls.d.ts +10 -1
- package/dist/types/kernel/socket.d.ts +13 -1
- package/dist/types/process/js/js-net.d.ts +10 -4
- package/package.json +4 -4
package/dist/kernel-worker.js
CHANGED
|
@@ -2372,6 +2372,7 @@ var OpfsFs = class {
|
|
|
2372
2372
|
}));
|
|
2373
2373
|
}
|
|
2374
2374
|
async reconcile() {
|
|
2375
|
+
if (this.remote && await this.remote.peered()) return 0;
|
|
2375
2376
|
let removed = 0;
|
|
2376
2377
|
const entries = await this.meta.all();
|
|
2377
2378
|
const carried = new Set(entries.filter((e) => !e.vacated).map((e) => e.ino));
|
|
@@ -2380,7 +2381,11 @@ var OpfsFs = class {
|
|
|
2380
2381
|
const real = await this.real(entry.path);
|
|
2381
2382
|
const stale = entry.link === void 0 ? !real : real || !await this.real(parentOf3(entry.path));
|
|
2382
2383
|
if (!stale) continue;
|
|
2383
|
-
|
|
2384
|
+
const seen = JSON.stringify(entry);
|
|
2385
|
+
await this.meta.update(
|
|
2386
|
+
entry.path,
|
|
2387
|
+
(now) => now === void 0 || JSON.stringify(now) === seen ? void 0 : now
|
|
2388
|
+
);
|
|
2384
2389
|
removed++;
|
|
2385
2390
|
}
|
|
2386
2391
|
return removed;
|
|
@@ -4437,6 +4442,111 @@ var Routes = class {
|
|
|
4437
4442
|
}
|
|
4438
4443
|
};
|
|
4439
4444
|
|
|
4445
|
+
// src/kernel/net/switch-conn.ts
|
|
4446
|
+
var SwitchConn = class {
|
|
4447
|
+
raw;
|
|
4448
|
+
box = [];
|
|
4449
|
+
pulling = false;
|
|
4450
|
+
waiters = [];
|
|
4451
|
+
switching = false;
|
|
4452
|
+
secure;
|
|
4453
|
+
failed;
|
|
4454
|
+
constructor(raw) {
|
|
4455
|
+
this.raw = raw;
|
|
4456
|
+
}
|
|
4457
|
+
get localAddr() {
|
|
4458
|
+
return this.raw.localAddr;
|
|
4459
|
+
}
|
|
4460
|
+
get remoteAddr() {
|
|
4461
|
+
return this.raw.remoteAddr;
|
|
4462
|
+
}
|
|
4463
|
+
get upgraded() {
|
|
4464
|
+
return this.switching || this.secure !== void 0;
|
|
4465
|
+
}
|
|
4466
|
+
wake() {
|
|
4467
|
+
for (const wake of this.waiters.splice(0)) wake();
|
|
4468
|
+
}
|
|
4469
|
+
changed() {
|
|
4470
|
+
return new Promise((resolve2) => this.waiters.push(resolve2));
|
|
4471
|
+
}
|
|
4472
|
+
pull() {
|
|
4473
|
+
if (this.pulling || this.box.length > 0) return;
|
|
4474
|
+
this.pulling = true;
|
|
4475
|
+
this.raw.read().then(
|
|
4476
|
+
(bytes) => this.box.push(bytes),
|
|
4477
|
+
(err) => this.box.push(err instanceof Error ? err : new Error(String(err)))
|
|
4478
|
+
).finally(() => {
|
|
4479
|
+
this.pulling = false;
|
|
4480
|
+
this.wake();
|
|
4481
|
+
});
|
|
4482
|
+
}
|
|
4483
|
+
take() {
|
|
4484
|
+
const next3 = this.box.shift();
|
|
4485
|
+
if (next3 instanceof Error) throw next3;
|
|
4486
|
+
return next3;
|
|
4487
|
+
}
|
|
4488
|
+
async rawRead() {
|
|
4489
|
+
while (this.box.length === 0) {
|
|
4490
|
+
this.pull();
|
|
4491
|
+
await this.changed();
|
|
4492
|
+
}
|
|
4493
|
+
return this.take();
|
|
4494
|
+
}
|
|
4495
|
+
async read() {
|
|
4496
|
+
for (; ; ) {
|
|
4497
|
+
if (this.failed) throw this.failed;
|
|
4498
|
+
if (this.secure) return this.secure.read();
|
|
4499
|
+
if (!this.switching && this.box.length > 0) return this.take();
|
|
4500
|
+
if (!this.switching) this.pull();
|
|
4501
|
+
await this.changed();
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
async settled() {
|
|
4505
|
+
while (this.switching) await this.changed();
|
|
4506
|
+
if (this.failed) throw this.failed;
|
|
4507
|
+
return this.secure ?? this.raw;
|
|
4508
|
+
}
|
|
4509
|
+
async write(bytes) {
|
|
4510
|
+
return (await this.settled()).write(bytes);
|
|
4511
|
+
}
|
|
4512
|
+
closeWrite() {
|
|
4513
|
+
void this.settled().then(
|
|
4514
|
+
(conn) => conn.closeWrite(),
|
|
4515
|
+
() => void 0
|
|
4516
|
+
);
|
|
4517
|
+
}
|
|
4518
|
+
close() {
|
|
4519
|
+
this.failed ??= new Error("closed");
|
|
4520
|
+
this.secure?.close();
|
|
4521
|
+
this.raw.close();
|
|
4522
|
+
this.wake();
|
|
4523
|
+
}
|
|
4524
|
+
async upgrade(make) {
|
|
4525
|
+
if (this.upgraded) throw new Error("already upgraded");
|
|
4526
|
+
this.switching = true;
|
|
4527
|
+
this.wake();
|
|
4528
|
+
const view2 = {
|
|
4529
|
+
localAddr: this.raw.localAddr,
|
|
4530
|
+
remoteAddr: this.raw.remoteAddr,
|
|
4531
|
+
read: () => this.rawRead(),
|
|
4532
|
+
write: (bytes) => this.raw.write(bytes),
|
|
4533
|
+
closeWrite: () => this.raw.closeWrite(),
|
|
4534
|
+
close: () => this.raw.close()
|
|
4535
|
+
};
|
|
4536
|
+
try {
|
|
4537
|
+
const { conn, info } = await make(view2);
|
|
4538
|
+
this.secure = conn;
|
|
4539
|
+
return info;
|
|
4540
|
+
} catch (err) {
|
|
4541
|
+
this.failed = err instanceof Error ? err : new Error(String(err));
|
|
4542
|
+
throw err;
|
|
4543
|
+
} finally {
|
|
4544
|
+
this.switching = false;
|
|
4545
|
+
this.wake();
|
|
4546
|
+
}
|
|
4547
|
+
}
|
|
4548
|
+
};
|
|
4549
|
+
|
|
4440
4550
|
// src/kernel/net/uplink-socket.ts
|
|
4441
4551
|
var CHUNK = 64 * 1024;
|
|
4442
4552
|
function hostPort(text) {
|
|
@@ -4761,7 +4871,18 @@ var KernelSocket = class _KernelSocket {
|
|
|
4761
4871
|
clearTimeout(timer);
|
|
4762
4872
|
}
|
|
4763
4873
|
}
|
|
4764
|
-
|
|
4874
|
+
switch;
|
|
4875
|
+
connectSecure(addr, route, secure2) {
|
|
4876
|
+
if (this.state !== "open") throw new KernelError("EISCONN");
|
|
4877
|
+
return this.dial(addr, route, secure2);
|
|
4878
|
+
}
|
|
4879
|
+
upgradeSecure(make) {
|
|
4880
|
+
if (this.state !== "connected") throw new KernelError("ENOTCONN");
|
|
4881
|
+
if (!this.switch) throw new KernelError("EOPNOTSUPP");
|
|
4882
|
+
if (this.switch.upgraded || this.writeShut || this.readShut) throw new KernelError("EINVAL");
|
|
4883
|
+
return this.switch.upgrade(make);
|
|
4884
|
+
}
|
|
4885
|
+
dial(addr, route, secure2) {
|
|
4765
4886
|
this.state = "connecting";
|
|
4766
4887
|
const abort = new AbortController();
|
|
4767
4888
|
this.dialing = abort;
|
|
@@ -4782,11 +4903,25 @@ var KernelSocket = class _KernelSocket {
|
|
|
4782
4903
|
() => void 0
|
|
4783
4904
|
);
|
|
4784
4905
|
return Promise.race([dialled, abandoned]).then(
|
|
4785
|
-
(
|
|
4906
|
+
async (raw) => {
|
|
4786
4907
|
if (abort.signal.aborted) throw dialError(abort.signal.reason, timedOut, true);
|
|
4908
|
+
const conn = new SwitchConn(raw);
|
|
4909
|
+
if (secure2) {
|
|
4910
|
+
clearTimeout(timer);
|
|
4911
|
+
try {
|
|
4912
|
+
await Promise.race([secure2(conn), abandoned]);
|
|
4913
|
+
} catch (e) {
|
|
4914
|
+
conn.close();
|
|
4915
|
+
throw this.dialFailed(
|
|
4916
|
+
abort,
|
|
4917
|
+
e instanceof KernelError ? e : new KernelError("ENOTSUP", e instanceof Error ? e.message : String(e))
|
|
4918
|
+
);
|
|
4919
|
+
}
|
|
4920
|
+
}
|
|
4787
4921
|
this.local = { family: "inet", host: "0.0.0.0", port: 0, ...hostPort(conn.localAddr) };
|
|
4788
4922
|
this.peer = { ...addr, ...hostPort(conn.remoteAddr) };
|
|
4789
4923
|
this.dialing = void 0;
|
|
4924
|
+
this.switch = conn;
|
|
4790
4925
|
this.attach(
|
|
4791
4926
|
uplinkLink(conn, () => {
|
|
4792
4927
|
this.reset = true;
|
|
@@ -4795,17 +4930,19 @@ var KernelSocket = class _KernelSocket {
|
|
|
4795
4930
|
);
|
|
4796
4931
|
},
|
|
4797
4932
|
(e) => {
|
|
4798
|
-
|
|
4799
|
-
if (this.dialing === abort) {
|
|
4800
|
-
this.dialing = void 0;
|
|
4801
|
-
this.failed = error.code;
|
|
4802
|
-
this.state = "open";
|
|
4803
|
-
this.changes.wake();
|
|
4804
|
-
}
|
|
4805
|
-
throw error;
|
|
4933
|
+
throw this.dialFailed(abort, dialError(e, timedOut, abort.signal.aborted));
|
|
4806
4934
|
}
|
|
4807
4935
|
).finally(() => clearTimeout(timer));
|
|
4808
4936
|
}
|
|
4937
|
+
dialFailed(abort, error) {
|
|
4938
|
+
if (this.dialing === abort) {
|
|
4939
|
+
this.dialing = void 0;
|
|
4940
|
+
this.failed = error.code;
|
|
4941
|
+
this.state = "open";
|
|
4942
|
+
this.changes.wake();
|
|
4943
|
+
}
|
|
4944
|
+
return error;
|
|
4945
|
+
}
|
|
4809
4946
|
unlink() {
|
|
4810
4947
|
const link2 = this.link;
|
|
4811
4948
|
if (link2) {
|
|
@@ -4911,6 +5048,7 @@ var LoopbackNet = class {
|
|
|
4911
5048
|
useUplink(route) {
|
|
4912
5049
|
this.route = route;
|
|
4913
5050
|
}
|
|
5051
|
+
tlsClient;
|
|
4914
5052
|
uplinkFor(host) {
|
|
4915
5053
|
const route = this.route;
|
|
4916
5054
|
if (!route) return void 0;
|
|
@@ -5052,12 +5190,12 @@ function serveSocket(socket, port, onClose) {
|
|
|
5052
5190
|
let writes = Promise.resolve();
|
|
5053
5191
|
let credit = 0;
|
|
5054
5192
|
let granted2;
|
|
5055
|
-
const
|
|
5193
|
+
const send2 = (message3, transfer) => {
|
|
5056
5194
|
if (!closed) port.postMessage(message3, transfer);
|
|
5057
5195
|
};
|
|
5058
5196
|
const close = (reset = false) => {
|
|
5059
5197
|
if (closed) return;
|
|
5060
|
-
if (reset)
|
|
5198
|
+
if (reset) send2({ error: "ECONNRESET" });
|
|
5061
5199
|
closed = true;
|
|
5062
5200
|
granted2?.();
|
|
5063
5201
|
socket.close();
|
|
@@ -5069,9 +5207,9 @@ function serveSocket(socket, port, onClose) {
|
|
|
5069
5207
|
if (closed) return;
|
|
5070
5208
|
try {
|
|
5071
5209
|
await socket.write(data);
|
|
5072
|
-
|
|
5210
|
+
send2({ ack: true });
|
|
5073
5211
|
} catch (err) {
|
|
5074
|
-
|
|
5212
|
+
send2({ error: codeOf(err) });
|
|
5075
5213
|
}
|
|
5076
5214
|
});
|
|
5077
5215
|
};
|
|
@@ -5096,11 +5234,11 @@ function serveSocket(socket, port, onClose) {
|
|
|
5096
5234
|
const chunk2 = await socket.read(CHUNK2);
|
|
5097
5235
|
if (chunk2.length === 0) break;
|
|
5098
5236
|
credit--;
|
|
5099
|
-
|
|
5237
|
+
send2(chunk2, [chunk2.buffer]);
|
|
5100
5238
|
}
|
|
5101
|
-
|
|
5239
|
+
send2({ end: true });
|
|
5102
5240
|
} catch (err) {
|
|
5103
|
-
|
|
5241
|
+
send2({ error: codeOf(err) });
|
|
5104
5242
|
}
|
|
5105
5243
|
})();
|
|
5106
5244
|
return () => close(true);
|
|
@@ -6013,7 +6151,7 @@ function joinable(l, pgid, ours) {
|
|
|
6013
6151
|
if (sid === void 0) throw fsError("ESRCH", `no process group ${pgid}`);
|
|
6014
6152
|
if (!ours(sid)) throw fsError("EPERM", `process group ${pgid} is in another session`);
|
|
6015
6153
|
}
|
|
6016
|
-
function cdpRegistry(
|
|
6154
|
+
function cdpRegistry(send2, gone) {
|
|
6017
6155
|
const registered = /* @__PURE__ */ new Map();
|
|
6018
6156
|
const drop = (id2) => {
|
|
6019
6157
|
registered.get(id2)?.();
|
|
@@ -6022,7 +6160,7 @@ function cdpRegistry(send, gone) {
|
|
|
6022
6160
|
return {
|
|
6023
6161
|
serve(l, req) {
|
|
6024
6162
|
const hook = portCdpHook(
|
|
6025
|
-
(request2, cdp) =>
|
|
6163
|
+
(request2, cdp) => send2({ cdpOpen: { ...request2, registration: req.id }, port: cdp }, [
|
|
6026
6164
|
cdp
|
|
6027
6165
|
]),
|
|
6028
6166
|
gone
|
|
@@ -6036,7 +6174,7 @@ function cdpRegistry(send, gone) {
|
|
|
6036
6174
|
}
|
|
6037
6175
|
};
|
|
6038
6176
|
}
|
|
6039
|
-
function facadeRegistry(
|
|
6177
|
+
function facadeRegistry(send2, gone) {
|
|
6040
6178
|
const registered = /* @__PURE__ */ new Map();
|
|
6041
6179
|
const drop = (id2) => {
|
|
6042
6180
|
registered.get(id2)?.();
|
|
@@ -6045,7 +6183,7 @@ function facadeRegistry(send, gone) {
|
|
|
6045
6183
|
return {
|
|
6046
6184
|
serve(l, req) {
|
|
6047
6185
|
const hook = portFacadeHook(
|
|
6048
|
-
(request2, facade) =>
|
|
6186
|
+
(request2, facade) => send2({ facadeOpen: { ...request2, registration: req.id }, port: facade }, [
|
|
6049
6187
|
facade
|
|
6050
6188
|
]),
|
|
6051
6189
|
gone
|
|
@@ -6059,9 +6197,9 @@ function facadeRegistry(send, gone) {
|
|
|
6059
6197
|
}
|
|
6060
6198
|
};
|
|
6061
6199
|
}
|
|
6062
|
-
function hostRegistries(
|
|
6063
|
-
const cdps = cdpRegistry(
|
|
6064
|
-
const facades = facadeRegistry(
|
|
6200
|
+
function hostRegistries(send2, gone) {
|
|
6201
|
+
const cdps = cdpRegistry(send2, gone);
|
|
6202
|
+
const facades = facadeRegistry(send2, gone);
|
|
6065
6203
|
return {
|
|
6066
6204
|
answer(l, req) {
|
|
6067
6205
|
if (req.op === "serve-cdp") return cdps.serve(l, req);
|
|
@@ -6088,21 +6226,21 @@ function visibleTo(g, notify) {
|
|
|
6088
6226
|
});
|
|
6089
6227
|
};
|
|
6090
6228
|
}
|
|
6091
|
-
async function watchOp(l, req, watches,
|
|
6229
|
+
async function watchOp(l, req, watches, send2, g) {
|
|
6092
6230
|
if (req.op === "unwatch") {
|
|
6093
6231
|
watches.get(req.watch)?.();
|
|
6094
6232
|
watches.delete(req.watch);
|
|
6095
6233
|
return { result: true };
|
|
6096
6234
|
}
|
|
6097
6235
|
if (g) for (const path of req.paths) await readable(g, "watch", l.fs.resolvePath("/", path));
|
|
6098
|
-
const notify = visibleTo(g, (change) =>
|
|
6236
|
+
const notify = visibleTo(g, (change) => send2({ watch: req.id, change }));
|
|
6099
6237
|
const unwatch = l.watchers.watch(req.paths, { recursive: req.recursive }, notify);
|
|
6100
6238
|
watches.set(req.id, unwatch);
|
|
6101
6239
|
return { result: req.id };
|
|
6102
6240
|
}
|
|
6103
6241
|
var TRAITS_WATCH = -1;
|
|
6104
|
-
function traitsWatch(launcher, transport,
|
|
6105
|
-
return launcher.onTraits(() =>
|
|
6242
|
+
function traitsWatch(launcher, transport, send2) {
|
|
6243
|
+
return launcher.onTraits(() => send2({ traits: transport.traits }));
|
|
6106
6244
|
}
|
|
6107
6245
|
function serveClient(port, host) {
|
|
6108
6246
|
let state = "new";
|
|
@@ -6114,14 +6252,14 @@ function serveClient(port, host) {
|
|
|
6114
6252
|
const watches = /* @__PURE__ */ new Map();
|
|
6115
6253
|
let net;
|
|
6116
6254
|
const ended = Promise.withResolvers();
|
|
6117
|
-
const
|
|
6255
|
+
const send2 = (message3, transfer = []) => {
|
|
6118
6256
|
if (state !== "closed") port.postMessage(message3, transfer);
|
|
6119
6257
|
};
|
|
6120
|
-
const reply = (id2, body, transfer) =>
|
|
6121
|
-
const hosts = hostRegistries(
|
|
6258
|
+
const reply = (id2, body, transfer) => send2({ id: id2, ...body }, transfer);
|
|
6259
|
+
const hosts = hostRegistries(send2, ended.promise);
|
|
6122
6260
|
function detach(kill = false, bye = "the slicc-kernel detached this client") {
|
|
6123
6261
|
if (state === "closed") return;
|
|
6124
|
-
|
|
6262
|
+
send2({ bye });
|
|
6125
6263
|
state = "closed";
|
|
6126
6264
|
net?.close();
|
|
6127
6265
|
for (const unwatch of watches.values()) unwatch();
|
|
@@ -6135,19 +6273,19 @@ function serveClient(port, host) {
|
|
|
6135
6273
|
ended.resolve();
|
|
6136
6274
|
}
|
|
6137
6275
|
async function hello(message3) {
|
|
6138
|
-
const
|
|
6139
|
-
if (
|
|
6140
|
-
|
|
6276
|
+
const refused3 = versionError(message3.protocol);
|
|
6277
|
+
if (refused3) {
|
|
6278
|
+
send2({ hello: { protocol: PROTOCOL, error: refused3 } });
|
|
6141
6279
|
detach();
|
|
6142
6280
|
return;
|
|
6143
6281
|
}
|
|
6144
6282
|
const launcher = await host.launcher();
|
|
6145
6283
|
if (host.scope !== "transport") self = await accountOf(launcher, host.user ?? 0);
|
|
6146
6284
|
const transport = host.transport?.() ?? launcher.transport;
|
|
6147
|
-
net = serveTransport({ postMessage: (m, t) =>
|
|
6285
|
+
net = serveTransport({ postMessage: (m, t) => send2(m, t) }, transport);
|
|
6148
6286
|
state = "open";
|
|
6149
6287
|
if (message3.lock && host.locks) void host.locks.request(message3.lock, () => detach());
|
|
6150
|
-
|
|
6288
|
+
send2({
|
|
6151
6289
|
hello: {
|
|
6152
6290
|
protocol: PROTOCOL,
|
|
6153
6291
|
traits: transport.traits,
|
|
@@ -6155,7 +6293,7 @@ function serveClient(port, host) {
|
|
|
6155
6293
|
...host.lock ? { lock: host.lock } : {}
|
|
6156
6294
|
}
|
|
6157
6295
|
});
|
|
6158
|
-
watches.set(TRAITS_WATCH, traitsWatch(launcher, transport,
|
|
6296
|
+
watches.set(TRAITS_WATCH, traitsWatch(launcher, transport, send2));
|
|
6159
6297
|
}
|
|
6160
6298
|
async function terminal(req, l) {
|
|
6161
6299
|
const session = await l.openTerminal(req.argv, {
|
|
@@ -6219,7 +6357,7 @@ function serveClient(port, host) {
|
|
|
6219
6357
|
return clientFs(l, host.tag, self, req);
|
|
6220
6358
|
case "watch":
|
|
6221
6359
|
case "unwatch":
|
|
6222
|
-
return watchOp(l, req, watches,
|
|
6360
|
+
return watchOp(l, req, watches, send2, guard2(l));
|
|
6223
6361
|
case "mount":
|
|
6224
6362
|
return { result: await l.mountAs(clientCred(self), req.spec) };
|
|
6225
6363
|
case "umount":
|
|
@@ -6245,7 +6383,7 @@ function serveClient(port, host) {
|
|
|
6245
6383
|
if (data.hello) {
|
|
6246
6384
|
if (state === "new") {
|
|
6247
6385
|
hello(data.hello).catch((err) => {
|
|
6248
|
-
|
|
6386
|
+
send2({ hello: { protocol: PROTOCOL, error: String(err?.message ?? err) } });
|
|
6249
6387
|
detach();
|
|
6250
6388
|
});
|
|
6251
6389
|
}
|
|
@@ -6427,7 +6565,7 @@ function satisfies(version, range2) {
|
|
|
6427
6565
|
}
|
|
6428
6566
|
|
|
6429
6567
|
// src/version.ts
|
|
6430
|
-
var KERNEL_VERSION = true ? "1.
|
|
6568
|
+
var KERNEL_VERSION = true ? "1.124.0" : "0.0.0-dev";
|
|
6431
6569
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6432
6570
|
function procVersion() {
|
|
6433
6571
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -6709,13 +6847,13 @@ async function tierPackages(fs, physical, roots, bins, kernel) {
|
|
|
6709
6847
|
const own = commandsOf(pkg, manifest);
|
|
6710
6848
|
const named = new Set(own.map((command) => command.name));
|
|
6711
6849
|
const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
|
|
6712
|
-
const
|
|
6850
|
+
const refused3 = engineRefusal(manifest, kernel);
|
|
6713
6851
|
const commands = [...own, ...extra];
|
|
6714
6852
|
out.push({
|
|
6715
6853
|
name: pkg.slice(root.length + 1),
|
|
6716
6854
|
pkg,
|
|
6717
6855
|
replaces: replacesOf(manifest),
|
|
6718
|
-
commands:
|
|
6856
|
+
commands: refused3 ? commands.map((command) => ({ ...command, refused: refused3 })) : commands
|
|
6719
6857
|
});
|
|
6720
6858
|
}
|
|
6721
6859
|
}
|
|
@@ -8300,8 +8438,8 @@ var RealmProxy = class {
|
|
|
8300
8438
|
}
|
|
8301
8439
|
async connect(conn, incoming, req, idle) {
|
|
8302
8440
|
const target = tunnelTarget(req);
|
|
8303
|
-
const
|
|
8304
|
-
if (
|
|
8441
|
+
const refused3 = target.port === 443 ? await this.tunnelReady(target) : void 0;
|
|
8442
|
+
if (refused3) throw refused3;
|
|
8305
8443
|
await conn.write(latin1Bytes("HTTP/1.1 200 Connection Established\r\n\r\n"), this.stop.signal);
|
|
8306
8444
|
try {
|
|
8307
8445
|
const first = await incoming.peek(this.stop.signal);
|
|
@@ -9955,8 +10093,8 @@ var DriverConnection = class _DriverConnection {
|
|
|
9955
10093
|
} finally {
|
|
9956
10094
|
clearTimeout(timer);
|
|
9957
10095
|
}
|
|
9958
|
-
const
|
|
9959
|
-
if (
|
|
10096
|
+
const refused3 = driverVersionError(hello.protocol);
|
|
10097
|
+
if (refused3) throw errnoError("EPROTO", refused3);
|
|
9960
10098
|
if (hello.error) throw errnoError(hello.errno ?? "EIO", hello.error);
|
|
9961
10099
|
return new _DriverConnection(port, hello.capabilities ?? {}, waiting, timeoutMs, options);
|
|
9962
10100
|
}
|
|
@@ -11778,8 +11916,8 @@ async function guarded(entry, path, req) {
|
|
|
11778
11916
|
return { paths };
|
|
11779
11917
|
} catch (err) {
|
|
11780
11918
|
const refusal = err.code === "EACCES";
|
|
11781
|
-
const
|
|
11782
|
-
return { refused:
|
|
11919
|
+
const refused3 = req.op === "exists" && refusal ? json2(false) : toErrno(err);
|
|
11920
|
+
return { refused: refused3 };
|
|
11783
11921
|
}
|
|
11784
11922
|
}
|
|
11785
11923
|
async function createExclusive(fs, path, owner) {
|
|
@@ -11890,13 +12028,13 @@ async function dispatchSyncFs(req) {
|
|
|
11890
12028
|
}
|
|
11891
12029
|
}
|
|
11892
12030
|
var DENIED = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
|
|
11893
|
-
async function rmPermitted(entry, path, req,
|
|
12031
|
+
async function rmPermitted(entry, path, req, refused3) {
|
|
11894
12032
|
const st = await entry.fs.lstat(path).catch(() => void 0);
|
|
11895
|
-
if (!st?.isDirectory) return
|
|
12033
|
+
if (!st?.isDirectory) return refused3;
|
|
11896
12034
|
const unlisted = await guarded(entry, path, { ...req, op: "readdir" });
|
|
11897
12035
|
if ("refused" in unlisted) return unlisted.refused;
|
|
11898
12036
|
const names = await entry.fs.readdir(path).catch(() => void 0);
|
|
11899
|
-
if (!names) return
|
|
12037
|
+
if (!names) return refused3;
|
|
11900
12038
|
let first;
|
|
11901
12039
|
for (const name2 of names) {
|
|
11902
12040
|
const child = await dispatchOne(entry, {
|
|
@@ -11947,14 +12085,14 @@ async function newDevName(entry, path, req) {
|
|
|
11947
12085
|
const named = NAMING.has(req.op);
|
|
11948
12086
|
if (!named && !CREATIONS.has(req.op)) return void 0;
|
|
11949
12087
|
const target = named ? entry.fs.resolvePath(entry.cwd, req.arg2 ?? "") : path;
|
|
11950
|
-
const
|
|
11951
|
-
if (!
|
|
12088
|
+
const refused3 = devCreation(target, entry.cred?.());
|
|
12089
|
+
if (!refused3) return void 0;
|
|
11952
12090
|
const there = await entry.fs.lstat(target).then(
|
|
11953
12091
|
() => true,
|
|
11954
12092
|
() => false
|
|
11955
12093
|
);
|
|
11956
12094
|
if (there) return void 0;
|
|
11957
|
-
return { ok: false, errno:
|
|
12095
|
+
return { ok: false, errno: refused3, message: `${target}: no new names in /dev or /proc` };
|
|
11958
12096
|
}
|
|
11959
12097
|
async function dispatchOne(entry, req) {
|
|
11960
12098
|
const { fs, cwd } = entry;
|
|
@@ -13357,6 +13495,9 @@ var FlockTable = class {
|
|
|
13357
13495
|
held = /* @__PURE__ */ new Map();
|
|
13358
13496
|
keys = /* @__PURE__ */ new WeakMap();
|
|
13359
13497
|
wakers = /* @__PURE__ */ new Map();
|
|
13498
|
+
isFree(key, owner, kind) {
|
|
13499
|
+
return this.free(key, owner, kind);
|
|
13500
|
+
}
|
|
13360
13501
|
free(key, owner, kind) {
|
|
13361
13502
|
for (const [other, has] of this.held.get(key) ?? [])
|
|
13362
13503
|
if (other !== owner && (kind === "exclusive" || has === "exclusive")) return false;
|
|
@@ -13483,9 +13624,18 @@ var LockTable = class {
|
|
|
13483
13624
|
);
|
|
13484
13625
|
this.wake(key);
|
|
13485
13626
|
}
|
|
13627
|
+
wholeFree(pid, path, exclusive) {
|
|
13628
|
+
for (const [other, h] of this.held.get(path) ?? []) {
|
|
13629
|
+
if (other !== pid && (exclusive || h.exclusive)) return false;
|
|
13630
|
+
}
|
|
13631
|
+
return true;
|
|
13632
|
+
}
|
|
13633
|
+
flockFree(key, owner, kind) {
|
|
13634
|
+
return this.flocks.isFree(key, owner, kind);
|
|
13635
|
+
}
|
|
13486
13636
|
lock(pid, path, exclusive, fd) {
|
|
13637
|
+
if (!this.wholeFree(pid, path, exclusive)) return false;
|
|
13487
13638
|
const holders = this.held.get(path) ?? /* @__PURE__ */ new Map();
|
|
13488
|
-
for (const [other, h] of holders) if (other !== pid && (exclusive || h.exclusive)) return false;
|
|
13489
13639
|
const mine = holders.get(pid) ?? { exclusive, fds: /* @__PURE__ */ new Set() };
|
|
13490
13640
|
mine.exclusive = exclusive;
|
|
13491
13641
|
mine.fds.add(fd);
|
|
@@ -13670,12 +13820,12 @@ var AsyncOps = class {
|
|
|
13670
13820
|
async function hostSyscall(req, ctx) {
|
|
13671
13821
|
switch (req.op) {
|
|
13672
13822
|
case "lock":
|
|
13673
|
-
|
|
13674
|
-
if (!ctx.locks.lock(ctx.pid, req.path, req.exclusive, req.fd))
|
|
13675
|
-
throw new KernelError("EAGAIN");
|
|
13676
|
-
return done2;
|
|
13823
|
+
return wholeLock(req, ctx);
|
|
13677
13824
|
case "unlock":
|
|
13678
13825
|
ctx.locks?.unlock(ctx.pid, req.path);
|
|
13826
|
+
if (req.fd !== void 0 && ctx.locks?.shared?.() && ctx.flockOf) {
|
|
13827
|
+
return flock({ op: "flock", fd: req.fd, kind: "unlock" }, ctx);
|
|
13828
|
+
}
|
|
13679
13829
|
return done2;
|
|
13680
13830
|
case "lk-set":
|
|
13681
13831
|
case "lk-get":
|
|
@@ -13705,6 +13855,23 @@ async function hostSyscall(req, ctx) {
|
|
|
13705
13855
|
return done2;
|
|
13706
13856
|
}
|
|
13707
13857
|
}
|
|
13858
|
+
async function wholeLock(req, ctx) {
|
|
13859
|
+
const { locks, flockOf } = ctx;
|
|
13860
|
+
if (!locks) throw new KernelError("ENOSYS");
|
|
13861
|
+
const kind = req.exclusive ? "exclusive" : "shared";
|
|
13862
|
+
if (locks.shared?.() && flockOf) {
|
|
13863
|
+
if (locks.wholeFree?.(ctx.pid, req.path, req.exclusive) === false) {
|
|
13864
|
+
throw new KernelError("EAGAIN");
|
|
13865
|
+
}
|
|
13866
|
+
return flock({ op: "flock", fd: req.fd, kind }, ctx);
|
|
13867
|
+
}
|
|
13868
|
+
if (flockOf && locks.flockFree) {
|
|
13869
|
+
const { key, owner } = await flockOf(req.fd);
|
|
13870
|
+
if (!locks.flockFree(key, owner, kind)) throw new KernelError("EAGAIN");
|
|
13871
|
+
}
|
|
13872
|
+
if (!locks.lock(ctx.pid, req.path, req.exclusive, req.fd)) throw new KernelError("EAGAIN");
|
|
13873
|
+
return done2;
|
|
13874
|
+
}
|
|
13708
13875
|
var FLOCK_KINDS = /* @__PURE__ */ new Set(["shared", "exclusive", "unlock"]);
|
|
13709
13876
|
async function flock(req, ctx) {
|
|
13710
13877
|
const { locks, flockOf } = ctx;
|
|
@@ -13891,8 +14058,8 @@ var KernelLoopback = class {
|
|
|
13891
14058
|
);
|
|
13892
14059
|
} catch (err) {
|
|
13893
14060
|
socket.close();
|
|
13894
|
-
const
|
|
13895
|
-
throw
|
|
14061
|
+
const refused3 = err instanceof KernelError && err.code === "ECONNREFUSED";
|
|
14062
|
+
throw refused3 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
|
|
13896
14063
|
}
|
|
13897
14064
|
signal.addEventListener("abort", () => socket.close(), { once: true });
|
|
13898
14065
|
return socket;
|
|
@@ -14428,6 +14595,7 @@ function realmCa(owner, store) {
|
|
|
14428
14595
|
}
|
|
14429
14596
|
|
|
14430
14597
|
// src/kernel/net/tls-engine.ts
|
|
14598
|
+
var TLS_CLIENT_INSECURE_SKIP_VERIFY = 1;
|
|
14431
14599
|
var SCRATCH = 64 * 1024;
|
|
14432
14600
|
var EOF = -1;
|
|
14433
14601
|
var TlsError = class extends Error {
|
|
@@ -14488,6 +14656,76 @@ var TlsEngine = class {
|
|
|
14488
14656
|
const n = fn(this.scratch, SCRATCH);
|
|
14489
14657
|
return n > 0 ? this.taken(n) : n;
|
|
14490
14658
|
}
|
|
14659
|
+
get client() {
|
|
14660
|
+
return typeof this.m._tls_client_new === "function" ? this.m : void 0;
|
|
14661
|
+
}
|
|
14662
|
+
clientModule() {
|
|
14663
|
+
const m = this.client;
|
|
14664
|
+
if (!m) throw new TlsError(0, "tls client: the installed tls engine has no client sessions");
|
|
14665
|
+
return m;
|
|
14666
|
+
}
|
|
14667
|
+
store() {
|
|
14668
|
+
const m = this.clientModule();
|
|
14669
|
+
const ptr = m._tls_ca_new();
|
|
14670
|
+
if (!ptr) throw this.error(m._tls_last_error(), "trust store");
|
|
14671
|
+
return new TlsStore(this, m, ptr);
|
|
14672
|
+
}
|
|
14673
|
+
clientSession(store, servername, alpn, flags2) {
|
|
14674
|
+
const m = this.clientModule();
|
|
14675
|
+
const wire = alpnWire(alpn);
|
|
14676
|
+
const name2 = this.put(new TextEncoder().encode(servername));
|
|
14677
|
+
try {
|
|
14678
|
+
const at = store?.ptr ?? 0;
|
|
14679
|
+
const ptr = this.withBytes(wire, (p) => m._tls_client_new(at, name2, p, wire.length, flags2));
|
|
14680
|
+
if (!ptr) throw this.error(m._tls_last_error(), "tls client");
|
|
14681
|
+
return new TlsSession(this, m, ptr);
|
|
14682
|
+
} finally {
|
|
14683
|
+
this.m._free(name2);
|
|
14684
|
+
}
|
|
14685
|
+
}
|
|
14686
|
+
verifyInfo(flags2) {
|
|
14687
|
+
const m = this.clientModule();
|
|
14688
|
+
const n = m._tls_verify_info(flags2, this.scratch, SCRATCH);
|
|
14689
|
+
const end = this.m.HEAPU8.indexOf(0, this.scratch);
|
|
14690
|
+
const text = new TextDecoder().decode(this.m.HEAPU8.subarray(this.scratch, end));
|
|
14691
|
+
return n < 0 ? `${text}\u2026` : text;
|
|
14692
|
+
}
|
|
14693
|
+
};
|
|
14694
|
+
function alpnWire(names) {
|
|
14695
|
+
const parts2 = names.map((name2) => new TextEncoder().encode(name2));
|
|
14696
|
+
const out = new Uint8Array(parts2.reduce((n, p) => n + p.length + 1, 0));
|
|
14697
|
+
let at = 0;
|
|
14698
|
+
for (const part of parts2) {
|
|
14699
|
+
out[at++] = part.length;
|
|
14700
|
+
out.set(part, at);
|
|
14701
|
+
at += part.length;
|
|
14702
|
+
}
|
|
14703
|
+
return out;
|
|
14704
|
+
}
|
|
14705
|
+
var TlsStore = class {
|
|
14706
|
+
engine;
|
|
14707
|
+
m;
|
|
14708
|
+
ptr;
|
|
14709
|
+
constructor(engine, m, ptr) {
|
|
14710
|
+
this.engine = engine;
|
|
14711
|
+
this.m = m;
|
|
14712
|
+
this.ptr = ptr;
|
|
14713
|
+
}
|
|
14714
|
+
add(der) {
|
|
14715
|
+
const ret = this.engine.withBytes(der, (p) => this.m._tls_ca_add_der(this.ptr, p, der.length));
|
|
14716
|
+
if (ret !== 0) throw this.engine.error(ret, "trust store certificate");
|
|
14717
|
+
}
|
|
14718
|
+
addBundle(bytes) {
|
|
14719
|
+
const n = this.engine.withBytes(
|
|
14720
|
+
bytes,
|
|
14721
|
+
(p) => this.m._tls_ca_add_bundle(this.ptr, p, bytes.length)
|
|
14722
|
+
);
|
|
14723
|
+
if (n < 0) throw this.engine.error(n, "trust store bundle");
|
|
14724
|
+
return n;
|
|
14725
|
+
}
|
|
14726
|
+
release() {
|
|
14727
|
+
this.m._tls_ca_free(this.ptr);
|
|
14728
|
+
}
|
|
14491
14729
|
};
|
|
14492
14730
|
var TlsLeaf = class {
|
|
14493
14731
|
engine;
|
|
@@ -14552,6 +14790,33 @@ var TlsSession = class {
|
|
|
14552
14790
|
free() {
|
|
14553
14791
|
this.m._tls_session_free(this.ptr);
|
|
14554
14792
|
}
|
|
14793
|
+
get c() {
|
|
14794
|
+
return this.m;
|
|
14795
|
+
}
|
|
14796
|
+
handshake() {
|
|
14797
|
+
const ret = this.c._tls_handshake(this.ptr);
|
|
14798
|
+
if (ret < 0) throw this.engine.error(ret, "tls handshake");
|
|
14799
|
+
return ret === 1;
|
|
14800
|
+
}
|
|
14801
|
+
get verifyResult() {
|
|
14802
|
+
return this.c._tls_verify_result(this.ptr);
|
|
14803
|
+
}
|
|
14804
|
+
get version() {
|
|
14805
|
+
return this.c._tls_version(this.ptr);
|
|
14806
|
+
}
|
|
14807
|
+
get alpn() {
|
|
14808
|
+
const out = this.engine.intoScratch((p, max) => this.c._tls_alpn(this.ptr, p, max));
|
|
14809
|
+
return out instanceof Uint8Array ? new TextDecoder().decode(out) : void 0;
|
|
14810
|
+
}
|
|
14811
|
+
peerChain() {
|
|
14812
|
+
const chain2 = [];
|
|
14813
|
+
const count2 = this.c._tls_peer_count(this.ptr);
|
|
14814
|
+
for (let i = 0; i < count2; i++) {
|
|
14815
|
+
const der = this.engine.intoScratch((p, max) => this.c._tls_peer_der(this.ptr, i, p, max));
|
|
14816
|
+
if (der instanceof Uint8Array) chain2.push(der);
|
|
14817
|
+
}
|
|
14818
|
+
return chain2;
|
|
14819
|
+
}
|
|
14555
14820
|
};
|
|
14556
14821
|
var loading = /* @__PURE__ */ new WeakMap();
|
|
14557
14822
|
function loadTlsEngine(load) {
|
|
@@ -14764,6 +15029,16 @@ function packageTlsEngine(fs, modules) {
|
|
|
14764
15029
|
return factory.default({ wasmBinary, locateFile: (path) => path });
|
|
14765
15030
|
};
|
|
14766
15031
|
}
|
|
15032
|
+
function packageTlsRoots(fs, modules) {
|
|
15033
|
+
const file = `${modules.replace(/\/+$/, "")}/${TLS_ENGINE_PACKAGE}/dist/roots.der`;
|
|
15034
|
+
return async () => {
|
|
15035
|
+
try {
|
|
15036
|
+
return await fs.readFileBuffer(file);
|
|
15037
|
+
} catch {
|
|
15038
|
+
throw new Error(`TLS client sessions need ${TLS_ENGINE_PACKAGE}'s roots.der in ${modules}`);
|
|
15039
|
+
}
|
|
15040
|
+
};
|
|
15041
|
+
}
|
|
14767
15042
|
function kernelCa(store) {
|
|
14768
15043
|
return () => realmCa(CA_OWNER, store);
|
|
14769
15044
|
}
|
|
@@ -14795,6 +15070,7 @@ async function writeCaFile(fs, ca, locks = globalThis.navigator?.locks) {
|
|
|
14795
15070
|
function enableNetwork(net, options) {
|
|
14796
15071
|
let proxy;
|
|
14797
15072
|
const transport = options.transport ?? missingTransport();
|
|
15073
|
+
if (options.roots) net.tlsClient = { engine: options.engine, roots: options.roots };
|
|
14798
15074
|
const start2 = () => {
|
|
14799
15075
|
const tls = new TlsTerminator({
|
|
14800
15076
|
ca: options.ca,
|
|
@@ -16574,6 +16850,285 @@ function encodeReceived(got) {
|
|
|
16574
16850
|
return out;
|
|
16575
16851
|
}
|
|
16576
16852
|
|
|
16853
|
+
// src/kernel/net/tls-client.ts
|
|
16854
|
+
var WRITE_CHUNK = 16 * 1024;
|
|
16855
|
+
var BADCERT = [
|
|
16856
|
+
[8, "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"],
|
|
16857
|
+
[1, "CERT_HAS_EXPIRED"],
|
|
16858
|
+
[512, "CERT_NOT_YET_VALID"],
|
|
16859
|
+
[2, "CERT_REVOKED"],
|
|
16860
|
+
[4, "ERR_TLS_CERT_ALTNAME_INVALID"],
|
|
16861
|
+
[2048, "INVALID_PURPOSE"],
|
|
16862
|
+
[4096, "INVALID_PURPOSE"]
|
|
16863
|
+
];
|
|
16864
|
+
function verifyCode(flags2) {
|
|
16865
|
+
if (flags2 === 0) return void 0;
|
|
16866
|
+
if (flags2 === -1) return "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
|
|
16867
|
+
return BADCERT.find(([bit]) => (flags2 & bit) !== 0)?.[1] ?? "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
|
|
16868
|
+
}
|
|
16869
|
+
var Ciphertext = class {
|
|
16870
|
+
queue = [];
|
|
16871
|
+
ended = false;
|
|
16872
|
+
conn;
|
|
16873
|
+
session;
|
|
16874
|
+
constructor(conn, session) {
|
|
16875
|
+
this.conn = conn;
|
|
16876
|
+
this.session = session;
|
|
16877
|
+
}
|
|
16878
|
+
hand(bytes) {
|
|
16879
|
+
if (bytes.length > 0) this.queue.push(bytes);
|
|
16880
|
+
}
|
|
16881
|
+
async more() {
|
|
16882
|
+
if (this.queue.length === 0 && !this.ended) {
|
|
16883
|
+
const bytes = await this.conn.read();
|
|
16884
|
+
if (bytes) this.queue.push(bytes);
|
|
16885
|
+
else this.ended = true;
|
|
16886
|
+
}
|
|
16887
|
+
if (this.queue.length === 0) {
|
|
16888
|
+
this.session.feedEnd();
|
|
16889
|
+
return false;
|
|
16890
|
+
}
|
|
16891
|
+
while (this.queue.length > 0) {
|
|
16892
|
+
const head = this.queue[0];
|
|
16893
|
+
const n = this.session.feed(head);
|
|
16894
|
+
if (n < head.length) {
|
|
16895
|
+
this.queue[0] = head.subarray(n);
|
|
16896
|
+
break;
|
|
16897
|
+
}
|
|
16898
|
+
this.queue.shift();
|
|
16899
|
+
}
|
|
16900
|
+
return true;
|
|
16901
|
+
}
|
|
16902
|
+
};
|
|
16903
|
+
async function send(conn, session) {
|
|
16904
|
+
for (; ; ) {
|
|
16905
|
+
const out = session.take();
|
|
16906
|
+
if (out.length === 0) return;
|
|
16907
|
+
for (let at = 0; at < out.length; ) {
|
|
16908
|
+
const n = await conn.write(out.subarray(at));
|
|
16909
|
+
if (!(n > 0)) throw new KernelError("EPIPE");
|
|
16910
|
+
at += n;
|
|
16911
|
+
}
|
|
16912
|
+
}
|
|
16913
|
+
}
|
|
16914
|
+
function refused2(engine, session, err) {
|
|
16915
|
+
const flags2 = session.verifyResult;
|
|
16916
|
+
const code = verifyCode(flags2);
|
|
16917
|
+
if (code && flags2 !== -1)
|
|
16918
|
+
return new KernelError("EPROTO", `${code}: ${engine.verifyInfo(flags2).trim()}`);
|
|
16919
|
+
const text = err instanceof TlsError ? err.message : String(err);
|
|
16920
|
+
return new KernelError("EPROTO", `ERR_SSL_HANDSHAKE_FAILURE: ${text}`);
|
|
16921
|
+
}
|
|
16922
|
+
async function handshake(conn, o, session, inbox) {
|
|
16923
|
+
for (; ; ) {
|
|
16924
|
+
let done4;
|
|
16925
|
+
try {
|
|
16926
|
+
done4 = session.handshake();
|
|
16927
|
+
} catch (err) {
|
|
16928
|
+
await send(conn, session).catch(() => void 0);
|
|
16929
|
+
throw refused2(o.engine, session, err);
|
|
16930
|
+
}
|
|
16931
|
+
await send(conn, session);
|
|
16932
|
+
if (done4) return;
|
|
16933
|
+
if (!await inbox.more()) {
|
|
16934
|
+
throw new KernelError(
|
|
16935
|
+
"ECONNRESET",
|
|
16936
|
+
"the server closed the connection during the TLS handshake"
|
|
16937
|
+
);
|
|
16938
|
+
}
|
|
16939
|
+
}
|
|
16940
|
+
}
|
|
16941
|
+
function infoOf(o, session) {
|
|
16942
|
+
const flags2 = session.verifyResult;
|
|
16943
|
+
const code = verifyCode(flags2);
|
|
16944
|
+
return {
|
|
16945
|
+
protocol: session.version === 772 ? "TLSv1.3" : "TLSv1.2",
|
|
16946
|
+
alpnProtocol: session.alpn ?? false,
|
|
16947
|
+
authorized: code === void 0,
|
|
16948
|
+
...code ? { authorizationError: code, authorizationText: o.engine.verifyInfo(flags2).trim() } : {},
|
|
16949
|
+
peerCertificates: session.peerChain()
|
|
16950
|
+
};
|
|
16951
|
+
}
|
|
16952
|
+
function plaintext(conn, session, inbox) {
|
|
16953
|
+
let freed = false;
|
|
16954
|
+
let writeClosed = false;
|
|
16955
|
+
const free = () => {
|
|
16956
|
+
if (freed) return;
|
|
16957
|
+
freed = true;
|
|
16958
|
+
session.free();
|
|
16959
|
+
};
|
|
16960
|
+
return {
|
|
16961
|
+
localAddr: conn.localAddr,
|
|
16962
|
+
remoteAddr: conn.remoteAddr,
|
|
16963
|
+
async read() {
|
|
16964
|
+
for (; ; ) {
|
|
16965
|
+
if (freed) return null;
|
|
16966
|
+
const got = session.read();
|
|
16967
|
+
await send(conn, session);
|
|
16968
|
+
if (got instanceof Uint8Array) return got;
|
|
16969
|
+
if (got === "eof") return null;
|
|
16970
|
+
await inbox.more();
|
|
16971
|
+
}
|
|
16972
|
+
},
|
|
16973
|
+
async write(bytes) {
|
|
16974
|
+
if (freed) throw new KernelError("EPIPE");
|
|
16975
|
+
for (; ; ) {
|
|
16976
|
+
const n = session.write(bytes.subarray(0, WRITE_CHUNK));
|
|
16977
|
+
await send(conn, session);
|
|
16978
|
+
if (n > 0) return n;
|
|
16979
|
+
}
|
|
16980
|
+
},
|
|
16981
|
+
closeWrite() {
|
|
16982
|
+
if (writeClosed || freed) return;
|
|
16983
|
+
writeClosed = true;
|
|
16984
|
+
session.close();
|
|
16985
|
+
void send(conn, session).catch(() => void 0).finally(() => conn.closeWrite());
|
|
16986
|
+
},
|
|
16987
|
+
close() {
|
|
16988
|
+
free();
|
|
16989
|
+
conn.close();
|
|
16990
|
+
}
|
|
16991
|
+
};
|
|
16992
|
+
}
|
|
16993
|
+
async function tlsClient(conn, o, taken = new Uint8Array(0)) {
|
|
16994
|
+
const flags2 = o.insecure ? TLS_CLIENT_INSECURE_SKIP_VERIFY : 0;
|
|
16995
|
+
const session = o.engine.clientSession(o.store, o.servername, o.alpn, flags2);
|
|
16996
|
+
const inbox = new Ciphertext(conn, session);
|
|
16997
|
+
inbox.hand(taken);
|
|
16998
|
+
try {
|
|
16999
|
+
await handshake(conn, o, session, inbox);
|
|
17000
|
+
return { conn: plaintext(conn, session, inbox), info: infoOf(o, session) };
|
|
17001
|
+
} catch (err) {
|
|
17002
|
+
session.free();
|
|
17003
|
+
throw err;
|
|
17004
|
+
}
|
|
17005
|
+
}
|
|
17006
|
+
|
|
17007
|
+
// src/kernel/net/tls-uplink.ts
|
|
17008
|
+
var isIP = (text) => ipv4Bytes(text) !== void 0 || text.includes(":") && ipv6Groups(text) !== void 0;
|
|
17009
|
+
var LABEL2 = /^(?!-)[A-Za-z0-9-]{1,63}(?<!-)$/;
|
|
17010
|
+
function serverName(name2) {
|
|
17011
|
+
if (isIP(name2.replace(/^\[|\]$/g, ""))) return name2.replace(/^\[|\]$/g, "");
|
|
17012
|
+
const bare = name2.endsWith(".") ? name2.slice(0, -1) : name2;
|
|
17013
|
+
if (bare.length === 0 || bare.length > 253 || !bare.split(".").every((l) => LABEL2.test(l))) {
|
|
17014
|
+
throw new KernelError(
|
|
17015
|
+
"EINVAL",
|
|
17016
|
+
`ERR_INVALID_ARG_VALUE: not a host name: ${JSON.stringify(name2)}`
|
|
17017
|
+
);
|
|
17018
|
+
}
|
|
17019
|
+
return name2;
|
|
17020
|
+
}
|
|
17021
|
+
var defaults = /* @__PURE__ */ new WeakMap();
|
|
17022
|
+
function defaultStore(engine, roots) {
|
|
17023
|
+
let store = defaults.get(engine);
|
|
17024
|
+
if (!store) {
|
|
17025
|
+
const made2 = roots().then((bundle) => {
|
|
17026
|
+
const s = engine.store();
|
|
17027
|
+
s.addBundle(bundle);
|
|
17028
|
+
return s;
|
|
17029
|
+
});
|
|
17030
|
+
store = made2;
|
|
17031
|
+
defaults.set(engine, made2);
|
|
17032
|
+
made2.catch(() => {
|
|
17033
|
+
if (defaults.get(engine) === made2) defaults.delete(engine);
|
|
17034
|
+
});
|
|
17035
|
+
}
|
|
17036
|
+
return store;
|
|
17037
|
+
}
|
|
17038
|
+
function base64Der(text) {
|
|
17039
|
+
const bin = atob(text);
|
|
17040
|
+
const out = new Uint8Array(bin.length);
|
|
17041
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
17042
|
+
return out;
|
|
17043
|
+
}
|
|
17044
|
+
function encode(bytes) {
|
|
17045
|
+
let bin = "";
|
|
17046
|
+
for (const b of bytes) bin += String.fromCharCode(b);
|
|
17047
|
+
return btoa(bin);
|
|
17048
|
+
}
|
|
17049
|
+
function sessionOf(info, servername) {
|
|
17050
|
+
return {
|
|
17051
|
+
path: "kernel",
|
|
17052
|
+
substitutes: false,
|
|
17053
|
+
protocol: info.protocol,
|
|
17054
|
+
alpnProtocol: info.alpnProtocol,
|
|
17055
|
+
authorized: info.authorized,
|
|
17056
|
+
...info.authorizationError ? {
|
|
17057
|
+
authorizationError: info.authorizationError,
|
|
17058
|
+
authorizationText: info.authorizationText
|
|
17059
|
+
} : {},
|
|
17060
|
+
servername,
|
|
17061
|
+
peerCertificates: info.peerCertificates.map(encode)
|
|
17062
|
+
};
|
|
17063
|
+
}
|
|
17064
|
+
async function setUp(support, req) {
|
|
17065
|
+
const engine = await support.engine();
|
|
17066
|
+
if (!engine.client)
|
|
17067
|
+
throw new KernelError("ENOTSUP", "the installed tls engine has no client sessions");
|
|
17068
|
+
const custom = Array.isArray(req.ca) ? req.ca : void 0;
|
|
17069
|
+
if (!custom) return { engine, store: await defaultStore(engine, support.roots), own: void 0 };
|
|
17070
|
+
if (custom.length === 0)
|
|
17071
|
+
throw new KernelError("EINVAL", "ERR_INVALID_ARG_VALUE: ca has no certificate");
|
|
17072
|
+
const own = engine.store();
|
|
17073
|
+
try {
|
|
17074
|
+
for (const der of custom) own.add(base64Der(der));
|
|
17075
|
+
} catch (err) {
|
|
17076
|
+
own.release();
|
|
17077
|
+
throw new KernelError("EINVAL", `ERR_INVALID_ARG_VALUE: ca: ${err.message}`);
|
|
17078
|
+
}
|
|
17079
|
+
return { engine, store: own, own };
|
|
17080
|
+
}
|
|
17081
|
+
function secure(support, req, servername) {
|
|
17082
|
+
return async (raw) => {
|
|
17083
|
+
const { engine, store, own } = await setUp(support, req);
|
|
17084
|
+
try {
|
|
17085
|
+
return await tlsClient(raw, {
|
|
17086
|
+
engine,
|
|
17087
|
+
store,
|
|
17088
|
+
servername,
|
|
17089
|
+
alpn: req.alpn ?? [],
|
|
17090
|
+
insecure: req.insecure === true
|
|
17091
|
+
});
|
|
17092
|
+
} finally {
|
|
17093
|
+
own?.release();
|
|
17094
|
+
}
|
|
17095
|
+
};
|
|
17096
|
+
}
|
|
17097
|
+
function supportOf(net) {
|
|
17098
|
+
const support = net.tlsClient;
|
|
17099
|
+
if (!support) throw new KernelError("ENOTSUP", "no tls engine for client sessions");
|
|
17100
|
+
return support;
|
|
17101
|
+
}
|
|
17102
|
+
async function uplinkAddress(proc, host) {
|
|
17103
|
+
const bare = host.replace(/^\[|\]$/g, "");
|
|
17104
|
+
if (isIP(bare)) return bare;
|
|
17105
|
+
const [first] = await proc.resolve(host, 0, () => proc.blocking());
|
|
17106
|
+
if (!first) throw new KernelError("ENOENT", `ENOTFOUND: ${host}`);
|
|
17107
|
+
return first;
|
|
17108
|
+
}
|
|
17109
|
+
async function connectSecure(proc, socket, host, port, req) {
|
|
17110
|
+
const servername = serverName(req.servername || host);
|
|
17111
|
+
if (isLoopbackHost(servername) || isLoopbackHost(host)) throw new KernelError("ENOTSUP");
|
|
17112
|
+
const address = await uplinkAddress(proc, host);
|
|
17113
|
+
const route = proc.net.uplinkFor(address);
|
|
17114
|
+
if (!route)
|
|
17115
|
+
throw new KernelError("ENOTSUP", "TLS in the kernel needs a destination the uplink routes");
|
|
17116
|
+
const support = supportOf(proc.net);
|
|
17117
|
+
let info;
|
|
17118
|
+
const make = secure(support, req, servername);
|
|
17119
|
+
await socket.connectSecure({ family: "inet", host: address, port }, route, async (conn) => {
|
|
17120
|
+
info = await conn.upgrade(make);
|
|
17121
|
+
});
|
|
17122
|
+
return sessionOf(info, servername);
|
|
17123
|
+
}
|
|
17124
|
+
async function upgradeSecure(proc, socket, req) {
|
|
17125
|
+
const peer = socket.peer;
|
|
17126
|
+
const host = req.servername || (peer?.family === "inet" ? peer.host : "");
|
|
17127
|
+
const servername = serverName(host);
|
|
17128
|
+
const info = await socket.upgradeSecure(secure(supportOf(proc.net), req, servername));
|
|
17129
|
+
return sessionOf(info, servername);
|
|
17130
|
+
}
|
|
17131
|
+
|
|
16577
17132
|
// src/kernel/unix-dgram.ts
|
|
16578
17133
|
var SOL_SOCKET3 = 1;
|
|
16579
17134
|
var SO_TYPE3 = 3;
|
|
@@ -16735,7 +17290,8 @@ var SOCKET_OPS = [
|
|
|
16735
17290
|
"sock-resolve",
|
|
16736
17291
|
"sock-sendto",
|
|
16737
17292
|
"sock-recvfrom",
|
|
16738
|
-
"sock-tls"
|
|
17293
|
+
"sock-tls",
|
|
17294
|
+
"sock-tls-upgrade"
|
|
16739
17295
|
];
|
|
16740
17296
|
function socketAt(fds, fd) {
|
|
16741
17297
|
const file = anySocketAt(fds, fd);
|
|
@@ -16808,7 +17364,9 @@ async function socketSyscall(req, proc) {
|
|
|
16808
17364
|
return ok3(addresses);
|
|
16809
17365
|
}
|
|
16810
17366
|
case "sock-tls":
|
|
16811
|
-
return ok3(
|
|
17367
|
+
return ok3(await secureConnect(req, proc));
|
|
17368
|
+
case "sock-tls-upgrade":
|
|
17369
|
+
return ok3(await upgradeSecure(proc, socketAt(fds, req.fd), req));
|
|
16812
17370
|
default:
|
|
16813
17371
|
return datagram(req, proc);
|
|
16814
17372
|
}
|
|
@@ -16930,6 +17488,36 @@ var NOT_HTTP_PORTS = /* @__PURE__ */ new Set([
|
|
|
16930
17488
|
8883
|
|
16931
17489
|
]);
|
|
16932
17490
|
var HOST_NAME = /^[A-Za-z0-9.-]+$|^\[?[0-9A-Fa-f:.]+\]?$/;
|
|
17491
|
+
function wantsKernel(req) {
|
|
17492
|
+
if (req.path === "kernel") return true;
|
|
17493
|
+
if (req.path === "transport") return false;
|
|
17494
|
+
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);
|
|
17495
|
+
}
|
|
17496
|
+
async function secureConnect(req, proc) {
|
|
17497
|
+
if (!Number.isInteger(req.port) || req.port < 1 || req.port > 65535)
|
|
17498
|
+
throw new KernelError("EINVAL");
|
|
17499
|
+
const kernelPath = wantsKernel(req) && await uplinked(proc, req.host);
|
|
17500
|
+
if (!kernelPath) {
|
|
17501
|
+
if (req.path === "kernel" || Array.isArray(req.ca)) throw new KernelError("ENOTSUP");
|
|
17502
|
+
return { ...tlsOverTransport(req, proc), path: "transport", substitutes: true };
|
|
17503
|
+
}
|
|
17504
|
+
const socket = proc.net.socket("inet");
|
|
17505
|
+
const fd = proc.fds.install(new OpenFile(socket), 3);
|
|
17506
|
+
try {
|
|
17507
|
+
return { fd, ...await connectSecure(proc, socket, req.host, req.port, req) };
|
|
17508
|
+
} catch (e) {
|
|
17509
|
+
await Promise.resolve(proc.fds.close(fd));
|
|
17510
|
+
throw e;
|
|
17511
|
+
}
|
|
17512
|
+
}
|
|
17513
|
+
async function uplinked(proc, host) {
|
|
17514
|
+
if (!proc.net.tlsClient || isLoopbackHost(host)) return false;
|
|
17515
|
+
try {
|
|
17516
|
+
return proc.net.uplinkFor(await uplinkAddress(proc, host)) !== void 0;
|
|
17517
|
+
} catch {
|
|
17518
|
+
return false;
|
|
17519
|
+
}
|
|
17520
|
+
}
|
|
16933
17521
|
function tlsOverTransport(req, proc) {
|
|
16934
17522
|
if (req.ca) throw new KernelError("ENOTSUP");
|
|
16935
17523
|
if (req.alpn && req.alpn.length > 0 && !req.alpn.includes("http/1.1")) {
|
|
@@ -19930,10 +20518,10 @@ var JobTable = class {
|
|
|
19930
20518
|
signalForeground(tty, fallback, sig) {
|
|
19931
20519
|
this.killGroup(this.tcgetpgrp(tty, fallback), sig);
|
|
19932
20520
|
}
|
|
19933
|
-
fromKeyboard(
|
|
20521
|
+
fromKeyboard(send2) {
|
|
19934
20522
|
this.keyboard = true;
|
|
19935
20523
|
try {
|
|
19936
|
-
|
|
20524
|
+
send2();
|
|
19937
20525
|
} finally {
|
|
19938
20526
|
this.keyboard = false;
|
|
19939
20527
|
}
|
|
@@ -20244,6 +20832,12 @@ var LockService = class {
|
|
|
20244
20832
|
lock(pid, path, exclusive, fd) {
|
|
20245
20833
|
return this.table.lock(pid, path, exclusive, fd);
|
|
20246
20834
|
}
|
|
20835
|
+
wholeFree(pid, path, exclusive) {
|
|
20836
|
+
return this.table.wholeFree(pid, path, exclusive);
|
|
20837
|
+
}
|
|
20838
|
+
flockFree(key, owner, kind) {
|
|
20839
|
+
return this.table.flockFree(key, owner, kind);
|
|
20840
|
+
}
|
|
20247
20841
|
unlock(pid, path) {
|
|
20248
20842
|
this.table.unlock(pid, path);
|
|
20249
20843
|
}
|
|
@@ -20919,7 +21513,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
20919
21513
|
await changed(signal);
|
|
20920
21514
|
}
|
|
20921
21515
|
};
|
|
20922
|
-
const
|
|
21516
|
+
const send2 = async (out, signal) => {
|
|
20923
21517
|
const write = file.write;
|
|
20924
21518
|
for (let at = 0; at < out.length; ) {
|
|
20925
21519
|
try {
|
|
@@ -20954,7 +21548,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
20954
21548
|
raise();
|
|
20955
21549
|
if (timer !== void 0) clearTimeout(timer);
|
|
20956
21550
|
timer = void 0;
|
|
20957
|
-
await
|
|
21551
|
+
await send2(stream.push(taken), signal);
|
|
20958
21552
|
} finally {
|
|
20959
21553
|
busy = false;
|
|
20960
21554
|
if (quiet2()) wake();
|
|
@@ -21300,19 +21894,19 @@ var SettlingChildren = class {
|
|
|
21300
21894
|
this.held = this.held.filter((h) => this.blocking(h.pgid));
|
|
21301
21895
|
for (const h of ready2) h.send();
|
|
21302
21896
|
}
|
|
21303
|
-
deliver(sig, pgid,
|
|
21897
|
+
deliver(sig, pgid, send2, foreground) {
|
|
21304
21898
|
if (!KEY_SIGNALS.has(sig)) {
|
|
21305
|
-
|
|
21899
|
+
send2();
|
|
21306
21900
|
} else if (this.blocking(pgid)) {
|
|
21307
|
-
this.held.push({ pgid, send });
|
|
21901
|
+
this.held.push({ pgid, send: send2 });
|
|
21308
21902
|
} else if (foreground) {
|
|
21309
|
-
|
|
21903
|
+
send2();
|
|
21310
21904
|
const moved2 = () => {
|
|
21311
|
-
if (foreground() !== pgid)
|
|
21905
|
+
if (foreground() !== pgid) send2();
|
|
21312
21906
|
};
|
|
21313
21907
|
this.parked.push({ pgid, send: moved2 });
|
|
21314
21908
|
} else {
|
|
21315
|
-
|
|
21909
|
+
send2();
|
|
21316
21910
|
}
|
|
21317
21911
|
}
|
|
21318
21912
|
blocking(pgid) {
|
|
@@ -21457,9 +22051,9 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
|
|
|
21457
22051
|
let open = false;
|
|
21458
22052
|
const reply = (message3, transfer = []) => port.postMessage(message3, transfer);
|
|
21459
22053
|
async function hello(message3) {
|
|
21460
|
-
const
|
|
21461
|
-
if (
|
|
21462
|
-
reply({ hello: { protocol: DRIVER_PROTOCOL, error:
|
|
22054
|
+
const refused3 = driverVersionError(message3.protocol);
|
|
22055
|
+
if (refused3) {
|
|
22056
|
+
reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused3, errno: "EPROTO" } });
|
|
21463
22057
|
return;
|
|
21464
22058
|
}
|
|
21465
22059
|
try {
|
|
@@ -23528,9 +24122,9 @@ function interpreter(head) {
|
|
|
23528
24122
|
if (words2[0] === "-S") words2.shift();
|
|
23529
24123
|
return baseName2(words2[0] ?? "");
|
|
23530
24124
|
}
|
|
23531
|
-
function expandDefaults(
|
|
24125
|
+
function expandDefaults(defaults2, env) {
|
|
23532
24126
|
const out = {};
|
|
23533
|
-
for (const [key, value2] of Object.entries(
|
|
24127
|
+
for (const [key, value2] of Object.entries(defaults2 ?? {})) {
|
|
23534
24128
|
let missing4 = false;
|
|
23535
24129
|
const expanded = value2.replace(ENV_REFERENCE, (_, name2) => {
|
|
23536
24130
|
const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
|
|
@@ -23780,6 +24374,7 @@ var Launcher = class {
|
|
|
23780
24374
|
enableNetwork(this.net, {
|
|
23781
24375
|
transport: this.transport,
|
|
23782
24376
|
engine: kernelTlsEngine(packageTlsEngine(this.verifiedFs(options.fs), this.modulesDir)),
|
|
24377
|
+
roots: packageTlsRoots(this.verifiedFs(options.fs), this.modulesDir),
|
|
23783
24378
|
ca: this.ca
|
|
23784
24379
|
});
|
|
23785
24380
|
enableCdp(this.net, this.cdp);
|
|
@@ -24192,13 +24787,13 @@ var Launcher = class {
|
|
|
24192
24787
|
if (planned?.target.copy) await need(g, "exec", planned.target.copy, R_OK | X_OK);
|
|
24193
24788
|
}
|
|
24194
24789
|
async checkedPlan(req, { ppid, cred, scope }, fds) {
|
|
24195
|
-
const
|
|
24790
|
+
const refused3 = async (err) => {
|
|
24196
24791
|
await fds.closeAll();
|
|
24197
24792
|
throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
|
|
24198
24793
|
};
|
|
24199
|
-
const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(
|
|
24794
|
+
const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
|
|
24200
24795
|
const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0);
|
|
24201
|
-
await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(
|
|
24796
|
+
await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused3);
|
|
24202
24797
|
if (planned) return planned;
|
|
24203
24798
|
await fds.closeAll();
|
|
24204
24799
|
throw new SpawnError(await this.unrunnable(file, req.cwd, scope));
|
|
@@ -25033,10 +25628,10 @@ var Launcher = class {
|
|
|
25033
25628
|
return childHandle(await this.admitted(parent.program.abi !== "js", given, fresh2));
|
|
25034
25629
|
};
|
|
25035
25630
|
}
|
|
25036
|
-
keySignal(tty, fallback, sig,
|
|
25631
|
+
keySignal(tty, fallback, sig, send2) {
|
|
25037
25632
|
const pgid = this.jobs.tcgetpgrp(tty, fallback);
|
|
25038
25633
|
const foreground = () => this.jobs.tcgetpgrp(tty, fallback);
|
|
25039
|
-
const keyed = () => this.jobs.fromKeyboard(
|
|
25634
|
+
const keyed = () => this.jobs.fromKeyboard(send2);
|
|
25040
25635
|
this.settling.deliver(sig, pgid, keyed, tty.reading ? void 0 : foreground);
|
|
25041
25636
|
}
|
|
25042
25637
|
async resolvePrefixes() {
|