summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2019-04-02 11:18:50 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2019-04-02 11:18:50 +0200
commit38c2cdf164f0cc12db65f9f51b3b4a7815543d12 (patch)
treedcbc5be2643fab1ada96d7e4e17781c4da12966e
parentccbffa67318df0c6fe5210133698b403490d6611 (diff)
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.
-rw-r--r--sys/src/cmd/ssh.c117
1 files changed, 69 insertions, 48 deletions
diff --git a/sys/src/cmd/ssh.c b/sys/src/cmd/ssh.c
index 29d6e2de3..cce0c0fae 100644
--- a/sys/src/cmd/ssh.c
+++ b/sys/src/cmd/ssh.c
@@ -80,7 +80,7 @@ int nsid;
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;
@@ -987,6 +987,19 @@ dispatch(void)
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;
@@ -1051,9 +1064,6 @@ dispatch(void)
case MSG_CHANNEL_CLOSE:
shutdown();
return;
- case MSG_KEXINIT:
- kex(1);
- return;
}
sysfatal("got: %.*H", (int)(recv.w - recv.r), recv.r);
}
@@ -1147,7 +1157,7 @@ kfmt(Fmt *f)
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");
}
@@ -1203,6 +1213,10 @@ main(int argc, char *argv[])
MaxPwTries = strtol(EARGF(usage()), &s, 0);
if(*s != 0) usage();
break;
+ case 'X':
+ mux = 1;
+ raw = 0;
+ break;
} ARGEND;
if(host == nil){
@@ -1269,50 +1283,51 @@ Next0: switch(recvpkt()){
if(noneauth() < 0 && pubkeyauth() < 0 && passauth() < 0 && kbintauth() < 0)
sysfatal("auth: %r");
- recv.pkt = MaxPacket;
- recv.win = WinPackets*recv.pkt;
- recv.chan = 0;
-
- /* open hailing frequencies */
- if(remote != nil){
- NetConnInfo *nci = getnetconninfo(nil, fd);
- if(nci == nil)
- sysfatal("can't get netconninfo: %r");
- sendpkt("bsuuususu", MSG_CHANNEL_OPEN,
- "direct-tcpip", 12,
- recv.chan,
- recv.win,
- recv.pkt,
- remote, strlen(remote),
- port,
- nci->laddr, strlen(nci->laddr),
- atoi(nci->lserv));
- free(nci);
- } else {
- sendpkt("bsuuu", MSG_CHANNEL_OPEN,
- "session", 7,
- recv.chan,
- recv.win,
- recv.pkt);
- }
+ recv.pkt = send.pkt = MaxPacket;
+ recv.win = send.win = WinPackets*recv.pkt;
+ recv.chan = send.win = 0;
+
+ if(!mux){
+ /* open hailing frequencies */
+ if(remote != nil){
+ NetConnInfo *nci = getnetconninfo(nil, fd);
+ if(nci == nil)
+ sysfatal("can't get netconninfo: %r");
+ sendpkt("bsuuususu", MSG_CHANNEL_OPEN,
+ "direct-tcpip", 12,
+ recv.chan,
+ recv.win,
+ recv.pkt,
+ remote, strlen(remote),
+ port,
+ nci->laddr, strlen(nci->laddr),
+ atoi(nci->lserv));
+ free(nci);
+ } else {
+ sendpkt("bsuuu", MSG_CHANNEL_OPEN,
+ "session", 7,
+ recv.chan,
+ recv.win,
+ recv.pkt);
+ }
+Next1: switch(recvpkt()){
+ default:
+ dispatch();
+ goto Next1;
+ case MSG_CHANNEL_OPEN_FAILURE:
+ if(unpack(recv.r, recv.w-recv.r, "_uus", &c, &b, &s, &n) < 0)
+ n = strlen(s = "???");
+ sysfatal("channel open failure: (%d) %.*s", b, utfnlen(s, n), s);
+ case MSG_CHANNEL_OPEN_CONFIRMATION:
+ break;
+ }
-Next1: switch(recvpkt()){
- default:
- dispatch();
- goto Next1;
- case MSG_CHANNEL_OPEN_FAILURE:
- if(unpack(recv.r, recv.w-recv.r, "_uus", &c, &b, &s, &n) < 0)
- n = strlen(s = "???");
- sysfatal("channel open failure: (%d) %.*s", b, utfnlen(s, n), s);
- case MSG_CHANNEL_OPEN_CONFIRMATION:
- break;
+ if(unpack(recv.r, recv.w-recv.r, "_uuuu", &recv.chan, &send.chan, &send.win, &send.pkt) < 0)
+ sysfatal("bad channel open confirmation");
+ if(send.pkt <= 0 || send.pkt > MaxPacket)
+ send.pkt = MaxPacket;
}
- if(unpack(recv.r, recv.w-recv.r, "_uuuu", &recv.chan, &send.chan, &send.win, &send.pkt) < 0)
- sysfatal("bad channel open confirmation");
- if(send.pkt <= 0 || send.pkt > MaxPacket)
- send.pkt = MaxPacket;
-
notify(catch);
atexit(shutdown);
@@ -1337,7 +1352,7 @@ Next1: switch(recvpkt()){
/* child reads input and sends packets */
qlock(&sl);
- if(remote == nil){
+ if(remote == nil && !mux){
if(raw) {
rawon();
sendpkt("busbsuuuus", MSG_CHANNEL_REQUEST,
@@ -1400,6 +1415,10 @@ Next1: switch(recvpkt()){
}
if(n <= 0)
break;
+ if(mux){
+ sendpkt("[", buf, n);
+ continue;
+ }
send.win -= n;
while(send.win < 0)
rsleep(&send);
@@ -1407,8 +1426,10 @@ Next1: switch(recvpkt()){
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);