code wiki / _hdl_build / nx_apistack_svctoken_gate.nx

nx_apistack_svctoken_gate.nx source

↩ module page · 50 lines · 3689 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_apistack_svctoken_gate.nx -- hermetic gate for CAP-API-SVCTOKEN. Proves a presented token resolves to its 4// service+level via the HASHED store, unknown tokens are denied, and the store holds only the hash (not the token). 5// expect_exit: 0 6import "nx_syscalls.nx" 7import "nx_apistack_svctoken.nx" 8import "nx_gate_verdict.nx" 9 10func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 11" as *u8); return ok } 12func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 13func g_app(buf: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){buf[off+i]=s[i];i=i+1} return off+i } 14func g_eq(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 } 15func g_contains(hay: *u8, hlen: i64, needle: *u8) -> i64 { let nl: i64=g_slen(needle); var i: i64=0; while i+nl<=hlen { var j: i64=0; var m: i64=1; while j<nl { if hay[i+j]!=needle[j] { m=0; j=nl } else { j=j+1 } } if m==1 { return 1 } i=i+1 } return 0 } 16 17func main(argc: i64, argv: *i64) -> i64 { 18 gp("=== nx_apistack_svctoken_gate (scoped hashed service tokens) ===\n" as *u8) 19 let C: *u8 = "/tmp/svctokens.conf" as *u8 20 let tok: *u8 = "deploy-bot-secret-abc123" as *u8; let tokn: i64 = g_slen(tok) 21 // build the store row: HASH(token) TAB deploy-bot TAB 3 22 let th: *u8 = sys_mmap(24); st_hex16(st_fnv(tok, tokn), th) 23 let sf: *u8 = sys_mmap(256); var sn: i64 = 0 24 var i: i64 = 0; while i < 16 { sf[sn] = th[i]; sn = sn + 1; i = i + 1 } 25 sf[sn] = 9 as u8; sn = sn + 1; sn = g_app(sf, sn, "deploy-bot" as *u8); sf[sn] = 9 as u8; sn = sn + 1; sf[sn] = 51 as u8; sn = sn + 1; sf[sn] = 10 as u8; sn = sn + 1 26 let fd: i64 = sys_openat_wr(C, 0x1a4); if fd >= 0 { sys_write(fd, sf, sn); sys_close(fd) } 27 var pass: i64 = 0; var fail: i64 = 0 28 29 // T1 valid token -> service + level 30 let svc: *u8 = sys_mmap(64); let lvl: *i64 = sys_mmap(8) as *i64 31 if st_resolve(C, tok, tokn, svc, 64, lvl) == 1 { if g_eq(svc, "deploy-bot" as *u8, 10) == 1 { if lvl[0] == 3 { pass=pass+1; gp(" T1 token -> deploy-bot / level 3 PASS\n" as *u8) } else { fail=fail+1; gp(" T1 FAIL level\n" as *u8) } } else { fail=fail+1; gp(" T1 FAIL service\n" as *u8) } } else { fail=fail+1; gp(" T1 FAIL not resolved\n" as *u8) } 32 33 // T2 unknown token -> denied 34 let svc2: *u8 = sys_mmap(64); let lvl2: *i64 = sys_mmap(8) as *i64 35 if st_resolve(C, "wrong-token" as *u8, 11, svc2, 64, lvl2) == 0 { if lvl2[0] == 0 { pass=pass+1; gp(" T2 unknown token -> denied (level 0) PASS\n" as *u8) } else { fail=fail+1; gp(" T2 FAIL level\n" as *u8) } } else { fail=fail+1; gp(" T2 FAIL resolved\n" as *u8) } 36 37 // T3 store holds only the HASH, not the plaintext token 38 if g_contains(sf, sn, "deploy-bot-secret" as *u8) == 0 { pass=pass+1; gp(" T3 store holds hash NOT the token (leak-safe) PASS\n" as *u8) } else { fail=fail+1; gp(" T3 FAIL plaintext token in store\n" as *u8) } 39 40 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail) 41 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 42 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 43 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 44 let ctr__dry: *i64 = gv_ctr() 45 ctr__dry[0] = pass 46 ctr__dry[1] = pass + fail 47 let rc__dry: i64 = gv_verdict("APISTACK-SVCTOKEN-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 48 sys_exit(rc__dry) 49 return rc__dry 50}