code wiki / _hdl_build / nx_gallery_gateway_smoke.nx

nx_gallery_gateway_smoke.nx source

↩ module page · 138 lines · 7637 B

1// nx_gallery_gateway_smoke.nx -- R1 GATE PROOF. Forks the gallery gateway and drives it as a real HTTP 2// client over the wire: register -> login -> GET /gallery/api/list (no token)=401 -> (valid token)=200 3// PROXIED from the live gallery (:18090) -> (bad token)=401 -> GET /gallery/sw.js=200 -> /gallery/login=200. 4// Proves the OPAQUE session gate + the reverse-proxy. Requires /tmp/nx_gallery_gateway.sov.elf built in the 5// same WSL session AND the gallery backend live on 127.0.0.1:18090. exit 0 = GREEN, N = assertion N failed. 6import "nx_syscalls.nx" 7import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 8import "nx_assert.nx" 9const SMK_MAGIC_8388608: i64 = 8388608 10const SMK_MAGIC_4096: i64 = 4096 11const SMK_MAGIC_8388607: i64 = 8388607 12 13const SMK_PORT: i64 = 18091 14const DAEMON_ELF: *u8 = "/tmp/nx_gallery_gateway.sov.elf" as *u8 15 16func smk_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 17func smk_find(buf: *u8, n: i64, needle: *u8, nl: i64) -> i64 { 18 if nl==0 { return 0 } 19 var i: i64=0 20 while i+nl<=n { var j: i64=0; var ok: i64=1; while j<nl { if buf[i+j]!=needle[j]{ok=0;j=nl} else {j=j+1} } if ok==1 {return i} i=i+1 } 21 return 0-1 22} 23func smk_http(req: *u8, reqn: i64, resp: *u8, cap: i64) -> i64 { 24 let fd: i64 = sys_socket(2, 1, 0); if fd < 0 { return 0-1 } 25 sys_set_socket_timeout(fd, 20) 26 let a: *u8 = sys_mmap(16) 27 a[0]=2 as u8; a[1]=0 as u8; a[2]=((SMK_PORT>>8)&0xff) as u8; a[3]=(SMK_PORT&0xff) as u8 28 a[4]=127 as u8; a[5]=0 as u8; a[6]=0 as u8; a[7]=1 as u8 29 var zi: i64=8; while zi<16 { a[zi]=0 as u8; zi=zi+1 } 30 if nx_connect_bounded(fd, a, 16, NX_CONN_DEFAULT_MS) != 0 { sys_close(fd); return 0-2 } 31 sys_write(fd, req, reqn) 32 var off: i64=0; var go: i64=1 33 while go==1 { let r: i64=sys_read(fd, ((resp as i64)+off) as *u8, cap-off); if r<=0 {go=0} else { off=off+r; if off>=cap {go=0} } } 34 sys_close(fd); return off 35} 36func smk_post(reqbuf: *u8, path: *u8, body: *u8) -> i64 { 37 let bl: i64 = smk_slen(body) 38 var o: i64=0 39 let p1: *u8="POST " as *u8; var i: i64=0; while p1[i]!=(0 as u8){reqbuf[o]=p1[i];o=o+1;i=i+1} 40 i=0; while path[i]!=(0 as u8){reqbuf[o]=path[i];o=o+1;i=i+1} 41 let p2: *u8=" HTTP/1.1\r\nHost: x\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: " as *u8; i=0; while p2[i]!=(0 as u8){reqbuf[o]=p2[i];o=o+1;i=i+1} 42 let t: *u8=sys_mmap(28); var m: i64=bl; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var q: i64=k-1; while q>=0{reqbuf[o]=t[q];o=o+1;q=q-1} 43 let p3: *u8="\r\nConnection: close\r\n\r\n" as *u8; i=0; while p3[i]!=(0 as u8){reqbuf[o]=p3[i];o=o+1;i=i+1} 44 i=0; while body[i]!=(0 as u8){reqbuf[o]=body[i];o=o+1;i=i+1} 45 return o 46} 47// GET with optional X-Nishi-Session header (tok[0]==0 -> no header). 48func smk_get(reqbuf: *u8, path: *u8, tok: *u8) -> i64 { 49 var o: i64=0; var i: i64=0 50 let g: *u8="GET " as *u8; i=0; while g[i]!=(0 as u8){reqbuf[o]=g[i];o=o+1;i=i+1} 51 i=0; while path[i]!=(0 as u8){reqbuf[o]=path[i];o=o+1;i=i+1} 52 let h: *u8=" HTTP/1.1\r\nHost: x\r\n" as *u8; i=0; while h[i]!=(0 as u8){reqbuf[o]=h[i];o=o+1;i=i+1} 53 if tok[0]!=(0 as u8) { 54 let xs: *u8="X-Nishi-Session: " as *u8; i=0; while xs[i]!=(0 as u8){reqbuf[o]=xs[i];o=o+1;i=i+1} 55 i=0; while tok[i]!=(0 as u8){reqbuf[o]=tok[i];o=o+1;i=i+1} 56 reqbuf[o]=13 as u8; o=o+1; reqbuf[o]=10 as u8; o=o+1 57 } 58 let c: *u8="Connection: close\r\n\r\n" as *u8; i=0; while c[i]!=(0 as u8){reqbuf[o]=c[i];o=o+1;i=i+1} 59 return o 60} 61 62func main() -> i64 { 63 let kfd: i64=sys_openat_wr("/tmp/ggw_keys.log" as *u8, 0x1a4); if kfd>=0 {sys_close(kfd)} 64 let sfd: i64=sys_openat_wr("/tmp/ggw_store.log" as *u8, 0x1a4); if sfd>=0 {sys_close(sfd)} 65 66 let pid: i64 = sys_fork() 67 if pid == 0 { 68 let argv: *i64 = sys_mmap(96) as *i64 69 argv[0]=DAEMON_ELF as i64 70 argv[1]="18091" as *u8 as i64 71 argv[2]="/tmp/ggw_keys.log" as *u8 as i64 72 argv[3]="/tmp/ggw_store.log" as *u8 as i64 73 argv[4]="50" as *u8 as i64 74 argv[5]="18090" as *u8 as i64 75 argv[6]="1" as *u8 as i64 76 argv[7]="8192" as *u8 as i64 77 argv[8]="1" as *u8 as i64 78 argv[9]="1" as *u8 as i64 79 argv[10]=0 80 let envp: *i64 = sys_mmap(16) as *i64; envp[0]="PATH=/usr/bin:/bin" as *u8 as i64; envp[1]=0 81 sys_execve(DAEMON_ELF, argv, envp) 82 sys_exit(127) 83 } 84 sys_sleep_ms(700) 85 86 let resp: *u8 = sys_mmap(SMK_MAGIC_8388608) 87 let req: *u8 = sys_mmap(SMK_MAGIC_4096) 88 let empty: *u8 = sys_mmap(4); empty[0]=0 as u8 89 90 let rqn: i64 = smk_post(req, "/gallery/auth/register" as *u8, "handle=tester&pw=testpass123" as *u8) 91 let r1: i64 = smk_http(req, rqn, resp, SMK_MAGIC_8388607) 92 nx_puts_err("register bytes=" as *u8); nx_puti_err(r1); nx_puts_err("\n" as *u8) 93 if smk_find(resp, r1, "200 OK" as *u8, 6) < 0 { nx_kill(pid,9); return 1 } 94 if smk_find(resp, r1, "mnemonic" as *u8, 8) < 0 { nx_kill(pid,9); return 2 } 95 96 let lqn: i64 = smk_post(req, "/gallery/auth/login" as *u8, "handle=tester&pw=testpass123" as *u8) 97 let r2: i64 = smk_http(req, lqn, resp, SMK_MAGIC_8388607) 98 if smk_find(resp, r2, "200 OK" as *u8, 6) < 0 { nx_kill(pid,9); return 3 } 99 let tp: i64 = smk_find(resp, r2, "\"token\":\"" as *u8, 9) 100 if tp < 0 { nx_kill(pid,9); return 4 } 101 let tok: *u8 = sys_mmap(512); var ti: i64=0; var si: i64=tp+9 102 while si < r2 { if resp[si]==(34 as u8) { si=r2 } else { tok[ti]=resp[si]; ti=ti+1; si=si+1 } } 103 tok[ti]=0 as u8 104 nx_puts_err("login token chars=" as *u8); nx_puti_err(ti); nx_puts_err("\n" as *u8) 105 106 let q3: i64 = smk_get(req, "/gallery/api/list" as *u8, empty) 107 let r3: i64 = smk_http(req, q3, resp, SMK_MAGIC_8388607) 108 if smk_find(resp, r3, "401" as *u8, 3) < 0 { nx_kill(pid,9); return 5 } 109 nx_puts_err("api/list(no token) -> 401 OK\n" as *u8) 110 111 let q4: i64 = smk_get(req, "/gallery/api/list?filter=recordings" as *u8, tok) 112 let r4: i64 = smk_http(req, q4, resp, SMK_MAGIC_8388607) 113 if smk_find(resp, r4, "200 OK" as *u8, 6) < 0 { nx_kill(pid,9); return 6 } 114 if smk_find(resp, r4, "items" as *u8, 5) < 0 { if smk_find(resp, r4, "kind" as *u8, 4) < 0 { nx_kill(pid,9); return 7 } } 115 nx_puts_err("api/list(valid) -> 200 PROXIED from :18090 OK\n" as *u8) 116 117 let bad: *u8 = sys_mmap(64); var bi: i64=0; while bi<40 { bad[bi]=65 as u8; bi=bi+1 } bad[40]=0 as u8 118 let q5: i64 = smk_get(req, "/gallery/api/list" as *u8, bad) 119 let r5: i64 = smk_http(req, q5, resp, SMK_MAGIC_8388607) 120 if smk_find(resp, r5, "401" as *u8, 3) < 0 { nx_kill(pid,9); return 8 } 121 nx_puts_err("api/list(bad token) -> 401 OK\n" as *u8) 122 123 let q6: i64 = smk_get(req, "/gallery/sw.js" as *u8, empty) 124 let r6: i64 = smk_http(req, q6, resp, SMK_MAGIC_8388607) 125 if smk_find(resp, r6, "200 OK" as *u8, 6) < 0 { nx_kill(pid,9); return 9 } 126 if smk_find(resp, r6, "respondWith" as *u8, 11) < 0 { nx_kill(pid,9); return 10 } 127 nx_puts_err("sw.js -> 200 + respondWith OK\n" as *u8) 128 129 let q7: i64 = smk_get(req, "/gallery/login" as *u8, empty) 130 let r7: i64 = smk_http(req, q7, resp, SMK_MAGIC_8388607) 131 if smk_find(resp, r7, "200 OK" as *u8, 6) < 0 { nx_kill(pid,9); return 11 } 132 if smk_find(resp, r7, "Nishi Gallery" as *u8, 13) < 0 { nx_kill(pid,9); return 12 } 133 nx_puts_err("login page -> 200 OK\n" as *u8) 134 135 let st: *i64 = sys_mmap(16) as *i64; nx_kill(pid, 9); sys_wait4(pid, st, 0) 136 nx_puts_err("nx_gallery_gateway_smoke verdict=GREEN pass=7 (register/login/gate401/proxy200/bad401/sw.js/loginpage)\n" as *u8) 137 return 0 138}