code wiki / (root) / nx_lan_signup.nx

nx_lan_signup.nx source

↩ module page · 40 lines · 3077 B

1// nx_lan_signup.nx -- the SIGNUP-ALLOWED decision, BY CONSTRUCTION. The operator's law: "signup exposed only on 2// LAN, for the family to sign up." Two independent gates must BOTH hold before any registration is permitted: 3// 4// (a) the PEER SOURCE IP is LAN -- RFC1918 private (10/8, 172.16/12, 192.168/16) or loopback (127/8). A WAN 5// client can NEVER register, regardless of any flag, because the daemon reads the real connecting address 6// from accept() (sys_accept_with_addr) -- not a spoofable header. This is the "only on LAN" guarantee. 7// (b) the HANDLE is INVITED in this realm's HR store (the operator provisioned it via nx_hr_admin.hra_invite). 8// A LAN stranger with an un-provisioned handle is denied; a handle already CLAIMED (active) is denied 9// (re-registration blocked) because a claimed record is no longer "invited". This is the "only the family". 10// 11// So the registration surface is closed to the world AND closed to anyone the operator did not invite -- replacing 12// the old single global open/closed flag with an invite-governed, LAN-scoped gate. Pure decision (no I/O beyond the 13// HR read inside hra_is_invited); the daemon supplies the 4 peer-IP octets + handle + the HR store/realm. 14import "nx_hr_admin.nx" // hra_is_invited 15import "nx_syscalls.nx" 16 17// 1 iff the 4 raw IPv4 octets ip4[0..4] are a LAN address (RFC1918 private + loopback). The daemon gets these from 18// the sockaddr_in returned by accept(): bytes [4..8] of the sockaddr are the address in network/big-endian order, 19// i.e. ip4[0]=first octet. Everything else (public/WAN, including TEST-NET and 192.169/11.x near-misses) -> 0. 20func ls_ip_is_lan(ip4: *u8) -> i64 { 21 let a: i64 = ip4[0] as i64 22 let b: i64 = ip4[1] as i64 23 if a == 10 { return 1 } // 10.0.0.0/8 24 if a == 127 { return 1 } // 127.0.0.0/8 loopback (local + publisher proxy) 25 if a == 192 { if b == 168 { return 1 } } // 192.168.0.0/16 (the home LAN, e.g. 192.168.8.x) 26 if a == 172 { if b >= 16 { if b <= 31 { return 1 } } } // 172.16.0.0/12 27 return 0 28} 29 30// copy the 4 IPv4 octets out of a sockaddr_in buffer (offset 4) -- a daemon convenience for the accept() path. 31func ls_ip4_from_sockaddr(sa: *u8, out4: *u8) -> i64 { out4[0]=sa[4]; out4[1]=sa[5]; out4[2]=sa[6]; out4[3]=sa[7]; return 0 } 32 33// THE SIGNUP DECISION: 1=ALLOW registration, 0=DENY. Allows ONLY when the peer is LAN AND the handle is invited. 34// FAIL-CLOSED: either condition false -> deny. (Order matters only for which reason a logger would print; both 35// must pass.) The OPAQUE registration itself, and the post-register hra_claim, happen in the daemon AFTER a 1 here. 36func ls_signup_allowed(ip4: *u8, hr_store: *u8, realm: *u8, realm_n: i64, handle: *u8, hn: i64) -> i64 { 37 if ls_ip_is_lan(ip4) == 0 { return 0 } // (a) WAN -> never register 38 if hra_is_invited(hr_store, realm, realm_n, handle, hn) == 0 { return 0 } // (b) not invited -> deny 39 return 1 40}