code wiki / _hdl_build / nx_aw_nasfix.nx
nx_aw_nasfix.nx source
↩ module page · 86 lines · 4614 B
1// nx_aw_nasfix.nx -- SOVEREIGN NAS diagnose+restore for the live sites daemon (andelinwest.com +
2// nishifamily.com). No shells, no /tmp pre-staging: gets the NAS password straight from the sovereign
3// vault (composes _offc/nx_machine_key.elf + _offc/nx_vault.elf, exactly as nx_secret_cli does), then
4// SSHes to the NAS via the team's own nx_ssh_lib and runs the command read from a file (so diagnose vs
5// restart is driven without rebuilding). ssh_exec streams remote stdout/stderr to fd 1. READ-ONLY unless
6// the command file says otherwise. license_tier: ORIGINAL (spine reused from nx_aw_nasrecon)
7import "nx_syscalls.nx"
8import "nx_ssh_lib.nx"
9
10const NF_CMD_PATH: *u8 = "/mnt/c/Users/elder/AppData/Local/Temp/nascmd.txt" as *u8
11const NF_SECRET_OUT: *u8 = "/tmp/nxsecret.out" as *u8
12const NF_VAULT_NV: *u8 = "/home/elderwesto/.nishi/secrets/nas.nv" as *u8
13
14func nf_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
15
16// fork+execve a sovereign helper binary; parent waits; returns child WEXITSTATUS (mirrors nx_secret_cli).
17func nf_run(path: *u8, a1: *u8, a2: *u8) -> i64 {
18 let pid: i64 = sys_fork()
19 if pid == 0 {
20 let argv: *i64 = sys_mmap(64) as *i64
21 argv[0] = path as i64
22 var ai: i64 = 1
23 if (a1 as i64) != 0 { argv[ai] = a1 as i64; ai = ai + 1 }
24 if (a2 as i64) != 0 { argv[ai] = a2 as i64; ai = ai + 1 }
25 argv[ai] = 0
26 let envp: *i64 = sys_mmap(16) as *i64
27 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0
28 sys_execve(path, argv, envp)
29 sys_exit(127)
30 }
31 let st: *i64 = sys_mmap(16) as *i64
32 sys_wait4(pid, st, 0)
33 return (st[0] >> 8) & 0xff
34}
35func nf_unlink(path: *u8) -> i64 { __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) return 0 }
36
37func main() -> i64 {
38 // ---- sovereign credential retrieval (no shell, no typed passphrase) ----
39 if nf_run("_offc/nx_machine_key.elf" as *u8, 0 as *u8, 0 as *u8) != 0 {
40 ssh_puts("nasfix: machine-key derive FAILED\n" as *u8); nf_unlink("/tmp/nxpass" as *u8); return 1
41 }
42 if nf_run("_offc/nx_vault.elf" as *u8, "open" as *u8, NF_VAULT_NV) != 0 {
43 ssh_puts("nasfix: vault open nas.nv FAILED (no secret / wrong machine / tampered)\n" as *u8)
44 nf_unlink("/tmp/nxpass" as *u8); return 2
45 }
46 nf_unlink("/tmp/nxpass" as *u8) // shred the passphrase ephemeral immediately
47 let pwbox: *i64 = sys_mmap(16) as *i64
48 let pw: *u8 = sys_read_file(NF_SECRET_OUT, pwbox)
49 if (pw as i64) == 0 { ssh_puts("nasfix: cannot read decrypted secret\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
53 // ---- the command to run on the NAS (file-driven: diagnose vs restart, no rebuild) ----
54 let cbox: *i64 = sys_mmap(16) as *i64
55 let cmd: *u8 = sys_read_file(NF_CMD_PATH, cbox)
56 if (cmd as i64) == 0 { ssh_puts("nasfix: no command file\n" as *u8); nf_unlink(NF_SECRET_OUT); return 4 }
57 var clen: i64 = cbox[0]
58 while clen > 0 { if cmd[clen-1] == 10 as u8 { clen = clen - 1 } else { break } }
59
60 // ---- sovereign SSH to the NAS (192.168.8.227) ----
61 let st: *SshState = sys_mmap(SSH_STATE_BYTES) as *SshState
62 if ssh_open_session(st, (192 << 24) | (168 << 16) | (8 << 8) | 227) != 0 {
63 ssh_puts("nasfix: SSH session FAILED (NAS unreachable on :22)\n" as *u8); nf_unlink(NF_SECRET_OUT); return 5
64 }
65 if ssh_userauth_password(st, "elderwesto" as *u8, 10, pw, pwlen) != 1 {
66 ssh_puts("nasfix: SSH auth FAILED\n" as *u8); sys_close(st.fd); nf_unlink(NF_SECRET_OUT); return 6
67 }
68 ssh_puts("nasfix: [auth ok] running remote command:\n" as *u8)
69 // Make the vault password available to the remote script as $NXPW (in-memory only; never staged
70 // on disk) so a root step can do: echo "$NXPW" | sudo -S -p '' sh -c '...'. Prepend an export.
71 let full: *u8 = sys_mmap(clen + pwlen + 64)
72 var fo: i64 = 0
73 let pfx: *u8 = "export NXPW='" as *u8
74 var pi: i64 = 0
75 while pfx[pi] != (0 as u8) { full[fo] = pfx[pi]; fo = fo + 1; pi = pi + 1 }
76 var qi: i64 = 0
77 while qi < pwlen { full[fo] = pw[qi]; fo = fo + 1; qi = qi + 1 }
78 full[fo] = 39 as u8; fo = fo + 1 // closing single quote
79 full[fo] = 10 as u8; fo = fo + 1 // newline
80 var ci: i64 = 0
81 while ci < clen { full[fo] = cmd[ci]; fo = fo + 1; ci = ci + 1 }
82 nf_unlink(NF_SECRET_OUT) // shred the decrypted secret file (the pw stays only in this process)
83 ssh_exec(st, full, fo)
84 sys_close(st.fd)
85 return 0
86}