code wiki / _hdl_build / nx_aw_routerfix.nx
nx_aw_routerfix.nx source
↩ module page · 70 lines · 3928 B
1// nx_aw_routerfix.nx -- SOVEREIGN router (GL.iNet/OpenWrt 192.168.8.1) admin for the andelinwest DNS
2// revert. No shells, no printed secret: retrieves router_password from the sovereign vault
3// (~/.nishi/nx_vault get vault.key vault.nxv router_password -> captured to a temp fd, in-memory only),
4// SSHes the router as root via nx_ssh_lib, and runs the command read from a file (so read-only query vs
5// the actual uci set is driven without rebuilding). ssh_exec streams remote stdout to fd 1.
6// license_tier: ORIGINAL (spine reused from nx_aw_nasfix)
7import "nx_syscalls.nx"
8import "nx_ssh_lib.nx"
9
10const RF_CMD_PATH: *u8 = "/mnt/c/Users/elder/AppData/Local/Temp/routercmd.txt" as *u8
11const RF_PW_OUT: *u8 = "/tmp/nxrouter.out" as *u8
12const RF_VAULT_BIN: *u8 = "/home/elderwesto/.nishi/nx_vault" as *u8
13const RF_VAULT_KEY: *u8 = "/home/elderwesto/.nishi/vault.key" as *u8
14const RF_VAULT_NXV: *u8 = "/home/elderwesto/.nishi/vault.nxv" as *u8
15
16// fork/exec a helper with stdout redirected to outfd; parent waits; returns child WEXITSTATUS.
17func rf_run_capture(path: *u8, a1: *u8, a2: *u8, a3: *u8, a4: *u8, outfd: i64) -> i64 {
18 let pid: i64 = sys_fork()
19 if pid == 0 {
20 if outfd >= 0 { sys_dup3(outfd, 1, 0) }
21 let argv: *i64 = sys_mmap(64) as *i64
22 argv[0] = path as i64
23 var ai: i64 = 1
24 if (a1 as i64) != 0 { argv[ai] = a1 as i64; ai = ai + 1 }
25 if (a2 as i64) != 0 { argv[ai] = a2 as i64; ai = ai + 1 }
26 if (a3 as i64) != 0 { argv[ai] = a3 as i64; ai = ai + 1 }
27 if (a4 as i64) != 0 { argv[ai] = a4 as i64; ai = ai + 1 }
28 argv[ai] = 0
29 let envp: *i64 = sys_mmap(16) as *i64
30 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
31 sys_execve(path, argv, envp)
32 sys_exit(127)
33 }
34 let st: *i64 = sys_mmap(16) as *i64
35 sys_wait4(pid, st, 0)
36 return (st[0] >> 8) & 0xff
37}
38func rf_unlink(path: *u8) -> i64 { __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) return 0 }
39
40func main() -> i64 {
41 // ---- retrieve router_password from the sovereign vault (stdout -> temp file, in-memory only) ----
42 let ofd: i64 = sys_openat_wr(RF_PW_OUT, 0x180) // 0600
43 if ofd < 0 { ssh_puts("routerfix: cannot open pw temp\n" as *u8); return 1 }
44 let grc: i64 = rf_run_capture(RF_VAULT_BIN, "get" as *u8, RF_VAULT_KEY, RF_VAULT_NXV, "router_password" as *u8, ofd)
45 sys_close(ofd)
46 if grc != 0 { ssh_puts("routerfix: vault get router_password FAILED\n" as *u8); rf_unlink(RF_PW_OUT); return 2 }
47 let pwbox: *i64 = sys_mmap(16) as *i64
48 let pw: *u8 = sys_read_file(RF_PW_OUT, pwbox)
49 if (pw as i64) == 0 { ssh_puts("routerfix: cannot read pw\n" as *u8); return 3 }
50 var pwlen: i64 = pwbox[0]
51 while pwlen > 0 { if pw[pwlen-1] == 10 as u8 { pwlen = pwlen - 1 } else { if pw[pwlen-1] == 13 as u8 { pwlen = pwlen - 1 } else { break } } }
52 rf_unlink(RF_PW_OUT)
53 if pwlen <= 0 { ssh_puts("routerfix: empty router password\n" as *u8); return 3 }
54
55 // ---- the command to run on the router (file-driven: read-only query vs uci set) ----
56 let cbox: *i64 = sys_mmap(16) as *i64
57 let cmd: *u8 = sys_read_file(RF_CMD_PATH, cbox)
58 if (cmd as i64) == 0 { ssh_puts("routerfix: no command file\n" as *u8); return 4 }
59 var clen: i64 = cbox[0]
60 while clen > 0 { if cmd[clen-1] == 10 as u8 { clen = clen - 1 } else { break } }
61
62 // ---- sovereign SSH to the router 192.168.8.1 as root ----
63 let st: *SshState = sys_mmap(SSH_STATE_BYTES) as *SshState
64 if ssh_open_session(st, (192 << 24) | (168 << 16) | (8 << 8) | 1) != 0 { ssh_puts("routerfix: SSH session FAILED (router unreachable :22)\n" as *u8); return 5 }
65 if ssh_userauth_password(st, "root" as *u8, 4, pw, pwlen) != 1 { ssh_puts("routerfix: SSH auth FAILED\n" as *u8); sys_close(st.fd); return 6 }
66 ssh_puts("routerfix: [auth ok] running on router:\n" as *u8)
67 ssh_exec(st, cmd, clen)
68 sys_close(st.fd)
69 return 0
70}