code wiki / _hdl_build / nx_opaque_login_smoke.nx
nx_opaque_login_smoke.nx source
↩ module page · 108 lines · 6121 B
1// nx_opaque_login_smoke.nx -- R2 smoke: fork the OPAQUE login daemon, drive it as a REAL HTTP client over a
2// socket (POST /register -> POST /login -> GET /whoami[valid] -> GET /whoami[bad token]), proving the
3// no-cookie OPAQUE login works end-to-end over the wire. Requires /tmp/nx_opaque_login_daemon.sov.elf built
4// in the same WSL session (the WOMB emits there). exit 0 = pass, N = assertion N failed.
5import "nx_syscalls.nx"
6import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
7import "nx_assert.nx"
8const SMK_MAGIC_32768: i64 = 32768
9const SMK_MAGIC_2048: i64 = 2048
10const SMK_MAGIC_32767: i64 = 32767
11
12const SMK_PORT: i64 = 18099
13const DAEMON_ELF: *u8 = "/tmp/nx_opaque_login_daemon.sov.elf" as *u8
14
15func smk_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
16func smk_find(buf: *u8, n: i64, needle: *u8, nl: i64) -> i64 {
17 if nl==0 { return 0 }
18 var i: i64=0
19 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 }
20 return 0-1
21}
22func smk_trunc(path: *u8) -> i64 { let fd: i64=sys_openat_wr(path, 0x1a4); if fd>=0 { sys_close(fd) } return 0 }
23
24// connect 127.0.0.1:SMK_PORT, send req[0..reqn], read response into resp -> resp length (or <0).
25func smk_http(req: *u8, reqn: i64, resp: *u8, cap: i64) -> i64 {
26 let fd: i64 = sys_socket(2, 1, 0); if fd < 0 { return 0-1 }
27 sys_set_socket_timeout(fd, 5)
28 let a: *u8 = sys_mmap(16)
29 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
30 a[4]=127 as u8; a[5]=0 as u8; a[6]=0 as u8; a[7]=1 as u8
31 var zi: i64=8; while zi<16 { a[zi]=0 as u8; zi=zi+1 }
32 if nx_connect_bounded(fd, a, 16, NX_CONN_DEFAULT_MS) != 0 { sys_close(fd); return 0-2 }
33 sys_write(fd, req, reqn)
34 var off: i64=0; var go: i64=1
35 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} } }
36 sys_close(fd); return off
37}
38// build a POST with form body; returns request length into reqbuf.
39func smk_post(reqbuf: *u8, path: *u8, body: *u8) -> i64 {
40 let bl: i64 = smk_slen(body)
41 var o: i64=0
42 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}
43 i=0; while path[i]!=(0 as u8){reqbuf[o]=path[i];o=o+1;i=i+1}
44 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}
45 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}
46 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}
47 i=0; while body[i]!=(0 as u8){reqbuf[o]=body[i];o=o+1;i=i+1}
48 return o
49}
50
51func main() -> i64 {
52 smk_trunc("/tmp/nx_olgd_keys.log" as *u8)
53 smk_trunc("/tmp/nx_olgd_store.log" as *u8)
54
55 let pid: i64 = sys_fork()
56 if pid == 0 {
57 let argv: *i64 = sys_mmap(64) as *i64
58 argv[0]=DAEMON_ELF as i64; argv[1]="18099" as *u8 as i64; argv[2]="/tmp/nx_olgd_keys.log" as *u8 as i64
59 argv[3]="/tmp/nx_olgd_store.log" as *u8 as i64; argv[4]="14" as *u8 as i64; argv[5]="8192" as *u8 as i64; argv[6]=0
60 let envp: *i64 = sys_mmap(16) as *i64; envp[0]="PATH=/usr/bin:/bin" as *u8 as i64; envp[1]=0
61 sys_execve(DAEMON_ELF, argv, envp)
62 sys_exit(127)
63 }
64 sys_sleep_ms(500) // let the daemon bind + init the auth context
65
66 let resp: *u8 = sys_mmap(SMK_MAGIC_32768)
67 let req: *u8 = sys_mmap(SMK_MAGIC_2048)
68
69 // 1. register
70 let rqn: i64 = smk_post(req, "/register" as *u8, "handle=smoke&pw=testpass123" as *u8)
71 let r1: i64 = smk_http(req, rqn, resp, SMK_MAGIC_32767)
72 nx_puts_err("register resp bytes="); nx_puti_err(r1)
73 if smk_find(resp, r1, "200 OK" as *u8, 6) < 0 { nx_kill(pid,9); return 1 }
74 if smk_find(resp, r1, "mnemonic" as *u8, 8) < 0 { nx_kill(pid,9); return 2 }
75
76 // 2. login -> extract the no-cookie token
77 let lqn: i64 = smk_post(req, "/login" as *u8, "handle=smoke&pw=testpass123" as *u8)
78 let r2: i64 = smk_http(req, lqn, resp, SMK_MAGIC_32767)
79 if smk_find(resp, r2, "200 OK" as *u8, 6) < 0 { nx_kill(pid,9); return 3 }
80 let tp: i64 = smk_find(resp, r2, "\"token\":\"" as *u8, 9)
81 if tp < 0 { nx_kill(pid,9); return 4 }
82 let tok: *u8 = sys_mmap(512); var ti: i64=0; var si: i64=tp+9
83 while si < r2 { if resp[si]==(34 as u8) { si=r2 } else { tok[ti]=resp[si]; ti=ti+1; si=si+1 } }
84 tok[ti]=0 as u8
85 nx_puts_err("\nlogin OK; token chars="); nx_puti_err(ti)
86
87 // 3. whoami with the valid token -> 200 + uid
88 let wq: *u8 = sys_mmap(SMK_MAGIC_2048); var o: i64=0
89 let h1: *u8="GET /whoami HTTP/1.1\r\nHost: x\r\nX-Nishi-Session: " as *u8; var i: i64=0; while h1[i]!=(0 as u8){wq[o]=h1[i];o=o+1;i=i+1}
90 i=0; while tok[i]!=(0 as u8){wq[o]=tok[i];o=o+1;i=i+1}
91 let h2: *u8="\r\nConnection: close\r\n\r\n" as *u8; i=0; while h2[i]!=(0 as u8){wq[o]=h2[i];o=o+1;i=i+1}
92 let r3: i64 = smk_http(wq, o, resp, SMK_MAGIC_32767)
93 if smk_find(resp, r3, "200 OK" as *u8, 6) < 0 { nx_kill(pid,9); return 5 }
94 if smk_find(resp, r3, "uid" as *u8, 3) < 0 { nx_kill(pid,9); return 6 }
95 nx_puts_err("\nwhoami(valid) -> 200 + uid\n" as *u8)
96
97 // 4. whoami with a bad token -> 401
98 let bq: *u8 = sys_mmap(512)
99 let b1: *u8="GET /whoami HTTP/1.1\r\nHost: x\r\nX-Nishi-Session: AAAAAAAAAAAAAAAAAAAAAAAA\r\nConnection: close\r\n\r\n" as *u8
100 var bo: i64=0; i=0; while b1[i]!=(0 as u8){bq[bo]=b1[i];bo=bo+1;i=i+1}
101 let r4: i64 = smk_http(bq, bo, resp, SMK_MAGIC_32767)
102 if smk_find(resp, r4, "401" as *u8, 3) < 0 { nx_kill(pid,9); return 7 }
103 nx_puts_err("whoami(bad token) -> 401 rejected\n" as *u8)
104
105 let st: *i64 = sys_mmap(16) as *i64; nx_kill(pid, 9); sys_wait4(pid, st, 0)
106 nx_puts_err("nx_opaque_login_smoke verdict=GREEN pass=4 (HTTP register/login/whoami-valid/bad-token over the wire)\n" as *u8)
107 return 0
108}