code wiki / _hdl_build / nx_aw_push.nx
nx_aw_push.nx source
↩ module page · 145 lines · 8149 B
1// nx_aw_push.nx -- SOVEREIGN file push to the NAS (vault-backed, no /tmp staging, no shells). Gets the NAS
2// password from the vault (nx_machine_key + nx_vault.elf), SSHes to 192.168.8.227 as elderwesto, and STREAMS
3// a local file into a remote write-command via chunked SSH channel data (ssh_put_file from nx_ssh_putpage).
4// payload = local file path read from /mnt/c/.../awpush.src (one line)
5// dst-cmd = remote command read from /mnt/c/.../awpush.dst (e.g. "mkdir -p d; cat > d/f; chmod +x d/f")
6// license_tier: ORIGINAL (vault spine from nx_aw_nasfix, stream spine from nx_ssh_putpage)
7import "nx_syscalls.nx"
8import "nx_ssh_lib.nx"
9const P_MAGIC_1000000: i64 = 1000000
10const P_MAGIC_65536: i64 = 65536
11const P_MAGIC_1048576: i64 = 1048576
12const P_MAGIC_16384: i64 = 16384
13const P_MAGIC_1024: i64 = 1024
14
15const P_SRC: *u8 = "/mnt/c/Users/elder/AppData/Local/Temp/awpush.src" as *u8
16const P_DST: *u8 = "/mnt/c/Users/elder/AppData/Local/Temp/awpush.dst" as *u8
17const P_SECRET_OUT: *u8 = "/tmp/nxsecret.out" as *u8
18const P_VAULT_NV: *u8 = "/home/elderwesto/.nishi/secrets/nas.nv" as *u8
19
20func p_run(path: *u8, a1: *u8, a2: *u8) -> i64 {
21 let pid: i64 = sys_fork()
22 if pid == 0 {
23 let argv: *i64 = sys_mmap(64) as *i64
24 argv[0] = path as i64
25 var ai: i64 = 1
26 if (a1 as i64) != 0 { argv[ai] = a1 as i64; ai = ai + 1 }
27 if (a2 as i64) != 0 { argv[ai] = a2 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 p_unlink(path: *u8) -> i64 { __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) return 0 }
39func aw_napms(ms: i64) -> i64 { let ts: *i64 = sys_mmap(16) as *i64; ts[0] = 0; ts[1] = ms * P_MAGIC_1000000; __syscall(35, ts as i64, 0, 0, 0, 0, 0); return 0 }
40
41// non-blocking drain of pending server packets (WINDOW_ADJUST) -- prevents bidirectional deadlock.
42func ssh_drain(st: *SshState) -> i64 {
43 let pfd: *u8 = sys_mmap(8); let fdv: i64 = st.fd
44 pfd[0]=(fdv&0xff) as u8; pfd[1]=((fdv>>8)&0xff) as u8; pfd[2]=((fdv>>16)&0xff) as u8; pfd[3]=((fdv>>24)&0xff) as u8
45 pfd[4]=1 as u8; pfd[5]=0 as u8
46 let buf: *u8 = sys_mmap(P_MAGIC_65536); var run: i64 = 1
47 while run == 1 { let r: i64 = sys_poll(pfd, 1, 0); if r <= 0 { run = 0 } else { if ssh_enc_recv(st, buf) < 0 { run = 0 } } }
48 return 0
49}
50func ssh_put_file(st: *SshState, wcmd: *u8, wcmdlen: i64, data: *u8, datalen: i64) -> i64 {
51 let co: *u8 = sys_mmap(64); var c: i64 = 0
52 c = ssh_put_byte(co, c, 90); c = ssh_put_str(co, c, "session" as *u8, 7)
53 c = ssh_put_u32(co, c, 0); c = ssh_put_u32(co, c, P_MAGIC_1048576); c = ssh_put_u32(co, c, P_MAGIC_16384)
54 ssh_enc_send(st, co, c)
55 let rep: *u8 = sys_mmap(P_MAGIC_65536); var rcid: i64 = 0 - 1; var guard: i64 = 0
56 while rcid < 0 {
57 if guard > 16 { return 0 - 1 }
58 let rl: i64 = ssh_enc_recv(st, rep); if rl < 0 { return 0 - 1 }
59 if rep[0] == 91 as u8 { rcid = ssh_u32be(rep, 5) }
60 if rep[0] == 92 as u8 { return 0 - 2 }
61 guard = guard + 1
62 }
63 let cr: *u8 = sys_mmap(P_MAGIC_1024); var q: i64 = 0
64 q = ssh_put_byte(cr, q, 98); q = ssh_put_u32(cr, q, rcid); q = ssh_put_str(cr, q, "exec" as *u8, 4); q = ssh_put_byte(cr, q, 1); q = ssh_put_str(cr, q, wcmd, wcmdlen)
65 ssh_enc_send(st, cr, q)
66 var off: i64 = 0
67 while off < datalen {
68 var nn: i64 = datalen - off; if nn > P_MAGIC_16384 { nn = P_MAGIC_16384 }
69 let dp: *u8 = sys_mmap(nn + 64); var p: i64 = 0
70 p = ssh_put_byte(dp, p, 94); p = ssh_put_u32(dp, p, rcid); p = ssh_put_u32(dp, p, nn)
71 var i: i64 = 0; while i < nn { dp[p + i] = data[off + i]; i = i + 1 } p = p + nn
72 ssh_enc_send(st, dp, p)
73 ssh_drain(st)
74 off = off + nn
75 }
76 let eo: *u8 = sys_mmap(16); var e: i64 = 0; e = ssh_put_byte(eo, e, 96); e = ssh_put_u32(eo, e, rcid); ssh_enc_send(st, eo, e)
77 let pfd2: *u8 = sys_mmap(8); let fdv2: i64 = st.fd
78 pfd2[0]=(fdv2&0xff) as u8; pfd2[1]=((fdv2>>8)&0xff) as u8; pfd2[2]=((fdv2>>16)&0xff) as u8; pfd2[3]=((fdv2>>24)&0xff) as u8
79 pfd2[4]=1 as u8; pfd2[5]=0 as u8
80 var done: i64 = 0; var quiet: i64 = 0
81 while done == 0 {
82 let pr: i64 = sys_poll(pfd2, 1, 500)
83 if pr <= 0 { quiet = quiet + 1; if quiet >= 6 { done = 1 } }
84 else { let rl: i64 = ssh_enc_recv(st, rep); if rl < 0 { done = 1 } else { if rep[0] == 97 as u8 { done = 1 } } }
85 }
86 let clo: *u8 = sys_mmap(16); var k: i64 = 0; k = ssh_put_byte(clo, k, 97); k = ssh_put_u32(clo, k, rcid); ssh_enc_send(st, clo, k)
87 return 0
88}
89
90func main(argc: i64, argv: *i64) -> i64 {
91 // backward-compatible: no args -> the fixed awpush.src/awpush.dst (unchanged); with args, use
92 // argv[1]=src-spec-file argv[2]=dst-cmd-file so a SECOND workflow can push without sharing awpush.*
93 var src_file: *u8 = P_SRC
94 var dst_file: *u8 = P_DST
95 if argc >= 3 { src_file = argv[1] as *u8; dst_file = argv[2] as *u8 }
96 // RESILIENT secret derivation: WSL's systemd-tmpfiles churns /tmp mid-operation, so the
97 // machine-key -> vault -> read-secret sequence can transiently fail. Retry until it succeeds
98 // (transient-fault tolerant, CLAUDE.md #14 graceful degradation) instead of aborting the push.
99 let pwbox: *i64 = sys_mmap(16) as *i64
100 var pw: *u8 = 0 as *u8
101 var att: i64 = 0
102 while att < 12 {
103 if p_run("_offc/nx_machine_key.elf" as *u8, 0 as *u8, 0 as *u8) == 0 {
104 if p_run("_offc/nx_vault.elf" as *u8, "open" as *u8, P_VAULT_NV) == 0 {
105 pw = sys_read_file(P_SECRET_OUT, pwbox)
106 if (pw as i64) != 0 { att = 1000 }
107 }
108 }
109 if att < 1000 { att = att + 1; aw_napms(150) }
110 }
111 p_unlink("/tmp/nxpass" as *u8)
112 if (pw as i64) == 0 { ssh_puts("push: secret derivation FAIL after 12 retries\n" as *u8); return 3 }
113 var pwlen: i64 = pwbox[0]
114 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 } } }
115
116 let sbox: *i64 = sys_mmap(16) as *i64
117 let spath: *u8 = sys_read_file(src_file, sbox)
118 if (spath as i64) == 0 { ssh_puts("push: no src-spec file\n" as *u8); p_unlink(P_SECRET_OUT); return 4 }
119 var slen2: i64 = sbox[0]
120 while slen2 > 0 { if spath[slen2-1] == 10 as u8 { slen2 = slen2 - 1 } else { if spath[slen2-1] == 13 as u8 { slen2 = slen2 - 1 } else { break } } }
121 spath[slen2] = 0 as u8
122 let pbox: *i64 = sys_mmap(16) as *i64
123 let payload: *u8 = sys_read_file(spath, pbox)
124 if (payload as i64) == 0 { ssh_puts("push: cannot read payload file\n" as *u8); p_unlink(P_SECRET_OUT); return 5 }
125 let plen: i64 = pbox[0]
126
127 let dbox: *i64 = sys_mmap(16) as *i64
128 let dcmd: *u8 = sys_read_file(dst_file, dbox)
129 if (dcmd as i64) == 0 { ssh_puts("push: no dst-cmd file\n" as *u8); p_unlink(P_SECRET_OUT); return 6 }
130 var dlen: i64 = dbox[0]
131 while dlen > 0 { if dcmd[dlen-1] == 10 as u8 { dlen = dlen - 1 } else { break } }
132
133 let st: *SshState = sys_mmap(SSH_STATE_BYTES) as *SshState
134 if ssh_open_session(st, (192 << 24) | (168 << 16) | (8 << 8) | 227) != 0 { ssh_puts("push: SSH session FAIL\n" as *u8); p_unlink(P_SECRET_OUT); return 7 }
135 if ssh_userauth_password(st, "elderwesto" as *u8, 10, pw, pwlen) != 1 { ssh_puts("push: SSH auth FAIL\n" as *u8); sys_close(st.fd); p_unlink(P_SECRET_OUT); return 8 }
136 p_unlink(P_SECRET_OUT)
137 ssh_puts("push: [auth ok] streaming bytes=" as *u8)
138 let nb: *u8 = sys_mmap(28); var m: i64=plen; let t: *u8=sys_mmap(28); var kk: i64=0; if m==0{t[0]=48 as u8;kk=1}; while m>0{t[kk]=(48+(m%10)) as u8;m=m/10;kk=kk+1}; var ii: i64=0; while ii<kk{nb[ii]=t[kk-1-ii];ii=ii+1}; sys_write(1,nb,kk); ssh_puts("\n" as *u8)
139 ssh_put_file(st, dcmd, dlen, payload, plen)
140 let vcmd: *u8 = "echo ===PUSH-DONE===" as *u8
141 var vl: i64 = 0; while vcmd[vl] != (0 as u8) { vl = vl + 1 }
142 ssh_exec(st, vcmd, vl)
143 sys_close(st.fd)
144 return 0
145}