code wiki / _hdl_build / nx_access_gate.nx
nx_access_gate.nx source
↩ module page · 120 lines · 7931 B
1import "nx_gate_gn.nx"
2// nx_access_gate.nx -- hermetic gate for the S-class authorization core (ag_allow). Builds fixture
3// site-locks + a roles registry in memory and proves the load-bearing security properties:
4// T1 public area -> ALLOW for anyone (even no session)
5// T2 family area + member(L1) -> ALLOW
6// T3 (NEG) family area + no-session(L0) -> DENY [deny-by-default]
7// T4 owner area + owner(L3) -> ALLOW
8// T5 (NEG) owner area + member(L1) -> DENY [NO privilege escalation]
9// T6 (NEG) owner area + no-session(L0) -> DENY
10// T7 owner(L3) on a family area(L1) -> ALLOW [owner clears everything]
11// T8 (NEG) unknown handle on a gated area -> DENY [unlisted = level 0]
12// Sovereign: nx_syscalls + nx_access_lib. license_tier: ORIGINAL
13import "nx_syscalls.nx"
14import "nx_access_lib.nx"
15
16func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
17func g_app(buf: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { buf[off + i] = s[i]; i = i + 1 } return off + i }
18func g_row2(buf: *u8, off: i64, a: *u8, b: *u8) -> i64 {
19 var o: i64 = g_app(buf, off, a); buf[o] = 9 as u8; o = o + 1
20 o = g_app(buf, o, b); buf[o] = 10 as u8; o = o + 1
21 return o
22}
23func g_row4(buf: *u8, off: i64, a: *u8, b: *u8, c: *u8, d: *u8) -> i64 {
24 var o: i64 = g_app(buf, off, a); buf[o] = 9 as u8; o = o + 1
25 o = g_app(buf, o, b); buf[o] = 9 as u8; o = o + 1
26 o = g_app(buf, o, c); buf[o] = 9 as u8; o = o + 1
27 o = g_app(buf, o, d); buf[o] = 10 as u8; o = o + 1
28 return o
29}
30func g_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
31func g_write_file(path: *u8, buf: *u8, n: i64) -> i64 {
32 let fd: i64 = sys_openat_wr(path, 0x1a4)
33 if fd < 0 { return 0 - 1 }
34 sys_write(fd, buf, n); sys_close(fd)
35 return n
36}
37
38func main(argc: i64, argv: *i64) -> i64 {
39 gp("=== nx_access_gate (S-class authz: allow iff granted>=required, deny-by-default) ===\n" as *u8)
40 // fixture site-locks: a family area (L1) + an owner-only area (L3); everything else public.
41 let sl: *u8 = sys_mmap(4096); var sn: i64 = 0
42 sn = g_row4(sl, sn, "area" as *u8, "nishifamily/family" as *u8, "Nishi Family" as *u8, "1" as *u8)
43 sn = g_row4(sl, sn, "area" as *u8, "nishifamily/gallery" as *u8, "Nishi Gallery" as *u8, "3" as *u8)
44 // fixture roles: owner=3, a family member=1; anyone else unlisted=0.
45 let roles: *u8 = sys_mmap(4096); var rn: i64 = 0
46 rn = g_row2(roles, rn, "owner_h" as *u8, "3" as *u8)
47 rn = g_row2(roles, rn, "family_h" as *u8, "1" as *u8)
48
49 let realm: *u8 = sys_mmap(128); let req: *i64 = sys_mmap(8); let grant: *i64 = sys_mmap(8)
50 let nf: *u8 = "nishifamily" as *u8; let nfl: i64 = g_slen(nf)
51 let p_pub: *u8 = "/charter.html" as *u8
52 let p_fam: *u8 = "/family/notes.html" as *u8
53 let p_gal: *u8 = "/gallery/photo1.jpg" as *u8
54 let owner: *u8 = "owner_h" as *u8; let fam: *u8 = "family_h" as *u8; let ghost: *u8 = "ghost_h" as *u8
55 var pass: i64 = 0; var fail: i64 = 0
56
57 // T1 public -> allow for nobody-session
58 var a: i64 = ag_allow(sl, sn, roles, rn, nf, nfl, p_pub, g_slen(p_pub), "none" as *u8, 0, req, grant, realm, 128)
59 if a == 1 { pass = pass + 1; gp(" T1 public->ALLOW(any) PASS\n" as *u8) } else { fail = fail + 1; gp(" T1 FAIL\n" as *u8) }
60
61 // T2 family area + member -> allow
62 a = ag_allow(sl, sn, roles, rn, nf, nfl, p_fam, g_slen(p_fam), fam, g_slen(fam), req, grant, realm, 128)
63 if a == 1 { if req[0] == 1 { if grant[0] == 1 { pass = pass + 1; gp(" T2 family+member->ALLOW PASS\n" as *u8) } } }
64 if a != 1 { fail = fail + 1; gp(" T2 FAIL denied\n" as *u8) }
65
66 // T3 (NEG) family area + no session -> DENY
67 a = ag_allow(sl, sn, roles, rn, nf, nfl, p_fam, g_slen(p_fam), "none" as *u8, 0, req, grant, realm, 128)
68 if a == 0 { pass = pass + 1; gp(" T3 family+no-session->DENY PASS\n" as *u8) } else { fail = fail + 1; gp(" T3 FAIL allowed\n" as *u8) }
69
70 // T4 owner area + owner -> allow
71 a = ag_allow(sl, sn, roles, rn, nf, nfl, p_gal, g_slen(p_gal), owner, g_slen(owner), req, grant, realm, 128)
72 if a == 1 { if req[0] == 3 { pass = pass + 1; gp(" T4 owner-area+owner->ALLOW PASS\n" as *u8) } }
73 if a != 1 { fail = fail + 1; gp(" T4 FAIL\n" as *u8) }
74
75 // T5 (NEG) owner area + family member -> DENY (no escalation)
76 a = ag_allow(sl, sn, roles, rn, nf, nfl, p_gal, g_slen(p_gal), fam, g_slen(fam), req, grant, realm, 128)
77 if a == 0 { pass = pass + 1; gp(" T5 owner-area+member->DENY (no escalation) PASS\n" as *u8) } else { fail = fail + 1; gp(" T5 FAIL escalation\n" as *u8) }
78
79 // T6 (NEG) owner area + no session -> DENY
80 a = ag_allow(sl, sn, roles, rn, nf, nfl, p_gal, g_slen(p_gal), "none" as *u8, 0, req, grant, realm, 128)
81 if a == 0 { pass = pass + 1; gp(" T6 owner-area+no-session->DENY PASS\n" as *u8) } else { fail = fail + 1; gp(" T6 FAIL\n" as *u8) }
82
83 // T7 owner on family area -> allow (clears everything)
84 a = ag_allow(sl, sn, roles, rn, nf, nfl, p_fam, g_slen(p_fam), owner, g_slen(owner), req, grant, realm, 128)
85 if a == 1 { pass = pass + 1; gp(" T7 owner-clears-family-area->ALLOW PASS\n" as *u8) } else { fail = fail + 1; gp(" T7 FAIL\n" as *u8) }
86
87 // T8 (NEG) unknown handle on gated area -> DENY
88 a = ag_allow(sl, sn, roles, rn, nf, nfl, p_fam, g_slen(p_fam), ghost, g_slen(ghost), req, grant, realm, 128)
89 if a == 0 { if grant[0] == 0 { pass = pass + 1; gp(" T8 unknown-handle->DENY (level 0) PASS\n" as *u8) } }
90 if a != 0 { fail = fail + 1; gp(" T8 FAIL allowed\n" as *u8) }
91
92 // ---- ag_uid_to_level: the SHARED session-identity -> level chain the mgmt API + hub gw now compose ----
93 // (session uid HASH -> hex -> the uid->handle index -> the roles registry -> level). File fixtures written to /tmp.
94 let fidx: *u8 = sys_mmap(256); var fin: i64 = 0
95 fin = g_row2(fidx, fin, "aabb" as *u8, "elderwesto" as *u8) // uid 0xAA 0xBB -> handle elderwesto
96 fin = g_row2(fidx, fin, "ccdd" as *u8, "ghost_h" as *u8) // a uid whose handle is absent from roles
97 g_write_file("/tmp/ag_fix_idx.tsv" as *u8, fidx, fin)
98 let frol: *u8 = sys_mmap(256); var frn: i64 = 0
99 frn = g_row2(frol, frn, "elderwesto" as *u8, "3" as *u8) // operator=3
100 g_write_file("/tmp/ag_fix_roles.tsv" as *u8, frol, frn)
101
102 // T9 uid -> index handle -> roles level = operator(3)
103 let uid1: *u8 = sys_mmap(8); uid1[0]=0xaa as u8; uid1[1]=0xbb as u8
104 let lv1: i64 = ag_uid_to_level(uid1, 2, "/tmp/ag_fix_idx.tsv" as *u8, "/tmp/ag_fix_roles.tsv" as *u8)
105 if lv1 == 3 { pass = pass + 1; gp(" T9 uid->index->roles = operator(3) PASS\n" as *u8) } else { fail = fail + 1; gp(" T9 FAIL lv=" as *u8); gn(lv1); gp("\n" as *u8) }
106
107 // T10 (NEG) uid not in the index -> 0 (deny-by-default: an ecosystem session with no identity row grants nothing)
108 let uid2: *u8 = sys_mmap(8); uid2[0]=0xee as u8; uid2[1]=0xff as u8
109 let lv2: i64 = ag_uid_to_level(uid2, 2, "/tmp/ag_fix_idx.tsv" as *u8, "/tmp/ag_fix_roles.tsv" as *u8)
110 if lv2 == 0 { pass = pass + 1; gp(" T10 uid-not-in-index->0 (deny-by-default) PASS\n" as *u8) } else { fail = fail + 1; gp(" T10 FAIL lv=" as *u8); gn(lv2); gp("\n" as *u8) }
111
112 // T11 (NEG) uid -> handle present but NOT in roles -> 0 (a family member's session can't reach operator routes)
113 let uid3: *u8 = sys_mmap(8); uid3[0]=0xcc as u8; uid3[1]=0xdd as u8
114 let lv3: i64 = ag_uid_to_level(uid3, 2, "/tmp/ag_fix_idx.tsv" as *u8, "/tmp/ag_fix_roles.tsv" as *u8)
115 if lv3 == 0 { pass = pass + 1; gp(" T11 handle-not-in-roles->0 PASS\n" as *u8) } else { fail = fail + 1; gp(" T11 FAIL lv=" as *u8); gn(lv3); gp("\n" as *u8) }
116
117 gp("RESULT pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail)
118 if fail == 0 { gp(" verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
119 gp(" verdict=RED\n" as *u8); sys_exit(1); return 1
120}