code wiki / (root) / nx_https_get_cli.nx

nx_https_get_cli.nx source

↩ module page · 105 lines · 4984 B

1// nx_https_get_cli.nx -- the OPERATOR/MCP-facing sovereign HTTPS fetch (replaces WebFetch + curl). 2// nx_https_get <url> [connect-host:port] 3// <url> fetched over OUR TLS 1.3 + Mozilla trust store; raw response (status+headers+body) to stdout. 4// [connect-host:port] OPTIONAL connect override (curl --connect-to): open the TCP+TLS to THIS endpoint while 5// keeping SNI + Host + cert-name = the URL's host. Lets us fetch our OWN vhosts straight 6// from the sovereign edge (sites.elf 127.0.0.1:8443), bypassing the DSM nginx that also 7// squats :443 for unclaimed SNIs (andelinwest.com internally hit DSM's self-signed cert). 8// The tools daemon fork-execs this on a GREEN tool_allowlist.conf row, cap-gated to nx_https_get, and returns 9// stdout as the tools/call result. Uses PRODUCTION entropy (nx_csprng_fill from /dev/urandom). license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_csprng.nx" 12import "nx_x509_trust_store.nx" 13import "nx_trust_store_load_from_certdata.nx" 14import "nx_tls13_client_validate_certificate.nx" 15import "nx_tls13_client_session_run.nx" 16import "nx_tls13_chrome_session.nx" // Chrome-JA3 ClientHello runner (beats anti-bot CDN TLS walls; inherits the recv_hs reassembly fix) 17import "nx_https_url_for_fetch.nx" 18import "nx_https_url_connect.nx" 19import "nx_https_get_complete.nx" 20import "nx_tls_cert_cache.nx" 21import "nx_https_fetch_lib.nx" // the shared fetch composition (one implementation, shared with nx_mvault_fetch) 22const HGC_MAGIC_4194304: i64 = 4194304 23const HGC_MAGIC_65535: i64 = 65535 24 25const HGC_CERTDATA: *u8 = "data/mozilla_certdata.txt" as *u8 26const HGC_OUTCAP: i64 = 4194304 // 4 MiB response cap 27 28func hgc_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 29func hgc_put(s: *u8) -> i64 { sys_write(1, s, hgc_slen(s)); return 0 } 30func hgc_putn(v: i64) -> i64 { 31 let b: *u8 = sys_mmap(24) 32 var m: i64 = v 33 if m == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 } 34 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 35 var nd: i64 = 0 36 var t: i64 = m 37 while t > 0 { nd = nd + 1; t = t / 10 } 38 var i: i64 = nd - 1 39 while i >= 0 { b[i] = (48 + (m % 10)) as u8; m = m / 10; i = i - 1 } 40 sys_write(1, b, nd) 41 return 0 42} 43 44func main(argc: i64, argv: *i64) -> i64 { 45 if argc < 2 { hgc_put("ERROR: usage: nx_https_get <url> [connect-host:port]\n" as *u8); return 2 } 46 let url: *u8 = argv[1] as *u8 47 let now: i64 = sys_now_realtime_sec() 48 49 // ---- trust store (loaded once; the fetch composition now lives in 50 // nx_https_fetch_lib so the album downloader shares ONE implementation 51 // instead of duplicating ~90 lines of crypto setup -- 2026-07-31) ---- 52 let store_i: i64 = hf_store_load() 53 if store_i <= 0 { hgc_put("ERROR: trust-store load failed (data/mozilla_certdata.txt on daemon CWD?)\n" as *u8); return 3 } 54 55 var cip: i64 = 0 56 var cport: i64 = 0 57 if argc >= 3 { 58 let ipbox: *i64 = sys_mmap(8) as *i64 59 let portbox: *i64 = sys_mmap(8) as *i64 60 if hgc_parse_ipport(argv[2] as *u8, ipbox, portbox) != 1 { hgc_put("ERROR: bad connect-override (want a.b.c.d:port)\n" as *u8); return 2 } 61 cip = ipbox[0] 62 cport = portbox[0] 63 } 64 65 let out: *u8 = sys_mmap(HGC_OUTCAP) 66 let n: i64 = hf_fetch(store_i, url, cip, cport, out, HGC_OUTCAP) 67 if n == HF_ERR_URL { hgc_put("ERROR: bad url\n" as *u8); return 2 } 68 if n == HF_ERR_CONNECT { hgc_put("ERROR: connect failed\n" as *u8); return 3 } 69 if n == HF_ERR_TLS { hgc_put("ERROR: TLS handshake failed\n" as *u8); return 4 } 70 if n == HF_ERR_HTTP { hgc_put("ERROR: HTTP fetch failed\n" as *u8); return 5 } 71 if n < 0 { hgc_put("ERROR: fetch failed\n" as *u8); return 5 } 72 sys_write(1, out, n) 73 return 0 74} 75 76 77// parse "a.b.c.d:port" -> ip_out (big-endian packed u32, e.g. 127.0.0.1 -> 0x7F000001) + port_out. 1 ok / 0 bad. 78func hgc_parse_ipport(s: *u8, ip_out: *i64, port_out: *i64) -> i64 { 79 var packed: i64 = 0 80 var val: i64 = 0 81 var nocts: i64 = 0 82 var port: i64 = 0 83 var indots: i64 = 1 84 var i: i64 = 0 85 while s[i] != (0 as u8) { 86 let c: i64 = s[i] as i64 87 if indots == 1 { 88 if c == 46 { packed = (packed << 8) | (val & 0xff); nocts = nocts + 1; val = 0 } 89 else { if c == 58 { packed = (packed << 8) | (val & 0xff); nocts = nocts + 1; val = 0; indots = 0 } 90 else { if c < 48 { return 0 } if c > 57 { return 0 } val = val * 10 + (c - 48) } } 91 } else { 92 if c < 48 { return 0 } 93 if c > 57 { return 0 } 94 port = port * 10 + (c - 48) 95 } 96 i = i + 1 97 } 98 if indots == 1 { return 0 } // no ':' -> no port given 99 if nocts != 4 { return 0 } // need exactly 4 octets 100 if port <= 0 { return 0 } 101 if port > HGC_MAGIC_65535 { return 0 } 102 ip_out[0] = packed 103 port_out[0] = port 104 return 1 105}