uchar sid[256];
char thumb[2*SHA2_256dlen+1], *thumbfile;
-int fd, intr, raw, port, debug;
+int fd, intr, raw, port, mux, debug;
char *user, *service, *status, *host, *remote, *cmd;
Oneway recv, send;
static char kexalgs[] = "curve25519-sha256,curve25519-sha256@libssh.org";
static char cipheralgs[] = "chacha20-poly1305@openssh.com";
static char zipalgs[] = "none";
- static char macalgs[] = "";
+ static char macalgs[] = "hmac-sha1"; /* work around for github.com */
static char langs[] = "";
uchar cookie[16], x[32], yc[32], z[32], k[32+1], h[SHA2_256dlen], *ys, *ks, *sig;
break;
if(raw) write(2, s, n);
return;
+ case MSG_KEXINIT:
+ kex(1);
+ return;
+ }
+
+ if(mux){
+ n = recv.w - recv.r;
+ if(write(1, recv.r, n) != n)
+ sysfatal("write out: %r");
+ return;
+ }
+
+ switch(recv.r[0]){
case MSG_CHANNEL_DATA:
if(unpack(recv.r, recv.w-recv.r, "_us", &c, &s, &n) < 0)
break;
case MSG_CHANNEL_CLOSE:
shutdown();
return;
- case MSG_KEXINIT:
- kex(1);
- return;
}
sysfatal("got: %.*H", (int)(recv.w - recv.r), recv.r);
}
MaxPwTries = strtol(EARGF(usage()), &s, 0);
if(*s != 0) usage();
break;
+ case 'X':
+ mux = 1;
+ raw = 0;
+ break;
+ default:
+ usage();
} ARGEND;
if(host == nil){
if(noneauth() < 0 && pubkeyauth() < 0 && passauth() < 0 && kbintauth() < 0)
sysfatal("auth: %r");
- recv.pkt = MaxPacket;
- recv.win = WinPackets*recv.pkt;
- recv.chan = 0;
+ recv.pkt = send.pkt = MaxPacket;
+ recv.win = send.win = WinPackets*recv.pkt;
+ recv.chan = send.win = 0;
+
+ if(mux)
+ goto Mux;
/* open hailing frequencies */
if(remote != nil){
recv.win,
recv.pkt);
}
-
Next1: switch(recvpkt()){
default:
dispatch();
if(send.pkt <= 0 || send.pkt > MaxPacket)
send.pkt = MaxPacket;
+ if(remote != nil)
+ goto Mux;
+
+ if(raw) {
+ rawon();
+ sendpkt("busbsuuuus", MSG_CHANNEL_REQUEST,
+ send.chan,
+ "pty-req", 7,
+ 0,
+ tty.term, strlen(tty.term),
+ tty.cols,
+ tty.lines,
+ tty.xpixels,
+ tty.ypixels,
+ "", 0);
+ }
+ if(cmd == nil){
+ sendpkt("busb", MSG_CHANNEL_REQUEST,
+ send.chan,
+ "shell", 5,
+ 0);
+ } else if(*cmd == '#') {
+ sendpkt("busbs", MSG_CHANNEL_REQUEST,
+ send.chan,
+ "subsystem", 9,
+ 0,
+ cmd+1, strlen(cmd)-1);
+ } else {
+ sendpkt("busbs", MSG_CHANNEL_REQUEST,
+ send.chan,
+ "exec", 4,
+ 0,
+ cmd, strlen(cmd));
+ }
+
+Mux:
notify(catch);
atexit(shutdown);
/* child reads input and sends packets */
qlock(&sl);
- if(remote == nil){
- if(raw) {
- rawon();
- sendpkt("busbsuuuus", MSG_CHANNEL_REQUEST,
- send.chan,
- "pty-req", 7,
- 0,
- tty.term, strlen(tty.term),
- tty.cols,
- tty.lines,
- tty.xpixels,
- tty.ypixels,
- "", 0);
- }
- if(cmd == nil){
- sendpkt("busb", MSG_CHANNEL_REQUEST,
- send.chan,
- "shell", 5,
- 0);
- } else if(*cmd == '#') {
- sendpkt("busbs", MSG_CHANNEL_REQUEST,
- send.chan,
- "subsystem", 9,
- 0,
- cmd+1, strlen(cmd)-1);
- } else {
- sendpkt("busbs", MSG_CHANNEL_REQUEST,
- send.chan,
- "exec", 4,
- 0,
- cmd, strlen(cmd));
- }
- }
for(;;){
static uchar buf[MaxPacket];
qunlock(&sl);
}
if(n <= 0)
break;
+ if(mux){
+ sendpkt("[", buf, n);
+ continue;
+ }
send.win -= n;
while(send.win < 0)
rsleep(&send);
send.chan,
buf, n);
}
- if(send.eof++ == 0)
+ if(send.eof++ == 0 && !mux)
sendpkt("bu", raw ? MSG_CHANNEL_CLOSE : MSG_CHANNEL_EOF, send.chan);
+ else if(recv.pid > 0 && mux)
+ postnote(PNPROC, recv.pid, "shutdown");
qunlock(&sl);
exits(nil);