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}