code wiki / _hdl_build / nx_gen_gateway.nx

nx_gen_gateway.nx

buildroot/runtime/_hdl_build/nx_gen_gateway.nx

25279 B310 linesdepth 16pulls 55 transitivereach 2 importersview sourcekind librarytopic gen
docsdependenciesstructsconstsfunctions

about

nx_gallery_gateway.nx -- OPAQUE-gated reverse proxy for the NSFW gallery, mounted under /gen/*. Auth = the gallery's OWN OPAQUE realm (own keys+store via argv -> isolated NSFW realm) + the Service-Worker header-injection model (the SW adds X-Nishi-Session to every /gen/* request incl. media -> NO cookie, cardinal C1 preserved). The gateway validates X-Nishi-Session per request via olg_whoami, then reverse-proxies the request (prefix-stripped) to the gallery backend. No valid session -> 401 (never a public byte). Bootstrap: GET /gen/login (page) registers the SW. argv: [1]=listen_port [2]=keys_path [3]=store_path [4]=budget [5]=backend_port [6]=allow_register(0|1; PROD=0) [7]=m_cost(opt 65536) [8]=t(opt 3) [9]=p(opt 4) R1 = loopback proof (no TLS yet; TLS termination + path-route into nishifamily.com = R3).

dependencies 4 imports · 2 importers

nx_opaque_login.nx nx_http_form.nx nx_hr_entitle.nx nx_connect.nx nx_gen_gateway.nx nx_gen_gateway_daemon.nx nx_gen_gateway_gate.nx

imports: nx_opaque_login.nxnx_http_form.nxnx_hr_entitle.nxnx_connect.nx

imported by: nx_gen_gateway_daemon.nxnx_gen_gateway_gate.nx

structs

none

consts

14const GGW_MAGIC_262144: i64 = 262144
15const GGW_MAGIC_6291456: i64 = 6291456
16const GGW_MAGIC_131072: i64 = 131072
17const GGW_MAGIC_131071: i64 = 131071
18const GGW_MAGIC_8192: i64 = 8192
20const GGW_PROD_M: i64 = 65536
25const GGW_SESSION_TTL: i64 = 86400
28const GEN_ENT_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/nishi_entitlements-" as *u8
31const GEN_HR_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/nishi_hr-" as *u8
184const GGW_SW_JS: *u8 = "var DBN='nishi_gen',ST='auth';function tok(){return new Promise(function(res){try{var r=indexedDB.open(DBN,1);r.onupgradeneeded=function(e){e.target.result.createObjectStore(ST)};r.onsuccess=function(e){var db=e.target.result;try{var g=db.transaction(ST,'readonly').objectStore(ST).get('nsess');g.onsuccess=function(){res(g.result||'')};g.onerror=function(){res('')}}catch(x){res('')}};r.onerror=function(){res('')}}catch(x){res('')}})}self.addEventListener('install',function(e){self.skipWaiting()});self.addEventListener('activate',function(e){e.waitUntil(self.clients.claim())});self.addEventListener('fetch',function(e){var u;try{u=new URL(e.request.url)}catch(x){return}if(u.origin!==self.location.origin){return}var pn=u.pathname;if(pn.indexOf('/gen/')!==0){return}if(pn.indexOf('/gen/auth/')===0||pn==='/gen/sw.js'||pn==='/gen/login'){return}e.respondWith(tok().then(function(t){var h=new Headers(e.request.headers);if(t){h.set('X-Nishi-Session',t)}if(e.request.method==='GET'){return fetch(new Request(u.href,{headers:h}))}var rq;try{rq=new Request(e.request,{headers:h})}catch(x){rq=e.request}return fetch(rq)}).catch(function(){return fetch(e.request)}))});" as *u8
188const GGW_LOGIN_HTML: *u8 = "<!doctype html><html><head><meta charset=utf-8><meta name=viewport content=\"width=device-width,initial-scale=1\"><title>Nishi Gen</title><style>body{font-family:system-ui,sans-serif;max-width:420px;margin:8vh auto;padding:0 18px;color:#cdd7e6;background:#0b1019}h1{font-size:1.2rem;color:#e8eef7}p{color:#7c8aa5;font-size:.86rem}input{width:100%;padding:9px;margin:5px 0;box-sizing:border-box;border:1px solid #2a3550;border-radius:5px;background:#121a28;color:#e8eef7}button{padding:9px 16px;margin:6px 6px 0 0;background:#2d6cdf;color:#fff;border:0;border-radius:5px;cursor:pointer}#m{margin:14px 0;padding:12px;background:#121a28;border-left:3px solid #2d6cdf;color:#cdd7e6;word-break:break-all;min-height:1.2em}</style></head><body><h1>Nishi Gen &mdash; private</h1><p>Full OPAQUE aPAKE (RFC 9807). The passphrase never leaves your browser as anything crackable; the session rides a Service Worker, not a cookie.</p><div id=m>Log in to view the gallery.</div><input id=h placeholder=handle autocomplete=username><input id=p type=password placeholder=passphrase autocomplete=current-password><button onclick=login()>Login</button> <button onclick=reg()>Register</button><script>function $(i){return document.getElementById(i)} function M(t){$('m').textContent=t} function setTok(t){return new Promise(function(res){var r=indexedDB.open('nishi_gen',1);r.onupgradeneeded=function(e){e.target.result.createObjectStore('auth')};r.onsuccess=function(e){var db=e.target.result;var tx=db.transaction('auth','readwrite').objectStore('auth').put(t,'nsess');tx.onsuccess=function(){res()};tx.onerror=function(){res()}};r.onerror=function(){res()}})} async function reg(){M('Registering (memory-hard, a moment)...');try{var r=await fetch('/gen/auth/register',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'handle='+encodeURIComponent($('h').value)+'&pw='+encodeURIComponent($('p').value)});var j=await r.json();M(r.ok?('Registered. SAVE THIS RECOVERY MNEMONIC: '+j.mnemonic):('Register failed: '+(j.error||r.status)))}catch(e){M('error: '+e)}} async function login(){M('Logging in...');try{var r=await fetch('/gen/auth/login',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'handle='+encodeURIComponent($('h').value)+'&pw='+encodeURIComponent($('p').value)});var j=await r.json();if(!r.ok){M('Login failed: '+(j.error||r.status));return}await setTok(j.token);if('serviceWorker' in navigator){try{await navigator.serviceWorker.register('/gen/sw.js',{scope:'/gen/'});await navigator.serviceWorker.ready}catch(e){}}M('Logged in. Opening gallery...');location.href='/gen/'}catch(e){M('error: '+e)}}</script></body></html>" as *u8

functions

33func gw_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
34func gw_atoi(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ let c: i64=s[i] as i64; if c<48{return v} if c>57{return v} v=v*10+(c-48); i=i+1 } return v }
called by 2: gw_read_fullmain
35func gw_starts(buf: *u8, n: i64, pre: *u8) -> i64 { var i: i64=0; while pre[i]!=(0 as u8){ if i>=n {return 0} if buf[i]!=pre[i]{return 0} i=i+1 } return 1 }
called by 1: gw_serve_conn
36func gw_find(buf: *u8, n: i64, needle: *u8, nl: i64) -> i64
42func gw_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var i: i64=0; while s[i]!=(0 as u8){dst[o]=s[i]; o=o+1; i=i+1} return o }
43func gw_catb(dst: *u8, off: i64, src: *u8, n: i64) -> i64 { var o: i64=off; var i: i64=0; while i<n {dst[o]=src[i]; o=o+1; i=i+1} return o }
44func gw_itoa(dst: *u8, off: i64, v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; 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 o: i64=off; var q: i64=k-1; while q>=0{dst[o]=t[q];o=o+1;q=q-1} return o }
47func gw_send(cfd: i64, status: *u8, ctype: *u8, body: *u8, blen: i64) -> i64
56func gw_401(cfd: i64) -> i64
called by 1: gw_serve_conn calls 2: gw_sendgw_slen
61func gw_403(cfd: i64) -> i64
called by 1: gw_serve_conn calls 2: gw_sendgw_slen
66func gw_eqs(a: *u8, an: i64, b: *u8) -> i64 { var i: i64=0; while b[i]!=(0 as u8){ if i>=an {return 0} if a[i]!=b[i]{return 0} i=i+1 } if i!=an {return 0} return 1 }
called by 1: gw_is_op
69func gw_is_op(h: *u8, n: i64) -> i64 { if gw_eqs(h, n, "elderwesto" as *u8)==1 {return 1} if gw_eqs(h, n, "elder" as *u8)==1 {return 1} return 0 }
calls 1: gw_eqs
72func gw_is_nav(req: *u8, n: i64) -> i64 { if gw_find(req, n, "Sec-Fetch-Mode: navigate" as *u8, 24) >= 0 { return 1 } return 0 }
called by 1: gw_serve_conn calls 1: gw_find
74func gw_302_login(cfd: i64) -> i64
called by 1: gw_serve_conn calls 1: gw_slen
81func gw_send_ck(cfd: i64, ctype: *u8, body: *u8, blen: i64, ckval: *u8, ckvallen: i64, ttl: i64) -> i64
called by 1: gw_serve_conn calls 3: gw_catgw_catbgw_itoa
100func gw_hdr_val(req: *u8, hend: i64, name: *u8, nl: i64, out: *u8, cap: i64) -> i64
110func gw_reqpath(req: *u8, rn: i64, out: *u8, cap: i64) -> i64
called by 1: gw_serve_conn
121func gw_emit_range_raw(rq: *u8, o0: i64, rng: *u8, rngn: i64) -> i64
called by 1: gw_cap_range calls 2: gw_catgw_catb
129func gw_cap_range(rq: *u8, o0: i64, rng: *u8, rngn: i64) -> i64
149func gw_proxy(cfd: i64, bport: i64, method: *u8, mlen: i64, bpath: *u8, bplen: i64, body: *u8, blen: i64, oreq: *u8, ohe: i64) -> i64
194func gw_read_full(cfd: i64, req: *u8, cap: i64) -> i64
220func gw_serve_conn(cfd: i64, ctx: *NxAuthContext, allow_reg: i64, bport: i64, session_ttl: i64, hr_path: *u8, ent_path: *u8) -> i64