code wiki / _hdl_build / nx_gen_gateway_daemon.nx

nx_gen_gateway_daemon.nx source

↩ module page · 96 lines · 5226 B

1// nx_gen_gateway_daemon.nx -- the deployable OPAQUE /gen gateway: argv config + auth-context setup 2// + accept-fork loop over gw_serve_conn (nx_gen_gateway lib). Shares the family realm 3// (nishi_site_admin) keys+store = SSO with the existing nishifamily login; reverse-proxies 4// authenticated /gen/* to the gen orchestrator backend. 5// argv: [1]=listen_port [2]=keys [3]=store [4]=budget [5]=backend_port [6]=allow_register(PROD=0) 6// [7]=m_cost [8]=t [9]=p [10]=session_ttl 7// license_tier: ORIGINAL 8import "nx_gen_gateway.nx" 9import "nx_opaque_login.nx" 10import "nx_hr_admin.nx" // hra_enroll + hra_is_superadmin + HRA_LVL_OWNER (owner bootstrap) 11import "nx_syscalls.nx" 12 13func main(argc: i64, argv: *i64) -> i64 { 14 if argc < 6 { 15 sys_write(1, "usage: nx_gen_gateway_daemon <port> <keys> <store> <budget> <backend_port> [allow_register] [m] [t] [p] [ttl]\n" as *u8, 110) 16 sys_exit(2); return 2 17 } 18 let port: i64 = gw_atoi(argv[1] as *u8) 19 let keys_path: *u8 = argv[2] as *u8 20 let store_path: *u8 = argv[3] as *u8 21 let budget: i64 = gw_atoi(argv[4] as *u8) 22 let bport: i64 = gw_atoi(argv[5] as *u8) 23 var allow_reg: i64 = 0 24 if argc > 6 { allow_reg = gw_atoi(argv[6] as *u8) } 25 var m_cost: i64 = GGW_PROD_M 26 if argc > 7 { m_cost = gw_atoi(argv[7] as *u8) } 27 var t_cost: i64 = 3 28 if argc > 8 { t_cost = gw_atoi(argv[8] as *u8) } 29 var p_cost: i64 = 4 30 if argc > 9 { p_cost = gw_atoi(argv[9] as *u8) } 31 var session_ttl: i64 = GGW_SESSION_TTL 32 if argc > 10 { session_ttl = gw_atoi(argv[10] as *u8) } 33 34 let ctx: *NxAuthContext = sys_mmap(256) as *NxAuthContext 35 if olg_ctx_setup_ttl(ctx, keys_path, store_path, "nishi_site_admin" as *u8, 16, "Nishi Family" as *u8, 12, session_ttl, m_cost, t_cost, p_cost) != 0 { 36 sys_write(1, "CTX-INIT-FAIL\n" as *u8, 14); sys_exit(1); return 1 37 } 38 39 // OWNER BOOTSTRAP (Rule 20 fail-fast): enroll the family owner as HR superadmin so the /gen authz 40 // (hra_is_superadmin on the hex-encoded session uid) grants the owner. Idempotent (enroll-if-absent). 41 // Without this the live nishi_hr- has NO owner record -> every session, incl. the owner's, is denied 403. 42 // This is the production analog of nx_gen_gateway_gate's hra_enroll("elderwesto", OWNER) which proved 200. 43 // Grant the owner /gen via the ENTITLEMENT store (he_ent_put). The HR superadmin seg_store does NOT round-trip 44 // on the live nishi_hr- (PROVEN by nx_gen_live_probe: in_proc_super=0 despite enroll_rc=0 + manifest present), 45 // but the entitlement store DOES (ent_put+has_access=1). The gateway authorizes via he_has_access on this exact 46 // store, so this is the path that actually grants access. Idempotent: grant only if not already present. 47 let owner_cid: *u8 = sys_mmap(96) 48 let owner_chl: i64 = hr_cred_id("nishi_site_admin" as *u8, 16, "elderwesto" as *u8, 10, owner_cid) 49 if he_has_access(0, owner_cid, owner_chl, GEN_ENT_PATH, "/gen" as *u8) != 1 { 50 he_ent_put(GEN_ENT_PATH, owner_cid, "Gen Studio" as *u8, "/gen" as *u8) 51 let m1: *u8 = "OWNER-BOOTSTRAP: granted elderwesto /gen via the entitlement store\n" as *u8 52 sys_write(1, m1, gw_slen(m1)) 53 } else { 54 let m2: *u8 = "OWNER-BOOTSTRAP: elderwesto already has the /gen entitlement\n" as *u8 55 sys_write(1, m2, gw_slen(m2)) 56 } 57 58 let addr: *u8 = sys_mmap(16) 59 addr[0]=2 as u8; addr[1]=0 as u8 60 addr[2]=((port>>8)&0xff) as u8; addr[3]=(port&0xff) as u8 61 addr[4]=0 as u8; addr[5]=0 as u8; addr[6]=0 as u8; addr[7]=0 as u8 62 var zi: i64=8; while zi<16 { addr[zi]=0 as u8; zi=zi+1 } 63 let lfd: i64 = sys_socket(2, 1, 0) 64 if lfd < 0 { sys_write(1, "SOCKET-FAIL\n" as *u8, 12); sys_exit(1); return 1 } 65 let optv: *u8 = sys_mmap(4); optv[0]=1 as u8 66 sys_setsockopt(lfd, 1, 2, optv, 4) 67 if sys_bind(lfd, addr, 16) < 0 { sys_write(1, "BIND-FAIL\n" as *u8, 10); sys_exit(1); return 1 } 68 if sys_listen(lfd, 16) < 0 { sys_write(1, "LISTEN-FAIL\n" as *u8, 12); sys_exit(1); return 1 } 69 // FD_CLOEXEC on the LISTENER (debt 1785529579). Binds by RAW SYSCALL, never calls 70 // nx_http_server_listen, so the helper's CLOEXEC fix cannot reach it -- rebuilding alone changes 71 // nothing. Measured live by nx_livecloexec_gate: this pid held a listener on fd=4 with the bit CLEAR. 72 // A forked+exec'd child that inherits a listening fd holds the port FOREVER; restarting the victim 73 // can never free it. 72 = SYS_FCNTL, 2 = F_SETFD, 1 = FD_CLOEXEC. 74 __syscall(72, lfd, 2, 1, 0, 0, 0) 75 sys_write(1, "GEN-GATEWAY-UP\n" as *u8, 15) 76 77 let st: *i64 = sys_mmap(16) as *i64 78 var served: i64 = 0 79 while served < budget { 80 let cfd: i64 = sys_accept(lfd) 81 if cfd >= 0 { 82 let pid: i64 = sys_fork() 83 if pid == 0 { 84 sys_close(lfd) 85 gw_serve_conn(cfd, ctx, allow_reg, bport, session_ttl, GEN_HR_PATH, GEN_ENT_PATH) 86 sys_close(cfd) 87 sys_exit(0) 88 } 89 sys_close(cfd) 90 var reaped: i64 = 1 91 while reaped > 0 { reaped = sys_wait4(0 - 1, st, 1) } 92 } 93 served = served + 1 94 } 95 sys_close(lfd); sys_exit(0); return 0 96}