@ai-ecoverse/slicc-kernel 1.135.6 → 1.136.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/dist/node.js CHANGED
@@ -7486,7 +7486,7 @@ function satisfies(version, range2) {
7486
7486
  }
7487
7487
 
7488
7488
  // src/version.ts
7489
- var KERNEL_VERSION = true ? "1.135.6" : "0.0.0-dev";
7489
+ var KERNEL_VERSION = true ? "1.136.0" : "0.0.0-dev";
7490
7490
  var OS_RELEASE = "6.0.0-slicc";
7491
7491
  function procVersion() {
7492
7492
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -11665,8 +11665,8 @@ var MountFs = class _MountFs {
11665
11665
  }
11666
11666
  async across(from, to, redirects) {
11667
11667
  const moved2 = [await this.through(from), await this.through(to)];
11668
- const same = moved2[0] === normalizePath(from) && moved2[1] === normalizePath(to);
11669
- if (same || redirects >= MAX_LINKS7) throw errnoError("EXDEV", `${from} -> ${to}`);
11668
+ const same2 = moved2[0] === normalizePath(from) && moved2[1] === normalizePath(to);
11669
+ if (same2 || redirects >= MAX_LINKS7) throw errnoError("EXDEV", `${from} -> ${to}`);
11670
11670
  return moved2;
11671
11671
  }
11672
11672
  async based(paths, redirects, run2, again) {
@@ -15366,27 +15366,27 @@ function name(dn) {
15366
15366
  function extension(id2, critical, value2) {
15367
15367
  return critical ? seq(oid(id2), TRUE, octets(value2)) : seq(oid(id2), octets(value2));
15368
15368
  }
15369
- function children(der) {
15369
+ function children(der2) {
15370
15370
  const out = [];
15371
- const [, bodyStart, bodyEnd] = header(der, 0);
15371
+ const [, bodyStart, bodyEnd] = header(der2, 0);
15372
15372
  for (let at = bodyStart; at < bodyEnd; ) {
15373
- const [, , end] = header(der, at);
15374
- out.push(der.subarray(at, end));
15373
+ const [, , end] = header(der2, at);
15374
+ out.push(der2.subarray(at, end));
15375
15375
  at = end;
15376
15376
  }
15377
15377
  return out;
15378
15378
  }
15379
- function header(der, at) {
15380
- const tag = der[at];
15381
- let len = der[at + 1];
15379
+ function header(der2, at) {
15380
+ const tag = der2[at];
15381
+ let len = der2[at + 1];
15382
15382
  let start2 = at + 2;
15383
15383
  if (len & 128) {
15384
15384
  const count2 = len & 127;
15385
15385
  len = 0;
15386
- for (let i = 0; i < count2; i++) len = len * 256 + der[start2 + i];
15386
+ for (let i = 0; i < count2; i++) len = len * 256 + der2[start2 + i];
15387
15387
  start2 += count2;
15388
15388
  }
15389
- if (start2 + len > der.length) throw new Error("truncated DER");
15389
+ if (start2 + len > der2.length) throw new Error("truncated DER");
15390
15390
  return [tag, start2, start2 + len];
15391
15391
  }
15392
15392
  function contents(element) {
@@ -15475,12 +15475,12 @@ async function certificate(req) {
15475
15475
  const signature = ecdsaDer(await req.sign(tbs));
15476
15476
  return seq(tbs, ECDSA_SHA256, bits(signature));
15477
15477
  }
15478
- function pem(der) {
15479
- let b64 = "";
15480
- for (let i = 0; i < der.length; i += 32768) {
15481
- b64 += String.fromCharCode(...der.subarray(i, i + 32768));
15478
+ function pem(der2) {
15479
+ let b642 = "";
15480
+ for (let i = 0; i < der2.length; i += 32768) {
15481
+ b642 += String.fromCharCode(...der2.subarray(i, i + 32768));
15482
15482
  }
15483
- const lines2 = btoa(b64).match(/.{1,64}/g) ?? [];
15483
+ const lines2 = btoa(b642).match(/.{1,64}/g) ?? [];
15484
15484
  return `-----BEGIN CERTIFICATE-----
15485
15485
  ${lines2.join("\n")}
15486
15486
  -----END CERTIFICATE-----
@@ -15685,6 +15685,32 @@ var TlsEngine = class {
15685
15685
  this.m._free(name2);
15686
15686
  }
15687
15687
  }
15688
+ get chainVerify() {
15689
+ return typeof this.m._tls_chain_verify === "function";
15690
+ }
15691
+ chainFlags(store, chain2, hostname) {
15692
+ const verify = this.m._tls_chain_verify;
15693
+ if (!verify || chain2.length === 0) return void 0;
15694
+ const joined4 = new Uint8Array(chain2.reduce((n, c) => n + c.length, 0));
15695
+ let at = 0;
15696
+ for (const der2 of chain2) {
15697
+ joined4.set(der2, at);
15698
+ at += der2.length;
15699
+ }
15700
+ const name2 = this.put(new TextEncoder().encode(hostname));
15701
+ try {
15702
+ return this.withBytes(joined4, (p) => {
15703
+ const out = this.scratch;
15704
+ this.m.HEAPU8.fill(255, out, out + 4);
15705
+ const ret = verify(store.ptr, p, joined4.length, name2, out);
15706
+ const flags2 = new DataView(this.m.HEAPU8.buffer, out, 4).getUint32(0, true);
15707
+ if (ret === 0) return flags2 === 0 ? 0 : void 0;
15708
+ return ret === 1 && flags2 !== 0 ? flags2 : void 0;
15709
+ });
15710
+ } finally {
15711
+ this.m._free(name2);
15712
+ }
15713
+ }
15688
15714
  verifyInfo(flags2) {
15689
15715
  const m = this.clientModule();
15690
15716
  const n = m._tls_verify_info(flags2, this.scratch, SCRATCH);
@@ -15713,8 +15739,8 @@ var TlsStore = class {
15713
15739
  this.m = m;
15714
15740
  this.ptr = ptr;
15715
15741
  }
15716
- add(der) {
15717
- const ret = this.engine.withBytes(der, (p) => this.m._tls_ca_add_der(this.ptr, p, der.length));
15742
+ add(der2) {
15743
+ const ret = this.engine.withBytes(der2, (p) => this.m._tls_ca_add_der(this.ptr, p, der2.length));
15718
15744
  if (ret !== 0) throw this.engine.error(ret, "trust store certificate");
15719
15745
  }
15720
15746
  addBundle(bytes) {
@@ -15743,10 +15769,10 @@ var TlsLeaf = class {
15743
15769
  if (typeof out === "number") throw this.engine.error(out, "leaf public key");
15744
15770
  return out;
15745
15771
  }
15746
- addCert(der) {
15772
+ addCert(der2) {
15747
15773
  const ret = this.engine.withBytes(
15748
- der,
15749
- (ptr) => this.m._tls_leaf_add_cert(this.ptr, ptr, der.length)
15774
+ der2,
15775
+ (ptr) => this.m._tls_leaf_add_cert(this.ptr, ptr, der2.length)
15750
15776
  );
15751
15777
  if (ret !== 0) throw this.engine.error(ret, "leaf certificate");
15752
15778
  }
@@ -15839,8 +15865,8 @@ var TlsSession = class {
15839
15865
  const chain2 = [];
15840
15866
  const count2 = this.c._tls_peer_count(this.ptr);
15841
15867
  for (let i = 0; i < count2; i++) {
15842
- const der = this.engine.intoScratch((p, max) => this.c._tls_peer_der(this.ptr, i, p, max));
15843
- if (der instanceof Uint8Array) chain2.push(der);
15868
+ const der2 = this.engine.intoScratch((p, max) => this.c._tls_peer_der(this.ptr, i, p, max));
15869
+ if (der2 instanceof Uint8Array) chain2.push(der2);
15844
15870
  }
15845
15871
  return chain2;
15846
15872
  }
@@ -17781,6 +17807,30 @@ var TARGET = /^[\x21-\x7e]+$/;
17781
17807
  var SESSION_EXIT = /^(tailscale|device:[A-Za-z0-9._:-]+)$/;
17782
17808
  var HOST = /^[a-z0-9.:-]+$/;
17783
17809
  var UNSAFE = /[\r\n\0]/;
17810
+ var ANCHOR_ID = /^[A-Za-z0-9+/]{43}=$/;
17811
+ function verifiedByOk(f) {
17812
+ if (f.verifiedBy === void 0 || f.verifiedBy === "roots") return f.anchor === void 0;
17813
+ return f.verifiedBy === "anchored" && typeof f.anchor === "string" && ANCHOR_ID.test(f.anchor);
17814
+ }
17815
+ function anchorsAskable(f) {
17816
+ if (!Object.hasOwn(POSITIONS, f.protocol)) return false;
17817
+ if (typeof f.session !== "string" || !SESSION_ID.test(f.session) || !hostOk(f.host)) return false;
17818
+ if (!Number.isInteger(f.port) || f.port < 1 || f.port > 65535) return false;
17819
+ return typeof f.exit === "string" && SESSION_EXIT.test(f.exit);
17820
+ }
17821
+ function anchorsRequest(f) {
17822
+ return {
17823
+ v: 1,
17824
+ op: "sessionAnchors",
17825
+ caller: f.stamp,
17826
+ stamp: f.stamp,
17827
+ session: f.session,
17828
+ host: f.host,
17829
+ port: f.port,
17830
+ protocol: f.protocol,
17831
+ exit: f.exit
17832
+ };
17833
+ }
17784
17834
  var POSITIONS = {
17785
17835
  http1: (position) => HEADER.test(position),
17786
17836
  smtp: (position) => position === "auth-plain" || position === "auth-login",
@@ -17819,7 +17869,8 @@ function sessionAskable(f, now) {
17819
17869
  if (!Number.isInteger(f.port) || f.port < 1 || f.port > 65535) return false;
17820
17870
  const age = now - f.handshakeAt;
17821
17871
  if (!Number.isFinite(age) || age < 0 || age > SESSION_WINDOW_MS) return false;
17822
- return typeof f.exit === "string" && SESSION_EXIT.test(f.exit) && scramOk(f) && headOk(f);
17872
+ const exitOk = typeof f.exit === "string" && SESSION_EXIT.test(f.exit);
17873
+ return exitOk && scramOk(f) && verifiedByOk(f) && headOk(f);
17823
17874
  }
17824
17875
  function sessionRequest(f) {
17825
17876
  return {
@@ -17833,6 +17884,8 @@ function sessionRequest(f) {
17833
17884
  protocol: f.protocol,
17834
17885
  position: f.position,
17835
17886
  verified: true,
17887
+ verifiedBy: f.verifiedBy ?? "roots",
17888
+ ...f.verifiedBy === "anchored" ? { anchor: f.anchor } : {},
17836
17889
  handshakeAt: f.handshakeAt,
17837
17890
  exit: f.exit,
17838
17891
  ...f.placeholders ? { placeholders: [...f.placeholders] } : {},
@@ -17861,1852 +17914,1951 @@ function sessionValues(reply, asked) {
17861
17914
  return Object.keys(out).length > 0 ? out : void 0;
17862
17915
  }
17863
17916
 
17864
- // node_modules/@ai-ecoverse/slicc-scrub/dist/index.js
17865
- var FRAGMENT = 16;
17866
- var MIN_VALUE = 8;
17867
- var MIN_BASE64 = 8;
17868
- var encoder5 = new TextEncoder();
17869
- var STD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
17870
- function utf82(text) {
17871
- return encoder5.encode(text);
17917
+ // src/kernel/net/tls-ciphers.ts
17918
+ var SUITES = [
17919
+ [4865, "TLS_AES_128_GCM_SHA256", "TLS_AES_128_GCM_SHA256", "TLSv1.3"],
17920
+ [4866, "TLS_AES_256_GCM_SHA384", "TLS_AES_256_GCM_SHA384", "TLSv1.3"],
17921
+ [4867, "TLS_CHACHA20_POLY1305_SHA256", "TLS_CHACHA20_POLY1305_SHA256", "TLSv1.3"],
17922
+ [4868, "TLS_AES_128_CCM_SHA256", "TLS_AES_128_CCM_SHA256", "TLSv1.3"],
17923
+ [4869, "TLS_AES_128_CCM_8_SHA256", "TLS_AES_128_CCM_8_SHA256", "TLSv1.3"],
17924
+ [49195, "ECDHE-ECDSA-AES128-GCM-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
17925
+ [49196, "ECDHE-ECDSA-AES256-GCM-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
17926
+ [49199, "ECDHE-RSA-AES128-GCM-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
17927
+ [49200, "ECDHE-RSA-AES256-GCM-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
17928
+ [52392, "ECDHE-RSA-CHACHA20-POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLSv1.2"],
17929
+ [
17930
+ 52393,
17931
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
17932
+ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
17933
+ "TLSv1.2"
17934
+ ],
17935
+ [49187, "ECDHE-ECDSA-AES128-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLSv1.2"],
17936
+ [49188, "ECDHE-ECDSA-AES256-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLSv1.2"],
17937
+ [49191, "ECDHE-RSA-AES128-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLSv1.2"],
17938
+ [49192, "ECDHE-RSA-AES256-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLSv1.2"],
17939
+ [49161, "ECDHE-ECDSA-AES128-SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLSv1.0"],
17940
+ [49162, "ECDHE-ECDSA-AES256-SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLSv1.0"],
17941
+ [49171, "ECDHE-RSA-AES128-SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLSv1.0"],
17942
+ [49172, "ECDHE-RSA-AES256-SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLSv1.0"],
17943
+ [156, "AES128-GCM-SHA256", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
17944
+ [157, "AES256-GCM-SHA384", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
17945
+ [158, "DHE-RSA-AES128-GCM-SHA256", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
17946
+ [159, "DHE-RSA-AES256-GCM-SHA384", "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"]
17947
+ ];
17948
+ function cipherOf(id2, protocol) {
17949
+ const known = SUITES.find(([n]) => n === id2);
17950
+ const hex4 = `0x${id2.toString(16).padStart(4, "0").toUpperCase()}`;
17951
+ return {
17952
+ name: known?.[1] ?? hex4,
17953
+ standardName: known?.[2] ?? hex4,
17954
+ version: known?.[3] ?? protocol
17955
+ };
17872
17956
  }
17873
- function base642(bytes, padded = true) {
17874
- let out = "";
17875
- for (let i = 0; i < bytes.length; i += 3) {
17876
- const a = bytes[i];
17877
- const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
17878
- const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
17879
- const triple = a << 16 | b << 8 | c;
17880
- const left = bytes.length - i;
17881
- out += STD[triple >> 18 & 63] + STD[triple >> 12 & 63];
17882
- out += left > 1 ? STD[triple >> 6 & 63] : padded ? "=" : "";
17883
- out += left > 2 ? STD[triple & 63] : padded ? "=" : "";
17884
- }
17885
- return out;
17957
+
17958
+ // src/kernel/net/tls-client.ts
17959
+ var WRITE_CHUNK = 16 * 1024;
17960
+ var BADCERT = [
17961
+ [8, "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"],
17962
+ [1, "CERT_HAS_EXPIRED"],
17963
+ [512, "CERT_NOT_YET_VALID"],
17964
+ [2, "CERT_REVOKED"],
17965
+ [4, "ERR_TLS_CERT_ALTNAME_INVALID"],
17966
+ [2048, "INVALID_PURPOSE"],
17967
+ [4096, "INVALID_PURPOSE"]
17968
+ ];
17969
+ function verifyCode(flags2) {
17970
+ if (flags2 === 0) return void 0;
17971
+ if (flags2 === -1) return "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
17972
+ return BADCERT.find(([bit]) => (flags2 & bit) !== 0)?.[1] ?? "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
17886
17973
  }
17887
- function urlSafe(text) {
17888
- return text.replace(/\+/g, "-").replace(/\//g, "_");
17974
+ function isIP(name2) {
17975
+ return ipv4Bytes(name2) !== void 0 || name2.includes(":") && ipv6Groups(name2) !== void 0;
17889
17976
  }
17890
- function hex2(bytes) {
17891
- let out = "";
17892
- for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
17893
- return out;
17977
+ function clientFlags(o) {
17978
+ 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);
17894
17979
  }
17895
- function embedded(bytes, offset) {
17896
- const shifted = new Uint8Array(offset + bytes.length);
17897
- shifted.set(bytes, offset);
17898
- const encoded = base642(shifted);
17899
- const first = Math.ceil(8 * offset / 6);
17900
- const last = Math.floor(8 * (offset + bytes.length) / 6);
17901
- return encoded.slice(first, last);
17980
+ function openSession(o) {
17981
+ return o.engine.clientSession(o.store, o.servername, o.alpn, clientFlags(o));
17902
17982
  }
17903
- function unicode(value2, upper) {
17904
- let out = "";
17905
- for (let i = 0; i < value2.length; i++) {
17906
- const unit = value2.charCodeAt(i);
17907
- if (unit === 34) out += '\\"';
17908
- else if (unit === 92) out += "\\\\";
17909
- else if (unit < 32 || unit > 126) {
17910
- const code = unit.toString(16).padStart(4, "0");
17911
- out += `\\u${upper ? code.toUpperCase() : code}`;
17912
- } else out += value2[i];
17983
+ var Ciphertext = class {
17984
+ queue = [];
17985
+ ended = false;
17986
+ conn;
17987
+ session;
17988
+ constructor(conn, session) {
17989
+ this.conn = conn;
17990
+ this.session = session;
17913
17991
  }
17914
- return out;
17915
- }
17916
- function percent(value2) {
17917
- let component;
17918
- try {
17919
- component = encodeURIComponent(value2);
17920
- } catch {
17921
- return [];
17992
+ hand(bytes) {
17993
+ if (bytes.length > 0) this.queue.push(bytes);
17922
17994
  }
17923
- const lower = component.replace(/%[0-9A-F]{2}/g, (escape) => escape.toLowerCase());
17924
- const plus = component.replace(/%20/g, "+");
17925
- let form = "";
17926
- for (const byte of utf82(value2)) {
17927
- const char = String.fromCharCode(byte);
17928
- if (/[A-Za-z0-9*\-._]/.test(char)) form += char;
17929
- else if (byte === 32) form += "+";
17930
- else form += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
17995
+ async more() {
17996
+ if (this.queue.length === 0 && !this.ended) {
17997
+ const bytes = await this.conn.read();
17998
+ if (bytes) this.queue.push(bytes);
17999
+ else this.ended = true;
18000
+ }
18001
+ if (this.queue.length === 0) {
18002
+ this.session.feedEnd();
18003
+ return false;
18004
+ }
18005
+ while (this.queue.length > 0) {
18006
+ const head = this.queue[0];
18007
+ const n = this.session.feed(head);
18008
+ if (n < head.length) {
18009
+ this.queue[0] = head.subarray(n);
18010
+ break;
18011
+ }
18012
+ this.queue.shift();
18013
+ }
18014
+ return true;
18015
+ }
18016
+ };
18017
+ async function send(conn, session) {
18018
+ for (; ; ) {
18019
+ const out = session.take();
18020
+ if (out.length === 0) return;
18021
+ for (let at = 0; at < out.length; ) {
18022
+ const n = await conn.write(out.subarray(at));
18023
+ if (!(n > 0)) throw new KernelError("EPIPE");
18024
+ at += n;
18025
+ }
17931
18026
  }
17932
- return [component, lower, plus, form];
17933
18027
  }
17934
- function html(value2, apostrophe) {
17935
- return value2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, apostrophe);
18028
+ function refused2(engine, session, err) {
18029
+ const flags2 = session.verifyResult;
18030
+ const code = verifyCode(flags2);
18031
+ if (code && flags2 !== -1)
18032
+ return new KernelError("EPROTO", `${code}: ${engine.verifyInfo(flags2).trim()}`);
18033
+ const text = err instanceof TlsError ? err.message : String(err);
18034
+ return new KernelError("EPROTO", `ERR_SSL_HANDSHAKE_FAILURE: ${text}${alertOf(session)}`);
17936
18035
  }
17937
- function encodings(bytes) {
17938
- const standard = [base642(bytes), base642(bytes, false)];
17939
- for (const offset of [0, 1, 2]) {
17940
- const run2 = embedded(bytes, offset);
17941
- if (run2.length >= MIN_BASE64) standard.push(run2);
17942
- }
17943
- return [...standard, ...standard.map(urlSafe)];
18036
+ function alertOf(session) {
18037
+ const alert = session.lastAlert;
18038
+ return alert >= 0 ? ` (alert ${alert})` : "";
17944
18039
  }
17945
- function shapes(value2) {
17946
- const raw2 = utf82(value2);
17947
- const seen = /* @__PURE__ */ new Set([value2]);
17948
- const out = [];
17949
- if (raw2.length < FRAGMENT) out.push({ bytes: raw2, form: "raw" });
17950
- for (let offset = 0; raw2.length >= FRAGMENT && offset + FRAGMENT <= raw2.length; offset++) {
17951
- out.push({ bytes: raw2.subarray(offset, offset + FRAGMENT), form: "fragment", offset });
17952
- }
17953
- const add = (text, form) => {
17954
- if (seen.has(text)) return;
17955
- seen.add(text);
17956
- out.push({ bytes: utf82(text), form });
17957
- };
17958
- const json5 = JSON.stringify(value2).slice(1, -1);
17959
- for (const text of [
17960
- json5,
17961
- json5.replace(/\//g, "\\/"),
17962
- unicode(value2, false),
17963
- unicode(value2, true)
17964
- ]) {
17965
- add(text, "json");
18040
+ async function handshake(conn, o, session, inbox) {
18041
+ for (; ; ) {
18042
+ let done4;
18043
+ try {
18044
+ done4 = session.handshake();
18045
+ } catch (err) {
18046
+ await send(conn, session).catch(() => void 0);
18047
+ throw refused2(o.engine, session, err);
18048
+ }
18049
+ await send(conn, session);
18050
+ if (done4) return;
18051
+ if (!await inbox.more()) {
18052
+ throw new KernelError(
18053
+ "ECONNRESET",
18054
+ "the server closed the connection during the TLS handshake"
18055
+ );
18056
+ }
17966
18057
  }
17967
- for (const text of percent(value2)) add(text, "percent");
17968
- for (const text of [html(value2, "&#39;"), html(value2, "&#x27;")]) add(text, "html");
17969
- for (const text of encodings(raw2)) add(text, "base64");
17970
- add(hex2(raw2), "hex");
17971
- add(hex2(raw2).toUpperCase(), "hex");
17972
- return out;
17973
18058
  }
17974
- function wrappable(form) {
17975
- return form === "base64" || form === "hex";
18059
+ function insecureOf(session, chain2, shape) {
18060
+ const flags2 = session.verifyResult;
18061
+ const error = chainError(flags2, chain2, shape);
18062
+ return { hostnameMatches: nameMatches(flags2), ...error ? { chainError: error } : {} };
17976
18063
  }
17977
- var Automaton = class {
17978
- edges = /* @__PURE__ */ new Map();
17979
- fail = [0];
17980
- depth = [0];
17981
- children = [0];
17982
- out = [[]];
17983
- dict = [-1];
17984
- lengths = [];
17985
- add(bytes) {
17986
- let node = 0;
17987
- for (const byte of bytes) {
17988
- const key = node * 256 + byte;
17989
- let next3 = this.edges.get(key);
17990
- if (next3 === void 0) {
17991
- next3 = this.depth.length;
17992
- this.edges.set(key, next3);
17993
- this.fail.push(0);
17994
- this.depth.push(this.depth[node] + 1);
17995
- this.children.push(0);
17996
- this.children[node] += 1;
17997
- this.out.push([]);
17998
- this.dict.push(-1);
17999
- }
18000
- node = next3;
18001
- }
18002
- const id2 = this.lengths.length;
18003
- this.lengths.push(bytes.length);
18004
- this.out[node].push(id2);
18005
- return id2;
18006
- }
18007
- build() {
18008
- const queue = [];
18009
- const byNode = /* @__PURE__ */ new Map();
18010
- for (const [key, child] of this.edges) {
18011
- const parent = Math.floor(key / 256);
18012
- const list = byNode.get(parent) ?? [];
18013
- list.push([key % 256, child]);
18014
- byNode.set(parent, list);
18015
- }
18016
- for (const [, child] of byNode.get(0) ?? []) queue.push(child);
18017
- for (let head = 0; head < queue.length; head++) {
18018
- const node = queue[head];
18019
- const fallback = this.fail[node];
18020
- this.dict[node] = this.out[fallback].length > 0 ? fallback : this.dict[fallback];
18021
- for (const [byte, child] of byNode.get(node) ?? []) {
18022
- let state = fallback;
18023
- let target = this.edges.get(state * 256 + byte);
18024
- while (target === void 0 && state > 0) {
18025
- state = this.fail[state];
18026
- target = this.edges.get(state * 256 + byte);
18064
+ function controlsOf(o, session, protocol, chain2, shape) {
18065
+ if (!o.engine.sessionControls) return {};
18066
+ const checked = o.checkHostname !== false && !o.insecure;
18067
+ return {
18068
+ cipher: cipherOf(session.ciphersuite, protocol),
18069
+ clientCertificate: o.clientCertificate === true,
18070
+ sni: o.sni !== false && !isIP(o.servername),
18071
+ hostnameChecked: checked,
18072
+ ...o.insecure ? insecureOf(session, chain2, shape) : { hostnameMatches: checked || !session.nameMismatch }
18073
+ };
18074
+ }
18075
+ function verdictOf(o, session) {
18076
+ if (o.bundled !== true || isIP(o.servername) || session.verifyResult !== 0) return false;
18077
+ return o.checkHostname !== false || !session.nameMismatch;
18078
+ }
18079
+ async function infoOf(o, session) {
18080
+ const flags2 = session.verifyResult;
18081
+ const code = verifyCode(flags2);
18082
+ const protocol = session.version === 772 ? "TLSv1.3" : "TLSv1.2";
18083
+ const chain2 = session.peerChain();
18084
+ const shape = await chainShape(o.insecure ? chain2 : []);
18085
+ return {
18086
+ protocol,
18087
+ alpnProtocol: session.alpn ?? false,
18088
+ authorized: code === void 0,
18089
+ ...code ? { authorizationError: code, authorizationText: o.engine.verifyInfo(flags2).trim() } : {},
18090
+ peerCertificates: chain2,
18091
+ ...controlsOf(o, session, protocol, chain2, shape),
18092
+ verified: verdictOf(o, session),
18093
+ handshakeAt: Date.now()
18094
+ };
18095
+ }
18096
+ var FATAL_ALERT = -30592;
18097
+ function alerted(err, session) {
18098
+ if (err.code === FATAL_ALERT)
18099
+ return new KernelError(
18100
+ "EPROTO",
18101
+ `ERR_SSL_FATAL_ALERT: the server ended the session: ${err.message}${alertOf(session)}`
18102
+ );
18103
+ return new KernelError("EPROTO", `ERR_SSL_PROTOCOL_ERROR: ${err.message}`);
18104
+ }
18105
+ function plaintext(conn, session, inbox) {
18106
+ let freed = false;
18107
+ let writeClosed = false;
18108
+ const free = () => {
18109
+ if (freed) return;
18110
+ freed = true;
18111
+ session.free();
18112
+ };
18113
+ return {
18114
+ localAddr: conn.localAddr,
18115
+ remoteAddr: conn.remoteAddr,
18116
+ async read() {
18117
+ for (; ; ) {
18118
+ if (freed) return null;
18119
+ let got;
18120
+ try {
18121
+ got = session.read();
18122
+ } catch (err) {
18123
+ throw alerted(err, session);
18027
18124
  }
18028
- this.fail[child] = target ?? 0;
18029
- queue.push(child);
18125
+ await send(conn, session);
18126
+ if (got instanceof Uint8Array) return got;
18127
+ if (got === "eof") return null;
18128
+ await inbox.more();
18030
18129
  }
18130
+ },
18131
+ async write(bytes) {
18132
+ if (freed) throw new KernelError("EPIPE");
18133
+ for (; ; ) {
18134
+ const n = session.write(bytes.subarray(0, WRITE_CHUNK));
18135
+ await send(conn, session);
18136
+ if (n > 0) return n;
18137
+ }
18138
+ },
18139
+ closeWrite() {
18140
+ if (writeClosed || freed) return;
18141
+ writeClosed = true;
18142
+ session.close();
18143
+ void send(conn, session).catch(() => void 0).finally(() => conn.closeWrite());
18144
+ },
18145
+ close() {
18146
+ free();
18147
+ conn.close();
18031
18148
  }
18149
+ };
18150
+ }
18151
+ async function tlsClient(conn, o, taken = new Uint8Array(0)) {
18152
+ const session = o.session ?? openSession(o);
18153
+ const inbox = new Ciphertext(conn, session);
18154
+ inbox.hand(taken);
18155
+ try {
18156
+ await handshake(conn, o, session, inbox);
18157
+ const info = await infoOf(o, session);
18158
+ return { conn: plaintext(conn, session, inbox), info };
18159
+ } catch (err) {
18160
+ session.free();
18161
+ throw err;
18032
18162
  }
18033
- step(state, byte) {
18034
- let current = state;
18035
- for (; ; ) {
18036
- const next3 = this.edges.get(current * 256 + byte);
18037
- if (next3 !== void 0) return next3;
18038
- if (current === 0) return 0;
18039
- current = this.fail[current];
18040
- }
18041
- }
18042
- matches(state, visit) {
18043
- for (let node = state; node > 0; node = this.dict[node]) {
18044
- for (const id2 of this.out[node]) visit(id2);
18045
- }
18163
+ }
18164
+
18165
+ // src/kernel/net/tls-chain.ts
18166
+ var CN_MISMATCH = 4;
18167
+ var NOT_TRUSTED = 8;
18168
+ function tlv2(der2, at) {
18169
+ if (at + 2 > der2.length) return void 0;
18170
+ const first = der2[at + 1];
18171
+ let body = at + 2;
18172
+ let length2 = first;
18173
+ if (first & 128) {
18174
+ const n = first & 127;
18175
+ if (n === 0 || n > 4 || body + n > der2.length) return void 0;
18176
+ length2 = 0;
18177
+ for (let i = 0; i < n; i++) length2 = length2 * 256 + der2[body + i];
18178
+ body += n;
18046
18179
  }
18047
- partials(state, length2, visit) {
18048
- for (let node = state; node > 0; node = this.fail[node]) {
18049
- if (this.children[node] > 0) visit(length2 - this.depth[node]);
18050
- }
18180
+ const end = body + length2;
18181
+ return end > der2.length ? void 0 : { start: at, body, end };
18182
+ }
18183
+ function children2(der2, outer, max) {
18184
+ const fields = [];
18185
+ for (let at = outer.body; at < outer.end && fields.length < max; ) {
18186
+ const field4 = tlv2(der2, at);
18187
+ if (!field4) return void 0;
18188
+ fields.push(field4);
18189
+ at = field4.end;
18051
18190
  }
18191
+ return fields;
18192
+ }
18193
+ function tbsFields(der2) {
18194
+ const outer = tlv2(der2, 0);
18195
+ const cert = outer && children2(der2, outer, 3);
18196
+ const tbs = cert?.[0] && children2(der2, cert[0], 8);
18197
+ if (!cert || !tbs) return void 0;
18198
+ return { cert, tbs: der2[tbs[0]?.start ?? 0] === 160 ? tbs.slice(1) : tbs };
18199
+ }
18200
+ var raw = (der2, t) => der2.subarray(t.start, t.end);
18201
+ function spkiOf(der2) {
18202
+ const spki = tbsFields(der2)?.tbs[5];
18203
+ return spki ? raw(der2, spki) : void 0;
18204
+ }
18205
+ function names(der2) {
18206
+ const fields = tbsFields(der2)?.tbs;
18207
+ const [, , issuer, , subject] = fields ?? [];
18208
+ if (!issuer || !subject) return void 0;
18209
+ return [raw(der2, issuer), raw(der2, subject)];
18210
+ }
18211
+ var hex2 = (bytes) => Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
18212
+ var HASHES = {
18213
+ "2a864886f70d01010b": ["RSASSA-PKCS1-v1_5", "SHA-256"],
18214
+ "2a864886f70d01010c": ["RSASSA-PKCS1-v1_5", "SHA-384"],
18215
+ "2a864886f70d01010d": ["RSASSA-PKCS1-v1_5", "SHA-512"],
18216
+ "2a8648ce3d040302": ["ECDSA", "SHA-256"],
18217
+ "2a8648ce3d040303": ["ECDSA", "SHA-384"],
18218
+ "2a8648ce3d040304": ["ECDSA", "SHA-512"],
18219
+ "2b6570": ["Ed25519", ""],
18220
+ "2a864886f70d01010a": ["RSA-PSS", "SHA-1"]
18052
18221
  };
18053
- var RANK = {
18054
- raw: 0,
18055
- fragment: 1,
18056
- json: 2,
18057
- percent: 3,
18058
- html: 4,
18059
- base64: 5,
18060
- hex: 6,
18061
- wrapped: 7
18222
+ var PSS_HASHES = {
18223
+ "2b0e03021a": "SHA-1",
18224
+ "608648016503040201": "SHA-256",
18225
+ "608648016503040202": "SHA-384",
18226
+ "608648016503040203": "SHA-512"
18062
18227
  };
18063
- var CR2 = 13;
18064
- var LF2 = 10;
18065
- var EMPTY3 = new Uint8Array(0);
18066
- function register(automaton, sources, ids, bytes, source) {
18067
- const key = Array.from(bytes).join(",");
18068
- let id2 = ids.get(key);
18069
- if (id2 === void 0) {
18070
- id2 = automaton.add(bytes);
18071
- ids.set(key, id2);
18072
- sources[id2] = [];
18228
+ function pssOf(der2, algorithm) {
18229
+ const params = children2(der2, algorithm, 2)?.[1];
18230
+ let hash = "SHA-1";
18231
+ let salt = 20;
18232
+ for (const field4 of params && der2[params.start] === 48 ? children2(der2, params, 3) ?? [] : []) {
18233
+ const inner = tlv2(der2, field4.body);
18234
+ if (!inner) return void 0;
18235
+ if (der2[field4.start] === 160) {
18236
+ const known = PSS_HASHES[oidOf(der2, inner) ?? ""];
18237
+ if (!known) return void 0;
18238
+ hash = known;
18239
+ } else if (der2[field4.start] === 162) {
18240
+ salt = der2.subarray(inner.body, inner.end).reduce((n, b) => n * 256 + b, 0);
18241
+ }
18073
18242
  }
18074
- sources[id2].push(source);
18243
+ return { hash, salt };
18075
18244
  }
18076
- function prepare(secrets) {
18077
- const main = new Automaton();
18078
- const wrap = new Automaton();
18079
- const sources = [];
18080
- const wrapSources = [];
18081
- const ids = /* @__PURE__ */ new Map();
18082
- const wrapIds = /* @__PURE__ */ new Map();
18083
- const values = secrets.map((secret) => utf82(secret.value));
18084
- secrets.forEach((secret, index) => {
18085
- if (typeof secret.value !== "string" || values[index].length < MIN_VALUE) {
18086
- throw new RangeError(`the value of ${secret.name} is shorter than ${MIN_VALUE} bytes`);
18087
- }
18088
- for (const shape of shapes(secret.value)) {
18089
- const source = { secret: index, form: shape.form, offset: shape.offset };
18090
- register(main, sources, ids, shape.bytes, source);
18091
- if (wrappable(shape.form)) register(wrap, wrapSources, wrapIds, shape.bytes, source);
18092
- }
18093
- });
18094
- main.build();
18095
- wrap.build();
18096
- const replacements = secrets.map((secret) => [
18097
- utf82(secret.placeholder),
18098
- utf82(`[redacted:${secret.name}]`)
18099
- ]);
18100
- return { secrets, values, main, wrap, sources, wrapSources, replacements };
18245
+ var CURVES = {
18246
+ "2a8648ce3d030107": ["P-256", 32],
18247
+ "2b81040022": ["P-384", 48],
18248
+ "2b81040023": ["P-521", 66]
18249
+ };
18250
+ function oidOf(der2, algorithm, index = 0) {
18251
+ const parts2 = children2(der2, algorithm, 2);
18252
+ const oid2 = parts2?.[index];
18253
+ return oid2 && der2[oid2.start] === 6 ? hex2(der2.subarray(oid2.body, oid2.end)) : void 0;
18101
18254
  }
18102
- function better(a, b) {
18103
- if (!b) return true;
18104
- if (a.end !== b.end) return a.end > b.end;
18105
- if (a.rank !== b.rank) return a.rank < b.rank;
18106
- return a.secret < b.secret;
18255
+ function curveOf(der2, spki) {
18256
+ const algorithm = children2(der2, spki, 1)?.[0];
18257
+ const curve = algorithm && oidOf(der2, algorithm, 1);
18258
+ return curve ? CURVES[curve] : void 0;
18107
18259
  }
18108
- function resolve(c, input, start2, end, source) {
18109
- if (source.form !== "fragment") {
18110
- return {
18111
- start: start2,
18112
- end,
18113
- secret: source.secret,
18114
- form: source.form,
18115
- rank: RANK[source.form],
18116
- growing: false
18117
- };
18118
- }
18119
- const value2 = c.values[source.secret];
18120
- let stop = end;
18121
- let at = source.offset + FRAGMENT;
18122
- while (stop < input.length && at < value2.length && input[stop] === value2[at]) {
18123
- stop++;
18124
- at++;
18260
+ function fixedEcdsa(sig, size) {
18261
+ const outer = tlv2(sig, 0);
18262
+ const ints = outer && children2(sig, outer, 2);
18263
+ if (ints?.length !== 2) return void 0;
18264
+ const out = new Uint8Array(size * 2);
18265
+ for (const [i, int] of ints.entries()) {
18266
+ let value2 = sig.subarray(int.body, int.end);
18267
+ while (value2.length > size && value2[0] === 0) value2 = value2.subarray(1);
18268
+ if (value2.length > size) return void 0;
18269
+ out.set(value2, (i + 1) * size - value2.length);
18125
18270
  }
18126
- const form = source.offset === 0 && at === value2.length ? "raw" : "fragment";
18127
- const growing = stop === input.length && at < value2.length;
18128
- return { start: start2, end: stop, secret: source.secret, form, rank: RANK[form], growing };
18271
+ return out;
18129
18272
  }
18130
- function keep(best, candidate) {
18131
- if (better(candidate, best.get(candidate.start))) best.set(candidate.start, candidate);
18273
+ function signedOf(der2) {
18274
+ const parts2 = tbsFields(der2);
18275
+ const [tbs, algorithm, value2] = parts2?.cert ?? [];
18276
+ const spki = parts2?.tbs[5];
18277
+ if (!tbs || !algorithm || !value2 || !spki || der2[value2.start] !== 3) return void 0;
18278
+ const known = HASHES[oidOf(der2, algorithm) ?? ""];
18279
+ if (!known) return void 0;
18280
+ const [scheme] = known;
18281
+ const pss = scheme === "RSA-PSS" ? pssOf(der2, algorithm) : void 0;
18282
+ if (scheme === "RSA-PSS" && !pss) return void 0;
18283
+ const hash = pss?.hash ?? known[1];
18284
+ const curve = scheme === "ECDSA" ? curveOf(der2, spki) : void 0;
18285
+ if (scheme === "ECDSA" && !curve) return void 0;
18286
+ const signature = der2.subarray(value2.body + 1, value2.end);
18287
+ return {
18288
+ tbs: raw(der2, tbs),
18289
+ spki: raw(der2, spki),
18290
+ signature,
18291
+ scheme,
18292
+ hash,
18293
+ ...curve ? { curve } : {},
18294
+ ...pss ? { salt: pss.salt } : {}
18295
+ };
18132
18296
  }
18133
- function scanMain(c, input, best, partials) {
18134
- let state = 0;
18135
- for (let i = 0; i < input.length; i++) {
18136
- state = c.main.step(state, input[i]);
18137
- c.main.matches(state, (id2) => {
18138
- const start2 = i + 1 - c.main.lengths[id2];
18139
- for (const source of c.sources[id2]) {
18140
- const candidate = resolve(c, input, start2, i + 1, source);
18141
- if (candidate.growing) partials.push(candidate.start);
18142
- keep(best, candidate);
18143
- }
18144
- });
18145
- }
18146
- c.main.partials(state, input.length, (start2) => partials.push(start2));
18297
+ async function verifiesItself(s) {
18298
+ const name2 = s.curve?.[0];
18299
+ const algorithm = s.scheme === "ECDSA" ? { name: "ECDSA", namedCurve: name2 } : s.hash ? { name: s.scheme, hash: s.hash } : { name: s.scheme };
18300
+ const key = await crypto.subtle.importKey("spki", new Uint8Array(s.spki), algorithm, false, [
18301
+ "verify"
18302
+ ]);
18303
+ const signature = s.curve ? fixedEcdsa(s.signature, s.curve[1]) : s.signature;
18304
+ if (!signature) return false;
18305
+ const params = s.scheme === "ECDSA" ? { name: "ECDSA", hash: s.hash } : s.salt === void 0 ? { name: s.scheme } : { name: s.scheme, saltLength: s.salt };
18306
+ return crypto.subtle.verify(params, key, new Uint8Array(signature), new Uint8Array(s.tbs));
18147
18307
  }
18148
- function scanWrapped(c, input, best, partials) {
18149
- const map = [];
18150
- for (let i = 0; i < input.length; i++) if (input[i] !== CR2 && input[i] !== LF2) map.push(i);
18151
- if (map.length === input.length) return;
18152
- let state = 0;
18153
- for (let v = 0; v < map.length; v++) {
18154
- state = c.wrap.step(state, input[map[v]]);
18155
- c.wrap.matches(state, (id2) => {
18156
- const first = v + 1 - c.wrap.lengths[id2];
18157
- const start2 = map[first];
18158
- const end = map[v] + 1;
18159
- const wrapped = end - start2 !== c.wrap.lengths[id2];
18160
- for (const source of c.wrapSources[id2]) {
18161
- const form = wrapped ? "wrapped" : source.form;
18162
- keep(best, { start: start2, end, secret: source.secret, form, rank: RANK[form], growing: false });
18163
- }
18164
- });
18165
- }
18166
- c.wrap.partials(state, map.length, (start2) => partials.push(map[start2]));
18308
+ async function selfSigned(der2) {
18309
+ if (!selfIssued(der2)) return false;
18310
+ const signed = signedOf(der2);
18311
+ if (!signed) return false;
18312
+ return verifiesItself(signed).catch(() => false);
18167
18313
  }
18168
- function count(c, hits, candidate) {
18169
- const name2 = c.secrets[candidate.secret].name;
18170
- const key = `${name2}\0${candidate.form}`;
18171
- const hit = hits.get(key) ?? { name: name2, form: candidate.form, count: 0 };
18172
- hit.count += 1;
18173
- hits.set(key, hit);
18314
+ async function chainShape(chain2) {
18315
+ return {
18316
+ leafSelfSigned: chain2.length === 1 && await selfSigned(chain2[0]),
18317
+ topSelfSigned: chain2.length > 1 && await selfSigned(chain2.at(-1))
18318
+ };
18174
18319
  }
18175
- function concat6(parts2) {
18176
- let length2 = 0;
18177
- for (const part of parts2) length2 += part.length;
18178
- const out = new Uint8Array(length2);
18179
- let at = 0;
18180
- for (const part of parts2) {
18181
- out.set(part, at);
18182
- at += part.length;
18183
- }
18184
- return out;
18320
+ function selfIssued(der2) {
18321
+ const pair = der2 && names(der2);
18322
+ if (!pair) return false;
18323
+ const [issuer, subject] = pair;
18324
+ return issuer.length === subject.length && issuer.every((b, i) => b === subject[i]);
18185
18325
  }
18186
- function pass(c, input, final) {
18187
- const best = /* @__PURE__ */ new Map();
18188
- const partials = [];
18189
- scanMain(c, input, best, partials);
18190
- scanWrapped(c, input, best, partials);
18191
- const holds2 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
18192
- const starts = [...best.keys()].sort((a, b) => a - b);
18193
- const parts2 = [];
18194
- const hits = /* @__PURE__ */ new Map();
18195
- let pos = 0;
18196
- let cut = input.length;
18197
- let s = 0;
18198
- let h = 0;
18199
- for (; ; ) {
18200
- while (s < starts.length && starts[s] < pos) s++;
18201
- while (h < holds2.length && holds2[h] < pos) h++;
18202
- const hold = h < holds2.length ? holds2[h] : Infinity;
18203
- const next3 = s < starts.length ? starts[s] : Infinity;
18204
- if (hold <= next3) {
18205
- cut = Math.min(hold, input.length);
18206
- break;
18207
- }
18208
- const candidate = best.get(next3);
18209
- parts2.push(
18210
- input.subarray(pos, next3),
18211
- c.replacements[candidate.secret][candidate.form === "raw" ? 0 : 1]
18212
- );
18213
- count(c, hits, candidate);
18214
- pos = candidate.end;
18326
+ function untrusted(chain2, shape) {
18327
+ if (chain2.length === 1) {
18328
+ return shape.leafSelfSigned ? "DEPTH_ZERO_SELF_SIGNED_CERT" : "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
18215
18329
  }
18216
- parts2.push(input.subarray(pos, cut));
18217
- return { output: concat6(parts2), cut, hits };
18330
+ return shape.topSelfSigned ? "SELF_SIGNED_CERT_IN_CHAIN" : "UNABLE_TO_GET_ISSUER_CERT_LOCALLY";
18218
18331
  }
18219
- function merge(into, from) {
18220
- for (const [key, hit] of from) {
18221
- const known = into.get(key);
18222
- if (known) known.count += hit.count;
18223
- else into.set(key, { ...hit });
18224
- }
18332
+ function chainError(flags2, chain2, shape) {
18333
+ if (flags2 === -1) return "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
18334
+ const rest2 = flags2 & ~CN_MISMATCH;
18335
+ if (rest2 === 0) return void 0;
18336
+ if (rest2 & NOT_TRUSTED) return untrusted(chain2, shape);
18337
+ return verifyCode(rest2);
18225
18338
  }
18226
- function compile(secrets, options = {}) {
18227
- const c = prepare(secrets.map((secret) => ({ ...secret })));
18228
- const decoder4 = new TextDecoder();
18229
- const idleMs = options.idleMs ?? 250;
18230
- const scrubBytes = (input) => {
18231
- if (c.secrets.length === 0) return { bytes: input.slice(), hits: [] };
18232
- const result = pass(c, input, true);
18233
- return { bytes: result.output, hits: [...result.hits.values()] };
18234
- };
18235
- return {
18236
- version: options.version ?? 0,
18237
- idleMs,
18238
- size: c.main.lengths.length,
18239
- bytes: scrubBytes,
18240
- text(input) {
18241
- const { bytes, hits } = scrubBytes(utf82(input));
18242
- return { text: decoder4.decode(bytes), hits };
18243
- },
18244
- stream() {
18245
- let pending = EMPTY3;
18246
- const hits = /* @__PURE__ */ new Map();
18247
- const run2 = (final) => {
18248
- if (c.secrets.length === 0 || pending.length === 0) {
18249
- const out = pending;
18250
- pending = EMPTY3;
18251
- return out;
18252
- }
18253
- const result = pass(c, pending, final);
18254
- merge(hits, result.hits);
18255
- pending = pending.slice(result.cut);
18256
- return result.output;
18257
- };
18258
- return {
18259
- push(chunk2) {
18260
- pending = concat6([pending, chunk2]);
18261
- return run2(false);
18262
- },
18263
- idle() {
18264
- return pending.length < FRAGMENT ? run2(true) : EMPTY3;
18265
- },
18266
- end() {
18267
- return run2(true);
18268
- },
18269
- get hits() {
18270
- return [...hits.values()];
18271
- }
18272
- };
18273
- }
18274
- };
18339
+ function nameMatches(flags2) {
18340
+ return flags2 !== -1 && (flags2 & CN_MISMATCH) === 0;
18275
18341
  }
18276
18342
 
18277
- // src/kernel/scrub-file.ts
18278
- var SCRUB_IDLE_MS = 50;
18279
- var SCRUB_NONBLOCK_MAX = 64 * 1024;
18280
- var encoder6 = new TextEncoder();
18281
- function scrubberOf(secrets) {
18282
- const usable2 = secrets.filter((s) => encoder6.encode(s.value).length >= MIN_VALUE);
18283
- return usable2.length > 0 ? compile(usable2, { idleMs: SCRUB_IDLE_MS }) : void 0;
18343
+ // src/kernel/net/sealed-anchor.ts
18344
+ var ANCHORS_MAX = 64;
18345
+ var ANCHOR_BYTES_MAX = 8 * 1024;
18346
+ var NOT_TRUSTED2 = 8;
18347
+ var PIN = /^[A-Za-z0-9+/]{43}=$/;
18348
+ function b64(bytes) {
18349
+ let bin = "";
18350
+ for (const b of bytes) bin += String.fromCharCode(b);
18351
+ return btoa(bin);
18284
18352
  }
18285
- async function writeAll3(file, bytes) {
18286
- const write = file.write;
18287
- for (let at = 0; at < bytes.length; ) at += await write.call(file, bytes.subarray(at));
18353
+ function der(text) {
18354
+ if (typeof text !== "string" || text.length === 0 || text.length > ANCHOR_BYTES_MAX * 4 / 3 + 4)
18355
+ return void 0;
18356
+ try {
18357
+ return Uint8Array.from(atob(text), (c) => c.charCodeAt(0));
18358
+ } catch {
18359
+ return void 0;
18360
+ }
18288
18361
  }
18289
- function bound(file, key) {
18290
- const method = file[key];
18291
- return typeof method === "function" ? { [key]: method.bind(file) } : {};
18362
+ function anchorsOf(reply) {
18363
+ if (typeof reply !== "object" || reply === null || Array.isArray(reply)) return void 0;
18364
+ const r = reply;
18365
+ if (r.error !== void 0 || !Array.isArray(r.anchors) || !Array.isArray(r.pins))
18366
+ return void 0;
18367
+ if (r.anchors.length + r.pins.length > ANCHORS_MAX) return void 0;
18368
+ const anchors = r.anchors.map(der);
18369
+ if (anchors.some((a) => a === void 0)) return void 0;
18370
+ if (!r.pins.every((p) => typeof p === "string" && PIN.test(p))) return void 0;
18371
+ return { anchors, pins: r.pins };
18372
+ }
18373
+ async function sha2563(bytes) {
18374
+ return b64(
18375
+ new Uint8Array(await crypto.subtle.digest("SHA-256", bytes))
18376
+ );
18292
18377
  }
18293
- function interrupted2(err) {
18294
- const code = err?.code;
18295
- return code === "EINTR" || code === "EAGAIN";
18378
+ function same(a, b) {
18379
+ return a.length === b.length && a.every((x, i) => x === b[i]);
18296
18380
  }
18297
- function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
18298
- const file = inner.file;
18299
- const stream2 = scrubber.stream();
18300
- let tail2 = Promise.resolve();
18301
- let pending = 0;
18302
- let busy = false;
18303
- let timer;
18304
- let failed3;
18305
- const waiters = /* @__PURE__ */ new Set();
18306
- const quiet3 = () => !busy && pending === 0;
18307
- const wake = () => {
18308
- for (const waiter of [...waiters]) waiter();
18309
- };
18310
- const raise = () => {
18311
- if (failed3 === void 0) return;
18312
- const err = failed3;
18313
- failed3 = void 0;
18314
- throw err;
18315
- };
18316
- const later = (bytes) => {
18317
- if (bytes.length === 0) return;
18318
- pending += 1;
18319
- tail2 = tail2.then(() => writeAll3(file, bytes)).catch((err) => {
18320
- if (failed3 === void 0) failed3 = err;
18321
- }).finally(() => {
18322
- pending -= 1;
18323
- if (quiet3()) wake();
18324
- });
18325
- };
18326
- const settling = (signal) => new Promise((resolve2, reject) => {
18327
- const done4 = () => {
18328
- waiters.delete(done4);
18329
- signal?.removeEventListener("abort", stop);
18330
- resolve2();
18331
- };
18332
- const stop = () => {
18333
- waiters.delete(done4);
18334
- reject(new KernelError("EINTR"));
18335
- };
18336
- if (signal?.aborted) return stop();
18337
- waiters.add(done4);
18338
- signal?.addEventListener("abort", stop, { once: true });
18339
- });
18340
- const settled = async () => {
18341
- while (!quiet3()) await settling();
18342
- };
18343
- const changed = async (signal) => {
18344
- const round = new AbortController();
18345
- const stop = signal ? AbortSignal.any([signal, round.signal]) : round.signal;
18346
- try {
18347
- const own = settling(stop);
18348
- await Promise.race(file.changed ? [own, file.changed(stop)] : [own]);
18349
- } catch (err) {
18350
- throw signal?.aborted ? new KernelError("EINTR") : err;
18351
- } finally {
18352
- round.abort();
18353
- }
18354
- };
18355
- const turn = async (signal) => {
18356
- for (let waited = false; ; waited = true) {
18357
- if (quiet3() && (pollFile(file).writable || !file.changed)) {
18358
- busy = true;
18359
- return;
18360
- }
18361
- if (signal?.aborted) throw new KernelError(waited ? "EINTR" : "EAGAIN");
18362
- await changed(signal);
18363
- }
18364
- };
18365
- const send2 = async (out, signal) => {
18366
- const write = file.write;
18367
- for (let at = 0; at < out.length; ) {
18368
- try {
18369
- at += await write.call(file, out.subarray(at), signal);
18370
- } catch (err) {
18371
- if (!signal?.aborted || !interrupted2(err)) throw err;
18372
- }
18373
- if (at < out.length && signal?.aborted) return later(out.subarray(at));
18374
- }
18375
- };
18376
- const release = () => {
18377
- timer = void 0;
18378
- later(stream2.idle());
18379
- };
18380
- return new OpenFile({
18381
- ...bound(file, "read"),
18382
- ...bound(file, "peek"),
18383
- ...bound(file, "stat"),
18384
- poll: () => {
18385
- const state = pollFile(file);
18386
- return quiet3() ? state : { ...state, writable: false };
18387
- },
18388
- changed,
18389
- ...file.tty ? { tty: file.tty } : {},
18390
- identity: file.identity ?? file,
18391
- ...file.clipboard ? { clipboard: file.clipboard } : {},
18392
- ...file.write ? {
18393
- write: async (bytes, signal) => {
18394
- await turn(signal);
18395
- const taken = signal?.aborted && bytes.length > SCRUB_NONBLOCK_MAX ? bytes.subarray(0, SCRUB_NONBLOCK_MAX) : bytes;
18396
- try {
18397
- raise();
18398
- if (timer !== void 0) clearTimeout(timer);
18399
- timer = void 0;
18400
- await send2(stream2.push(taken), signal);
18401
- } finally {
18402
- busy = false;
18403
- if (quiet3()) wake();
18404
- }
18405
- timer = setTimeout(release, idleMs);
18406
- return taken.length;
18407
- }
18408
- } : {},
18409
- flush: async () => {
18410
- await settled();
18411
- raise();
18412
- await file.flush?.();
18413
- },
18414
- close: async () => {
18415
- if (timer !== void 0) clearTimeout(timer);
18416
- let failure;
18417
- try {
18418
- await settled();
18419
- later(stream2.end());
18420
- await settled();
18421
- raise();
18422
- } catch (err) {
18423
- failure = { err };
18424
- }
18425
- await inner.release();
18426
- if (failure) throw failure.err;
18427
- }
18428
- });
18381
+ function flagsWith(engine, anchor, chain2, host) {
18382
+ const store = engine.store();
18383
+ try {
18384
+ if (anchor) store.add(anchor);
18385
+ return engine.chainFlags(store, chain2, host);
18386
+ } catch {
18387
+ return void 0;
18388
+ } finally {
18389
+ store.release();
18390
+ }
18429
18391
  }
18430
- function scrubbedAll(file, scrubbers) {
18431
- return scrubbers.reduce((inner, scrubber) => scrubbed(inner, scrubber), file);
18392
+ function leafPinned(engine, leaf, host) {
18393
+ const flags2 = flagsWith(engine, void 0, [leaf], host);
18394
+ return flags2 !== void 0 && (flags2 & ~NOT_TRUSTED2) === 0;
18432
18395
  }
18433
- function stdioFiles(fds) {
18434
- const files = /* @__PURE__ */ new Set();
18435
- for (const fd of [1, 2]) {
18436
- try {
18437
- files.add(fds.get(fd));
18438
- } catch {
18439
- }
18440
- }
18441
- return files;
18396
+ function issuedBy(engine, anchor, chain2, host) {
18397
+ return flagsWith(engine, anchor, chain2, host) === 0;
18442
18398
  }
18443
- function scrubStdio(fds, scrubber) {
18444
- const wrapped = /* @__PURE__ */ new Map();
18445
- const stdio = stdioFiles(fds);
18446
- for (const fd of fds.numbers()) {
18447
- const original = fds.get(fd);
18448
- if (!stdio.has(original) && !original.file.tty && !original.file.clipboard) continue;
18449
- const known = wrapped.get(original);
18450
- const flags2 = fds.statusFlags(fd);
18451
- const wrapper = known ? known.retain() : scrubbed(original.retain(), scrubber);
18452
- wrapped.set(original, wrapper);
18453
- fds.installAt(fd, wrapper);
18454
- if (flags2 !== void 0) fds.setStatusFlags(fd, flags2);
18399
+ async function anchorFor(engine, chain2, host, found) {
18400
+ const leaf = chain2[0];
18401
+ if (!leaf || !engine.chainVerify) return void 0;
18402
+ for (const anchor of found.anchors) {
18403
+ const ok4 = same(anchor, leaf) ? leafPinned(engine, leaf, host) : issuedBy(engine, anchor, chain2, host);
18404
+ if (ok4) return sha2563(anchor);
18455
18405
  }
18406
+ for (const [i, cert] of chain2.entries()) {
18407
+ const spki = spkiOf(cert);
18408
+ if (!spki || !found.pins.includes(await sha2563(spki))) continue;
18409
+ const ok4 = i === 0 ? leafPinned(engine, leaf, host) : issuedBy(engine, cert, chain2, host);
18410
+ if (ok4) return sha2563(spki);
18411
+ }
18412
+ return void 0;
18456
18413
  }
18457
18414
 
18458
- // src/kernel/net/sealed-http1.ts
18459
- var HTTP1_METHODS = [
18460
- "GET",
18461
- "HEAD",
18462
- "POST",
18463
- "PUT",
18464
- "DELETE",
18465
- "PATCH",
18466
- "OPTIONS",
18467
- "CONNECT",
18468
- "TRACE"
18469
- ];
18470
- var HEAD_MAX = 16 * 1024;
18471
- var ANY_PLACEHOLDER = /fnox_proxy_[0-9a-f]{24}/g;
18472
- var REQUEST_LINE2 = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+) ([\x21-\x7e]+) HTTP\/1\.[01]$/;
18473
- var HEADER_LINE = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+):[ \t]*(.*?)[ \t]*$/;
18474
- var BASIC = /^(Basic[ \t]+)([A-Za-z0-9+/]+={0,2})$/i;
18475
- var encoder7 = new TextEncoder();
18476
- function binary(text) {
18415
+ // node_modules/@ai-ecoverse/slicc-scrub/dist/index.js
18416
+ var FRAGMENT = 16;
18417
+ var MIN_VALUE = 8;
18418
+ var MIN_BASE64 = 8;
18419
+ var encoder5 = new TextEncoder();
18420
+ var STD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18421
+ function utf82(text) {
18422
+ return encoder5.encode(text);
18423
+ }
18424
+ function base642(bytes, padded = true) {
18477
18425
  let out = "";
18478
- for (const b of encoder7.encode(text)) out += String.fromCharCode(b);
18426
+ for (let i = 0; i < bytes.length; i += 3) {
18427
+ const a = bytes[i];
18428
+ const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
18429
+ const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
18430
+ const triple = a << 16 | b << 8 | c;
18431
+ const left = bytes.length - i;
18432
+ out += STD[triple >> 18 & 63] + STD[triple >> 12 & 63];
18433
+ out += left > 1 ? STD[triple >> 6 & 63] : padded ? "=" : "";
18434
+ out += left > 2 ? STD[triple & 63] : padded ? "=" : "";
18435
+ }
18479
18436
  return out;
18480
18437
  }
18481
- function sniffHttp1(start2) {
18482
- for (const method of HTTP1_METHODS) {
18483
- const word = `${method} `;
18484
- if (start2.startsWith(word)) return "yes";
18485
- if (word.startsWith(start2)) return "more";
18438
+ function urlSafe(text) {
18439
+ return text.replace(/\+/g, "-").replace(/\//g, "_");
18440
+ }
18441
+ function hex3(bytes) {
18442
+ let out = "";
18443
+ for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
18444
+ return out;
18445
+ }
18446
+ function embedded(bytes, offset) {
18447
+ const shifted = new Uint8Array(offset + bytes.length);
18448
+ shifted.set(bytes, offset);
18449
+ const encoded = base642(shifted);
18450
+ const first = Math.ceil(8 * offset / 6);
18451
+ const last = Math.floor(8 * (offset + bytes.length) / 6);
18452
+ return encoded.slice(first, last);
18453
+ }
18454
+ function unicode(value2, upper) {
18455
+ let out = "";
18456
+ for (let i = 0; i < value2.length; i++) {
18457
+ const unit = value2.charCodeAt(i);
18458
+ if (unit === 34) out += '\\"';
18459
+ else if (unit === 92) out += "\\\\";
18460
+ else if (unit < 32 || unit > 126) {
18461
+ const code = unit.toString(16).padStart(4, "0");
18462
+ out += `\\u${upper ? code.toUpperCase() : code}`;
18463
+ } else out += value2[i];
18486
18464
  }
18487
- return "no";
18465
+ return out;
18488
18466
  }
18489
- function basicOf(value2) {
18490
- const m = BASIC.exec(value2);
18491
- if (!m) return void 0;
18467
+ function percent(value2) {
18468
+ let component;
18492
18469
  try {
18493
- return { scheme: m[1], decoded: atob(m[2]) };
18470
+ component = encodeURIComponent(value2);
18494
18471
  } catch {
18495
- return void 0;
18472
+ return [];
18473
+ }
18474
+ const lower = component.replace(/%[0-9A-F]{2}/g, (escape) => escape.toLowerCase());
18475
+ const plus = component.replace(/%20/g, "+");
18476
+ let form = "";
18477
+ for (const byte of utf82(value2)) {
18478
+ const char = String.fromCharCode(byte);
18479
+ if (/[A-Za-z0-9*\-._]/.test(char)) form += char;
18480
+ else if (byte === 32) form += "+";
18481
+ else form += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
18496
18482
  }
18483
+ return [component, lower, plus, form];
18497
18484
  }
18498
- function placeholdersIn(text) {
18499
- return [...new Set(text.match(ANY_PLACEHOLDER) ?? [])];
18485
+ function html(value2, apostrophe) {
18486
+ return value2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, apostrophe);
18500
18487
  }
18501
- function scan(lines2) {
18502
- const found = [];
18503
- for (let i = 1; i < lines2.length; i++) {
18504
- const m = HEADER_LINE.exec(lines2[i]);
18505
- if (!m) return void 0;
18506
- const value2 = m[2];
18507
- const basic = basicOf(value2);
18508
- const placeholders = placeholdersIn(basic ? basic.decoded : value2);
18509
- if (placeholders.length > 0)
18510
- found.push({ line: i, name: m[1].toLowerCase(), value: value2, basic, placeholders });
18488
+ function encodings(bytes) {
18489
+ const standard = [base642(bytes), base642(bytes, false)];
18490
+ for (const offset of [0, 1, 2]) {
18491
+ const run2 = embedded(bytes, offset);
18492
+ if (run2.length >= MIN_BASE64) standard.push(run2);
18511
18493
  }
18512
- return found;
18494
+ return [...standard, ...standard.map(urlSafe)];
18513
18495
  }
18514
- function replaced(text, values) {
18515
- let out = text;
18516
- for (const [ph, value2] of Object.entries(values)) out = out.split(ph).join(binary(value2));
18496
+ function shapes(value2) {
18497
+ const raw2 = utf82(value2);
18498
+ const seen = /* @__PURE__ */ new Set([value2]);
18499
+ const out = [];
18500
+ if (raw2.length < FRAGMENT) out.push({ bytes: raw2, form: "raw" });
18501
+ for (let offset = 0; raw2.length >= FRAGMENT && offset + FRAGMENT <= raw2.length; offset++) {
18502
+ out.push({ bytes: raw2.subarray(offset, offset + FRAGMENT), form: "fragment", offset });
18503
+ }
18504
+ const add = (text, form) => {
18505
+ if (seen.has(text)) return;
18506
+ seen.add(text);
18507
+ out.push({ bytes: utf82(text), form });
18508
+ };
18509
+ const json5 = JSON.stringify(value2).slice(1, -1);
18510
+ for (const text of [
18511
+ json5,
18512
+ json5.replace(/\//g, "\\/"),
18513
+ unicode(value2, false),
18514
+ unicode(value2, true)
18515
+ ]) {
18516
+ add(text, "json");
18517
+ }
18518
+ for (const text of percent(value2)) add(text, "percent");
18519
+ for (const text of [html(value2, "&#39;"), html(value2, "&#x27;")]) add(text, "html");
18520
+ for (const text of encodings(raw2)) add(text, "base64");
18521
+ add(hex3(raw2), "hex");
18522
+ add(hex3(raw2).toUpperCase(), "hex");
18517
18523
  return out;
18518
18524
  }
18519
- function usable(values) {
18520
- const out = {};
18521
- for (const [ph, value2] of Object.entries(values ?? {}))
18522
- if (encoder7.encode(value2).length >= MIN_VALUE) out[ph] = value2;
18523
- return out;
18525
+ function wrappable(form) {
18526
+ return form === "base64" || form === "hex";
18524
18527
  }
18525
- async function substituteHead(head, ask) {
18526
- if (!head.endsWith("\r\n\r\n")) return void 0;
18527
- const lines2 = head.slice(0, -4).split("\r\n");
18528
- if (lines2.some((l) => l.includes("\n") || l.includes("\r"))) return void 0;
18529
- const request = REQUEST_LINE2.exec(lines2[0]);
18530
- const found = request ? scan(lines2) : void 0;
18531
- if (!request || !found || found.length !== 1) return void 0;
18532
- const at = found[0];
18533
- if (at.placeholders.length > SESSION_PLACEHOLDERS) return void 0;
18534
- const values = usable(
18535
- await ask(`header:${at.name}`, at.placeholders, {
18536
- method: request[1],
18537
- path: request[2]
18538
- })
18539
- );
18540
- if (Object.keys(values).length === 0) return void 0;
18541
- const value2 = at.basic ? `${at.basic.scheme}${btoa(replaced(at.basic.decoded, values))}` : replaced(at.value, values);
18542
- const out = [...lines2];
18543
- out[at.line] = `${lines2[at.line].split(":")[0]}: ${value2}`;
18544
- return { head: `${out.join("\r\n")}\r
18545
- \r
18546
- `, values };
18528
+ var Automaton = class {
18529
+ edges = /* @__PURE__ */ new Map();
18530
+ fail = [0];
18531
+ depth = [0];
18532
+ children = [0];
18533
+ out = [[]];
18534
+ dict = [-1];
18535
+ lengths = [];
18536
+ add(bytes) {
18537
+ let node = 0;
18538
+ for (const byte of bytes) {
18539
+ const key = node * 256 + byte;
18540
+ let next3 = this.edges.get(key);
18541
+ if (next3 === void 0) {
18542
+ next3 = this.depth.length;
18543
+ this.edges.set(key, next3);
18544
+ this.fail.push(0);
18545
+ this.depth.push(this.depth[node] + 1);
18546
+ this.children.push(0);
18547
+ this.children[node] += 1;
18548
+ this.out.push([]);
18549
+ this.dict.push(-1);
18550
+ }
18551
+ node = next3;
18552
+ }
18553
+ const id2 = this.lengths.length;
18554
+ this.lengths.push(bytes.length);
18555
+ this.out[node].push(id2);
18556
+ return id2;
18557
+ }
18558
+ build() {
18559
+ const queue = [];
18560
+ const byNode = /* @__PURE__ */ new Map();
18561
+ for (const [key, child] of this.edges) {
18562
+ const parent = Math.floor(key / 256);
18563
+ const list = byNode.get(parent) ?? [];
18564
+ list.push([key % 256, child]);
18565
+ byNode.set(parent, list);
18566
+ }
18567
+ for (const [, child] of byNode.get(0) ?? []) queue.push(child);
18568
+ for (let head = 0; head < queue.length; head++) {
18569
+ const node = queue[head];
18570
+ const fallback = this.fail[node];
18571
+ this.dict[node] = this.out[fallback].length > 0 ? fallback : this.dict[fallback];
18572
+ for (const [byte, child] of byNode.get(node) ?? []) {
18573
+ let state = fallback;
18574
+ let target = this.edges.get(state * 256 + byte);
18575
+ while (target === void 0 && state > 0) {
18576
+ state = this.fail[state];
18577
+ target = this.edges.get(state * 256 + byte);
18578
+ }
18579
+ this.fail[child] = target ?? 0;
18580
+ queue.push(child);
18581
+ }
18582
+ }
18583
+ }
18584
+ step(state, byte) {
18585
+ let current = state;
18586
+ for (; ; ) {
18587
+ const next3 = this.edges.get(current * 256 + byte);
18588
+ if (next3 !== void 0) return next3;
18589
+ if (current === 0) return 0;
18590
+ current = this.fail[current];
18591
+ }
18592
+ }
18593
+ matches(state, visit) {
18594
+ for (let node = state; node > 0; node = this.dict[node]) {
18595
+ for (const id2 of this.out[node]) visit(id2);
18596
+ }
18597
+ }
18598
+ partials(state, length2, visit) {
18599
+ for (let node = state; node > 0; node = this.fail[node]) {
18600
+ if (this.children[node] > 0) visit(length2 - this.depth[node]);
18601
+ }
18602
+ }
18603
+ };
18604
+ var RANK = {
18605
+ raw: 0,
18606
+ fragment: 1,
18607
+ json: 2,
18608
+ percent: 3,
18609
+ html: 4,
18610
+ base64: 5,
18611
+ hex: 6,
18612
+ wrapped: 7
18613
+ };
18614
+ var CR2 = 13;
18615
+ var LF2 = 10;
18616
+ var EMPTY3 = new Uint8Array(0);
18617
+ function register(automaton, sources, ids, bytes, source) {
18618
+ const key = Array.from(bytes).join(",");
18619
+ let id2 = ids.get(key);
18620
+ if (id2 === void 0) {
18621
+ id2 = automaton.add(bytes);
18622
+ ids.set(key, id2);
18623
+ sources[id2] = [];
18624
+ }
18625
+ sources[id2].push(source);
18547
18626
  }
18548
-
18549
- // src/kernel/net/saslprep-tables.ts
18550
- function ranges(text) {
18551
- return text.split(" ").map((item) => {
18552
- const [lo = "0", hi = lo] = item.split("-");
18553
- return [Number.parseInt(lo, 16), Number.parseInt(hi, 16)];
18627
+ function prepare(secrets) {
18628
+ const main = new Automaton();
18629
+ const wrap = new Automaton();
18630
+ const sources = [];
18631
+ const wrapSources = [];
18632
+ const ids = /* @__PURE__ */ new Map();
18633
+ const wrapIds = /* @__PURE__ */ new Map();
18634
+ const values = secrets.map((secret) => utf82(secret.value));
18635
+ secrets.forEach((secret, index) => {
18636
+ if (typeof secret.value !== "string" || values[index].length < MIN_VALUE) {
18637
+ throw new RangeError(`the value of ${secret.name} is shorter than ${MIN_VALUE} bytes`);
18638
+ }
18639
+ for (const shape of shapes(secret.value)) {
18640
+ const source = { secret: index, form: shape.form, offset: shape.offset };
18641
+ register(main, sources, ids, shape.bytes, source);
18642
+ if (wrappable(shape.form)) register(wrap, wrapSources, wrapIds, shape.bytes, source);
18643
+ }
18554
18644
  });
18645
+ main.build();
18646
+ wrap.build();
18647
+ const replacements = secrets.map((secret) => [
18648
+ utf82(secret.placeholder),
18649
+ utf82(`[redacted:${secret.name}]`)
18650
+ ]);
18651
+ return { secrets, values, main, wrap, sources, wrapSources, replacements };
18555
18652
  }
18556
- function within7(table, code) {
18557
- let lo = 0;
18558
- let hi = table.length - 1;
18559
- while (lo <= hi) {
18560
- const mid = lo + hi >> 1;
18561
- const [from, to] = table[mid];
18562
- if (code < from) hi = mid - 1;
18563
- else if (code > to) lo = mid + 1;
18564
- else return true;
18565
- }
18566
- return false;
18567
- }
18568
- var PROHIBITED_TEXT = "0-1F 7F-A0 340-341 6DD 70F 1680 180E 2000-200F 2028-202F 205F-2063 206A-206F 2FF0-2FFB 3000 D800-F8FF FDD0-FDEF FEFF FFF9-FFFF 1D173-1D17A 1FFFE-1FFFF 2FFFE-2FFFF 3FFFE-3FFFF 4FFFE-4FFFF 5FFFE-5FFFF 6FFFE-6FFFF 7FFFE-7FFFF 8FFFE-8FFFF 9FFFE-9FFFF AFFFE-AFFFF BFFFE-BFFFF CFFFE-CFFFF DFFFE-DFFFF E0001 E0020-E007F EFFFE-10FFFF";
18569
- var UNASSIGNED_TEXT = "221 234-24F 2AE-2AF 2EF-2FF 350-35F 370-373 376-379 37B-37D 37F-383 38B 38D 3A2 3CF 3F7-3FF 487 4CF 4F6-4F7 4FA-4FF 510-530 557-558 560 588 58B-590 5A2 5BA 5C5-5CF 5EB-5EF 5F5-60B 60D-61A 61C-61E 620 63B-63F 656-65F 6EE-6EF 6FF 70E 72D-72F 74B-77F 7B2-900 904 93A-93B 94E-94F 955-957 971-980 984 98D-98E 991-992 9A9 9B1 9B3-9B5 9BA-9BB 9BD 9C5-9C6 9C9-9CA 9CE-9D6 9D8-9DB 9DE 9E4-9E5 9FB-A01 A03-A04 A0B-A0E A11-A12 A29 A31 A34 A37 A3A-A3B A3D A43-A46 A49-A4A A4E-A58 A5D A5F-A65 A75-A80 A84 A8C A8E A92 AA9 AB1 AB4 ABA-ABB AC6 ACA ACE-ACF AD1-ADF AE1-AE5 AF0-B00 B04 B0D-B0E B11-B12 B29 B31 B34-B35 B3A-B3B B44-B46 B49-B4A B4E-B55 B58-B5B B5E B62-B65 B71-B81 B84 B8B-B8D B91 B96-B98 B9B B9D BA0-BA2 BA5-BA7 BAB-BAD BB6 BBA-BBD BC3-BC5 BC9 BCE-BD6 BD8-BE6 BF3-C00 C04 C0D C11 C29 C34 C3A-C3D C45 C49 C4E-C54 C57-C5F C62-C65 C70-C81 C84 C8D C91 CA9 CB4 CBA-CBD CC5 CC9 CCE-CD4 CD7-CDD CDF CE2-CE5 CF0-D01 D04 D0D D11 D29 D3A-D3D D44-D45 D49 D4E-D56 D58-D5F D62-D65 D70-D81 D84 D97-D99 DB2 DBC DBE-DBF DC7-DC9 DCB-DCE DD5 DD7 DE0-DF1 DF5-E00 E3B-E3E E5C-E80 E83 E85-E86 E89 E8B-E8C E8E-E93 E98 EA0 EA4 EA6 EA8-EA9 EAC EBA EBE-EBF EC5 EC7 ECE-ECF EDA-EDB EDE-EFF F48 F6B-F70 F8C-F8F F98 FBD FCD-FCE FD0-FFF 1022 1028 102B 1033-1035 103A-103F 105A-109F 10C6-10CF 10F9-10FA 10FC-10FF 115A-115E 11A3-11A7 11FA-11FF 1207 1247 1249 124E-124F 1257 1259 125E-125F 1287 1289 128E-128F 12AF 12B1 12B6-12B7 12BF 12C1 12C6-12C7 12CF 12D7 12EF 130F 1311 1316-1317 131F 1347 135B-1360 137D-139F 13F5-1400 1677-167F 169D-169F 16F1-16FF 170D 1715-171F 1737-173F 1754-175F 176D 1771 1774-177F 17DD-17DF 17EA-17FF 180F 181A-181F 1878-187F 18AA-1DFF 1E9C-1E9F 1EFA-1EFF 1F16-1F17 1F1E-1F1F 1F46-1F47 1F4E-1F4F 1F58 1F5A 1F5C 1F5E 1F7E-1F7F 1FB5 1FC5 1FD4-1FD5 1FDC 1FF0-1FF1 1FF5 1FFF 2053-2056 2058-205E 2064-2069 2072-2073 208F-209F 20B2-20CF 20EB-20FF 213B-213C 214C-2152 2184-218F 23CF-23FF 2427-243F 244B-245F 24FF 2614-2615 2618 267E-267F 268A-2700 2705 270A-270B 2728 274C 274E 2753-2755 2757 275F-2760 2795-2797 27B0 27BF-27CF 27EC-27EF 2B00-2E7F 2E9A 2EF4-2EFF 2FD6-2FEF 2FFC-2FFF 3040 3097-3098 3100-3104 312D-3130 318F 31B8-31EF 321D-321F 3244-3250 327C-327E 32CC-32CF 32FF 3377-337A 33DE-33DF 33FF 4DB6-4DFF 9FA6-9FFF A48D-A48F A4C7-ABFF D7A4-D7FF FA2E-FA2F FA6B-FAFF FB07-FB12 FB18-FB1C FB37 FB3D FB3F FB42 FB45 FBB2-FBD2 FD40-FD4F FD90-FD91 FDC8-FDCF FDFD-FDFF FE10-FE1F FE24-FE2F FE47-FE48 FE53 FE67 FE6C-FE6F FE75 FEFD-FEFE FF00 FFBF-FFC1 FFC8-FFC9 FFD0-FFD1 FFD8-FFD9 FFDD-FFDF FFE7 FFEF-FFF8 10000-102FF 1031F 10324-1032F 1034B-103FF 10426-10427 1044E-1CFFF 1D0F6-1D0FF 1D127-1D129 1D1DE-1D3FF 1D455 1D49D 1D4A0-1D4A1 1D4A3-1D4A4 1D4A7-1D4A8 1D4AD 1D4BA 1D4BC 1D4C1 1D4C4 1D506 1D50B-1D50C 1D515 1D51D 1D53A 1D53F 1D545 1D547-1D549 1D551 1D6A4-1D6A7 1D7CA-1D7CD 1D800-1FFFD 2A6D7-2F7FF 2FA1E-2FFFD 30000-3FFFD 40000-4FFFD 50000-5FFFD 60000-6FFFD 70000-7FFFD 80000-8FFFD 90000-9FFFD A0000-AFFFD B0000-BFFFD C0000-CFFFD D0000-DFFFD E0000 E0002-E001F E0080-EFFFD";
18570
- var RANDAL_TEXT = "5BE 5C0 5C3 5D0-5EA 5F0-5F4 61B 61F 621-63A 640-64A 66D-66F 671-6D5 6DD 6E5-6E6 6FA-6FE 700-70D 710 712-72C 780-7A5 7B1 200F FB1D FB1F-FB28 FB2A-FB36 FB38-FB3C FB3E FB40-FB41 FB43-FB44 FB46-FBB1 FBD3-FD3D FD50-FD8F FD92-FDC7 FDF0-FDFC FE70-FE74 FE76-FEFC";
18571
- var LCAT_TEXT = "41-5A 61-7A AA B5 BA C0-D6 D8-F6 F8-220 222-233 250-2AD 2B0-2B8 2BB-2C1 2D0-2D1 2E0-2E4 2EE 37A 386 388-38A 38C 38E-3A1 3A3-3CE 3D0-3F5 400-482 48A-4CE 4D0-4F5 4F8-4F9 500-50F 531-556 559-55F 561-587 589 903 905-939 93D-940 949-94C 950 958-961 964-970 982-983 985-98C 98F-990 993-9A8 9AA-9B0 9B2 9B6-9B9 9BE-9C0 9C7-9C8 9CB-9CC 9D7 9DC-9DD 9DF-9E1 9E6-9F1 9F4-9FA A05-A0A A0F-A10 A13-A28 A2A-A30 A32-A33 A35-A36 A38-A39 A3E-A40 A59-A5C A5E A66-A6F A72-A74 A83 A85-A8B A8D A8F-A91 A93-AA8 AAA-AB0 AB2-AB3 AB5-AB9 ABD-AC0 AC9 ACB-ACC AD0 AE0 AE6-AEF B02-B03 B05-B0C B0F-B10 B13-B28 B2A-B30 B32-B33 B36-B39 B3D-B3E B40 B47-B48 B4B-B4C B57 B5C-B5D B5F-B61 B66-B70 B83 B85-B8A B8E-B90 B92-B95 B99-B9A B9C B9E-B9F BA3-BA4 BA8-BAA BAE-BB5 BB7-BB9 BBE-BBF BC1-BC2 BC6-BC8 BCA-BCC BD7 BE7-BF2 C01-C03 C05-C0C C0E-C10 C12-C28 C2A-C33 C35-C39 C41-C44 C60-C61 C66-C6F C82-C83 C85-C8C C8E-C90 C92-CA8 CAA-CB3 CB5-CB9 CBE CC0-CC4 CC7-CC8 CCA-CCB CD5-CD6 CDE CE0-CE1 CE6-CEF D02-D03 D05-D0C D0E-D10 D12-D28 D2A-D39 D3E-D40 D46-D48 D4A-D4C D57 D60-D61 D66-D6F D82-D83 D85-D96 D9A-DB1 DB3-DBB DBD DC0-DC6 DCF-DD1 DD8-DDF DF2-DF4 E01-E30 E32-E33 E40-E46 E4F-E5B E81-E82 E84 E87-E88 E8A E8D E94-E97 E99-E9F EA1-EA3 EA5 EA7 EAA-EAB EAD-EB0 EB2-EB3 EBD EC0-EC4 EC6 ED0-ED9 EDC-EDD F00-F17 F1A-F34 F36 F38 F3E-F47 F49-F6A F7F F85 F88-F8B FBE-FC5 FC7-FCC FCF 1000-1021 1023-1027 1029-102A 102C 1031 1038 1040-1057 10A0-10C5 10D0-10F8 10FB 1100-1159 115F-11A2 11A8-11F9 1200-1206 1208-1246 1248 124A-124D 1250-1256 1258 125A-125D 1260-1286 1288 128A-128D 1290-12AE 12B0 12B2-12B5 12B8-12BE 12C0 12C2-12C5 12C8-12CE 12D0-12D6 12D8-12EE 12F0-130E 1310 1312-1315 1318-131E 1320-1346 1348-135A 1361-137C 13A0-13F4 1401-1676 1681-169A 16A0-16F0 1700-170C 170E-1711 1720-1731 1735-1736 1740-1751 1760-176C 176E-1770 1780-17B6 17BE-17C5 17C7-17C8 17D4-17DA 17DC 17E0-17E9 1810-1819 1820-1877 1880-18A8 1E00-1E9B 1EA0-1EF9 1F00-1F15 1F18-1F1D 1F20-1F45 1F48-1F4D 1F50-1F57 1F59 1F5B 1F5D 1F5F-1F7D 1F80-1FB4 1FB6-1FBC 1FBE 1FC2-1FC4 1FC6-1FCC 1FD0-1FD3 1FD6-1FDB 1FE0-1FEC 1FF2-1FF4 1FF6-1FFC 200E 2071 207F 2102 2107 210A-2113 2115 2119-211D 2124 2126 2128 212A-212D 212F-2131 2133-2139 213D-213F 2145-2149 2160-2183 2336-237A 2395 249C-24E9 3005-3007 3021-3029 3031-3035 3038-303C 3041-3096 309D-309F 30A1-30FA 30FC-30FF 3105-312C 3131-318E 3190-31B7 31F0-321C 3220-3243 3260-327B 327F-32B0 32C0-32CB 32D0-32FE 3300-3376 337B-33DD 33E0-33FE 3400-4DB5 4E00-9FA5 A000-A48C AC00-D7A3 D800-FA2D FA30-FA6A FB00-FB06 FB13-FB17 FF21-FF3A FF41-FF5A FF66-FFBE FFC2-FFC7 FFCA-FFCF FFD2-FFD7 FFDA-FFDC 10300-1031E 10320-10323 10330-1034A 10400-10425 10428-1044D 1D000-1D0F5 1D100-1D126 1D12A-1D166 1D16A-1D172 1D183-1D184 1D18C-1D1A9 1D1AE-1D1DD 1D400-1D454 1D456-1D49C 1D49E-1D49F 1D4A2 1D4A5-1D4A6 1D4A9-1D4AC 1D4AE-1D4B9 1D4BB 1D4BD-1D4C0 1D4C2-1D4C3 1D4C5-1D505 1D507-1D50A 1D50D-1D514 1D516-1D51C 1D51E-1D539 1D53B-1D53E 1D540-1D544 1D546 1D54A-1D550 1D552-1D6A3 1D6A8-1D7C9 20000-2A6D6 2F800-2FA1D F0000-FFFFD 100000-10FFFD";
18572
- var PROHIBITED = ranges(PROHIBITED_TEXT);
18573
- var UNASSIGNED = ranges(UNASSIGNED_TEXT);
18574
- var RANDAL = ranges(RANDAL_TEXT);
18575
- var LCAT = ranges(LCAT_TEXT);
18576
- function prepFails(prepared) {
18577
- const codes = Array.from(prepared, (ch) => ch.codePointAt(0) ?? 0);
18578
- if (codes.length === 0) return true;
18579
- if (codes.some((c) => within7(PROHIBITED, c) || within7(UNASSIGNED, c))) return true;
18580
- if (!codes.some((c) => within7(RANDAL, c))) return false;
18581
- if (codes.some((c) => within7(LCAT, c))) return true;
18582
- return !within7(RANDAL, codes[0] ?? 0) || !within7(RANDAL, codes.at(-1) ?? 0);
18653
+ function better(a, b) {
18654
+ if (!b) return true;
18655
+ if (a.end !== b.end) return a.end > b.end;
18656
+ if (a.rank !== b.rank) return a.rank < b.rank;
18657
+ return a.secret < b.secret;
18583
18658
  }
18584
-
18585
- // src/kernel/net/sealed-scram.ts
18586
- var encoder8 = new TextEncoder();
18587
- function base64Bytes(text) {
18588
- try {
18589
- return Uint8Array.from(atob(text), (c) => c.charCodeAt(0));
18590
- } catch {
18591
- return void 0;
18659
+ function resolve(c, input, start2, end, source) {
18660
+ if (source.form !== "fragment") {
18661
+ return {
18662
+ start: start2,
18663
+ end,
18664
+ secret: source.secret,
18665
+ form: source.form,
18666
+ rank: RANK[source.form],
18667
+ growing: false
18668
+ };
18669
+ }
18670
+ const value2 = c.values[source.secret];
18671
+ let stop = end;
18672
+ let at = source.offset + FRAGMENT;
18673
+ while (stop < input.length && at < value2.length && input[stop] === value2[at]) {
18674
+ stop++;
18675
+ at++;
18592
18676
  }
18677
+ const form = source.offset === 0 && at === value2.length ? "raw" : "fragment";
18678
+ const growing = stop === input.length && at < value2.length;
18679
+ return { start: start2, end: stop, secret: source.secret, form, rank: RANK[form], growing };
18593
18680
  }
18594
- function base64Of(bytes) {
18595
- let bin = "";
18596
- for (const b of bytes) bin += String.fromCharCode(b);
18597
- return btoa(bin);
18681
+ function keep(best, candidate) {
18682
+ if (better(candidate, best.get(candidate.start))) best.set(candidate.start, candidate);
18598
18683
  }
18599
- function clientFirstBare(message3) {
18600
- const m = /^n,,(n=[^,]*,r=[^,]+)$/.exec(message3);
18601
- return m ? m[1] : void 0;
18684
+ function scanMain(c, input, best, partials) {
18685
+ let state = 0;
18686
+ for (let i = 0; i < input.length; i++) {
18687
+ state = c.main.step(state, input[i]);
18688
+ c.main.matches(state, (id2) => {
18689
+ const start2 = i + 1 - c.main.lengths[id2];
18690
+ for (const source of c.sources[id2]) {
18691
+ const candidate = resolve(c, input, start2, i + 1, source);
18692
+ if (candidate.growing) partials.push(candidate.start);
18693
+ keep(best, candidate);
18694
+ }
18695
+ });
18696
+ }
18697
+ c.main.partials(state, input.length, (start2) => partials.push(start2));
18602
18698
  }
18603
- var SERVER_FIRST = /^r=([^,]+),s=([^,]+),i=(\d{1,6})$/;
18604
- var CLIENT_FINAL = /^(c=biws,r=([^,]+)),p=([^,]+)$/;
18605
- var SCRAM_MAX = 1024;
18606
- function exchangeOf(clientFirst, serverFirst, clientFinal) {
18607
- const bare = clientFirstBare(clientFirst);
18608
- const sf = SERVER_FIRST.exec(serverFirst);
18609
- const fin = CLIENT_FINAL.exec(clientFinal);
18610
- if (!bare || !sf || !fin || [bare, serverFirst, clientFinal].some((t) => t.length > SCRAM_MAX))
18611
- return void 0;
18612
- const cnonce = bare.slice(bare.indexOf(",r=") + 3);
18613
- const nonce = sf[1];
18614
- const salt = base64Bytes(sf[2]);
18615
- const iterations = Number(sf[3]);
18616
- const proof = base64Bytes(fin[3]);
18617
- const ok4 = fin[2] === nonce && nonce.startsWith(cnonce) && iterations >= 1 && iterations <= 1e5 && salt !== void 0 && proof?.length === 32;
18618
- if (!ok4) return void 0;
18619
- return {
18620
- exchange: {
18621
- clientFirstBare: bare,
18622
- serverFirst,
18623
- clientFinalBare: fin[1],
18624
- salt,
18625
- iterations
18626
- },
18627
- proof
18628
- };
18699
+ function scanWrapped(c, input, best, partials) {
18700
+ const map = [];
18701
+ for (let i = 0; i < input.length; i++) if (input[i] !== CR2 && input[i] !== LF2) map.push(i);
18702
+ if (map.length === input.length) return;
18703
+ let state = 0;
18704
+ for (let v = 0; v < map.length; v++) {
18705
+ state = c.wrap.step(state, input[map[v]]);
18706
+ c.wrap.matches(state, (id2) => {
18707
+ const first = v + 1 - c.wrap.lengths[id2];
18708
+ const start2 = map[first];
18709
+ const end = map[v] + 1;
18710
+ const wrapped = end - start2 !== c.wrap.lengths[id2];
18711
+ for (const source of c.wrapSources[id2]) {
18712
+ const form = wrapped ? "wrapped" : source.form;
18713
+ keep(best, { start: start2, end, secret: source.secret, form, rank: RANK[form], growing: false });
18714
+ }
18715
+ });
18716
+ }
18717
+ c.wrap.partials(state, map.length, (start2) => partials.push(map[start2]));
18629
18718
  }
18630
- async function hmac(key, data) {
18631
- const k = await crypto.subtle.importKey(
18632
- "raw",
18633
- key,
18634
- { name: "HMAC", hash: "SHA-256" },
18635
- false,
18636
- ["sign"]
18637
- );
18638
- return new Uint8Array(await crypto.subtle.sign("HMAC", k, data));
18719
+ function count(c, hits, candidate) {
18720
+ const name2 = c.secrets[candidate.secret].name;
18721
+ const key = `${name2}\0${candidate.form}`;
18722
+ const hit = hits.get(key) ?? { name: name2, form: candidate.form, count: 0 };
18723
+ hit.count += 1;
18724
+ hits.set(key, hit);
18639
18725
  }
18640
- async function scramKeys(password, x) {
18641
- const base = await crypto.subtle.importKey("raw", encoder8.encode(password), "PBKDF2", false, [
18642
- "deriveBits"
18643
- ]);
18644
- const salted = new Uint8Array(
18645
- await crypto.subtle.deriveBits(
18646
- {
18647
- name: "PBKDF2",
18648
- hash: "SHA-256",
18649
- salt: x.salt,
18650
- iterations: x.iterations
18651
- },
18652
- base,
18653
- 256
18654
- )
18655
- );
18656
- const clientKey = await hmac(salted, encoder8.encode("Client Key"));
18657
- const stored = new Uint8Array(
18658
- await crypto.subtle.digest("SHA-256", clientKey)
18659
- );
18660
- const auth = encoder8.encode(`${x.clientFirstBare},${x.serverFirst},${x.clientFinalBare}`);
18661
- const signature = await hmac(stored, auth);
18662
- const proof = clientKey.map((b, i) => b ^ signature[i]);
18663
- const serverKey = await hmac(salted, encoder8.encode("Server Key"));
18664
- const serverSignature = await hmac(serverKey, auth);
18665
- for (const k of [salted, clientKey, stored, signature, serverKey]) k.fill(0);
18666
- return { proof, serverSignature };
18726
+ function concat6(parts2) {
18727
+ let length2 = 0;
18728
+ for (const part of parts2) length2 += part.length;
18729
+ const out = new Uint8Array(length2);
18730
+ let at = 0;
18731
+ for (const part of parts2) {
18732
+ out.set(part, at);
18733
+ at += part.length;
18734
+ }
18735
+ return out;
18667
18736
  }
18668
- var SPACES = /[\u00A0\u1680\u2000-\u200B\u202F\u205F\u3000]/g;
18669
- var NOTHING2 = /\u00AD|\u034F|\u1806|[\u180B-\u180D]|\u200C|\u200D|\u2060|[\uFE00-\uFE0F]|\uFEFF/g;
18670
- function saslprep(password) {
18671
- if (/^[\x00-\x7f]*$/.test(password)) return password;
18672
- const mapped = password.replace(SPACES, " ").replace(NOTHING2, "");
18673
- return prepFails(mapped) ? password : mapped.normalize("NFKC");
18737
+ function pass(c, input, final) {
18738
+ const best = /* @__PURE__ */ new Map();
18739
+ const partials = [];
18740
+ scanMain(c, input, best, partials);
18741
+ scanWrapped(c, input, best, partials);
18742
+ const holds2 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
18743
+ const starts = [...best.keys()].sort((a, b) => a - b);
18744
+ const parts2 = [];
18745
+ const hits = /* @__PURE__ */ new Map();
18746
+ let pos = 0;
18747
+ let cut = input.length;
18748
+ let s = 0;
18749
+ let h = 0;
18750
+ for (; ; ) {
18751
+ while (s < starts.length && starts[s] < pos) s++;
18752
+ while (h < holds2.length && holds2[h] < pos) h++;
18753
+ const hold = h < holds2.length ? holds2[h] : Infinity;
18754
+ const next3 = s < starts.length ? starts[s] : Infinity;
18755
+ if (hold <= next3) {
18756
+ cut = Math.min(hold, input.length);
18757
+ break;
18758
+ }
18759
+ const candidate = best.get(next3);
18760
+ parts2.push(
18761
+ input.subarray(pos, next3),
18762
+ c.replacements[candidate.secret][candidate.form === "raw" ? 0 : 1]
18763
+ );
18764
+ count(c, hits, candidate);
18765
+ pos = candidate.end;
18766
+ }
18767
+ parts2.push(input.subarray(pos, cut));
18768
+ return { output: concat6(parts2), cut, hits };
18674
18769
  }
18675
- function sameBytes(a, b) {
18676
- if (a.length !== b.length) return false;
18677
- let d = 0;
18678
- for (let i = 0; i < a.length; i++) d |= a[i] ^ b[i];
18679
- return d === 0;
18770
+ function merge(into, from) {
18771
+ for (const [key, hit] of from) {
18772
+ const known = into.get(key);
18773
+ if (known) known.count += hit.count;
18774
+ else into.set(key, { ...hit });
18775
+ }
18776
+ }
18777
+ function compile(secrets, options = {}) {
18778
+ const c = prepare(secrets.map((secret) => ({ ...secret })));
18779
+ const decoder4 = new TextDecoder();
18780
+ const idleMs = options.idleMs ?? 250;
18781
+ const scrubBytes = (input) => {
18782
+ if (c.secrets.length === 0) return { bytes: input.slice(), hits: [] };
18783
+ const result = pass(c, input, true);
18784
+ return { bytes: result.output, hits: [...result.hits.values()] };
18785
+ };
18786
+ return {
18787
+ version: options.version ?? 0,
18788
+ idleMs,
18789
+ size: c.main.lengths.length,
18790
+ bytes: scrubBytes,
18791
+ text(input) {
18792
+ const { bytes, hits } = scrubBytes(utf82(input));
18793
+ return { text: decoder4.decode(bytes), hits };
18794
+ },
18795
+ stream() {
18796
+ let pending = EMPTY3;
18797
+ const hits = /* @__PURE__ */ new Map();
18798
+ const run2 = (final) => {
18799
+ if (c.secrets.length === 0 || pending.length === 0) {
18800
+ const out = pending;
18801
+ pending = EMPTY3;
18802
+ return out;
18803
+ }
18804
+ const result = pass(c, pending, final);
18805
+ merge(hits, result.hits);
18806
+ pending = pending.slice(result.cut);
18807
+ return result.output;
18808
+ };
18809
+ return {
18810
+ push(chunk2) {
18811
+ pending = concat6([pending, chunk2]);
18812
+ return run2(false);
18813
+ },
18814
+ idle() {
18815
+ return pending.length < FRAGMENT ? run2(true) : EMPTY3;
18816
+ },
18817
+ end() {
18818
+ return run2(true);
18819
+ },
18820
+ get hits() {
18821
+ return [...hits.values()];
18822
+ }
18823
+ };
18824
+ }
18825
+ };
18680
18826
  }
18681
18827
 
18682
- // src/kernel/net/sealed-pg.ts
18683
- var PG_MESSAGE_MAX = 16 * 1024;
18684
- var PROTOCOL_3 = 196608;
18685
- var CLEARTEXT = 3;
18686
- function int32(bytes, at) {
18687
- return bytes[at] << 24 | bytes[at + 1] << 16 | bytes[at + 2] << 8 | bytes[at + 3];
18828
+ // src/kernel/scrub-file.ts
18829
+ var SCRUB_IDLE_MS = 50;
18830
+ var SCRUB_NONBLOCK_MAX = 64 * 1024;
18831
+ var encoder6 = new TextEncoder();
18832
+ function scrubberOf(secrets) {
18833
+ const usable2 = secrets.filter((s) => encoder6.encode(s.value).length >= MIN_VALUE);
18834
+ return usable2.length > 0 ? compile(usable2, { idleMs: SCRUB_IDLE_MS }) : void 0;
18688
18835
  }
18689
- function sniffPg(start2) {
18690
- const bytes = Uint8Array.from(start2, (c) => c.charCodeAt(0));
18691
- if (bytes.length === 0 || bytes[0] !== 0) return bytes.length === 0 ? "more" : "no";
18692
- if (bytes.length < 8) return "more";
18693
- const length2 = int32(bytes, 0);
18694
- return length2 >= 8 && length2 <= PG_MESSAGE_MAX && int32(bytes, 4) === PROTOCOL_3 ? "yes" : "no";
18836
+ async function writeAll3(file, bytes) {
18837
+ const write = file.write;
18838
+ for (let at = 0; at < bytes.length; ) at += await write.call(file, bytes.subarray(at));
18695
18839
  }
18696
- var PLUS = "SCRAM-SHA-256-PLUS";
18697
- var SASL = 10;
18698
- var SASL_CONTINUE = 11;
18699
- var SASL_FINAL = 12;
18700
- function latin(bytes) {
18701
- let out = "";
18702
- for (const b of bytes) out += String.fromCharCode(b);
18703
- return out;
18840
+ function bound(file, key) {
18841
+ const method = file[key];
18842
+ return typeof method === "function" ? { [key]: method.bind(file) } : {};
18704
18843
  }
18705
- var PgServer = class {
18706
- buffer = new Uint8Array(0);
18707
- skip = 0;
18708
- cleartext = false;
18709
- sasl = false;
18710
- serverFirst;
18711
- expect;
18712
- failed = false;
18713
- lost = false;
18714
- auth(message3) {
18715
- const code = message3.length >= 9 ? int32(message3, 5) : -1;
18716
- if (this.expect && code !== SASL_FINAL) this.failed = true;
18717
- this.cleartext = message3.length === 9 && code === CLEARTEXT;
18718
- if (code === SASL) return this.mechanisms(message3);
18719
- else if (code === SASL_CONTINUE) this.serverFirst = latin(message3.subarray(9));
18720
- else if (code === SASL_FINAL) this.final(message3);
18721
- return message3;
18722
- }
18723
- mechanisms(message3) {
18724
- this.sasl = true;
18725
- const names2 = latin(message3.subarray(9)).split("\0").filter((n) => n !== "" && n !== PLUS);
18726
- return frame3(82, `${latin(message3.subarray(5, 9))}${names2.map((n) => `${n}\0`).join("")}\0`);
18727
- }
18728
- final(message3) {
18729
- const expect = this.expect;
18730
- if (!expect) return;
18731
- this.expect = void 0;
18732
- const data = latin(message3.subarray(9));
18733
- if (data !== expect.real || expect.fake.length !== expect.real.length) {
18734
- this.failed = true;
18735
- return;
18844
+ function interrupted2(err) {
18845
+ const code = err?.code;
18846
+ return code === "EINTR" || code === "EAGAIN";
18847
+ }
18848
+ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
18849
+ const file = inner.file;
18850
+ const stream2 = scrubber.stream();
18851
+ let tail2 = Promise.resolve();
18852
+ let pending = 0;
18853
+ let busy = false;
18854
+ let timer;
18855
+ let failed3;
18856
+ const waiters = /* @__PURE__ */ new Set();
18857
+ const quiet3 = () => !busy && pending === 0;
18858
+ const wake = () => {
18859
+ for (const waiter of [...waiters]) waiter();
18860
+ };
18861
+ const raise = () => {
18862
+ if (failed3 === void 0) return;
18863
+ const err = failed3;
18864
+ failed3 = void 0;
18865
+ throw err;
18866
+ };
18867
+ const later = (bytes) => {
18868
+ if (bytes.length === 0) return;
18869
+ pending += 1;
18870
+ tail2 = tail2.then(() => writeAll3(file, bytes)).catch((err) => {
18871
+ if (failed3 === void 0) failed3 = err;
18872
+ }).finally(() => {
18873
+ pending -= 1;
18874
+ if (quiet3()) wake();
18875
+ });
18876
+ };
18877
+ const settling = (signal) => new Promise((resolve2, reject) => {
18878
+ const done4 = () => {
18879
+ waiters.delete(done4);
18880
+ signal?.removeEventListener("abort", stop);
18881
+ resolve2();
18882
+ };
18883
+ const stop = () => {
18884
+ waiters.delete(done4);
18885
+ reject(new KernelError("EINTR"));
18886
+ };
18887
+ if (signal?.aborted) return stop();
18888
+ waiters.add(done4);
18889
+ signal?.addEventListener("abort", stop, { once: true });
18890
+ });
18891
+ const settled = async () => {
18892
+ while (!quiet3()) await settling();
18893
+ };
18894
+ const changed = async (signal) => {
18895
+ const round = new AbortController();
18896
+ const stop = signal ? AbortSignal.any([signal, round.signal]) : round.signal;
18897
+ try {
18898
+ const own = settling(stop);
18899
+ await Promise.race(file.changed ? [own, file.changed(stop)] : [own]);
18900
+ } catch (err) {
18901
+ throw signal?.aborted ? new KernelError("EINTR") : err;
18902
+ } finally {
18903
+ round.abort();
18736
18904
  }
18737
- for (let i = 0; i < expect.fake.length; i++) message3[9 + i] = expect.fake.charCodeAt(i);
18738
- }
18739
- lose() {
18740
- this.lost = true;
18741
- this.cleartext = false;
18742
- this.sasl = false;
18743
- if (this.expect) this.failed = true;
18744
- this.expect = void 0;
18745
- }
18746
- filter(bytes) {
18747
- if (this.lost) return bytes;
18748
- const data = new Uint8Array(this.buffer.length + bytes.length);
18749
- data.set(this.buffer);
18750
- data.set(bytes, this.buffer.length);
18751
- const out = [];
18752
- let at = 0;
18753
- for (; ; ) {
18754
- const left = data.length - at;
18755
- if (this.skip > 0) {
18756
- const n = Math.min(this.skip, left);
18757
- out.push(data.subarray(at, at + n));
18758
- this.skip -= n;
18759
- at += n;
18760
- if (this.skip > 0) break;
18761
- continue;
18905
+ };
18906
+ const turn = async (signal) => {
18907
+ for (let waited = false; ; waited = true) {
18908
+ if (quiet3() && (pollFile(file).writable || !file.changed)) {
18909
+ busy = true;
18910
+ return;
18762
18911
  }
18763
- if (left < 5) break;
18764
- const whole = 1 + int32(data, at + 1);
18765
- if (whole < 5 || data[at] === 82 && whole > PG_MESSAGE_MAX) {
18766
- this.lose();
18767
- out.push(data.subarray(at));
18768
- at = data.length;
18769
- break;
18912
+ if (signal?.aborted) throw new KernelError(waited ? "EINTR" : "EAGAIN");
18913
+ await changed(signal);
18914
+ }
18915
+ };
18916
+ const send2 = async (out, signal) => {
18917
+ const write = file.write;
18918
+ for (let at = 0; at < out.length; ) {
18919
+ try {
18920
+ at += await write.call(file, out.subarray(at), signal);
18921
+ } catch (err) {
18922
+ if (!signal?.aborted || !interrupted2(err)) throw err;
18770
18923
  }
18771
- if (data[at] !== 82) {
18772
- if (this.expect) {
18773
- this.failed = true;
18774
- break;
18924
+ if (at < out.length && signal?.aborted) return later(out.subarray(at));
18925
+ }
18926
+ };
18927
+ const release = () => {
18928
+ timer = void 0;
18929
+ later(stream2.idle());
18930
+ };
18931
+ return new OpenFile({
18932
+ ...bound(file, "read"),
18933
+ ...bound(file, "peek"),
18934
+ ...bound(file, "stat"),
18935
+ poll: () => {
18936
+ const state = pollFile(file);
18937
+ return quiet3() ? state : { ...state, writable: false };
18938
+ },
18939
+ changed,
18940
+ ...file.tty ? { tty: file.tty } : {},
18941
+ identity: file.identity ?? file,
18942
+ ...file.clipboard ? { clipboard: file.clipboard } : {},
18943
+ ...file.write ? {
18944
+ write: async (bytes, signal) => {
18945
+ await turn(signal);
18946
+ const taken = signal?.aborted && bytes.length > SCRUB_NONBLOCK_MAX ? bytes.subarray(0, SCRUB_NONBLOCK_MAX) : bytes;
18947
+ try {
18948
+ raise();
18949
+ if (timer !== void 0) clearTimeout(timer);
18950
+ timer = void 0;
18951
+ await send2(stream2.push(taken), signal);
18952
+ } finally {
18953
+ busy = false;
18954
+ if (quiet3()) wake();
18775
18955
  }
18776
- this.skip = whole;
18777
- continue;
18956
+ timer = setTimeout(release, idleMs);
18957
+ return taken.length;
18778
18958
  }
18779
- if (left < whole) break;
18780
- out.push(this.auth(data.slice(at, at + whole)));
18781
- at += whole;
18959
+ } : {},
18960
+ flush: async () => {
18961
+ await settled();
18962
+ raise();
18963
+ await file.flush?.();
18964
+ },
18965
+ close: async () => {
18966
+ if (timer !== void 0) clearTimeout(timer);
18967
+ let failure;
18968
+ try {
18969
+ await settled();
18970
+ later(stream2.end());
18971
+ await settled();
18972
+ raise();
18973
+ } catch (err) {
18974
+ failure = { err };
18975
+ }
18976
+ await inner.release();
18977
+ if (failure) throw failure.err;
18782
18978
  }
18783
- this.buffer = data.slice(at);
18784
- const joined4 = new Uint8Array(out.reduce((n, b) => n + b.length, 0));
18785
- let to = 0;
18786
- for (const b of out) {
18787
- joined4.set(b, to);
18788
- to += b.length;
18979
+ });
18980
+ }
18981
+ function scrubbedAll(file, scrubbers) {
18982
+ return scrubbers.reduce((inner, scrubber) => scrubbed(inner, scrubber), file);
18983
+ }
18984
+ function stdioFiles(fds) {
18985
+ const files = /* @__PURE__ */ new Set();
18986
+ for (const fd of [1, 2]) {
18987
+ try {
18988
+ files.add(fds.get(fd));
18989
+ } catch {
18789
18990
  }
18790
- return joined4;
18791
18991
  }
18792
- };
18793
- function frame3(type, body) {
18794
- const out = new Uint8Array(5 + body.length);
18795
- out[0] = type;
18796
- const length2 = 4 + body.length;
18797
- out.set([length2 >>> 24 & 255, length2 >>> 16 & 255, length2 >>> 8 & 255, length2 & 255], 1);
18798
- for (let i = 0; i < body.length; i++) out[5 + i] = body.charCodeAt(i);
18799
- return out;
18800
- }
18801
- function pgLength(bytes, started) {
18802
- const header4 = started ? 5 : 4;
18803
- if (bytes.length < header4) return void 0;
18804
- const length2 = int32(bytes, started ? 1 : 0);
18805
- return started ? 1 + length2 : length2;
18992
+ return files;
18806
18993
  }
18807
- var MECHANISMS = /* @__PURE__ */ new Set(["SCRAM-SHA-256"]);
18808
- async function cleartext(message3, asks) {
18809
- const body = latin(message3.subarray(5));
18810
- if (!body.endsWith("\0") || body.indexOf("\0") !== body.length - 1)
18811
- return { bytes: message3, done: true };
18812
- const password = body.slice(0, -1);
18813
- const placeholders = placeholdersIn(password);
18814
- if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS)
18815
- return { bytes: message3, done: true };
18816
- const values = usable(await asks.cleartext(placeholders));
18817
- if (Object.keys(values).length === 0) return { bytes: message3, done: true };
18818
- return { bytes: frame3(112, `${replaced(password, values)}\0`), values, done: true };
18994
+ function scrubStdio(fds, scrubber) {
18995
+ const wrapped = /* @__PURE__ */ new Map();
18996
+ const stdio = stdioFiles(fds);
18997
+ for (const fd of fds.numbers()) {
18998
+ const original = fds.get(fd);
18999
+ if (!stdio.has(original) && !original.file.tty && !original.file.clipboard) continue;
19000
+ const known = wrapped.get(original);
19001
+ const flags2 = fds.statusFlags(fd);
19002
+ const wrapper = known ? known.retain() : scrubbed(original.retain(), scrubber);
19003
+ wrapped.set(original, wrapper);
19004
+ fds.installAt(fd, wrapper);
19005
+ if (flags2 !== void 0) fds.setStatusFlags(fd, flags2);
19006
+ }
18819
19007
  }
18820
- function initial(message3) {
18821
- const body = latin(message3.subarray(5));
18822
- const nul = body.indexOf("\0");
18823
- if (nul < 0 || !MECHANISMS.has(body.slice(0, nul)) || body.length < nul + 5) return void 0;
18824
- const data = message3.subarray(5 + nul + 5);
18825
- return int32(message3, 5 + nul + 1) === data.length ? latin(data) : void 0;
18826
- }
18827
- var PgClient = class {
18828
- clientFirst;
18829
- server;
18830
- asks;
18831
- constructor(server, asks) {
18832
- this.server = server;
18833
- this.asks = asks;
18834
- }
18835
- async message(message3) {
18836
- const server = this.server;
18837
- if (message3[0] !== 112) return { bytes: message3, done: true };
18838
- if (server.cleartext) {
18839
- server.cleartext = false;
18840
- return cleartext(message3, this.asks);
18841
- }
18842
- if (server.sasl && this.clientFirst === void 0) {
18843
- this.clientFirst = initial(message3);
18844
- return { bytes: message3, done: this.clientFirst === void 0 };
18845
- }
18846
- if (this.clientFirst !== void 0 && server.serverFirst !== void 0)
18847
- return this.final(message3, this.clientFirst, server.serverFirst);
18848
- return { bytes: message3, done: true };
18849
- }
18850
- async final(message3, first, serverFirst) {
18851
- const got = exchangeOf(first, serverFirst, latin(message3.subarray(5)));
18852
- if (!got) return { bytes: message3, done: true };
18853
- const x = got.exchange;
18854
- const values = usable(
18855
- await this.asks.scram({
18856
- clientFirstBare: x.clientFirstBare,
18857
- serverFirst: x.serverFirst,
18858
- clientFinalBare: x.clientFinalBare,
18859
- proof: base64Of(got.proof)
18860
- })
18861
- );
18862
- const [entry, ...more] = Object.entries(values);
18863
- if (!entry || more.length > 0) return { bytes: message3, done: true };
18864
- const [placeholder, value2] = entry;
18865
- const fake = await scramKeys(placeholder, x);
18866
- if (!sameBytes(fake.proof, got.proof)) return { bytes: message3, done: true };
18867
- const real = await scramKeys(saslprep(value2), x);
18868
- this.server.expect = {
18869
- real: `v=${base64Of(real.serverSignature)}`,
18870
- fake: `v=${base64Of(fake.serverSignature)}`
18871
- };
18872
- const bytes = frame3(112, `${x.clientFinalBare},p=${base64Of(real.proof)}`);
18873
- for (const k of [real.proof, real.serverSignature, fake.proof, fake.serverSignature]) k.fill(0);
18874
- return { bytes, values, done: true };
18875
- }
18876
- };
18877
19008
 
18878
- // src/kernel/net/sealed-smtp.ts
18879
- var SMTP_LINE_MAX = 4096;
18880
- var GREETING = ["EHLO ", "HELO "];
18881
- function sniffSmtp(start2) {
18882
- const upper = start2.toUpperCase();
18883
- for (const word of GREETING) {
18884
- if (upper.startsWith(word)) return "yes";
18885
- if (word.startsWith(upper)) return "more";
19009
+ // src/kernel/net/sealed-http1.ts
19010
+ var HTTP1_METHODS = [
19011
+ "GET",
19012
+ "HEAD",
19013
+ "POST",
19014
+ "PUT",
19015
+ "DELETE",
19016
+ "PATCH",
19017
+ "OPTIONS",
19018
+ "CONNECT",
19019
+ "TRACE"
19020
+ ];
19021
+ var HEAD_MAX = 16 * 1024;
19022
+ var ANY_PLACEHOLDER = /fnox_proxy_[0-9a-f]{24}/g;
19023
+ var REQUEST_LINE2 = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+) ([\x21-\x7e]+) HTTP\/1\.[01]$/;
19024
+ var HEADER_LINE = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+):[ \t]*(.*?)[ \t]*$/;
19025
+ var BASIC = /^(Basic[ \t]+)([A-Za-z0-9+/]+={0,2})$/i;
19026
+ var encoder7 = new TextEncoder();
19027
+ function binary(text) {
19028
+ let out = "";
19029
+ for (const b of encoder7.encode(text)) out += String.fromCharCode(b);
19030
+ return out;
19031
+ }
19032
+ function sniffHttp1(start2) {
19033
+ for (const method of HTTP1_METHODS) {
19034
+ const word = `${method} `;
19035
+ if (start2.startsWith(word)) return "yes";
19036
+ if (word.startsWith(start2)) return "more";
18886
19037
  }
18887
19038
  return "no";
18888
19039
  }
18889
- function decoded(b64) {
18890
- if (!/^[A-Za-z0-9+/]+={0,2}$/.test(b64)) return void 0;
19040
+ function basicOf(value2) {
19041
+ const m = BASIC.exec(value2);
19042
+ if (!m) return void 0;
18891
19043
  try {
18892
- return atob(b64);
19044
+ return { scheme: m[1], decoded: atob(m[2]) };
18893
19045
  } catch {
18894
19046
  return void 0;
18895
19047
  }
18896
19048
  }
18897
- async function swapped2(text, position, ask) {
18898
- const placeholders = placeholdersIn(text);
18899
- if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS) return void 0;
18900
- const values = usable(await ask(position, placeholders));
18901
- if (Object.keys(values).length === 0) return void 0;
18902
- return { text: replaced(text, values), values };
18903
- }
18904
- async function plain2(b64, ask) {
18905
- const text = decoded(b64);
18906
- const fields = text?.split("\0");
18907
- if (fields?.length !== 3) return { line: b64 };
18908
- const [authz, user, pass2] = fields;
18909
- if (placeholdersIn(authz + user).length > 0) return { line: b64 };
18910
- const done4 = await swapped2(pass2, "auth-plain", ask);
18911
- if (!done4) return { line: b64 };
18912
- return { line: btoa(`${authz}\0${user}\0${done4.text}`), values: done4.values };
18913
- }
18914
- async function login(b64, ask) {
18915
- const text = decoded(b64);
18916
- const done4 = text === void 0 ? void 0 : await swapped2(text, "auth-login", ask);
18917
- return done4 ? { line: btoa(done4.text), values: done4.values } : { line: b64 };
19049
+ function placeholdersIn(text) {
19050
+ return [...new Set(text.match(ANY_PLACEHOLDER) ?? [])];
18918
19051
  }
18919
- var SmtpClient = class {
18920
- state = "command";
18921
- ask;
18922
- constructor(ask) {
18923
- this.ask = ask;
18924
- }
18925
- get done() {
18926
- return this.state === "done";
18927
- }
18928
- async line(text) {
18929
- const state = this.state;
18930
- if (state === "done") return { line: text };
18931
- if (state === "plain" || state === "password") {
18932
- this.state = "done";
18933
- if (text === "*") return { line: text };
18934
- return state === "plain" ? plain2(text, this.ask) : login(text, this.ask);
18935
- }
18936
- if (state === "user") {
18937
- this.state = text === "*" ? "done" : "password";
18938
- return { line: text };
18939
- }
18940
- return this.command(text);
18941
- }
18942
- async command(text) {
18943
- const m = /^AUTH[ \t]+(PLAIN|LOGIN)(?:[ \t]+(\S+))?$/i.exec(text);
18944
- if (!m) {
18945
- if (/^(MAIL|RCPT|DATA|BDAT|AUTH)\b/i.test(text)) this.state = "done";
18946
- return { line: text };
18947
- }
18948
- const mech = m[1].toUpperCase();
18949
- const arg = m[2];
18950
- if (mech === "LOGIN") {
18951
- this.state = arg === void 0 ? "user" : "password";
18952
- return { line: text };
18953
- }
18954
- if (arg === void 0) {
18955
- this.state = "plain";
18956
- return { line: text };
18957
- }
18958
- this.state = "done";
18959
- const out = await plain2(arg, this.ask);
18960
- return {
18961
- line: `${text.slice(0, text.length - arg.length)}${out.line}`,
18962
- ...out.values ? { values: out.values } : {}
18963
- };
19052
+ function scan(lines2) {
19053
+ const found = [];
19054
+ for (let i = 1; i < lines2.length; i++) {
19055
+ const m = HEADER_LINE.exec(lines2[i]);
19056
+ if (!m) return void 0;
19057
+ const value2 = m[2];
19058
+ const basic = basicOf(value2);
19059
+ const placeholders = placeholdersIn(basic ? basic.decoded : value2);
19060
+ if (placeholders.length > 0)
19061
+ found.push({ line: i, name: m[1].toLowerCase(), value: value2, basic, placeholders });
18964
19062
  }
18965
- };
18966
-
18967
- // src/kernel/net/sealed-conn.ts
18968
- var HEAD_IDLE_MS = 2e3;
18969
- function substitutes(s) {
18970
- return s.verified && s.alpn !== "h2" && s.broker.hook !== void 0 && typeof s.exit === "string" && SESSION_EXIT.test(s.exit);
18971
- }
18972
- function sessionId() {
18973
- const bytes = crypto.getRandomValues(new Uint8Array(24));
18974
- let bin = "";
18975
- for (const b of bytes) bin += String.fromCharCode(b);
18976
- return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_");
19063
+ return found;
18977
19064
  }
18978
- function latin12(bytes) {
18979
- let out = "";
18980
- for (const b of bytes) out += String.fromCharCode(b);
19065
+ function replaced(text, values) {
19066
+ let out = text;
19067
+ for (const [ph, value2] of Object.entries(values)) out = out.split(ph).join(binary(value2));
18981
19068
  return out;
18982
19069
  }
18983
- function bytesOf(text) {
18984
- const out = new Uint8Array(text.length);
18985
- for (let i = 0; i < text.length; i++) out[i] = text.charCodeAt(i);
19070
+ function usable(values) {
19071
+ const out = {};
19072
+ for (const [ph, value2] of Object.entries(values ?? {}))
19073
+ if (encoder7.encode(value2).length >= MIN_VALUE) out[ph] = value2;
18986
19074
  return out;
18987
19075
  }
18988
- async function writeAll4(conn, bytes) {
18989
- for (let at = 0; at < bytes.length; ) at += await conn.write(bytes.subarray(at));
18990
- }
18991
- var CRLF2 = [13, 10, 13, 10];
18992
- function headEnd2(bytes) {
18993
- for (let i = 0; i + 3 < bytes.length; i++) {
18994
- if (CRLF2.every((b, k) => bytes[i + k] === b)) return i + 4;
18995
- }
18996
- return -1;
19076
+ async function substituteHead(head, ask) {
19077
+ if (!head.endsWith("\r\n\r\n")) return void 0;
19078
+ const lines2 = head.slice(0, -4).split("\r\n");
19079
+ if (lines2.some((l) => l.includes("\n") || l.includes("\r"))) return void 0;
19080
+ const request = REQUEST_LINE2.exec(lines2[0]);
19081
+ const found = request ? scan(lines2) : void 0;
19082
+ if (!request || !found || found.length !== 1) return void 0;
19083
+ const at = found[0];
19084
+ if (at.placeholders.length > SESSION_PLACEHOLDERS) return void 0;
19085
+ const values = usable(
19086
+ await ask(`header:${at.name}`, at.placeholders, {
19087
+ method: request[1],
19088
+ path: request[2]
19089
+ })
19090
+ );
19091
+ if (Object.keys(values).length === 0) return void 0;
19092
+ const value2 = at.basic ? `${at.basic.scheme}${btoa(replaced(at.basic.decoded, values))}` : replaced(at.value, values);
19093
+ const out = [...lines2];
19094
+ out[at.line] = `${lines2[at.line].split(":")[0]}: ${value2}`;
19095
+ return { head: `${out.join("\r\n")}\r
19096
+ \r
19097
+ `, values };
18997
19098
  }
18998
- function modeOf(start2) {
18999
- const sniffs = [
19000
- ["http1", sniffHttp1(start2)],
19001
- ["smtp", sniffSmtp(start2)],
19002
- ["pg", sniffPg(start2)]
19003
- ];
19004
- const hit = sniffs.find(([, v]) => v === "yes");
19005
- if (hit) return hit[0];
19006
- return sniffs.every(([, v]) => v === "no") ? "pass" : void 0;
19099
+
19100
+ // src/kernel/net/saslprep-tables.ts
19101
+ function ranges(text) {
19102
+ return text.split(" ").map((item) => {
19103
+ const [lo = "0", hi = lo] = item.split("-");
19104
+ return [Number.parseInt(lo, 16), Number.parseInt(hi, 16)];
19105
+ });
19007
19106
  }
19008
- function crlf(bytes) {
19009
- for (let i = 0; i + 1 < bytes.length; i++) if (bytes[i] === 13 && bytes[i + 1] === 10) return i;
19010
- return -1;
19107
+ function within7(table, code) {
19108
+ let lo = 0;
19109
+ let hi = table.length - 1;
19110
+ while (lo <= hi) {
19111
+ const mid = lo + hi >> 1;
19112
+ const [from, to] = table[mid];
19113
+ if (code < from) hi = mid - 1;
19114
+ else if (code > to) lo = mid + 1;
19115
+ else return true;
19116
+ }
19117
+ return false;
19011
19118
  }
19012
- var SessionWriter = class {
19013
- buffer = new Uint8Array(0);
19014
- mode = "sniff";
19015
- timer;
19016
- chain = Promise.resolve();
19017
- failed;
19018
- session = sessionId();
19019
- smtp;
19020
- pgStarted = false;
19021
- sawPg = false;
19022
- conn;
19023
- s;
19024
- pgClient;
19025
- scope;
19026
- constructor(conn, s, pg, scope) {
19027
- this.conn = conn;
19028
- this.s = s;
19029
- this.scope = scope;
19030
- this.pgClient = new PgClient(pg, {
19031
- cleartext: (placeholders) => this.ask("pg", "password-cleartext", { placeholders }),
19032
- scram: (scram) => this.ask("pg", "scram-sha-256", { scram })
19033
- });
19034
- this.smtp = new SmtpClient(
19035
- (position, placeholders) => this.ask("smtp", position, { placeholders })
19036
- );
19037
- }
19038
- write(bytes) {
19039
- const run2 = this.chain.then(() => this.take(bytes));
19040
- this.chain = run2.then(
19041
- () => void 0,
19042
- () => void 0
19043
- );
19044
- return run2;
19045
- }
19046
- async ask(protocol, position, extra) {
19047
- const s = this.s;
19048
- const values = await s.broker.sessionMaterialize({
19049
- stamp: await s.stamp(),
19050
- session: this.session,
19051
- host: s.host,
19052
- port: s.port,
19053
- protocol,
19054
- position,
19055
- verified: s.verified,
19056
- handshakeAt: s.handshakeAt,
19057
- exit: s.exit,
19058
- ...extra
19059
- });
19060
- return values;
19061
- }
19062
- remember(values) {
19063
- this.scope.add(
19064
- Object.entries(values).map(([placeholder, value2]) => ({ name: "sealed", value: value2, placeholder }))
19065
- );
19066
- }
19067
- async take(bytes) {
19068
- if (this.failed !== void 0) throw this.failed;
19069
- if (this.mode === "pass") return this.conn.write(bytes);
19070
- clearTimeout(this.timer);
19071
- const joined4 = new Uint8Array(this.buffer.length + bytes.length);
19072
- joined4.set(this.buffer);
19073
- joined4.set(bytes, this.buffer.length);
19074
- this.buffer.fill(0);
19075
- this.buffer = joined4;
19076
- if (this.mode === "sniff") this.mode = modeOf(latin12(joined4.subarray(0, 8))) ?? "sniff";
19077
- if (this.mode === "pg") this.sawPg = true;
19078
- if (this.mode === "pass") await this.release();
19079
- else if (this.mode === "http1") await this.http1();
19080
- else if (this.mode === "smtp") await this.lines();
19081
- else if (this.mode === "pg") await this.messages();
19082
- if (this.mode !== "pass" && this.buffer.length > 0)
19083
- this.timer = setTimeout(() => this.idle(), HEAD_IDLE_MS);
19084
- return bytes.length;
19085
- }
19086
- async http1() {
19087
- const end = headEnd2(this.buffer);
19088
- if (end > HEAD_MAX || end < 0 && this.buffer.length > HEAD_MAX) await this.release();
19089
- else if (end >= 0) await this.substitute(end);
19090
- }
19091
- async lines() {
19092
- for (; ; ) {
19093
- const at = crlf(this.buffer);
19094
- if (at < 0) break;
19095
- if (at > SMTP_LINE_MAX) return this.release();
19096
- const all = this.buffer;
19097
- this.buffer = all.slice(at + 2);
19098
- const out = await this.smtp.line(latin12(all.subarray(0, at))).catch(() => ({ line: latin12(all.subarray(0, at)) }));
19099
- all.fill(0);
19100
- if ("values" in out && out.values) this.remember(out.values);
19101
- const line = bytesOf(`${out.line}\r
19102
- `);
19103
- try {
19104
- await writeAll4(this.conn, line);
19105
- } finally {
19106
- line.fill(0);
19107
- }
19108
- if (this.smtp.done) return this.release();
19109
- }
19110
- if (this.buffer.length > SMTP_LINE_MAX) await this.release();
19111
- }
19112
- async messages() {
19113
- for (; ; ) {
19114
- const whole = pgLength(this.buffer, this.pgStarted);
19115
- if (whole === void 0 || whole < 4 || whole > PG_MESSAGE_MAX) {
19116
- if (whole !== void 0) await this.release();
19117
- return;
19118
- }
19119
- if (this.buffer.length < whole) return;
19120
- const message3 = this.buffer.slice(0, whole);
19121
- this.buffer = this.buffer.slice(whole);
19122
- const started = this.pgStarted;
19123
- this.pgStarted = true;
19124
- const out = started ? await this.pgClient.message(message3).catch(() => ({ bytes: message3, done: true })) : { bytes: message3, done: false };
19125
- if ("values" in out && out.values) this.remember(out.values);
19126
- try {
19127
- await writeAll4(this.conn, out.bytes);
19128
- } finally {
19129
- out.bytes.fill(0);
19130
- message3.fill(0);
19131
- }
19132
- if (out.done) return this.release();
19133
- }
19119
+ var PROHIBITED_TEXT = "0-1F 7F-A0 340-341 6DD 70F 1680 180E 2000-200F 2028-202F 205F-2063 206A-206F 2FF0-2FFB 3000 D800-F8FF FDD0-FDEF FEFF FFF9-FFFF 1D173-1D17A 1FFFE-1FFFF 2FFFE-2FFFF 3FFFE-3FFFF 4FFFE-4FFFF 5FFFE-5FFFF 6FFFE-6FFFF 7FFFE-7FFFF 8FFFE-8FFFF 9FFFE-9FFFF AFFFE-AFFFF BFFFE-BFFFF CFFFE-CFFFF DFFFE-DFFFF E0001 E0020-E007F EFFFE-10FFFF";
19120
+ var UNASSIGNED_TEXT = "221 234-24F 2AE-2AF 2EF-2FF 350-35F 370-373 376-379 37B-37D 37F-383 38B 38D 3A2 3CF 3F7-3FF 487 4CF 4F6-4F7 4FA-4FF 510-530 557-558 560 588 58B-590 5A2 5BA 5C5-5CF 5EB-5EF 5F5-60B 60D-61A 61C-61E 620 63B-63F 656-65F 6EE-6EF 6FF 70E 72D-72F 74B-77F 7B2-900 904 93A-93B 94E-94F 955-957 971-980 984 98D-98E 991-992 9A9 9B1 9B3-9B5 9BA-9BB 9BD 9C5-9C6 9C9-9CA 9CE-9D6 9D8-9DB 9DE 9E4-9E5 9FB-A01 A03-A04 A0B-A0E A11-A12 A29 A31 A34 A37 A3A-A3B A3D A43-A46 A49-A4A A4E-A58 A5D A5F-A65 A75-A80 A84 A8C A8E A92 AA9 AB1 AB4 ABA-ABB AC6 ACA ACE-ACF AD1-ADF AE1-AE5 AF0-B00 B04 B0D-B0E B11-B12 B29 B31 B34-B35 B3A-B3B B44-B46 B49-B4A B4E-B55 B58-B5B B5E B62-B65 B71-B81 B84 B8B-B8D B91 B96-B98 B9B B9D BA0-BA2 BA5-BA7 BAB-BAD BB6 BBA-BBD BC3-BC5 BC9 BCE-BD6 BD8-BE6 BF3-C00 C04 C0D C11 C29 C34 C3A-C3D C45 C49 C4E-C54 C57-C5F C62-C65 C70-C81 C84 C8D C91 CA9 CB4 CBA-CBD CC5 CC9 CCE-CD4 CD7-CDD CDF CE2-CE5 CF0-D01 D04 D0D D11 D29 D3A-D3D D44-D45 D49 D4E-D56 D58-D5F D62-D65 D70-D81 D84 D97-D99 DB2 DBC DBE-DBF DC7-DC9 DCB-DCE DD5 DD7 DE0-DF1 DF5-E00 E3B-E3E E5C-E80 E83 E85-E86 E89 E8B-E8C E8E-E93 E98 EA0 EA4 EA6 EA8-EA9 EAC EBA EBE-EBF EC5 EC7 ECE-ECF EDA-EDB EDE-EFF F48 F6B-F70 F8C-F8F F98 FBD FCD-FCE FD0-FFF 1022 1028 102B 1033-1035 103A-103F 105A-109F 10C6-10CF 10F9-10FA 10FC-10FF 115A-115E 11A3-11A7 11FA-11FF 1207 1247 1249 124E-124F 1257 1259 125E-125F 1287 1289 128E-128F 12AF 12B1 12B6-12B7 12BF 12C1 12C6-12C7 12CF 12D7 12EF 130F 1311 1316-1317 131F 1347 135B-1360 137D-139F 13F5-1400 1677-167F 169D-169F 16F1-16FF 170D 1715-171F 1737-173F 1754-175F 176D 1771 1774-177F 17DD-17DF 17EA-17FF 180F 181A-181F 1878-187F 18AA-1DFF 1E9C-1E9F 1EFA-1EFF 1F16-1F17 1F1E-1F1F 1F46-1F47 1F4E-1F4F 1F58 1F5A 1F5C 1F5E 1F7E-1F7F 1FB5 1FC5 1FD4-1FD5 1FDC 1FF0-1FF1 1FF5 1FFF 2053-2056 2058-205E 2064-2069 2072-2073 208F-209F 20B2-20CF 20EB-20FF 213B-213C 214C-2152 2184-218F 23CF-23FF 2427-243F 244B-245F 24FF 2614-2615 2618 267E-267F 268A-2700 2705 270A-270B 2728 274C 274E 2753-2755 2757 275F-2760 2795-2797 27B0 27BF-27CF 27EC-27EF 2B00-2E7F 2E9A 2EF4-2EFF 2FD6-2FEF 2FFC-2FFF 3040 3097-3098 3100-3104 312D-3130 318F 31B8-31EF 321D-321F 3244-3250 327C-327E 32CC-32CF 32FF 3377-337A 33DE-33DF 33FF 4DB6-4DFF 9FA6-9FFF A48D-A48F A4C7-ABFF D7A4-D7FF FA2E-FA2F FA6B-FAFF FB07-FB12 FB18-FB1C FB37 FB3D FB3F FB42 FB45 FBB2-FBD2 FD40-FD4F FD90-FD91 FDC8-FDCF FDFD-FDFF FE10-FE1F FE24-FE2F FE47-FE48 FE53 FE67 FE6C-FE6F FE75 FEFD-FEFE FF00 FFBF-FFC1 FFC8-FFC9 FFD0-FFD1 FFD8-FFD9 FFDD-FFDF FFE7 FFEF-FFF8 10000-102FF 1031F 10324-1032F 1034B-103FF 10426-10427 1044E-1CFFF 1D0F6-1D0FF 1D127-1D129 1D1DE-1D3FF 1D455 1D49D 1D4A0-1D4A1 1D4A3-1D4A4 1D4A7-1D4A8 1D4AD 1D4BA 1D4BC 1D4C1 1D4C4 1D506 1D50B-1D50C 1D515 1D51D 1D53A 1D53F 1D545 1D547-1D549 1D551 1D6A4-1D6A7 1D7CA-1D7CD 1D800-1FFFD 2A6D7-2F7FF 2FA1E-2FFFD 30000-3FFFD 40000-4FFFD 50000-5FFFD 60000-6FFFD 70000-7FFFD 80000-8FFFD 90000-9FFFD A0000-AFFFD B0000-BFFFD C0000-CFFFD D0000-DFFFD E0000 E0002-E001F E0080-EFFFD";
19121
+ var RANDAL_TEXT = "5BE 5C0 5C3 5D0-5EA 5F0-5F4 61B 61F 621-63A 640-64A 66D-66F 671-6D5 6DD 6E5-6E6 6FA-6FE 700-70D 710 712-72C 780-7A5 7B1 200F FB1D FB1F-FB28 FB2A-FB36 FB38-FB3C FB3E FB40-FB41 FB43-FB44 FB46-FBB1 FBD3-FD3D FD50-FD8F FD92-FDC7 FDF0-FDFC FE70-FE74 FE76-FEFC";
19122
+ var LCAT_TEXT = "41-5A 61-7A AA B5 BA C0-D6 D8-F6 F8-220 222-233 250-2AD 2B0-2B8 2BB-2C1 2D0-2D1 2E0-2E4 2EE 37A 386 388-38A 38C 38E-3A1 3A3-3CE 3D0-3F5 400-482 48A-4CE 4D0-4F5 4F8-4F9 500-50F 531-556 559-55F 561-587 589 903 905-939 93D-940 949-94C 950 958-961 964-970 982-983 985-98C 98F-990 993-9A8 9AA-9B0 9B2 9B6-9B9 9BE-9C0 9C7-9C8 9CB-9CC 9D7 9DC-9DD 9DF-9E1 9E6-9F1 9F4-9FA A05-A0A A0F-A10 A13-A28 A2A-A30 A32-A33 A35-A36 A38-A39 A3E-A40 A59-A5C A5E A66-A6F A72-A74 A83 A85-A8B A8D A8F-A91 A93-AA8 AAA-AB0 AB2-AB3 AB5-AB9 ABD-AC0 AC9 ACB-ACC AD0 AE0 AE6-AEF B02-B03 B05-B0C B0F-B10 B13-B28 B2A-B30 B32-B33 B36-B39 B3D-B3E B40 B47-B48 B4B-B4C B57 B5C-B5D B5F-B61 B66-B70 B83 B85-B8A B8E-B90 B92-B95 B99-B9A B9C B9E-B9F BA3-BA4 BA8-BAA BAE-BB5 BB7-BB9 BBE-BBF BC1-BC2 BC6-BC8 BCA-BCC BD7 BE7-BF2 C01-C03 C05-C0C C0E-C10 C12-C28 C2A-C33 C35-C39 C41-C44 C60-C61 C66-C6F C82-C83 C85-C8C C8E-C90 C92-CA8 CAA-CB3 CB5-CB9 CBE CC0-CC4 CC7-CC8 CCA-CCB CD5-CD6 CDE CE0-CE1 CE6-CEF D02-D03 D05-D0C D0E-D10 D12-D28 D2A-D39 D3E-D40 D46-D48 D4A-D4C D57 D60-D61 D66-D6F D82-D83 D85-D96 D9A-DB1 DB3-DBB DBD DC0-DC6 DCF-DD1 DD8-DDF DF2-DF4 E01-E30 E32-E33 E40-E46 E4F-E5B E81-E82 E84 E87-E88 E8A E8D E94-E97 E99-E9F EA1-EA3 EA5 EA7 EAA-EAB EAD-EB0 EB2-EB3 EBD EC0-EC4 EC6 ED0-ED9 EDC-EDD F00-F17 F1A-F34 F36 F38 F3E-F47 F49-F6A F7F F85 F88-F8B FBE-FC5 FC7-FCC FCF 1000-1021 1023-1027 1029-102A 102C 1031 1038 1040-1057 10A0-10C5 10D0-10F8 10FB 1100-1159 115F-11A2 11A8-11F9 1200-1206 1208-1246 1248 124A-124D 1250-1256 1258 125A-125D 1260-1286 1288 128A-128D 1290-12AE 12B0 12B2-12B5 12B8-12BE 12C0 12C2-12C5 12C8-12CE 12D0-12D6 12D8-12EE 12F0-130E 1310 1312-1315 1318-131E 1320-1346 1348-135A 1361-137C 13A0-13F4 1401-1676 1681-169A 16A0-16F0 1700-170C 170E-1711 1720-1731 1735-1736 1740-1751 1760-176C 176E-1770 1780-17B6 17BE-17C5 17C7-17C8 17D4-17DA 17DC 17E0-17E9 1810-1819 1820-1877 1880-18A8 1E00-1E9B 1EA0-1EF9 1F00-1F15 1F18-1F1D 1F20-1F45 1F48-1F4D 1F50-1F57 1F59 1F5B 1F5D 1F5F-1F7D 1F80-1FB4 1FB6-1FBC 1FBE 1FC2-1FC4 1FC6-1FCC 1FD0-1FD3 1FD6-1FDB 1FE0-1FEC 1FF2-1FF4 1FF6-1FFC 200E 2071 207F 2102 2107 210A-2113 2115 2119-211D 2124 2126 2128 212A-212D 212F-2131 2133-2139 213D-213F 2145-2149 2160-2183 2336-237A 2395 249C-24E9 3005-3007 3021-3029 3031-3035 3038-303C 3041-3096 309D-309F 30A1-30FA 30FC-30FF 3105-312C 3131-318E 3190-31B7 31F0-321C 3220-3243 3260-327B 327F-32B0 32C0-32CB 32D0-32FE 3300-3376 337B-33DD 33E0-33FE 3400-4DB5 4E00-9FA5 A000-A48C AC00-D7A3 D800-FA2D FA30-FA6A FB00-FB06 FB13-FB17 FF21-FF3A FF41-FF5A FF66-FFBE FFC2-FFC7 FFCA-FFCF FFD2-FFD7 FFDA-FFDC 10300-1031E 10320-10323 10330-1034A 10400-10425 10428-1044D 1D000-1D0F5 1D100-1D126 1D12A-1D166 1D16A-1D172 1D183-1D184 1D18C-1D1A9 1D1AE-1D1DD 1D400-1D454 1D456-1D49C 1D49E-1D49F 1D4A2 1D4A5-1D4A6 1D4A9-1D4AC 1D4AE-1D4B9 1D4BB 1D4BD-1D4C0 1D4C2-1D4C3 1D4C5-1D505 1D507-1D50A 1D50D-1D514 1D516-1D51C 1D51E-1D539 1D53B-1D53E 1D540-1D544 1D546 1D54A-1D550 1D552-1D6A3 1D6A8-1D7C9 20000-2A6D6 2F800-2FA1D F0000-FFFFD 100000-10FFFD";
19123
+ var PROHIBITED = ranges(PROHIBITED_TEXT);
19124
+ var UNASSIGNED = ranges(UNASSIGNED_TEXT);
19125
+ var RANDAL = ranges(RANDAL_TEXT);
19126
+ var LCAT = ranges(LCAT_TEXT);
19127
+ function prepFails(prepared) {
19128
+ const codes = Array.from(prepared, (ch) => ch.codePointAt(0) ?? 0);
19129
+ if (codes.length === 0) return true;
19130
+ if (codes.some((c) => within7(PROHIBITED, c) || within7(UNASSIGNED, c))) return true;
19131
+ if (!codes.some((c) => within7(RANDAL, c))) return false;
19132
+ if (codes.some((c) => within7(LCAT, c))) return true;
19133
+ return !within7(RANDAL, codes[0] ?? 0) || !within7(RANDAL, codes.at(-1) ?? 0);
19134
+ }
19135
+
19136
+ // src/kernel/net/sealed-scram.ts
19137
+ var encoder8 = new TextEncoder();
19138
+ function base64Bytes(text) {
19139
+ try {
19140
+ return Uint8Array.from(atob(text), (c) => c.charCodeAt(0));
19141
+ } catch {
19142
+ return void 0;
19134
19143
  }
19135
- idle() {
19136
- this.chain = this.chain.then(() => this.release()).catch((err) => {
19137
- this.failed ??= err;
19138
- });
19144
+ }
19145
+ function base64Of(bytes) {
19146
+ let bin = "";
19147
+ for (const b of bytes) bin += String.fromCharCode(b);
19148
+ return btoa(bin);
19149
+ }
19150
+ function clientFirstBare(message3) {
19151
+ const m = /^n,,(n=[^,]*,r=[^,]+)$/.exec(message3);
19152
+ return m ? m[1] : void 0;
19153
+ }
19154
+ var SERVER_FIRST = /^r=([^,]+),s=([^,]+),i=(\d{1,6})$/;
19155
+ var CLIENT_FINAL = /^(c=biws,r=([^,]+)),p=([^,]+)$/;
19156
+ var SCRAM_MAX = 1024;
19157
+ function exchangeOf(clientFirst, serverFirst, clientFinal) {
19158
+ const bare = clientFirstBare(clientFirst);
19159
+ const sf = SERVER_FIRST.exec(serverFirst);
19160
+ const fin = CLIENT_FINAL.exec(clientFinal);
19161
+ if (!bare || !sf || !fin || [bare, serverFirst, clientFinal].some((t) => t.length > SCRAM_MAX))
19162
+ return void 0;
19163
+ const cnonce = bare.slice(bare.indexOf(",r=") + 3);
19164
+ const nonce = sf[1];
19165
+ const salt = base64Bytes(sf[2]);
19166
+ const iterations = Number(sf[3]);
19167
+ const proof = base64Bytes(fin[3]);
19168
+ const ok4 = fin[2] === nonce && nonce.startsWith(cnonce) && iterations >= 1 && iterations <= 1e5 && salt !== void 0 && proof?.length === 32;
19169
+ if (!ok4) return void 0;
19170
+ return {
19171
+ exchange: {
19172
+ clientFirstBare: bare,
19173
+ serverFirst,
19174
+ clientFinalBare: fin[1],
19175
+ salt,
19176
+ iterations
19177
+ },
19178
+ proof
19179
+ };
19180
+ }
19181
+ async function hmac(key, data) {
19182
+ const k = await crypto.subtle.importKey(
19183
+ "raw",
19184
+ key,
19185
+ { name: "HMAC", hash: "SHA-256" },
19186
+ false,
19187
+ ["sign"]
19188
+ );
19189
+ return new Uint8Array(await crypto.subtle.sign("HMAC", k, data));
19190
+ }
19191
+ async function scramKeys(password, x) {
19192
+ const base = await crypto.subtle.importKey("raw", encoder8.encode(password), "PBKDF2", false, [
19193
+ "deriveBits"
19194
+ ]);
19195
+ const salted = new Uint8Array(
19196
+ await crypto.subtle.deriveBits(
19197
+ {
19198
+ name: "PBKDF2",
19199
+ hash: "SHA-256",
19200
+ salt: x.salt,
19201
+ iterations: x.iterations
19202
+ },
19203
+ base,
19204
+ 256
19205
+ )
19206
+ );
19207
+ const clientKey = await hmac(salted, encoder8.encode("Client Key"));
19208
+ const stored = new Uint8Array(
19209
+ await crypto.subtle.digest("SHA-256", clientKey)
19210
+ );
19211
+ const auth = encoder8.encode(`${x.clientFirstBare},${x.serverFirst},${x.clientFinalBare}`);
19212
+ const signature = await hmac(stored, auth);
19213
+ const proof = clientKey.map((b, i) => b ^ signature[i]);
19214
+ const serverKey = await hmac(salted, encoder8.encode("Server Key"));
19215
+ const serverSignature = await hmac(serverKey, auth);
19216
+ for (const k of [salted, clientKey, stored, signature, serverKey]) k.fill(0);
19217
+ return { proof, serverSignature };
19218
+ }
19219
+ var SPACES = /[\u00A0\u1680\u2000-\u200B\u202F\u205F\u3000]/g;
19220
+ var NOTHING2 = /\u00AD|\u034F|\u1806|[\u180B-\u180D]|\u200C|\u200D|\u2060|[\uFE00-\uFE0F]|\uFEFF/g;
19221
+ function saslprep(password) {
19222
+ if (/^[\x00-\x7f]*$/.test(password)) return password;
19223
+ const mapped = password.replace(SPACES, " ").replace(NOTHING2, "");
19224
+ return prepFails(mapped) ? password : mapped.normalize("NFKC");
19225
+ }
19226
+ function sameBytes(a, b) {
19227
+ if (a.length !== b.length) return false;
19228
+ let d = 0;
19229
+ for (let i = 0; i < a.length; i++) d |= a[i] ^ b[i];
19230
+ return d === 0;
19231
+ }
19232
+
19233
+ // src/kernel/net/sealed-pg.ts
19234
+ var PG_MESSAGE_MAX = 16 * 1024;
19235
+ var PROTOCOL_3 = 196608;
19236
+ var CLEARTEXT = 3;
19237
+ function int32(bytes, at) {
19238
+ return bytes[at] << 24 | bytes[at + 1] << 16 | bytes[at + 2] << 8 | bytes[at + 3];
19239
+ }
19240
+ function sniffPg(start2) {
19241
+ const bytes = Uint8Array.from(start2, (c) => c.charCodeAt(0));
19242
+ if (bytes.length === 0 || bytes[0] !== 0) return bytes.length === 0 ? "more" : "no";
19243
+ if (bytes.length < 8) return "more";
19244
+ const length2 = int32(bytes, 0);
19245
+ return length2 >= 8 && length2 <= PG_MESSAGE_MAX && int32(bytes, 4) === PROTOCOL_3 ? "yes" : "no";
19246
+ }
19247
+ var PLUS = "SCRAM-SHA-256-PLUS";
19248
+ var SASL = 10;
19249
+ var SASL_CONTINUE = 11;
19250
+ var SASL_FINAL = 12;
19251
+ function latin(bytes) {
19252
+ let out = "";
19253
+ for (const b of bytes) out += String.fromCharCode(b);
19254
+ return out;
19255
+ }
19256
+ var PgServer = class {
19257
+ buffer = new Uint8Array(0);
19258
+ skip = 0;
19259
+ cleartext = false;
19260
+ sasl = false;
19261
+ serverFirst;
19262
+ expect;
19263
+ failed = false;
19264
+ lost = false;
19265
+ auth(message3) {
19266
+ const code = message3.length >= 9 ? int32(message3, 5) : -1;
19267
+ if (this.expect && code !== SASL_FINAL) this.failed = true;
19268
+ this.cleartext = message3.length === 9 && code === CLEARTEXT;
19269
+ if (code === SASL) return this.mechanisms(message3);
19270
+ else if (code === SASL_CONTINUE) this.serverFirst = latin(message3.subarray(9));
19271
+ else if (code === SASL_FINAL) this.final(message3);
19272
+ return message3;
19139
19273
  }
19140
- async release() {
19141
- this.mode = "pass";
19142
- const out = this.buffer;
19143
- this.buffer = new Uint8Array(0);
19144
- try {
19145
- await writeAll4(this.conn, out);
19146
- } finally {
19147
- out.fill(0);
19148
- }
19274
+ mechanisms(message3) {
19275
+ this.sasl = true;
19276
+ const names2 = latin(message3.subarray(9)).split("\0").filter((n) => n !== "" && n !== PLUS);
19277
+ return frame3(82, `${latin(message3.subarray(5, 9))}${names2.map((n) => `${n}\0`).join("")}\0`);
19149
19278
  }
19150
- async substitute(end) {
19151
- this.mode = "pass";
19152
- const all = this.buffer;
19153
- this.buffer = new Uint8Array(0);
19154
- const done4 = await substituteHead(
19155
- latin12(all.subarray(0, end)),
19156
- (position, placeholders, head2) => this.ask("http1", position, { placeholders, head: head2 })
19157
- ).catch(() => void 0);
19158
- const head = done4 ? bytesOf(done4.head) : all.subarray(0, end);
19159
- if (done4) this.remember(done4.values);
19160
- try {
19161
- await writeAll4(this.conn, head);
19162
- await writeAll4(this.conn, all.subarray(end));
19163
- } finally {
19164
- head.fill(0);
19165
- all.fill(0);
19279
+ final(message3) {
19280
+ const expect = this.expect;
19281
+ if (!expect) return;
19282
+ this.expect = void 0;
19283
+ const data = latin(message3.subarray(9));
19284
+ if (data !== expect.real || expect.fake.length !== expect.real.length) {
19285
+ this.failed = true;
19286
+ return;
19166
19287
  }
19288
+ for (let i = 0; i < expect.fake.length; i++) message3[9 + i] = expect.fake.charCodeAt(i);
19167
19289
  }
19168
- flushed() {
19169
- clearTimeout(this.timer);
19170
- this.chain = this.chain.then(() => this.mode === "pass" ? void 0 : this.release());
19171
- return this.chain;
19172
- }
19173
- drop() {
19174
- clearTimeout(this.timer);
19175
- this.buffer.fill(0);
19176
- this.buffer = new Uint8Array(0);
19177
- this.mode = "pass";
19178
- }
19179
- };
19180
- var IDLE2 = /* @__PURE__ */ Symbol("idle");
19181
- var ScrubReader = class {
19182
- stream;
19183
- version = 0;
19184
- next;
19185
- held = false;
19186
- ended = false;
19187
- conn;
19188
- scope;
19189
- constructor(conn, scope) {
19190
- this.conn = conn;
19191
- this.scope = scope;
19192
- }
19193
- current() {
19194
- const scrub = this.scope.of();
19195
- if (!scrub || scrub.version === this.version) return new Uint8Array(0);
19196
- const tail2 = this.stream?.end() ?? new Uint8Array(0);
19197
- const stream2 = scrub.scrubber.stream();
19198
- this.stream = stream2;
19199
- this.version = scrub.version;
19200
- this.held = tail2.length > 0;
19201
- return tail2.length > 0 ? stream2.push(tail2) : tail2;
19290
+ lose() {
19291
+ this.lost = true;
19292
+ this.cleartext = false;
19293
+ this.sasl = false;
19294
+ if (this.expect) this.failed = true;
19295
+ this.expect = void 0;
19202
19296
  }
19203
- async read() {
19297
+ filter(bytes) {
19298
+ if (this.lost) return bytes;
19299
+ const data = new Uint8Array(this.buffer.length + bytes.length);
19300
+ data.set(this.buffer);
19301
+ data.set(bytes, this.buffer.length);
19302
+ const out = [];
19303
+ let at = 0;
19204
19304
  for (; ; ) {
19205
- if (this.ended) return null;
19206
- const tail2 = this.current();
19207
- if (tail2.length > 0) return tail2;
19208
- const next3 = this.next ?? this.conn.read();
19209
- this.next = void 0;
19210
- const got = this.held ? await Promise.race([next3, idle()]) : await next3;
19211
- if (got === IDLE2) {
19212
- this.next = next3;
19213
- this.held = false;
19214
- const out2 = this.stream.idle();
19215
- if (out2.length > 0) return out2;
19305
+ const left = data.length - at;
19306
+ if (this.skip > 0) {
19307
+ const n = Math.min(this.skip, left);
19308
+ out.push(data.subarray(at, at + n));
19309
+ this.skip -= n;
19310
+ at += n;
19311
+ if (this.skip > 0) break;
19216
19312
  continue;
19217
19313
  }
19218
- const before = this.current();
19219
- const out = this.through(got);
19220
- if (before.length === 0 && out !== void 0) return out;
19221
- if (before.length > 0) return joined3(before, out);
19222
- }
19223
- }
19224
- through(got) {
19225
- const stream2 = this.stream;
19226
- if (!stream2) return got;
19227
- if (got === null) {
19228
- this.ended = true;
19229
- const out2 = stream2.end();
19230
- return out2.length > 0 ? out2 : null;
19231
- }
19232
- const out = stream2.push(got);
19233
- this.held = true;
19234
- return out.length > 0 ? out : void 0;
19235
- }
19236
- };
19237
- function joined3(a, b) {
19238
- if (!b) return a;
19239
- const out = new Uint8Array(a.length + b.length);
19240
- out.set(a);
19241
- out.set(b, a.length);
19242
- return out;
19243
- }
19244
- function idle() {
19245
- return new Promise((resolve2) => setTimeout(() => resolve2(IDLE2), SCRUB_IDLE_MS));
19246
- }
19247
- function sealedConn(conn, s) {
19248
- const pg = new PgServer();
19249
- const scope = s.broker.sessions.scope(s.pid, s.host);
19250
- const writer = substitutes(s) ? new SessionWriter(conn, s, pg, scope) : void 0;
19251
- const observed = {
19252
- ...conn,
19253
- read: async () => {
19254
- for (; ; ) {
19255
- const bytes = await conn.read();
19256
- if (!bytes) return bytes;
19257
- const out = writer?.sawPg ? pg.filter(bytes) : bytes;
19258
- if (pg.failed) {
19259
- conn.close();
19260
- throw new KernelError(
19261
- "EPROTO",
19262
- "ERR_SSL_PROTOCOL_ERROR: the pg server failed the SCRAM proof"
19263
- );
19314
+ if (left < 5) break;
19315
+ const whole = 1 + int32(data, at + 1);
19316
+ if (whole < 5 || data[at] === 82 && whole > PG_MESSAGE_MAX) {
19317
+ this.lose();
19318
+ out.push(data.subarray(at));
19319
+ at = data.length;
19320
+ break;
19321
+ }
19322
+ if (data[at] !== 82) {
19323
+ if (this.expect) {
19324
+ this.failed = true;
19325
+ break;
19264
19326
  }
19265
- if (out.length > 0) return out;
19327
+ this.skip = whole;
19328
+ continue;
19266
19329
  }
19330
+ if (left < whole) break;
19331
+ out.push(this.auth(data.slice(at, at + whole)));
19332
+ at += whole;
19267
19333
  }
19268
- };
19269
- const reader = new ScrubReader(writer ? observed : conn, scope);
19270
- return {
19271
- localAddr: conn.localAddr,
19272
- remoteAddr: conn.remoteAddr,
19273
- read: () => reader.read(),
19274
- write: (bytes) => writer ? writer.write(bytes) : conn.write(bytes),
19275
- closeWrite() {
19276
- if (!writer) return conn.closeWrite();
19277
- void writer.flushed().then(
19278
- () => conn.closeWrite(),
19279
- () => conn.closeWrite()
19280
- );
19281
- },
19282
- close() {
19283
- writer?.drop();
19284
- conn.close();
19285
- }
19286
- };
19287
- }
19288
-
19289
- // src/kernel/net/tls-chain.ts
19290
- var CN_MISMATCH = 4;
19291
- var NOT_TRUSTED = 8;
19292
- function tlv2(der, at) {
19293
- if (at + 2 > der.length) return void 0;
19294
- const first = der[at + 1];
19295
- let body = at + 2;
19296
- let length2 = first;
19297
- if (first & 128) {
19298
- const n = first & 127;
19299
- if (n === 0 || n > 4 || body + n > der.length) return void 0;
19300
- length2 = 0;
19301
- for (let i = 0; i < n; i++) length2 = length2 * 256 + der[body + i];
19302
- body += n;
19334
+ this.buffer = data.slice(at);
19335
+ const joined4 = new Uint8Array(out.reduce((n, b) => n + b.length, 0));
19336
+ let to = 0;
19337
+ for (const b of out) {
19338
+ joined4.set(b, to);
19339
+ to += b.length;
19340
+ }
19341
+ return joined4;
19303
19342
  }
19304
- const end = body + length2;
19305
- return end > der.length ? void 0 : { start: at, body, end };
19343
+ };
19344
+ function frame3(type, body) {
19345
+ const out = new Uint8Array(5 + body.length);
19346
+ out[0] = type;
19347
+ const length2 = 4 + body.length;
19348
+ out.set([length2 >>> 24 & 255, length2 >>> 16 & 255, length2 >>> 8 & 255, length2 & 255], 1);
19349
+ for (let i = 0; i < body.length; i++) out[5 + i] = body.charCodeAt(i);
19350
+ return out;
19306
19351
  }
19307
- function children2(der, outer, max) {
19308
- const fields = [];
19309
- for (let at = outer.body; at < outer.end && fields.length < max; ) {
19310
- const field4 = tlv2(der, at);
19311
- if (!field4) return void 0;
19312
- fields.push(field4);
19313
- at = field4.end;
19314
- }
19315
- return fields;
19352
+ function pgLength(bytes, started) {
19353
+ const header4 = started ? 5 : 4;
19354
+ if (bytes.length < header4) return void 0;
19355
+ const length2 = int32(bytes, started ? 1 : 0);
19356
+ return started ? 1 + length2 : length2;
19316
19357
  }
19317
- function tbsFields(der) {
19318
- const outer = tlv2(der, 0);
19319
- const cert = outer && children2(der, outer, 3);
19320
- const tbs = cert?.[0] && children2(der, cert[0], 8);
19321
- if (!cert || !tbs) return void 0;
19322
- return { cert, tbs: der[tbs[0]?.start ?? 0] === 160 ? tbs.slice(1) : tbs };
19358
+ var MECHANISMS = /* @__PURE__ */ new Set(["SCRAM-SHA-256"]);
19359
+ async function cleartext(message3, asks) {
19360
+ const body = latin(message3.subarray(5));
19361
+ if (!body.endsWith("\0") || body.indexOf("\0") !== body.length - 1)
19362
+ return { bytes: message3, done: true };
19363
+ const password = body.slice(0, -1);
19364
+ const placeholders = placeholdersIn(password);
19365
+ if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS)
19366
+ return { bytes: message3, done: true };
19367
+ const values = usable(await asks.cleartext(placeholders));
19368
+ if (Object.keys(values).length === 0) return { bytes: message3, done: true };
19369
+ return { bytes: frame3(112, `${replaced(password, values)}\0`), values, done: true };
19323
19370
  }
19324
- var raw = (der, t) => der.subarray(t.start, t.end);
19325
- function names(der) {
19326
- const fields = tbsFields(der)?.tbs;
19327
- const [, , issuer, , subject] = fields ?? [];
19328
- if (!issuer || !subject) return void 0;
19329
- return [raw(der, issuer), raw(der, subject)];
19371
+ function initial(message3) {
19372
+ const body = latin(message3.subarray(5));
19373
+ const nul = body.indexOf("\0");
19374
+ if (nul < 0 || !MECHANISMS.has(body.slice(0, nul)) || body.length < nul + 5) return void 0;
19375
+ const data = message3.subarray(5 + nul + 5);
19376
+ return int32(message3, 5 + nul + 1) === data.length ? latin(data) : void 0;
19330
19377
  }
19331
- var hex3 = (bytes) => Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
19332
- var HASHES = {
19333
- "2a864886f70d01010b": ["RSASSA-PKCS1-v1_5", "SHA-256"],
19334
- "2a864886f70d01010c": ["RSASSA-PKCS1-v1_5", "SHA-384"],
19335
- "2a864886f70d01010d": ["RSASSA-PKCS1-v1_5", "SHA-512"],
19336
- "2a8648ce3d040302": ["ECDSA", "SHA-256"],
19337
- "2a8648ce3d040303": ["ECDSA", "SHA-384"],
19338
- "2a8648ce3d040304": ["ECDSA", "SHA-512"],
19339
- "2b6570": ["Ed25519", ""],
19340
- "2a864886f70d01010a": ["RSA-PSS", "SHA-1"]
19341
- };
19342
- var PSS_HASHES = {
19343
- "2b0e03021a": "SHA-1",
19344
- "608648016503040201": "SHA-256",
19345
- "608648016503040202": "SHA-384",
19346
- "608648016503040203": "SHA-512"
19347
- };
19348
- function pssOf(der, algorithm) {
19349
- const params = children2(der, algorithm, 2)?.[1];
19350
- let hash = "SHA-1";
19351
- let salt = 20;
19352
- for (const field4 of params && der[params.start] === 48 ? children2(der, params, 3) ?? [] : []) {
19353
- const inner = tlv2(der, field4.body);
19354
- if (!inner) return void 0;
19355
- if (der[field4.start] === 160) {
19356
- const known = PSS_HASHES[oidOf(der, inner) ?? ""];
19357
- if (!known) return void 0;
19358
- hash = known;
19359
- } else if (der[field4.start] === 162) {
19360
- salt = der.subarray(inner.body, inner.end).reduce((n, b) => n * 256 + b, 0);
19378
+ var PgClient = class {
19379
+ clientFirst;
19380
+ server;
19381
+ asks;
19382
+ constructor(server, asks) {
19383
+ this.server = server;
19384
+ this.asks = asks;
19385
+ }
19386
+ async message(message3) {
19387
+ const server = this.server;
19388
+ if (message3[0] !== 112) return { bytes: message3, done: true };
19389
+ if (server.cleartext) {
19390
+ server.cleartext = false;
19391
+ return cleartext(message3, this.asks);
19392
+ }
19393
+ if (server.sasl && this.clientFirst === void 0) {
19394
+ this.clientFirst = initial(message3);
19395
+ return { bytes: message3, done: this.clientFirst === void 0 };
19361
19396
  }
19397
+ if (this.clientFirst !== void 0 && server.serverFirst !== void 0)
19398
+ return this.final(message3, this.clientFirst, server.serverFirst);
19399
+ return { bytes: message3, done: true };
19400
+ }
19401
+ async final(message3, first, serverFirst) {
19402
+ const got = exchangeOf(first, serverFirst, latin(message3.subarray(5)));
19403
+ if (!got) return { bytes: message3, done: true };
19404
+ const x = got.exchange;
19405
+ const values = usable(
19406
+ await this.asks.scram({
19407
+ clientFirstBare: x.clientFirstBare,
19408
+ serverFirst: x.serverFirst,
19409
+ clientFinalBare: x.clientFinalBare,
19410
+ proof: base64Of(got.proof)
19411
+ })
19412
+ );
19413
+ const [entry, ...more] = Object.entries(values);
19414
+ if (!entry || more.length > 0) return { bytes: message3, done: true };
19415
+ const [placeholder, value2] = entry;
19416
+ const fake = await scramKeys(placeholder, x);
19417
+ if (!sameBytes(fake.proof, got.proof)) return { bytes: message3, done: true };
19418
+ const real = await scramKeys(saslprep(value2), x);
19419
+ this.server.expect = {
19420
+ real: `v=${base64Of(real.serverSignature)}`,
19421
+ fake: `v=${base64Of(fake.serverSignature)}`
19422
+ };
19423
+ const bytes = frame3(112, `${x.clientFinalBare},p=${base64Of(real.proof)}`);
19424
+ for (const k of [real.proof, real.serverSignature, fake.proof, fake.serverSignature]) k.fill(0);
19425
+ return { bytes, values, done: true };
19362
19426
  }
19363
- return { hash, salt };
19364
- }
19365
- var CURVES = {
19366
- "2a8648ce3d030107": ["P-256", 32],
19367
- "2b81040022": ["P-384", 48],
19368
- "2b81040023": ["P-521", 66]
19369
19427
  };
19370
- function oidOf(der, algorithm, index = 0) {
19371
- const parts2 = children2(der, algorithm, 2);
19372
- const oid2 = parts2?.[index];
19373
- return oid2 && der[oid2.start] === 6 ? hex3(der.subarray(oid2.body, oid2.end)) : void 0;
19374
- }
19375
- function curveOf(der, spki) {
19376
- const algorithm = children2(der, spki, 1)?.[0];
19377
- const curve = algorithm && oidOf(der, algorithm, 1);
19378
- return curve ? CURVES[curve] : void 0;
19379
- }
19380
- function fixedEcdsa(sig, size) {
19381
- const outer = tlv2(sig, 0);
19382
- const ints = outer && children2(sig, outer, 2);
19383
- if (ints?.length !== 2) return void 0;
19384
- const out = new Uint8Array(size * 2);
19385
- for (const [i, int] of ints.entries()) {
19386
- let value2 = sig.subarray(int.body, int.end);
19387
- while (value2.length > size && value2[0] === 0) value2 = value2.subarray(1);
19388
- if (value2.length > size) return void 0;
19389
- out.set(value2, (i + 1) * size - value2.length);
19428
+
19429
+ // src/kernel/net/sealed-smtp.ts
19430
+ var SMTP_LINE_MAX = 4096;
19431
+ var GREETING = ["EHLO ", "HELO "];
19432
+ function sniffSmtp(start2) {
19433
+ const upper = start2.toUpperCase();
19434
+ for (const word of GREETING) {
19435
+ if (upper.startsWith(word)) return "yes";
19436
+ if (word.startsWith(upper)) return "more";
19390
19437
  }
19391
- return out;
19392
- }
19393
- function signedOf(der) {
19394
- const parts2 = tbsFields(der);
19395
- const [tbs, algorithm, value2] = parts2?.cert ?? [];
19396
- const spki = parts2?.tbs[5];
19397
- if (!tbs || !algorithm || !value2 || !spki || der[value2.start] !== 3) return void 0;
19398
- const known = HASHES[oidOf(der, algorithm) ?? ""];
19399
- if (!known) return void 0;
19400
- const [scheme] = known;
19401
- const pss = scheme === "RSA-PSS" ? pssOf(der, algorithm) : void 0;
19402
- if (scheme === "RSA-PSS" && !pss) return void 0;
19403
- const hash = pss?.hash ?? known[1];
19404
- const curve = scheme === "ECDSA" ? curveOf(der, spki) : void 0;
19405
- if (scheme === "ECDSA" && !curve) return void 0;
19406
- const signature = der.subarray(value2.body + 1, value2.end);
19407
- return {
19408
- tbs: raw(der, tbs),
19409
- spki: raw(der, spki),
19410
- signature,
19411
- scheme,
19412
- hash,
19413
- ...curve ? { curve } : {},
19414
- ...pss ? { salt: pss.salt } : {}
19415
- };
19438
+ return "no";
19416
19439
  }
19417
- async function verifiesItself(s) {
19418
- const name2 = s.curve?.[0];
19419
- const algorithm = s.scheme === "ECDSA" ? { name: "ECDSA", namedCurve: name2 } : s.hash ? { name: s.scheme, hash: s.hash } : { name: s.scheme };
19420
- const key = await crypto.subtle.importKey("spki", new Uint8Array(s.spki), algorithm, false, [
19421
- "verify"
19422
- ]);
19423
- const signature = s.curve ? fixedEcdsa(s.signature, s.curve[1]) : s.signature;
19424
- if (!signature) return false;
19425
- const params = s.scheme === "ECDSA" ? { name: "ECDSA", hash: s.hash } : s.salt === void 0 ? { name: s.scheme } : { name: s.scheme, saltLength: s.salt };
19426
- return crypto.subtle.verify(params, key, new Uint8Array(signature), new Uint8Array(s.tbs));
19440
+ function decoded(b642) {
19441
+ if (!/^[A-Za-z0-9+/]+={0,2}$/.test(b642)) return void 0;
19442
+ try {
19443
+ return atob(b642);
19444
+ } catch {
19445
+ return void 0;
19446
+ }
19427
19447
  }
19428
- async function selfSigned(der) {
19429
- if (!selfIssued(der)) return false;
19430
- const signed = signedOf(der);
19431
- if (!signed) return false;
19432
- return verifiesItself(signed).catch(() => false);
19448
+ async function swapped2(text, position, ask) {
19449
+ const placeholders = placeholdersIn(text);
19450
+ if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS) return void 0;
19451
+ const values = usable(await ask(position, placeholders));
19452
+ if (Object.keys(values).length === 0) return void 0;
19453
+ return { text: replaced(text, values), values };
19433
19454
  }
19434
- async function chainShape(chain2) {
19435
- return {
19436
- leafSelfSigned: chain2.length === 1 && await selfSigned(chain2[0]),
19437
- topSelfSigned: chain2.length > 1 && await selfSigned(chain2.at(-1))
19438
- };
19455
+ async function plain2(b642, ask) {
19456
+ const text = decoded(b642);
19457
+ const fields = text?.split("\0");
19458
+ if (fields?.length !== 3) return { line: b642 };
19459
+ const [authz, user, pass2] = fields;
19460
+ if (placeholdersIn(authz + user).length > 0) return { line: b642 };
19461
+ const done4 = await swapped2(pass2, "auth-plain", ask);
19462
+ if (!done4) return { line: b642 };
19463
+ return { line: btoa(`${authz}\0${user}\0${done4.text}`), values: done4.values };
19439
19464
  }
19440
- function selfIssued(der) {
19441
- const pair = der && names(der);
19442
- if (!pair) return false;
19443
- const [issuer, subject] = pair;
19444
- return issuer.length === subject.length && issuer.every((b, i) => b === subject[i]);
19465
+ async function login(b642, ask) {
19466
+ const text = decoded(b642);
19467
+ const done4 = text === void 0 ? void 0 : await swapped2(text, "auth-login", ask);
19468
+ return done4 ? { line: btoa(done4.text), values: done4.values } : { line: b642 };
19445
19469
  }
19446
- function untrusted(chain2, shape) {
19447
- if (chain2.length === 1) {
19448
- return shape.leafSelfSigned ? "DEPTH_ZERO_SELF_SIGNED_CERT" : "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
19470
+ var SmtpClient = class {
19471
+ state = "command";
19472
+ ask;
19473
+ constructor(ask) {
19474
+ this.ask = ask;
19449
19475
  }
19450
- return shape.topSelfSigned ? "SELF_SIGNED_CERT_IN_CHAIN" : "UNABLE_TO_GET_ISSUER_CERT_LOCALLY";
19476
+ get done() {
19477
+ return this.state === "done";
19478
+ }
19479
+ async line(text) {
19480
+ const state = this.state;
19481
+ if (state === "done") return { line: text };
19482
+ if (state === "plain" || state === "password") {
19483
+ this.state = "done";
19484
+ if (text === "*") return { line: text };
19485
+ return state === "plain" ? plain2(text, this.ask) : login(text, this.ask);
19486
+ }
19487
+ if (state === "user") {
19488
+ this.state = text === "*" ? "done" : "password";
19489
+ return { line: text };
19490
+ }
19491
+ return this.command(text);
19492
+ }
19493
+ async command(text) {
19494
+ const m = /^AUTH[ \t]+(PLAIN|LOGIN)(?:[ \t]+(\S+))?$/i.exec(text);
19495
+ if (!m) {
19496
+ if (/^(MAIL|RCPT|DATA|BDAT|AUTH)\b/i.test(text)) this.state = "done";
19497
+ return { line: text };
19498
+ }
19499
+ const mech = m[1].toUpperCase();
19500
+ const arg = m[2];
19501
+ if (mech === "LOGIN") {
19502
+ this.state = arg === void 0 ? "user" : "password";
19503
+ return { line: text };
19504
+ }
19505
+ if (arg === void 0) {
19506
+ this.state = "plain";
19507
+ return { line: text };
19508
+ }
19509
+ this.state = "done";
19510
+ const out = await plain2(arg, this.ask);
19511
+ return {
19512
+ line: `${text.slice(0, text.length - arg.length)}${out.line}`,
19513
+ ...out.values ? { values: out.values } : {}
19514
+ };
19515
+ }
19516
+ };
19517
+
19518
+ // src/kernel/net/sealed-conn.ts
19519
+ var HEAD_IDLE_MS = 2e3;
19520
+ function substitutes(s) {
19521
+ return (s.verified || s.anchoring !== void 0) && s.alpn !== "h2" && s.broker.hook !== void 0 && typeof s.exit === "string" && SESSION_EXIT.test(s.exit);
19451
19522
  }
19452
- function chainError(flags2, chain2, shape) {
19453
- if (flags2 === -1) return "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
19454
- const rest2 = flags2 & ~CN_MISMATCH;
19455
- if (rest2 === 0) return void 0;
19456
- if (rest2 & NOT_TRUSTED) return untrusted(chain2, shape);
19457
- return verifyCode(rest2);
19523
+ function sessionId() {
19524
+ const bytes = crypto.getRandomValues(new Uint8Array(24));
19525
+ let bin = "";
19526
+ for (const b of bytes) bin += String.fromCharCode(b);
19527
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_");
19458
19528
  }
19459
- function nameMatches(flags2) {
19460
- return flags2 !== -1 && (flags2 & CN_MISMATCH) === 0;
19529
+ function latin12(bytes) {
19530
+ let out = "";
19531
+ for (const b of bytes) out += String.fromCharCode(b);
19532
+ return out;
19461
19533
  }
19462
-
19463
- // src/kernel/net/tls-ciphers.ts
19464
- var SUITES = [
19465
- [4865, "TLS_AES_128_GCM_SHA256", "TLS_AES_128_GCM_SHA256", "TLSv1.3"],
19466
- [4866, "TLS_AES_256_GCM_SHA384", "TLS_AES_256_GCM_SHA384", "TLSv1.3"],
19467
- [4867, "TLS_CHACHA20_POLY1305_SHA256", "TLS_CHACHA20_POLY1305_SHA256", "TLSv1.3"],
19468
- [4868, "TLS_AES_128_CCM_SHA256", "TLS_AES_128_CCM_SHA256", "TLSv1.3"],
19469
- [4869, "TLS_AES_128_CCM_8_SHA256", "TLS_AES_128_CCM_8_SHA256", "TLSv1.3"],
19470
- [49195, "ECDHE-ECDSA-AES128-GCM-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
19471
- [49196, "ECDHE-ECDSA-AES256-GCM-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
19472
- [49199, "ECDHE-RSA-AES128-GCM-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
19473
- [49200, "ECDHE-RSA-AES256-GCM-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
19474
- [52392, "ECDHE-RSA-CHACHA20-POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLSv1.2"],
19475
- [
19476
- 52393,
19477
- "ECDHE-ECDSA-CHACHA20-POLY1305",
19478
- "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
19479
- "TLSv1.2"
19480
- ],
19481
- [49187, "ECDHE-ECDSA-AES128-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLSv1.2"],
19482
- [49188, "ECDHE-ECDSA-AES256-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLSv1.2"],
19483
- [49191, "ECDHE-RSA-AES128-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLSv1.2"],
19484
- [49192, "ECDHE-RSA-AES256-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLSv1.2"],
19485
- [49161, "ECDHE-ECDSA-AES128-SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLSv1.0"],
19486
- [49162, "ECDHE-ECDSA-AES256-SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLSv1.0"],
19487
- [49171, "ECDHE-RSA-AES128-SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLSv1.0"],
19488
- [49172, "ECDHE-RSA-AES256-SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLSv1.0"],
19489
- [156, "AES128-GCM-SHA256", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
19490
- [157, "AES256-GCM-SHA384", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"],
19491
- [158, "DHE-RSA-AES128-GCM-SHA256", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLSv1.2"],
19492
- [159, "DHE-RSA-AES256-GCM-SHA384", "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLSv1.2"]
19493
- ];
19494
- function cipherOf(id2, protocol) {
19495
- const known = SUITES.find(([n]) => n === id2);
19496
- const hex4 = `0x${id2.toString(16).padStart(4, "0").toUpperCase()}`;
19497
- return {
19498
- name: known?.[1] ?? hex4,
19499
- standardName: known?.[2] ?? hex4,
19500
- version: known?.[3] ?? protocol
19501
- };
19534
+ function bytesOf(text) {
19535
+ const out = new Uint8Array(text.length);
19536
+ for (let i = 0; i < text.length; i++) out[i] = text.charCodeAt(i);
19537
+ return out;
19502
19538
  }
19503
-
19504
- // src/kernel/net/tls-client.ts
19505
- var WRITE_CHUNK = 16 * 1024;
19506
- var BADCERT = [
19507
- [8, "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"],
19508
- [1, "CERT_HAS_EXPIRED"],
19509
- [512, "CERT_NOT_YET_VALID"],
19510
- [2, "CERT_REVOKED"],
19511
- [4, "ERR_TLS_CERT_ALTNAME_INVALID"],
19512
- [2048, "INVALID_PURPOSE"],
19513
- [4096, "INVALID_PURPOSE"]
19514
- ];
19515
- function verifyCode(flags2) {
19516
- if (flags2 === 0) return void 0;
19517
- if (flags2 === -1) return "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
19518
- return BADCERT.find(([bit]) => (flags2 & bit) !== 0)?.[1] ?? "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
19539
+ async function writeAll4(conn, bytes) {
19540
+ for (let at = 0; at < bytes.length; ) at += await conn.write(bytes.subarray(at));
19519
19541
  }
19520
- function isIP(name2) {
19521
- return ipv4Bytes(name2) !== void 0 || name2.includes(":") && ipv6Groups(name2) !== void 0;
19542
+ var CRLF2 = [13, 10, 13, 10];
19543
+ function headEnd2(bytes) {
19544
+ for (let i = 0; i + 3 < bytes.length; i++) {
19545
+ if (CRLF2.every((b, k) => bytes[i + k] === b)) return i + 4;
19546
+ }
19547
+ return -1;
19522
19548
  }
19523
- function clientFlags(o) {
19524
- 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);
19549
+ function modeOf(start2) {
19550
+ const sniffs = [
19551
+ ["http1", sniffHttp1(start2)],
19552
+ ["smtp", sniffSmtp(start2)],
19553
+ ["pg", sniffPg(start2)]
19554
+ ];
19555
+ const hit = sniffs.find(([, v]) => v === "yes");
19556
+ if (hit) return hit[0];
19557
+ return sniffs.every(([, v]) => v === "no") ? "pass" : void 0;
19525
19558
  }
19526
- function openSession(o) {
19527
- return o.engine.clientSession(o.store, o.servername, o.alpn, clientFlags(o));
19559
+ function crlf(bytes) {
19560
+ for (let i = 0; i + 1 < bytes.length; i++) if (bytes[i] === 13 && bytes[i + 1] === 10) return i;
19561
+ return -1;
19528
19562
  }
19529
- var Ciphertext = class {
19530
- queue = [];
19563
+ var SessionWriter = class {
19564
+ buffer = new Uint8Array(0);
19565
+ mode = "sniff";
19566
+ timer;
19567
+ chain = Promise.resolve();
19568
+ failed;
19569
+ session = sessionId();
19570
+ smtp;
19571
+ pgStarted = false;
19572
+ sawPg = false;
19573
+ conn;
19574
+ s;
19575
+ pgClient;
19576
+ scope;
19577
+ constructor(conn, s, pg, scope) {
19578
+ this.conn = conn;
19579
+ this.s = s;
19580
+ this.scope = scope;
19581
+ this.pgClient = new PgClient(pg, {
19582
+ cleartext: (placeholders) => this.ask("pg", "password-cleartext", { placeholders }),
19583
+ scram: (scram) => this.ask("pg", "scram-sha-256", { scram })
19584
+ });
19585
+ this.smtp = new SmtpClient(
19586
+ (position, placeholders) => this.ask("smtp", position, { placeholders })
19587
+ );
19588
+ }
19589
+ write(bytes) {
19590
+ const run2 = this.chain.then(() => this.take(bytes));
19591
+ this.chain = run2.then(
19592
+ () => void 0,
19593
+ () => void 0
19594
+ );
19595
+ return run2;
19596
+ }
19597
+ proven;
19598
+ proof(protocol) {
19599
+ this.proven ??= this.prove(protocol).catch(() => void 0);
19600
+ return this.proven;
19601
+ }
19602
+ async prove(protocol) {
19603
+ const s = this.s;
19604
+ if (s.anchoring) {
19605
+ const found = await s.broker.sessionAnchors({
19606
+ stamp: await s.stamp(),
19607
+ session: this.session,
19608
+ host: s.host,
19609
+ port: s.port,
19610
+ protocol,
19611
+ exit: s.exit
19612
+ });
19613
+ const anchor = found ? await s.anchoring(found) : void 0;
19614
+ if (anchor) return { anchor };
19615
+ }
19616
+ return s.verified ? {} : void 0;
19617
+ }
19618
+ async ask(protocol, position, extra) {
19619
+ const s = this.s;
19620
+ const proof = await this.proof(protocol);
19621
+ if (!proof) return void 0;
19622
+ return s.broker.sessionMaterialize({
19623
+ stamp: await s.stamp(),
19624
+ session: this.session,
19625
+ host: s.host,
19626
+ port: s.port,
19627
+ protocol,
19628
+ position,
19629
+ verified: true,
19630
+ ...proof.anchor ? { verifiedBy: "anchored", anchor: proof.anchor } : { verifiedBy: "roots" },
19631
+ handshakeAt: s.handshakeAt,
19632
+ exit: s.exit,
19633
+ ...extra
19634
+ });
19635
+ }
19636
+ remember(values) {
19637
+ this.scope.add(
19638
+ Object.entries(values).map(([placeholder, value2]) => ({ name: "sealed", value: value2, placeholder }))
19639
+ );
19640
+ }
19641
+ async take(bytes) {
19642
+ if (this.failed !== void 0) throw this.failed;
19643
+ if (this.mode === "pass") return this.conn.write(bytes);
19644
+ clearTimeout(this.timer);
19645
+ const joined4 = new Uint8Array(this.buffer.length + bytes.length);
19646
+ joined4.set(this.buffer);
19647
+ joined4.set(bytes, this.buffer.length);
19648
+ this.buffer.fill(0);
19649
+ this.buffer = joined4;
19650
+ if (this.mode === "sniff") this.mode = modeOf(latin12(joined4.subarray(0, 8))) ?? "sniff";
19651
+ if (this.mode === "pg") this.sawPg = true;
19652
+ if (this.mode === "pass") await this.release();
19653
+ else if (this.mode === "http1") await this.http1();
19654
+ else if (this.mode === "smtp") await this.lines();
19655
+ else if (this.mode === "pg") await this.messages();
19656
+ if (this.mode !== "pass" && this.buffer.length > 0)
19657
+ this.timer = setTimeout(() => this.idle(), HEAD_IDLE_MS);
19658
+ return bytes.length;
19659
+ }
19660
+ async http1() {
19661
+ const end = headEnd2(this.buffer);
19662
+ if (end > HEAD_MAX || end < 0 && this.buffer.length > HEAD_MAX) await this.release();
19663
+ else if (end >= 0) await this.substitute(end);
19664
+ }
19665
+ async lines() {
19666
+ for (; ; ) {
19667
+ const at = crlf(this.buffer);
19668
+ if (at < 0) break;
19669
+ if (at > SMTP_LINE_MAX) return this.release();
19670
+ const all = this.buffer;
19671
+ this.buffer = all.slice(at + 2);
19672
+ const out = await this.smtp.line(latin12(all.subarray(0, at))).catch(() => ({ line: latin12(all.subarray(0, at)) }));
19673
+ all.fill(0);
19674
+ if ("values" in out && out.values) this.remember(out.values);
19675
+ const line = bytesOf(`${out.line}\r
19676
+ `);
19677
+ try {
19678
+ await writeAll4(this.conn, line);
19679
+ } finally {
19680
+ line.fill(0);
19681
+ }
19682
+ if (this.smtp.done) return this.release();
19683
+ }
19684
+ if (this.buffer.length > SMTP_LINE_MAX) await this.release();
19685
+ }
19686
+ async messages() {
19687
+ for (; ; ) {
19688
+ const whole = pgLength(this.buffer, this.pgStarted);
19689
+ if (whole === void 0 || whole < 4 || whole > PG_MESSAGE_MAX) {
19690
+ if (whole !== void 0) await this.release();
19691
+ return;
19692
+ }
19693
+ if (this.buffer.length < whole) return;
19694
+ const message3 = this.buffer.slice(0, whole);
19695
+ this.buffer = this.buffer.slice(whole);
19696
+ const started = this.pgStarted;
19697
+ this.pgStarted = true;
19698
+ const out = started ? await this.pgClient.message(message3).catch(() => ({ bytes: message3, done: true })) : { bytes: message3, done: false };
19699
+ if ("values" in out && out.values) this.remember(out.values);
19700
+ try {
19701
+ await writeAll4(this.conn, out.bytes);
19702
+ } finally {
19703
+ out.bytes.fill(0);
19704
+ message3.fill(0);
19705
+ }
19706
+ if (out.done) return this.release();
19707
+ }
19708
+ }
19709
+ idle() {
19710
+ this.chain = this.chain.then(() => this.release()).catch((err) => {
19711
+ this.failed ??= err;
19712
+ });
19713
+ }
19714
+ async release() {
19715
+ this.mode = "pass";
19716
+ const out = this.buffer;
19717
+ this.buffer = new Uint8Array(0);
19718
+ try {
19719
+ await writeAll4(this.conn, out);
19720
+ } finally {
19721
+ out.fill(0);
19722
+ }
19723
+ }
19724
+ async substitute(end) {
19725
+ this.mode = "pass";
19726
+ const all = this.buffer;
19727
+ this.buffer = new Uint8Array(0);
19728
+ const done4 = await substituteHead(
19729
+ latin12(all.subarray(0, end)),
19730
+ (position, placeholders, head2) => this.ask("http1", position, { placeholders, head: head2 })
19731
+ ).catch(() => void 0);
19732
+ const head = done4 ? bytesOf(done4.head) : all.subarray(0, end);
19733
+ if (done4) this.remember(done4.values);
19734
+ try {
19735
+ await writeAll4(this.conn, head);
19736
+ await writeAll4(this.conn, all.subarray(end));
19737
+ } finally {
19738
+ head.fill(0);
19739
+ all.fill(0);
19740
+ }
19741
+ }
19742
+ flushed() {
19743
+ clearTimeout(this.timer);
19744
+ this.chain = this.chain.then(() => this.mode === "pass" ? void 0 : this.release());
19745
+ return this.chain;
19746
+ }
19747
+ drop() {
19748
+ clearTimeout(this.timer);
19749
+ this.buffer.fill(0);
19750
+ this.buffer = new Uint8Array(0);
19751
+ this.mode = "pass";
19752
+ }
19753
+ };
19754
+ var IDLE2 = /* @__PURE__ */ Symbol("idle");
19755
+ var ScrubReader = class {
19756
+ stream;
19757
+ version = 0;
19758
+ next;
19759
+ held = false;
19531
19760
  ended = false;
19532
19761
  conn;
19533
- session;
19534
- constructor(conn, session) {
19762
+ scope;
19763
+ constructor(conn, scope) {
19535
19764
  this.conn = conn;
19536
- this.session = session;
19765
+ this.scope = scope;
19537
19766
  }
19538
- hand(bytes) {
19539
- if (bytes.length > 0) this.queue.push(bytes);
19767
+ current() {
19768
+ const scrub = this.scope.of();
19769
+ if (!scrub || scrub.version === this.version) return new Uint8Array(0);
19770
+ const tail2 = this.stream?.end() ?? new Uint8Array(0);
19771
+ const stream2 = scrub.scrubber.stream();
19772
+ this.stream = stream2;
19773
+ this.version = scrub.version;
19774
+ this.held = tail2.length > 0;
19775
+ return tail2.length > 0 ? stream2.push(tail2) : tail2;
19540
19776
  }
19541
- async more() {
19542
- if (this.queue.length === 0 && !this.ended) {
19543
- const bytes = await this.conn.read();
19544
- if (bytes) this.queue.push(bytes);
19545
- else this.ended = true;
19546
- }
19547
- if (this.queue.length === 0) {
19548
- this.session.feedEnd();
19549
- return false;
19550
- }
19551
- while (this.queue.length > 0) {
19552
- const head = this.queue[0];
19553
- const n = this.session.feed(head);
19554
- if (n < head.length) {
19555
- this.queue[0] = head.subarray(n);
19556
- break;
19777
+ async read() {
19778
+ for (; ; ) {
19779
+ if (this.ended) return null;
19780
+ const tail2 = this.current();
19781
+ if (tail2.length > 0) return tail2;
19782
+ const next3 = this.next ?? this.conn.read();
19783
+ this.next = void 0;
19784
+ const got = this.held ? await Promise.race([next3, idle()]) : await next3;
19785
+ if (got === IDLE2) {
19786
+ this.next = next3;
19787
+ this.held = false;
19788
+ const out2 = this.stream.idle();
19789
+ if (out2.length > 0) return out2;
19790
+ continue;
19557
19791
  }
19558
- this.queue.shift();
19792
+ const before = this.current();
19793
+ const out = this.through(got);
19794
+ if (before.length === 0 && out !== void 0) return out;
19795
+ if (before.length > 0) return joined3(before, out);
19559
19796
  }
19560
- return true;
19561
19797
  }
19562
- };
19563
- async function send(conn, session) {
19564
- for (; ; ) {
19565
- const out = session.take();
19566
- if (out.length === 0) return;
19567
- for (let at = 0; at < out.length; ) {
19568
- const n = await conn.write(out.subarray(at));
19569
- if (!(n > 0)) throw new KernelError("EPIPE");
19570
- at += n;
19798
+ through(got) {
19799
+ const stream2 = this.stream;
19800
+ if (!stream2) return got;
19801
+ if (got === null) {
19802
+ this.ended = true;
19803
+ const out2 = stream2.end();
19804
+ return out2.length > 0 ? out2 : null;
19571
19805
  }
19806
+ const out = stream2.push(got);
19807
+ this.held = true;
19808
+ return out.length > 0 ? out : void 0;
19572
19809
  }
19810
+ };
19811
+ function joined3(a, b) {
19812
+ if (!b) return a;
19813
+ const out = new Uint8Array(a.length + b.length);
19814
+ out.set(a);
19815
+ out.set(b, a.length);
19816
+ return out;
19573
19817
  }
19574
- function refused2(engine, session, err) {
19575
- const flags2 = session.verifyResult;
19576
- const code = verifyCode(flags2);
19577
- if (code && flags2 !== -1)
19578
- return new KernelError("EPROTO", `${code}: ${engine.verifyInfo(flags2).trim()}`);
19579
- const text = err instanceof TlsError ? err.message : String(err);
19580
- return new KernelError("EPROTO", `ERR_SSL_HANDSHAKE_FAILURE: ${text}${alertOf(session)}`);
19581
- }
19582
- function alertOf(session) {
19583
- const alert = session.lastAlert;
19584
- return alert >= 0 ? ` (alert ${alert})` : "";
19818
+ function idle() {
19819
+ return new Promise((resolve2) => setTimeout(() => resolve2(IDLE2), SCRUB_IDLE_MS));
19585
19820
  }
19586
- async function handshake(conn, o, session, inbox) {
19587
- for (; ; ) {
19588
- let done4;
19589
- try {
19590
- done4 = session.handshake();
19591
- } catch (err) {
19592
- await send(conn, session).catch(() => void 0);
19593
- throw refused2(o.engine, session, err);
19594
- }
19595
- await send(conn, session);
19596
- if (done4) return;
19597
- if (!await inbox.more()) {
19598
- throw new KernelError(
19599
- "ECONNRESET",
19600
- "the server closed the connection during the TLS handshake"
19601
- );
19821
+ function sealedConn(conn, s) {
19822
+ const pg = new PgServer();
19823
+ const scope = s.broker.sessions.scope(s.pid, s.host);
19824
+ const writer = substitutes(s) ? new SessionWriter(conn, s, pg, scope) : void 0;
19825
+ const observed = {
19826
+ ...conn,
19827
+ read: async () => {
19828
+ for (; ; ) {
19829
+ const bytes = await conn.read();
19830
+ if (!bytes) return bytes;
19831
+ const out = writer?.sawPg ? pg.filter(bytes) : bytes;
19832
+ if (pg.failed) {
19833
+ conn.close();
19834
+ throw new KernelError(
19835
+ "EPROTO",
19836
+ "ERR_SSL_PROTOCOL_ERROR: the pg server failed the SCRAM proof"
19837
+ );
19838
+ }
19839
+ if (out.length > 0) return out;
19840
+ }
19602
19841
  }
19603
- }
19604
- }
19605
- function insecureOf(session, chain2, shape) {
19606
- const flags2 = session.verifyResult;
19607
- const error = chainError(flags2, chain2, shape);
19608
- return { hostnameMatches: nameMatches(flags2), ...error ? { chainError: error } : {} };
19609
- }
19610
- function controlsOf(o, session, protocol, chain2, shape) {
19611
- if (!o.engine.sessionControls) return {};
19612
- const checked = o.checkHostname !== false && !o.insecure;
19613
- return {
19614
- cipher: cipherOf(session.ciphersuite, protocol),
19615
- clientCertificate: o.clientCertificate === true,
19616
- sni: o.sni !== false && !isIP(o.servername),
19617
- hostnameChecked: checked,
19618
- ...o.insecure ? insecureOf(session, chain2, shape) : { hostnameMatches: checked || !session.nameMismatch }
19619
- };
19620
- }
19621
- function verdictOf(o, session) {
19622
- if (o.bundled !== true || isIP(o.servername) || session.verifyResult !== 0) return false;
19623
- return o.checkHostname !== false || !session.nameMismatch;
19624
- }
19625
- async function infoOf(o, session) {
19626
- const flags2 = session.verifyResult;
19627
- const code = verifyCode(flags2);
19628
- const protocol = session.version === 772 ? "TLSv1.3" : "TLSv1.2";
19629
- const chain2 = session.peerChain();
19630
- const shape = await chainShape(o.insecure ? chain2 : []);
19631
- return {
19632
- protocol,
19633
- alpnProtocol: session.alpn ?? false,
19634
- authorized: code === void 0,
19635
- ...code ? { authorizationError: code, authorizationText: o.engine.verifyInfo(flags2).trim() } : {},
19636
- peerCertificates: chain2,
19637
- ...controlsOf(o, session, protocol, chain2, shape),
19638
- verified: verdictOf(o, session),
19639
- handshakeAt: Date.now()
19640
- };
19641
- }
19642
- var FATAL_ALERT = -30592;
19643
- function alerted(err, session) {
19644
- if (err.code === FATAL_ALERT)
19645
- return new KernelError(
19646
- "EPROTO",
19647
- `ERR_SSL_FATAL_ALERT: the server ended the session: ${err.message}${alertOf(session)}`
19648
- );
19649
- return new KernelError("EPROTO", `ERR_SSL_PROTOCOL_ERROR: ${err.message}`);
19650
- }
19651
- function plaintext(conn, session, inbox) {
19652
- let freed = false;
19653
- let writeClosed = false;
19654
- const free = () => {
19655
- if (freed) return;
19656
- freed = true;
19657
- session.free();
19658
19842
  };
19843
+ const reader = new ScrubReader(writer ? observed : conn, scope);
19659
19844
  return {
19660
19845
  localAddr: conn.localAddr,
19661
19846
  remoteAddr: conn.remoteAddr,
19662
- async read() {
19663
- for (; ; ) {
19664
- if (freed) return null;
19665
- let got;
19666
- try {
19667
- got = session.read();
19668
- } catch (err) {
19669
- throw alerted(err, session);
19670
- }
19671
- await send(conn, session);
19672
- if (got instanceof Uint8Array) return got;
19673
- if (got === "eof") return null;
19674
- await inbox.more();
19675
- }
19676
- },
19677
- async write(bytes) {
19678
- if (freed) throw new KernelError("EPIPE");
19679
- for (; ; ) {
19680
- const n = session.write(bytes.subarray(0, WRITE_CHUNK));
19681
- await send(conn, session);
19682
- if (n > 0) return n;
19683
- }
19684
- },
19847
+ read: () => reader.read(),
19848
+ write: (bytes) => writer ? writer.write(bytes) : conn.write(bytes),
19685
19849
  closeWrite() {
19686
- if (writeClosed || freed) return;
19687
- writeClosed = true;
19688
- session.close();
19689
- void send(conn, session).catch(() => void 0).finally(() => conn.closeWrite());
19850
+ if (!writer) return conn.closeWrite();
19851
+ void writer.flushed().then(
19852
+ () => conn.closeWrite(),
19853
+ () => conn.closeWrite()
19854
+ );
19690
19855
  },
19691
19856
  close() {
19692
- free();
19857
+ writer?.drop();
19693
19858
  conn.close();
19694
19859
  }
19695
19860
  };
19696
19861
  }
19697
- async function tlsClient(conn, o, taken = new Uint8Array(0)) {
19698
- const session = o.session ?? openSession(o);
19699
- const inbox = new Ciphertext(conn, session);
19700
- inbox.hand(taken);
19701
- try {
19702
- await handshake(conn, o, session, inbox);
19703
- const info = await infoOf(o, session);
19704
- return { conn: plaintext(conn, session, inbox), info };
19705
- } catch (err) {
19706
- session.free();
19707
- throw err;
19708
- }
19709
- }
19710
19862
 
19711
19863
  // src/kernel/net/tls-uplink.ts
19712
19864
  var isIP2 = (text) => ipv4Bytes(text) !== void 0 || text.includes(":") && ipv6Groups(text) !== void 0;
@@ -19755,6 +19907,7 @@ function sessionOf(info, servername) {
19755
19907
  path: "kernel",
19756
19908
  substitutes: info.substitutes === true,
19757
19909
  verified: info.verified,
19910
+ verifiedBy: info.verified ? "bundled" : "none",
19758
19911
  protocol: info.protocol,
19759
19912
  alpnProtocol: info.alpnProtocol,
19760
19913
  authorized: info.authorized,
@@ -19827,9 +19980,9 @@ function takeCert(req) {
19827
19980
  }
19828
19981
  const chain2 = new Uint8Array(ders.reduce((n, d) => n + d.length, 0));
19829
19982
  let at = 0;
19830
- for (const der of ders) {
19831
- chain2.set(der, at);
19832
- at += der.length;
19983
+ for (const der2 of ders) {
19984
+ chain2.set(der2, at);
19985
+ at += der2.length;
19833
19986
  }
19834
19987
  const pass2 = new TextEncoder().encode(cert.passphrase ?? "");
19835
19988
  return { chain: chain2, key, pass: pass2 };
@@ -19856,7 +20009,7 @@ async function setUp(support, req) {
19856
20009
  throw new KernelError("EINVAL", "ERR_INVALID_ARG_VALUE: ca has no certificate");
19857
20010
  const own = engine.store();
19858
20011
  try {
19859
- for (const der of custom) own.add(base64Der(der));
20012
+ for (const der2 of custom) own.add(base64Der(der2));
19860
20013
  } catch (err) {
19861
20014
  own.release();
19862
20015
  throw new KernelError("EINVAL", `ERR_INVALID_ARG_VALUE: ca: ${err.message}`);
@@ -19908,6 +20061,13 @@ async function prepareWith(support, req, servername, cert) {
19908
20061
  throw err;
19909
20062
  }
19910
20063
  }
20064
+ function anchoringOf(seal, info, servername) {
20065
+ const engine = seal.engine;
20066
+ if (!engine?.chainVerify || isIP2(servername) || info.peerCertificates.length === 0) return {};
20067
+ return {
20068
+ anchoring: (found) => anchorFor(engine, info.peerCertificates, servername, found)
20069
+ };
20070
+ }
19911
20071
  function sealing(seal, raw2, info, servername) {
19912
20072
  const { proc } = seal;
19913
20073
  const broker = proc.sealed;
@@ -19922,7 +20082,8 @@ function sealing(seal, raw2, info, servername) {
19922
20082
  exit: raw2.exit,
19923
20083
  verified: info.verified,
19924
20084
  handshakeAt: info.handshakeAt,
19925
- alpn: info.alpnProtocol
20085
+ alpn: info.alpnProtocol,
20086
+ ...anchoringOf(seal, info, servername)
19926
20087
  };
19927
20088
  return session;
19928
20089
  }
@@ -19932,7 +20093,8 @@ function secure(prepared, seal) {
19932
20093
  ran = true;
19933
20094
  try {
19934
20095
  const made2 = await tlsClient(raw2, prepared.options);
19935
- const session = sealing(seal, raw2, made2.info, prepared.options.servername);
20096
+ const engine = prepared.options.engine;
20097
+ const session = sealing({ ...seal, engine }, raw2, made2.info, prepared.options.servername);
19936
20098
  if (!session) return made2;
19937
20099
  made2.info.substitutes = substitutes(session);
19938
20100
  return { conn: sealedConn(made2.conn, session), info: made2.info };
@@ -20851,9 +21013,9 @@ var VfsNodes = class {
20851
21013
  }
20852
21014
  open(path, pin, writable2 = false, id2, ino) {
20853
21015
  const found = this.named(path, id2);
20854
- const same = !found || ino === void 0 || found.ino === void 0 || found.ino === ino;
20855
- if (found && !same) this.orphan(found);
20856
- const node = (same ? found : void 0) ?? this.create(path, id2, new VfsNode(this.fs, path, void 0, false, false, pin));
21016
+ const same2 = !found || ino === void 0 || found.ino === void 0 || found.ino === ino;
21017
+ if (found && !same2) this.orphan(found);
21018
+ const node = (same2 ? found : void 0) ?? this.create(path, id2, new VfsNode(this.fs, path, void 0, false, false, pin));
20857
21019
  node.ino ??= ino;
20858
21020
  node.opens++;
20859
21021
  if (writable2) node.writers++;
@@ -24568,6 +24730,10 @@ var SealedBroker = class {
24568
24730
  const req = sessionRequest(fields);
24569
24731
  return this.ask(req, (reply) => sessionValues(reply, req.placeholders));
24570
24732
  }
24733
+ async sessionAnchors(fields) {
24734
+ if (!anchorsAskable(fields)) return void 0;
24735
+ return this.ask(anchorsRequest(fields), anchorsOf);
24736
+ }
24571
24737
  async ask(req, parse) {
24572
24738
  const { hook } = this;
24573
24739
  if (!hook) return void 0;
@@ -25377,14 +25543,14 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
25377
25543
  return fresh2(remote);
25378
25544
  };
25379
25545
  const call = (op, body = {}) => current().call(op, body);
25380
- const same = (was, mode, seen) => seen?.mode === (mode | 128) && (was.ino !== void 0 && seen.ino !== void 0 ? seen.ino === was.ino : seen.size === was.size && seen.mtime === was.mtime);
25546
+ const same2 = (was, mode, seen) => seen?.mode === (mode | 128) && (was.ino !== void 0 && seen.ino !== void 0 ? seen.ino === was.ino : seen.size === was.size && seen.mtime === was.mtime);
25381
25547
  const settle = (client, { was, ...restore }) => client.call("setattr", restore).catch((err) => {
25382
25548
  if (!client.gone || !client.cleanup) throw err;
25383
25549
  void client.cleanup("setattr", restore).catch(() => {
25384
25550
  });
25385
25551
  const timer = setTimeout(async () => {
25386
25552
  const seen = await client.cleanup?.("stat", { path: restore.path }).catch(() => null);
25387
- if (same(was, restore.mode, seen))
25553
+ if (same2(was, restore.mode, seen))
25388
25554
  void client.cleanup?.("setattr", restore).catch(() => {
25389
25555
  });
25390
25556
  }, againMs);
@@ -27560,9 +27726,9 @@ var Launcher = class {
27560
27726
  const known = this.sameFiles.get(`${a}|${b}`);
27561
27727
  if (known?.stamp === stamp) return known.same;
27562
27728
  const [p, q] = await Promise.all([this.base.readFileBuffer(a), this.base.readFileBuffer(b)]);
27563
- const same = p.length === q.length && p.every((byte, i) => byte === q[i]);
27564
- this.sameFiles.set(`${a}|${b}`, { stamp, same });
27565
- return same;
27729
+ const same2 = p.length === q.length && p.every((byte, i) => byte === q[i]);
27730
+ this.sameFiles.set(`${a}|${b}`, { stamp, same: same2 });
27731
+ return same2;
27566
27732
  }
27567
27733
  async wasmOwner(wasm, name2, scope) {
27568
27734
  const leaf = baseName2(wasm);