ssh: add experimental mux mode

in mux mode, ssh relays raw MSG_CHANNEL_*
messages on standard input and output while
still handling authentication and key exchange
internally.

the intend is to use the mux mode to implement
something like the old sshnet ontop of ssh.
front
cinap_lenrek 2019-04-02 11:18:50 +02:00
parent ccbffa6731
commit 38c2cdf164
1 changed files with 69 additions and 48 deletions

View File

@ -80,7 +80,7 @@ int nsid;
uchar sid[256]; uchar sid[256];
char thumb[2*SHA2_256dlen+1], *thumbfile; 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; char *user, *service, *status, *host, *remote, *cmd;
Oneway recv, send; Oneway recv, send;
@ -987,6 +987,19 @@ dispatch(void)
break; break;
if(raw) write(2, s, n); if(raw) write(2, s, n);
return; 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: case MSG_CHANNEL_DATA:
if(unpack(recv.r, recv.w-recv.r, "_us", &c, &s, &n) < 0) if(unpack(recv.r, recv.w-recv.r, "_us", &c, &s, &n) < 0)
break; break;
@ -1051,9 +1064,6 @@ dispatch(void)
case MSG_CHANNEL_CLOSE: case MSG_CHANNEL_CLOSE:
shutdown(); shutdown();
return; return;
case MSG_KEXINIT:
kex(1);
return;
} }
sysfatal("got: %.*H", (int)(recv.w - recv.r), recv.r); sysfatal("got: %.*H", (int)(recv.w - recv.r), recv.r);
} }
@ -1147,7 +1157,7 @@ kfmt(Fmt *f)
void void
usage(void) usage(void)
{ {
fprint(2, "usage: %s [-dR] [-t thumbfile] [-T tries] [-u user] [-h] [user@]host [-W remote!port] [cmd args...]\n", argv0); fprint(2, "usage: %s [-dRX] [-t thumbfile] [-T tries] [-u user] [-h] [user@]host [-W remote!port] [cmd args...]\n", argv0);
exits("usage"); exits("usage");
} }
@ -1203,6 +1213,10 @@ main(int argc, char *argv[])
MaxPwTries = strtol(EARGF(usage()), &s, 0); MaxPwTries = strtol(EARGF(usage()), &s, 0);
if(*s != 0) usage(); if(*s != 0) usage();
break; break;
case 'X':
mux = 1;
raw = 0;
break;
} ARGEND; } ARGEND;
if(host == nil){ if(host == nil){
@ -1269,10 +1283,11 @@ Next0: switch(recvpkt()){
if(noneauth() < 0 && pubkeyauth() < 0 && passauth() < 0 && kbintauth() < 0) if(noneauth() < 0 && pubkeyauth() < 0 && passauth() < 0 && kbintauth() < 0)
sysfatal("auth: %r"); sysfatal("auth: %r");
recv.pkt = MaxPacket; recv.pkt = send.pkt = MaxPacket;
recv.win = WinPackets*recv.pkt; recv.win = send.win = WinPackets*recv.pkt;
recv.chan = 0; recv.chan = send.win = 0;
if(!mux){
/* open hailing frequencies */ /* open hailing frequencies */
if(remote != nil){ if(remote != nil){
NetConnInfo *nci = getnetconninfo(nil, fd); NetConnInfo *nci = getnetconninfo(nil, fd);
@ -1295,7 +1310,6 @@ Next0: switch(recvpkt()){
recv.win, recv.win,
recv.pkt); recv.pkt);
} }
Next1: switch(recvpkt()){ Next1: switch(recvpkt()){
default: default:
dispatch(); dispatch();
@ -1312,6 +1326,7 @@ Next1: switch(recvpkt()){
sysfatal("bad channel open confirmation"); sysfatal("bad channel open confirmation");
if(send.pkt <= 0 || send.pkt > MaxPacket) if(send.pkt <= 0 || send.pkt > MaxPacket)
send.pkt = MaxPacket; send.pkt = MaxPacket;
}
notify(catch); notify(catch);
atexit(shutdown); atexit(shutdown);
@ -1337,7 +1352,7 @@ Next1: switch(recvpkt()){
/* child reads input and sends packets */ /* child reads input and sends packets */
qlock(&sl); qlock(&sl);
if(remote == nil){ if(remote == nil && !mux){
if(raw) { if(raw) {
rawon(); rawon();
sendpkt("busbsuuuus", MSG_CHANNEL_REQUEST, sendpkt("busbsuuuus", MSG_CHANNEL_REQUEST,
@ -1400,6 +1415,10 @@ Next1: switch(recvpkt()){
} }
if(n <= 0) if(n <= 0)
break; break;
if(mux){
sendpkt("[", buf, n);
continue;
}
send.win -= n; send.win -= n;
while(send.win < 0) while(send.win < 0)
rsleep(&send); rsleep(&send);
@ -1407,8 +1426,10 @@ Next1: switch(recvpkt()){
send.chan, send.chan,
buf, n); buf, n);
} }
if(send.eof++ == 0) if(send.eof++ == 0 && !mux)
sendpkt("bu", raw ? MSG_CHANNEL_CLOSE : MSG_CHANNEL_EOF, send.chan); sendpkt("bu", raw ? MSG_CHANNEL_CLOSE : MSG_CHANNEL_EOF, send.chan);
else if(recv.pid > 0 && mux)
postnote(PNPROC, recv.pid, "shutdown");
qunlock(&sl); qunlock(&sl);
exits(nil); exits(nil);