code wiki / _hdl_build / nx_opaque_login_daemon.nx

nx_opaque_login_daemon.nx

buildroot/runtime/_hdl_build/nx_opaque_login_daemon.nx

41865 B505 linesdepth 16pulls 59 transitivereach 0 importersview sourcekind servicetopic opaque
docsdependenciesstructsconstsfunctions

about

nx_opaque_login_daemon.nx -- R2: thin HTTP daemon wrapping the gated no-cookie OPAQUE login (nx_opaque_login). Serves the wiki's auth model for any site: full OPAQUE (modauth, RFC 9807) + no-cookie X-Nishi-Session token. argv: [1]=port [2]=server-keys-path [3]=account-store-path [4]=request-budget [5]=argon2id_m_cost (opt; default 65536=64MiB production; smoke passes a small value). Plain HTTP (loopback/LAN); TLS termination = the R3 rung (route on the wiki HTTPS daemon). Routes: GET /login (page) | POST /login | GET /whoami | POST /register. No shortcuts: production KSF by default, every reject path returns a clean status, no token leak on failure.

dependencies 6 imports · 0 importers

nx_opaque_login.nx nx_http_form.nx nx_audio_web.nx nx_framed_append.nx nx_lan_signup.nx nx_hr_entitle.nx nx_opaque_login_daemon.nx

imports: nx_opaque_login.nxnx_http_form.nxnx_audio_web.nxnx_framed_append.nxnx_lan_signup.nxnx_hr_entitle.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main olgd_atoi olg_ctx_setup_ttl nx_uas_server_keys_load_or sys_mmap sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_close _uas_hex_dec _uas_nib nx_csprng_fill sys_mmap ↻ nx_csprng_urandom_path sys_openat_rd ↻ sys_read ↻ sys_close ↻ nx_opq_derive_keypair sys_mmap ↻ _voprf_load_context_string u256_alloc nx_scratch nx_scratch_init nx_scratch_oom sys_mmap ↻ nx_opq_hash_to_scalar sys_mmap ↻ nx_h2c_expand_message_xmd_ sys_mmap ↻ _h2c_i2osp_1 _h2c_i2osp_2 u256_alloc ↻ _opq_reduce_48be_mod_n u256_alloc ↻ sys_mmap ↻ u256_load_be p256_modn_load_n u256_cmp

structs

none

consts

13const OLGD_REALM_N: i64 = 16 // "nishi_site_admin" -- the same realm this daemon inits its auth context with
49const OLGD_MAGIC_2097152: i64 = 2097152
50const OLGD_MAGIC_16384: i64 = 16384
51const OLGD_MAGIC_86400: i64 = 86400
52const OLGD_MAGIC_16383: i64 = 16383
53const OLGD_MAGIC_8192: i64 = 8192
54const OLGD_MAGIC_2048: i64 = 2048
56const OLGD_PROD_M: i64 = 65536 // production argon2id m_cost (64 MiB, OWASP 2026); argv[5] overrides for smoke
57const OLGD_WIKI_DIR: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/knowledge/wiki_pages"
60const OLGD_SPA: *u8 = "<script>(function(){var t=sessionStorage.getItem('nsess');document.addEventListener('click',function(e){var a=e.target.closest&&e.target.closest('a');if(!a)return;var h=a.getAttribute('href');if(!h)return;if(h.slice(-5)!='.html')return;e.preventDefault();fetch('/wiki/'+h,{headers:{'X-Nishi-Session':t}}).then(function(r){return r.ok?r.text():null}).then(function(x){if(x){document.open();document.write(x);document.close()}else{location='/'}})})})();</script>"
81const OLGD_ENT_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/nishi_entitlements-" as *u8
82const OLGD_IDX_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/nishi_uid_handle.tsv" as *u8
84const OLGD_HR_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/nishi_hr-" as *u8 // CUTOVER: seg_store prefix (was .log)
176const OLGD_ADMINS_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/nishi_admins.tsv" as *u8
251const OLGD_HTML: *u8 = "<!doctype html><html><head><meta charset=utf-8><meta name=viewport content=\"width=device-width,initial-scale=1\"><title>Nishi OPAQUE login</title><style>body{font-family:system-ui,sans-serif;max-width:480px;margin:5vh auto;padding:0 18px;color:#16202e}h1{font-size:1.2rem}h3{margin:18px 0 4px}input{width:100%;padding:9px;margin:5px 0;box-sizing:border-box;border:1px solid #b9c2d6;border-radius:5px}button{padding:9px 16px;margin:6px 6px 6px 0;background:#0b2545;color:#fff;border:0;border-radius:5px;cursor:pointer;font-size:.95rem}#msg{margin:14px 0;padding:12px;background:#f1f4fa;border-left:3px solid #0b2545;word-break:break-all;min-height:1.2em}</style></head><body><h1>Nishi &mdash; no-cookie OPAQUE login</h1><p style=\"color:#667;font-size:.9rem\">Full OPAQUE aPAKE (RFC 9807). The server never stores your passphrase; sessions are Ed25519 no-cookie tokens (sessionStorage + X-Nishi-Session header), never cookies.</p><div id=msg>Register a handle + passphrase, then log in.</div><h3>1. Register</h3><input id=rh placeholder=\"handle (e.g. elder)\"><input id=rp type=password placeholder=\"passphrase\"><button onclick=reg()>Register</button><h3>2. Login</h3><input id=lh placeholder=handle><input id=lp type=password placeholder=passphrase><button onclick=login()>Login</button> <button onclick=who()>Who am I?</button> <button onclick=board()>Open Hub</button> <button onclick=out()>Sign out</button><script>function $(i){return document.getElementById(i)}function M(t){$('msg').textContent=t}async function G(p,b){try{var o={method:b?'POST':'GET',headers:{}};if(b){o.headers['Content-Type']='application/x-www-form-urlencoded';o.body=b}else{o.headers['X-Nishi-Session']=sessionStorage.getItem('nsess')||''}var r=await fetch(p,o);var j={};try{j=await r.json()}catch(e){}return{ok:r.ok,s:r.status,j:j}}catch(e){return{ok:false,s:0,j:{error:'network: '+e}}}}async function reg(){M('Registering\\u2026 (memory-hard OPAQUE step \\u2014 a moment)');var r=await G('/register','handle='+encodeURIComponent($('rh').value)+'&pw='+encodeURIComponent($('rp').value));M(r.ok?('Registered! SAVE THIS RECOVERY MNEMONIC: '+r.j.mnemonic):('Register failed ('+r.s+'): '+(r.j.error||'unknown')))}async function login(){M('Logging in\\u2026 (a moment)');var r=await G('/login','handle='+encodeURIComponent($('lh').value)+'&pw='+encodeURIComponent($('lp').value));if(r.ok){sessionStorage.setItem('nsess',r.j.token);var ret=new URLSearchParams(location.search).get('return');if(ret&&ret.charAt(0)=='/'&&ret.charAt(1)!='/'){location=ret}else if(location.pathname!='/login'){location.reload()}else{board()}}else{M('Login failed ('+r.s+'): '+(r.j.error||'unknown'))}}async function showSpace(){M('Loading your space\\u2026');var r=await G('/whoami');if(!r.ok){M('Session error ('+r.s+')');return}var j=r.j;var h='<h1>Welcome, '+(j.handle||'member')+'</h1><p style=color:#667>Signed in with a no-cookie OPAQUE session. Your access:</p>';if(j.links&&j.links.length){for(var i=0;i<j.links.length;i++){h+='<p><a href='+JSON.stringify(j.links[i].url)+'>'+j.links[i].label+' \\u2192</a></p>'}}else{h+='<p>No resources assigned to you yet.</p>'}h+='<p style=margin-top:20px><button onclick=out()>Sign out</button></p>';document.body.innerHTML=h}async function who(){if(!sessionStorage.getItem('nsess')){M('No session \\u2014 log in first.');return}M('Validating\\u2026');var r=await G('/whoami');M(r.ok?('Valid no-cookie session. user-id hash: '+r.j.uid):('Session rejected ('+r.s+'): '+(r.j.error||'unknown')))}async function board(){if(!sessionStorage.getItem('nsess')){M('Log in first.');return}M('Opening hub...');try{var r=await fetch('/wiki/hub.html',{headers:{'X-Nishi-Session':sessionStorage.getItem('nsess')}});if(r.ok){document.open();document.write(await r.text());document.close()}else{M('Hub denied ('+r.status+')')}}catch(e){M('hub error: '+e)}}function out(){sessionStorage.removeItem('nsess');location='/login'}</script></body></html>" as *u8
256const OLGD_WELCOME: *u8 = "<!doctype html><html><head><meta charset=utf-8><meta name=viewport content=\"width=device-width,initial-scale=1\"><title>Nishi &mdash; your space</title><style>body{font-family:system-ui,sans-serif;max-width:520px;margin:6vh auto;padding:0 18px;color:#16202e}h1{font-size:1.3rem}ul{list-style:none;padding:0}li{margin:10px 0}a.card{display:block;padding:14px 16px;background:#0b2545;color:#fff;text-decoration:none;border-radius:8px;font-size:1.05rem}a.card:hover{background:#13386b}.sub{color:#667;font-size:.9rem}button{margin-top:18px;padding:8px 14px;background:#eef;border:1px solid #b9c2d6;border-radius:6px;cursor:pointer}</style></head><body><h1 id=h>Your space</h1><p class=sub>Signed in with a no-cookie OPAQUE session. These are the resources you have access to.</p><div id=links>Loading\\u2026</div><button onclick=out()>Sign out</button><script>var t=sessionStorage.getItem('nsess');function out(){sessionStorage.removeItem('nsess');location='/login'}if(!t){location='/login'}else{fetch('/access',{headers:{'X-Nishi-Session':t}}).then(function(r){if(!r.ok){location='/login';return null}return r.json()}).then(function(j){if(!j)return;if(j.handle)document.getElementById('h').textContent='Welcome, '+j.handle;var d=document.getElementById('links');if(j.links&&j.links.length){var u='<ul>';for(var i=0;i<j.links.length;i++){u+='<li><a class=card href=\"'+j.links[i].url+'\">'+j.links[i].label+' &rarr;</a></li>'}u+='</ul>';d.innerHTML=u}else{d.textContent='No resources are assigned to you yet.'}}).catch(function(e){document.getElementById('links').textContent='error: '+e})}</script></body></html>" as *u8
261const OLGD_RECOVER: *u8 = "<div style=\"max-width:480px;margin:20px auto;padding:0 18px;font-family:system-ui,sans-serif;color:#16202e\"><h3>Recover access (forgot passphrase)</h3><input id=ch placeholder=handle style=\"width:100%;padding:9px;margin:4px 0;box-sizing:border-box\"><input id=cm placeholder=\"24-word recovery mnemonic\" style=\"width:100%;padding:9px;margin:4px 0;box-sizing:border-box\"><input id=cp type=password placeholder=\"new passphrase\" style=\"width:100%;padding:9px;margin:4px 0;box-sizing:border-box\"><button onclick=nrec() style=\"padding:9px 16px;background:#0b2545;color:#fff;border:0;border-radius:5px;cursor:pointer\">Recover</button><div id=rmsg style=\"margin:10px 0;word-break:break-all\"></div></div><script>function nrec(){var m=document.getElementById('rmsg');m.textContent='Recovering...';fetch('/register',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'handle='+encodeURIComponent(document.getElementById('ch').value)+'&mnemonic='+encodeURIComponent(document.getElementById('cm').value.trim())+'&pw='+encodeURIComponent(document.getElementById('cp').value)}).then(function(r){return r.json().then(function(j){return{ok:r.ok,j:j}})}).then(function(x){m.textContent=x.ok?('Recovered! SAVE THIS NEW MNEMONIC: '+x.j.mnemonic+' -- now log in above with your new passphrase.'):('Recovery failed: '+(x.j.error||'check handle and mnemonic'))})}</script>" as *u8
267const OLGD_AUTORECOVER: *u8 = "<script>(function(){var t=sessionStorage.getItem('nsess');if(t&&location.pathname!='/login'){fetch(location.pathname,{headers:{'X-Nishi-Session':t}}).then(function(r){return r.ok?r.text():null}).then(function(h){if(h){document.open();document.write(h);document.close()}})}})();</script>"

functions

22func olgd_signup_ok(ip4: *u8, hrstore: *u8, handle: *u8, hn: i64) -> i64
32func olgd_receipt(op: *u8, target: *u8, tn: i64, ok: i64, detail: *u8, now_s: i64) -> i64
called by 1: main calls 3: fa_catnfa_catfa_appendz
45func olgd_ms_detail(buf: *u8, ms: i64) -> *u8
called by 1: main calls 2: fa_catfa_catn
62func olgd_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
called by 1: main
63func olgd_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 1: main
64func olgd_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: main
65func olgd_find(buf: *u8, n: i64, needle: *u8, nl: i64) -> i64
71func olgd_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 }
72func olgd_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 }
73func olgd_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 }
called by 1: olgd_send
74func olgd_hex(dst: *u8, off: i64, src: *u8, n: i64) -> i64 { let hx: *u8="0123456789abcdef" as *u8; var o: i64=off; var i: i64=0; while i<n { let c: i64=(src[i] as i64)&0xff; dst[o]=hx[(c>>4)&15]; dst[o+1]=hx[c&15]; o=o+2; i=i+1 } return o }
called by 1: main
88func olgd_idx_lookup(uidhex: *u8, uxn: i64, out_h: *u8, cap: i64) -> i64
called by 2: olgd_idx_recordmain calls 1: sys_read_file
118func olgd_idx_record(uidhex: *u8, uxn: i64, handle: *u8, hn: i64) -> i64
132func olgd_emit_access(handle: *u8, hn: i64, resp: *u8, cap: i64) -> i64
179func olgd_is_admin(handle: *u8, hn: i64) -> i64
calls 1: sys_read_file
205func olgd_field_ok(s: *u8, n: i64, maxn: i64) -> i64
214func olgd_grant_append(who: *u8, wn: i64, label: *u8, ln: i64, url: *u8, un: i64) -> i64
231func olgd_send(cfd: i64, status: *u8, ctype: *u8, body: *u8, blen: i64) -> i64
241func olgd_hdr_val(req: *u8, hend: i64, name: *u8, nl: i64, out: *u8, cap: i64) -> i64
called by 1: main calls 1: olgd_find
270func olgd_send_loginpage(cfd: i64) -> i64
called by 1: main calls 2: olgd_catolgd_send
279func main(argc: i64, argv: *i64) -> i64