code wiki / _hdl_build / nx_docportal_authz_route_gate.nx

nx_docportal_authz_route_gate.nx source

↩ module page · 155 lines · 9050 B

1// nx_docportal_authz_route_gate.nx -- MEASURED end-to-end proof that the P2 wiring fired at the REAL da_handle 2// routes: it drives the pure router with per-session DaCtx (carrying the subject the daemon sets from 3// nx_sa_validate_handle) and inspects the sovereign store + the route responses. Fresh nonce domain per run. 4// T1 session A POST /admin/upload visibility=private -> 200 UPLOADED, and own:<cid> == A (ownership recorded). 5// T2 session A GET /admin/doc?cid= -> 200 + the DECRYPTED plaintext (owner reads through authz + at-rest decrypt). 6// T3 session B GET /admin/doc?cid= (same doc) -> 403 Forbidden (non-owner eyes-only DENY). 7// T4 session A POST /admin/upload visibility=public -> 200 UPLOADED + stored PLAINTEXT (public path unchanged). 8// Print pass=4 + GREEN/RED, append knowledge/status/dp_authz_route_gate.log. STANDALONE -- no socket/daemon/deploy. 9// (nx_chacha20_poly1305_decrypt prints one 'A' to STDERR on first decrypt -- shipped-AEAD marker; harmless.) 10// license_tier: ORIGINAL 11import "nx_docportal_admin_lib.nx" // da_handle + DaCtx (the wired routes) 12import "nx_doc_authz.nx" // authz_get_owner (verify recorded ownership) 13import "nx_doc_at_rest.nx" // at_is_magic (verify public stays plaintext) 14import "nx_docportal_lib.nx" // dp_cid / dp_prefix / dp_key / DP_VIS_* + ss_open/ss_hget 15 16func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 17func g_num(v: i64) -> i64 { 18 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 19 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 20 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 21 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 22} 23func g_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 24func g_wn(fd: i64, v: i64) -> i64 { 25 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 26 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 27 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 28 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(fd, bb, k); return 0 29} 30func g_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 31func g_cat(out: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { out[o] = s[i]; o = o + 1; i = i + 1 } return o } 32func g_catnum(out: *u8, o: i64, v: i64) -> i64 { 33 if v == 0 { out[o] = 48 as u8; return o + 1 } 34 var m: i64 = v; let t: *u8 = sys_mmap(28); var k: i64 = 0 35 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 36 var i: i64 = 0; while i < k { out[o] = t[k - 1 - i]; o = o + 1; i = i + 1 } return o 37} 38func g_eqbytes(a: *u8, b: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } 39func g_starts(buf: *u8, n: i64, s: *u8) -> i64 { let sn: i64 = g_slen(s); if n < sn { return 0 } var i: i64 = 0; while i < sn { if buf[i] != s[i] { return 0 } i = i + 1 } return 1 } 40func g_contains(hay: *u8, hn: i64, ndl: *u8) -> i64 { 41 let nl: i64 = g_slen(ndl); if nl == 0 { return 0 } 42 if hn < nl { return 0 } 43 var i: i64 = 0 44 while i + nl <= hn { 45 var j: i64 = 0; var hit: i64 = 1 46 while j < nl { if hay[i + j] != ndl[j] { hit = 0; j = nl } else { j = j + 1 } } 47 if hit == 1 { return 1 } 48 i = i + 1 49 } 50 return 0 51} 52 53func main() -> i64 { 54 g_puts("=== DOCPORTAL AUTHZ ROUTE GATE (wired da_handle: private upload->owner->read; other session->403) ===\n" as *u8) 55 let nonce: i64 = sys_now_realtime_sec() 56 let dom: *u8 = sys_mmap(64) 57 var dn: i64 = g_cat(dom, 0, "dpwireauthz" as *u8); dn = g_catnum(dom, dn, nonce); dom[dn] = 0 as u8 58 59 let subjA: *u8 = "SESSIONA-uid-aaaa" as *u8 60 let subjB: *u8 = "SESSIONB-uid-bbbb" as *u8 61 let dctxA: *DaCtx = sys_mmap(16) as *DaCtx 62 dctxA.user_level = 2 63 dctxA.subject = subjA 64 let dctxB: *DaCtx = sys_mmap(16) as *DaCtx 65 dctxB.user_level = 2 66 dctxB.subject = subjB 67 68 let req: *u8 = sys_mmap(8192) 69 let out: *u8 = sys_mmap(524288) 70 let pq: *i64 = sys_mmap(16) as *i64 71 let lq: *i64 = sys_mmap(16) as *i64 72 73 let ptConf: *u8 = "WIRE-AUTHZ-CANARY eyes-only client vault document via the live route." as *u8 74 let ptConfLen: i64 = g_slen(ptConf) 75 let cidConf: i64 = dp_cid(ptConf, ptConfLen) 76 77 var pass: i64 = 0 78 79 // T1: session A private upload -> 200 UPLOADED + ownership recorded == A 80 var r: i64 = g_cat(req, 0, "POST /admin/upload?domain=" as *u8) 81 r = g_cat(req, r, dom) 82 r = g_cat(req, r, "&visibility=private HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 83 r = g_cat(req, r, ptConf) 84 let resp1: i64 = da_handle(dctxA, req, r, out) 85 let ownbuf: *u8 = sys_mmap(256) 86 let ownlen: i64 = authz_get_owner(dom, DP_VIS_PRIVATE, cidConf, ownbuf, 255) 87 var t1: i64 = 0 88 if g_starts(out, resp1, "HTTP/1.1 200" as *u8) == 1 { if g_contains(out, resp1, "UPLOADED" as *u8) == 1 { 89 if ownlen == g_slen(subjA) { if g_eqbytes(ownbuf, subjA, ownlen) == 1 { t1 = 1 } } 90 } } 91 pass = pass + t1 92 g_puts(" T1 A private upload -> 200 + own:<cid>==A (ownlen=" as *u8); g_num(ownlen); g_puts("): " as *u8) 93 if t1 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 94 95 // T2: session A GET /admin/doc?cid= -> 200 + decrypted plaintext 96 var r2: i64 = g_cat(req, 0, "GET /admin/doc?domain=" as *u8) 97 r2 = g_cat(req, r2, dom) 98 r2 = g_cat(req, r2, "&cid=" as *u8) 99 r2 = g_catnum(req, r2, cidConf) 100 r2 = g_cat(req, r2, " HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 101 let resp2: i64 = da_handle(dctxA, req, r2, out) 102 var t2: i64 = 0 103 if g_starts(out, resp2, "HTTP/1.1 200" as *u8) == 1 { if g_contains(out, resp2, "WIRE-AUTHZ-CANARY" as *u8) == 1 { t2 = 1 } } 104 pass = pass + t2 105 g_puts(" T2 A reads own doc -> 200 + decrypted plaintext: " as *u8) 106 if t2 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 107 108 // T3: session B GET the SAME doc -> 403 (non-owner denied). Reuse the identical request bytes, dctxB. 109 var r3: i64 = g_cat(req, 0, "GET /admin/doc?domain=" as *u8) 110 r3 = g_cat(req, r3, dom) 111 r3 = g_cat(req, r3, "&cid=" as *u8) 112 r3 = g_catnum(req, r3, cidConf) 113 r3 = g_cat(req, r3, " HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 114 let resp3: i64 = da_handle(dctxB, req, r3, out) 115 var t3: i64 = 0 116 if g_starts(out, resp3, "HTTP/1.1 403" as *u8) == 1 { t3 = 1 } 117 pass = pass + t3 118 g_puts(" T3 B reads A's doc -> 403 Forbidden (eyes-only deny): " as *u8) 119 if t3 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 120 121 // T4: public path unchanged -- A public upload -> 200 UPLOADED + stored PLAINTEXT (no NXENC1 magic) 122 let ptPub: *u8 = "WIRE-AUTHZ-PUBLIC corpus article, no restriction." as *u8 123 let ptPubLen: i64 = g_slen(ptPub) 124 let cidPub: i64 = dp_cid(ptPub, ptPubLen) 125 var r4: i64 = g_cat(req, 0, "POST /admin/upload?domain=" as *u8) 126 r4 = g_cat(req, r4, dom) 127 r4 = g_cat(req, r4, "&visibility=public&pub_search=1 HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 128 r4 = g_cat(req, r4, ptPub) 129 let resp4: i64 = da_handle(dctxA, req, r4, out) 130 let prefixPub: *u8 = sys_mmap(512); dp_prefix(dom, DP_VIS_PUBLIC, prefixPub) 131 let dkeyPub: *u8 = sys_mmap(64); dp_key(cidPub, dkeyPub) 132 var pubPlain: i64 = 0 133 let hPub: *i64 = ss_open(prefixPub) 134 if (hPub as i64) != 0 { if ss_hget(hPub, dkeyPub, pq, lq) == 1 { 135 let pvp: *u8 = pq[0] as *u8; let pvl: i64 = lq[0] 136 if at_is_magic(pvp, pvl) == 0 { if pvl == ptPubLen { if g_eqbytes(pvp, ptPub, ptPubLen) == 1 { pubPlain = 1 } } } 137 } } 138 var t4: i64 = 0 139 if g_starts(out, resp4, "HTTP/1.1 200" as *u8) == 1 { if g_contains(out, resp4, "UPLOADED" as *u8) == 1 { if pubPlain == 1 { t4 = 1 } } } 140 pass = pass + t4 141 g_puts(" T4 A public upload -> 200 + stored PLAINTEXT (public unchanged, plain=" as *u8); g_num(pubPlain); g_puts("): " as *u8) 142 if t4 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 143 144 g_puts("----\nDP-AUTHZ-ROUTE rows=4 pass=" as *u8); g_num(pass); g_puts("\n" as *u8) 145 let lg: i64 = sys_openat_append("knowledge/status/dp_authz_route_gate.log" as *u8, 0x1a4) 146 if lg >= 0 { 147 g_w(lg, "DP-AUTHZ-ROUTE own_recorded=" as *u8); g_wn(lg, t1); g_w(lg, " owner_read=" as *u8); g_wn(lg, t2) 148 g_w(lg, " other_403=" as *u8); g_wn(lg, t3); g_w(lg, " public_plaintext=" as *u8); g_wn(lg, t4) 149 g_w(lg, " rows=4 pass=" as *u8); g_wn(lg, pass) 150 if pass == 4 { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) } 151 sys_close(lg) 152 } 153 if pass == 4 { g_puts("DP-AUTHZ-ROUTE GREEN (wired route: owner records + reads decrypted, non-owner 403, public plaintext -- measured)\n" as *u8); sys_exit(0); return 0 } 154 g_puts("DP-AUTHZ-ROUTE RED\n" as *u8); sys_exit(1); return 1 155}