# HG changeset patch # User Ron Minnich # Date 1315870219 25200 # Node ID ff808386c75dd19ce1875bf3b0d734563d3ce3f4 # Parent 4b6ef67cbbcae29f17aaef14885ce98233779816 This ssh is useless, it's v1 and 10 years says it's never getting fixed. R=nix-dev, john CC=nix-dev http://codereview.appspot.com/4956078 diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/agent.c --- a/sys/src/cmd/ssh/agent.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,450 +0,0 @@ -#include "ssh.h" -#include - -typedef struct Key Key; -struct Key -{ - mpint *mod; - mpint *ek; - char *comment; -}; - -typedef struct Achan Achan; -struct Achan -{ - int open; - u32int chan; /* of remote */ - uchar lbuf[4]; - uint nlbuf; - uint len; - uchar *data; - int ndata; - int needeof; - int needclosed; -}; - -Achan achan[16]; - -static char* -find(char **f, int nf, char *k) -{ - int i, len; - - len = strlen(k); - for(i=1; iarg); - m = strtomp(rpc->arg, nil, 16, nil); - if(mpcmp(m, mod) == 0) - break; - mpfree(m); - m = nil; - } - if(m == nil) - goto Die; - mpfree(m); - - p = mptoa(chal, 16, nil, 0); - if(p == nil){ - debug(DBG_AUTH, "\tmptoa failed: %r\n"); - goto Die; - } - if(auth_rpc(rpc, "write", p, strlen(p)) != ARok){ - debug(DBG_AUTH, "\tauth_rpc write failed: %r\n"); - free(p); - goto Die; - } - free(p); - if(auth_rpc(rpc, "read", nil, 0) != ARok){ - debug(DBG_AUTH, "\tauth_rpc read failed: %r\n"); - goto Die; - } - decr = strtomp(rpc->arg, nil, 16, nil); - if(decr == nil){ - debug(DBG_AUTH, "\tdecr %s failed\n", rpc->arg); - goto Die; - } - debug(DBG_AUTH, "\tdecrypted %B\n", decr); - unpad = rsaunpad(decr); - if(unpad == nil){ - debug(DBG_AUTH, "\tunpad %B failed\n", decr); - mpfree(decr); - goto Die; - } - debug(DBG_AUTH, "\tunpadded %B\n", unpad); - mpfree(decr); - mptoberjust(unpad, chalbuf, 32); - mpfree(unpad); - auth_freerpc(rpc); - close(afd); - return 0; -} - -int -startagent(Conn *c) -{ - int ret; - Msg *m; - - m = allocmsg(c, SSH_CMSG_AGENT_REQUEST_FORWARDING, 0); - sendmsg(m); - - m = recvmsg(c, -1); - switch(m->type){ - case SSH_SMSG_SUCCESS: - debug(DBG_AUTH, "agent allocated\n"); - ret = 0; - break; - case SSH_SMSG_FAILURE: - debug(DBG_AUTH, "agent failed to allocate\n"); - ret = -1; - break; - default: - badmsg(m, 0); - ret = -1; - break; - } - free(m); - return ret; -} - -void handlefullmsg(Conn*, Achan*); - -void -handleagentmsg(Msg *m) -{ - u32int chan, len; - int n; - Achan *a; - - assert(m->type == SSH_MSG_CHANNEL_DATA); - - debug(DBG_AUTH, "agent data\n"); - debug(DBG_AUTH, "\t%.*H\n", (int)(m->ep - m->rp), m->rp); - chan = getlong(m); - len = getlong(m); - if(m->rp+len != m->ep) - sysfatal("got bad channel data"); - - if(chan >= nelem(achan)) - error("bad channel in agent request"); - - a = &achan[chan]; - - while(m->rp < m->ep){ - if(a->nlbuf < 4){ - a->lbuf[a->nlbuf++] = getbyte(m); - if(a->nlbuf == 4){ - a->len = (a->lbuf[0]<<24) | (a->lbuf[1]<<16) | (a->lbuf[2]<<8) | a->lbuf[3]; - a->data = erealloc(a->data, a->len); - a->ndata = 0; - } - continue; - } - if(a->ndata < a->len){ - n = a->len - a->ndata; - if(n > m->ep - m->rp) - n = m->ep - m->rp; - memmove(a->data+a->ndata, getbytes(m, n), n); - a->ndata += n; - } - if(a->ndata == a->len){ - handlefullmsg(m->c, a); - a->nlbuf = 0; - } - } -} - -void -handlefullmsg(Conn *c, Achan *a) -{ - int i; - u32int chan, len, n, rt; - uchar type; - Msg *m, mm; - Msg *r; - Key *k; - int nk; - mpint *mod, *ek, *chal; - uchar sessid[16]; - uchar chalbuf[32]; - uchar digest[16]; - DigestState *s; - static int first; - - assert(a->len == a->ndata); - - chan = a->chan; - mm.rp = a->data; - mm.ep = a->data+a->ndata; - mm.c = c; - m = &mm; - - type = getbyte(m); - - if(first == 0){ - first++; - fmtinstall('H', encodefmt); - } - - switch(type){ - default: - debug(DBG_AUTH, "unknown msg type\n"); - Failure: - debug(DBG_AUTH, "agent sending failure\n"); - r = allocmsg(m->c, SSH_MSG_CHANNEL_DATA, 13); - putlong(r, chan); - putlong(r, 5); - putlong(r, 1); - putbyte(r, SSH_AGENT_FAILURE); - sendmsg(r); - return; - - case SSH_AGENTC_REQUEST_RSA_IDENTITIES: - debug(DBG_AUTH, "agent request identities\n"); - nk = listkeys(&k); - if(nk < 0) - goto Failure; - len = 1+4; /* type, nk */ - for(i=0; ic, SSH_MSG_CHANNEL_DATA, 12+len); - putlong(r, chan); - putlong(r, len+4); - putlong(r, len); - putbyte(r, SSH_AGENT_RSA_IDENTITIES_ANSWER); - putlong(r, nk); - for(i=0; irp, m->ep); - if(rt != 1 || dorsa(mod, ek, chal, chalbuf) < 0){ - mpfree(ek); - mpfree(mod); - mpfree(chal); - goto Failure; - } - s = md5(chalbuf, 32, nil, nil); - md5(sessid, 16, digest, s); - r = allocmsg(m->c, SSH_MSG_CHANNEL_DATA, 12+1+16); - putlong(r, chan); - putlong(r, 4+16+1); - putlong(r, 16+1); - putbyte(r, SSH_AGENT_RSA_RESPONSE); - putbytes(r, digest, 16); - debug(DBG_AUTH, "digest %.16H\n", digest); - sendmsg(r); - mpfree(ek); - mpfree(mod); - mpfree(chal); - return; - - case SSH_AGENTC_ADD_RSA_IDENTITY: - goto Failure; -/* - n = getlong(m); - pubmod = getmpint(m); - pubexp = getmpint(m); - privexp = getmpint(m); - pinversemodq = getmpint(m); - p = getmpint(m); - q = getmpint(m); - comment = getstring(m); - add to factotum; - send SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE; -*/ - - case SSH_AGENTC_REMOVE_RSA_IDENTITY: - goto Failure; -/* - n = getlong(m); - pubmod = getmpint(m); - pubexp = getmpint(m); - tell factotum to del key - send SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE; -*/ - } -} - -void -handleagentopen(Msg *m) -{ - int i; - u32int remote; - - assert(m->type == SSH_SMSG_AGENT_OPEN); - remote = getlong(m); - debug(DBG_AUTH, "agent open %d\n", remote); - - for(i=0; ic, SSH_MSG_CHANNEL_OPEN_FAILURE, 4); - putlong(m, remote); - sendmsg(m); - return; - } - - debug(DBG_AUTH, "\tremote %d is local %d\n", remote, i); - achan[i].open = 1; - achan[i].needeof = 1; - achan[i].needclosed = 1; - achan[i].nlbuf = 0; - achan[i].chan = remote; - m = allocmsg(m->c, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 8); - putlong(m, remote); - putlong(m, i); - sendmsg(m); -} - -void -handleagentieof(Msg *m) -{ - u32int local; - - assert(m->type == SSH_MSG_CHANNEL_INPUT_EOF); - local = getlong(m); - debug(DBG_AUTH, "agent close %d\n", local); - if(local < nelem(achan)){ - debug(DBG_AUTH, "\tlocal %d is remote %d\n", local, achan[local].chan); - achan[local].open = 0; -/* - m = allocmsg(m->c, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4); - putlong(m, achan[local].chan); - sendmsg(m); -*/ - if(achan[local].needeof){ - achan[local].needeof = 0; - m = allocmsg(m->c, SSH_MSG_CHANNEL_INPUT_EOF, 4); - putlong(m, achan[local].chan); - sendmsg(m); - } - } -} - -void -handleagentoclose(Msg *m) -{ - u32int local; - - assert(m->type == SSH_MSG_CHANNEL_OUTPUT_CLOSED); - local = getlong(m); - debug(DBG_AUTH, "agent close %d\n", local); - if(local < nelem(achan)){ - debug(DBG_AUTH, "\tlocal %d is remote %d\n", local, achan[local].chan); - if(achan[local].needclosed){ - achan[local].needclosed = 0; - m = allocmsg(m->c, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4); - putlong(m, achan[local].chan); - sendmsg(m); - } - } -} diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/authpasswd.c --- a/sys/src/cmd/ssh/authpasswd.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -#include "ssh.h" - -static int -authpasswordfn(Conn *c) -{ - Msg *m; - UserPasswd *up; - - up = auth_getuserpasswd(c->interactive ? auth_getkey : nil, "proto=pass service=ssh server=%q user=%q", c->host, c->user); - if(up == nil){ - debug(DBG_AUTH, "getuserpasswd returned nothing (interactive=%d)\n", c->interactive); - return -1; - } - - debug(DBG_AUTH, "try using password from factotum\n"); - m = allocmsg(c, SSH_CMSG_AUTH_PASSWORD, 4+strlen(up->passwd)); - putstring(m, up->passwd); - sendmsg(m); - - m = recvmsg(c, -1); - switch(m->type){ - default: - badmsg(m, 0); - case SSH_SMSG_SUCCESS: - free(m); - return 0; - case SSH_SMSG_FAILURE: - free(m); - return -1; - } -} - -Auth authpassword = -{ - SSH_AUTH_PASSWORD, - "password", - authpasswordfn, -}; diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/authrsa.c --- a/sys/src/cmd/ssh/authrsa.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -#include "ssh.h" - -static int -authrsafn(Conn *c) -{ - uchar chalbuf[32+SESSIDLEN], response[MD5dlen]; - char *s, *p; - int afd, ret; - AuthRpc *rpc; - Msg *m; - mpint *chal, *decr, *unpad, *mod; - - debug(DBG_AUTH, "rsa!\n"); - - if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0){ - debug(DBG_AUTH, "open /mnt/factotum/rpc: %r\n"); - return -1; - } - if((rpc = auth_allocrpc(afd)) == nil){ - debug(DBG_AUTH, "auth_allocrpc: %r\n"); - close(afd); - return -1; - } - s = "proto=rsa role=client"; - if(auth_rpc(rpc, "start", s, strlen(s)) != ARok){ - debug(DBG_AUTH, "auth_rpc start %s failed: %r\n", s); - auth_freerpc(rpc); - close(afd); - return -1; - } - - ret = -1; - debug(DBG_AUTH, "trying factotum rsa keys\n"); - while(auth_rpc(rpc, "read", nil, 0) == ARok){ - debug(DBG_AUTH, "try %s\n", (char*)rpc->arg); - mod = strtomp(rpc->arg, nil, 16, nil); - m = allocmsg(c, SSH_CMSG_AUTH_RSA, 16+(mpsignif(mod)+7/8)); - putmpint(m, mod); - sendmsg(m); - mpfree(mod); - m = recvmsg(c, -1); - switch(m->type){ - case SSH_SMSG_FAILURE: - debug(DBG_AUTH, "\tnot accepted %s\n", (char*)rpc->arg); - free(m); - continue; - default: - badmsg(m, 0); - case SSH_SMSG_AUTH_RSA_CHALLENGE: - break; - } - chal = getmpint(m); - debug(DBG_AUTH, "\tgot challenge %B\n", chal); - free(m); - p = mptoa(chal, 16, nil, 0); - mpfree(chal); - if(p == nil){ - debug(DBG_AUTH, "\tmptoa failed: %r\n"); - unpad = mpnew(0); - goto Keepgoing; - } - if(auth_rpc(rpc, "write", p, strlen(p)) != ARok){ - debug(DBG_AUTH, "\tauth_rpc write failed: %r\n"); - free(p); - unpad = mpnew(0); /* it will fail, we'll go round again */ - goto Keepgoing; - } - free(p); - if(auth_rpc(rpc, "read", nil, 0) != ARok){ - debug(DBG_AUTH, "\tauth_rpc read failed: %r\n"); - unpad = mpnew(0); - goto Keepgoing; - } - decr = strtomp(rpc->arg, nil, 16, nil); - debug(DBG_AUTH, "\tdecrypted %B\n", decr); - unpad = rsaunpad(decr); - debug(DBG_AUTH, "\tunpadded %B\n", unpad); - mpfree(decr); - Keepgoing: - mptoberjust(unpad, chalbuf, 32); - mpfree(unpad); - debug(DBG_AUTH, "\trjusted %.*H\n", 32, chalbuf); - memmove(chalbuf+32, c->sessid, SESSIDLEN); - debug(DBG_AUTH, "\tappend sesskey %.*H\n", 32, chalbuf); - md5(chalbuf, 32+SESSIDLEN, response, nil); - m = allocmsg(c, SSH_CMSG_AUTH_RSA_RESPONSE, MD5dlen); - putbytes(m, response, MD5dlen); - sendmsg(m); - - m = recvmsg(c, -1); - switch(m->type){ - case SSH_SMSG_FAILURE: - free(m); - continue; - default: - badmsg(m, 0); - case SSH_SMSG_SUCCESS: - break; - } - ret = 0; - break; - } - auth_freerpc(rpc); - close(afd); - return ret; -} - -Auth authrsa = -{ - SSH_AUTH_RSA, - "rsa", - authrsafn, -}; diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/authsrvpasswd.c --- a/sys/src/cmd/ssh/authsrvpasswd.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -#include "ssh.h" - -static AuthInfo* -authsrvpasswordfn(Conn *c, Msg *m) -{ - char *pass; - AuthInfo *ai; - - pass = getstring(m); - ai = auth_userpasswd(c->user, pass); - free(m); - return ai; -} - -Authsrv authsrvpassword = -{ - SSH_AUTH_PASSWORD, - "password", - SSH_CMSG_AUTH_PASSWORD, - authsrvpasswordfn, -}; - diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/authsrvtis.c --- a/sys/src/cmd/ssh/authsrvtis.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -#include "ssh.h" - -static AuthInfo* -authsrvtisfn(Conn *conn, Msg *m) -{ - char *s; - AuthInfo *ai; - Chalstate *c; - - free(m); - if((c = auth_challenge("proto=p9cr user=%q role=server", conn->user)) == nil){ - sshlog("auth_challenge failed for %s", conn->user); - return nil; - } - s = smprint("Challenge: %s\nResponse: ", c->chal); - if(s == nil){ - auth_freechal(c); - return nil; - } - m = allocmsg(conn, SSH_SMSG_AUTH_TIS_CHALLENGE, 4+strlen(s)); - putstring(m, s); - sendmsg(m); - free(s); - - m = recvmsg(conn, 0); - if(m == nil){ - auth_freechal(c); - return nil; - } - if(m->type != SSH_CMSG_AUTH_TIS_RESPONSE){ - /* - * apparently you can just give up on - * this protocol and start a new one. - */ - unrecvmsg(conn, m); - return nil; - } - - c->resp = getstring(m); - c->nresp = strlen(c->resp); - ai = auth_response(c); - auth_freechal(c); - return ai; -} - -Authsrv authsrvtis = -{ - SSH_AUTH_TIS, - "tis", - SSH_CMSG_AUTH_TIS, - authsrvtisfn, -}; diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/authtis.c --- a/sys/src/cmd/ssh/authtis.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -#include "ssh.h" - -static int -authtisfn(Conn *c) -{ - int fd, n; - char *chal, resp[256]; - Msg *m; - - if(!c->interactive) - return -1; - - debug(DBG_AUTH, "try TIS\n"); - sendmsg(allocmsg(c, SSH_CMSG_AUTH_TIS, 0)); - - m = recvmsg(c, -1); - switch(m->type){ - default: - badmsg(m, SSH_SMSG_AUTH_TIS_CHALLENGE); - case SSH_SMSG_FAILURE: - free(m); - return -1; - case SSH_SMSG_AUTH_TIS_CHALLENGE: - break; - } - - chal = getstring(m); - free(m); - - if((fd = open("/dev/cons", ORDWR)) < 0) - error("can't open console"); - - fprint(fd, "TIS Authentication\n%s", chal); - n = read(fd, resp, sizeof resp-1); - if(n < 0) - resp[0] = '\0'; - else - resp[n] = '\0'; - - if(resp[0] == 0 || resp[0] == '\n') - return -1; - - m = allocmsg(c, SSH_CMSG_AUTH_TIS_RESPONSE, 4+strlen(resp)); - putstring(m, resp); - sendmsg(m); - - m = recvmsg(c, -1); - switch(m->type){ - default: - badmsg(m, 0); - case SSH_SMSG_SUCCESS: - free(m); - return 0; - case SSH_SMSG_FAILURE: - free(m); - return -1; - } -} - -Auth authtis = -{ - SSH_AUTH_TIS, - "tis", - authtisfn, -}; diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/cipher3des.c --- a/sys/src/cmd/ssh/cipher3des.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -#include "ssh.h" - -struct CipherState -{ - DESstate enc3des[3]; - DESstate dec3des[3]; -}; - -static CipherState* -init3des(Conn *c, int) -{ - int i; - CipherState *cs; - - cs = emalloc(sizeof(CipherState)); - for(i=0; i<3; i++){ - setupDESstate(&cs->enc3des[i], c->sesskey+8*i, nil); - setupDESstate(&cs->dec3des[i], c->sesskey+8*i, nil); - } - return cs; -} - -static void -encrypt3des(CipherState *cs, uchar *buf, int nbuf) -{ - desCBCencrypt(buf, nbuf, &cs->enc3des[0]); - desCBCdecrypt(buf, nbuf, &cs->enc3des[1]); - desCBCencrypt(buf, nbuf, &cs->enc3des[2]); -} - -static void -decrypt3des(CipherState *cs, uchar *buf, int nbuf) -{ - desCBCdecrypt(buf, nbuf, &cs->dec3des[2]); - desCBCencrypt(buf, nbuf, &cs->dec3des[1]); - desCBCdecrypt(buf, nbuf, &cs->dec3des[0]); -} - -Cipher cipher3des = -{ - SSH_CIPHER_3DES, - "3des", - init3des, - encrypt3des, - decrypt3des, -}; - diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/cipherblowfish.c --- a/sys/src/cmd/ssh/cipherblowfish.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -#include "ssh.h" - -struct CipherState -{ - BFstate enc; - BFstate dec; -}; - -static CipherState* -initblowfish(Conn *c, int) -{ - CipherState *cs; - - cs = emalloc(sizeof(CipherState)); - setupBFstate(&cs->enc, c->sesskey, SESSKEYLEN, nil); - setupBFstate(&cs->dec, c->sesskey, SESSKEYLEN, nil); - return cs; -} - -static void -encryptblowfish(CipherState *cs, uchar *buf, int nbuf) -{ - bfCBCencrypt(buf, nbuf, &cs->enc); -} - -static void -decryptblowfish(CipherState *cs, uchar *buf, int nbuf) -{ - bfCBCdecrypt(buf, nbuf, &cs->dec); -} - -Cipher cipherblowfish = -{ - SSH_CIPHER_BLOWFISH, - "blowfish", - initblowfish, - encryptblowfish, - decryptblowfish, -}; - diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/cipherdes.c --- a/sys/src/cmd/ssh/cipherdes.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -#include "ssh.h" - -struct CipherState -{ - DESstate enc; - DESstate dec; -}; - -static CipherState* -initdes(Conn *c, int) -{ - CipherState *cs; - - cs = emalloc(sizeof(CipherState)); - setupDESstate(&cs->enc, c->sesskey, nil); - setupDESstate(&cs->dec, c->sesskey, nil); - return cs; -} - -static void -encryptdes(CipherState *cs, uchar *buf, int nbuf) -{ - desCBCencrypt(buf, nbuf, &cs->enc); -} - -static void -decryptdes(CipherState *cs, uchar *buf, int nbuf) -{ - desCBCdecrypt(buf, nbuf, &cs->dec); -} - -Cipher cipherdes = -{ - SSH_CIPHER_DES, - "des", - initdes, - encryptdes, - decryptdes, -}; - diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/ciphernone.c --- a/sys/src/cmd/ssh/ciphernone.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#include "ssh.h" - -static CipherState* -initnone(Conn*, int) -{ - /* must be non-nil */ - return (CipherState*)~0; -} - -static void -encryptnone(CipherState*, uchar*, int) -{ -} - -static void -decryptnone(CipherState*, uchar*, int) -{ -} - -Cipher ciphernone = -{ - SSH_CIPHER_NONE, - "none", - initnone, - encryptnone, - decryptnone, -}; - diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/cipherrc4.c --- a/sys/src/cmd/ssh/cipherrc4.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -#include "ssh.h" - -struct CipherState -{ - RC4state enc; - RC4state dec; -}; - -static CipherState* -initrc4(Conn *c, int isserver) -{ - CipherState *cs; - - cs = emalloc(sizeof(CipherState)); - if(isserver){ - setupRC4state(&cs->enc, c->sesskey, 16); - setupRC4state(&cs->dec, c->sesskey+16, 16); - }else{ - setupRC4state(&cs->dec, c->sesskey, 16); - setupRC4state(&cs->enc, c->sesskey+16, 16); - } - return cs; -} - -static void -encryptrc4(CipherState *cs, uchar *buf, int nbuf) -{ - rc4(&cs->enc, buf, nbuf); -} - -static void -decryptrc4(CipherState *cs, uchar *buf, int nbuf) -{ - rc4(&cs->dec, buf, nbuf); -} - -Cipher cipherrc4 = -{ - SSH_CIPHER_RC4, - "rc4", - initrc4, - encryptrc4, - decryptrc4, -}; - diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/ciphertwiddle.c --- a/sys/src/cmd/ssh/ciphertwiddle.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#include "ssh.h" - -static CipherState* -inittwiddle(Conn *c, int) -{ - /* must be non-nil */ - fprint(2, "twiddle key is %.*H\n", SESSKEYLEN, c->sesskey); - return (CipherState*)~0; -} - -static void -twiddle(CipherState*, uchar *buf, int n) -{ - int i; - - for(i=0; icookie, getbytes(m, COOKIELEN), COOKIELEN); - c->serverkey = getRSApub(m); - c->hostkey = getRSApub(m); - c->flags = getlong(m); - c->ciphermask = getlong(m); - c->authmask = getlong(m); - free(m); -} - -static void -send_ssh_cmsg_session_key(Conn *c) -{ - int i, n, buflen, serverkeylen, hostkeylen; - mpint *b; - uchar *buf; - Msg *m; - RSApub *ksmall, *kbig; - - m = allocmsg(c, SSH_CMSG_SESSION_KEY, 2048); - putbyte(m, c->cipher->id); - putbytes(m, c->cookie, COOKIELEN); - - serverkeylen = mpsignif(c->serverkey->n); - hostkeylen = mpsignif(c->hostkey->n); - ksmall = kbig = nil; - if(serverkeylen+128 <= hostkeylen){ - ksmall = c->serverkey; - kbig = c->hostkey; - }else if(hostkeylen+128 <= serverkeylen){ - ksmall = c->hostkey; - kbig = c->serverkey; - }else - error("server session and host keys do not differ by at least 128 bits"); - - buflen = (mpsignif(kbig->n)+7)/8; - buf = emalloc(buflen); - - debug(DBG_CRYPTO, "session key is %.*H\n", SESSKEYLEN, c->sesskey); - memmove(buf, c->sesskey, SESSKEYLEN); - for(i = 0; i < SESSIDLEN; i++) - buf[i] ^= c->sessid[i]; - debug(DBG_CRYPTO, "munged session key is %.*H\n", SESSKEYLEN, buf); - - b = rsaencryptbuf(ksmall, buf, SESSKEYLEN); - n = (mpsignif(ksmall->n)+7) / 8; - mptoberjust(b, buf, n); - mpfree(b); - debug(DBG_CRYPTO, "encrypted with ksmall is %.*H\n", n, buf); - - b = rsaencryptbuf(kbig, buf, n); - putmpint(m, b); - debug(DBG_CRYPTO, "encrypted with kbig is %B\n", b); - mpfree(b); - - memset(buf, 0, buflen); - free(buf); - - putlong(m, c->flags); - sendmsg(m); -} - -static int -authuser(Conn *c) -{ - int i; - Msg *m; - - m = allocmsg(c, SSH_CMSG_USER, 4+strlen(c->user)); - putstring(m, c->user); - sendmsg(m); - - m = recvmsg(c, -1); - switch(m->type){ - case SSH_SMSG_SUCCESS: - free(m); - return 0; - case SSH_SMSG_FAILURE: - free(m); - break; - default: - badmsg(m, 0); - } - - for(i=0; inokauth; i++){ - debug(DBG_AUTH, "authmask %#lux, consider %s (%#x)\n", - c->authmask, c->okauth[i]->name, 1<okauth[i]->id); - if(c->authmask & (1<okauth[i]->id)) - if((*c->okauth[i]->fn)(c) == 0) - return 0; - } - - debug(DBG_AUTH, "no auth methods worked; (authmask=%#lux)\n", c->authmask); - return -1; -} - -static char -ask(Conn *c, char *answers, char *question) -{ - int fd; - char buf[256]; - - if(!c->interactive) - return answers[0]; - - if((fd = open("/dev/cons", ORDWR)) < 0) - return answers[0]; - - fprint(fd, "%s", question); - if(read(fd, buf, 256) <= 0 || buf[0]=='\n'){ - close(fd); - return answers[0]; - } - close(fd); - return buf[0]; -} -static void -checkkey(Conn *c) -{ - char *home, *keyfile; - - debug(DBG_CRYPTO, "checking key %B %B\n", c->hostkey->n, c->hostkey->ek); - switch(findkey("/sys/lib/ssh/keyring", c->aliases, c->hostkey)){ - default: - abort(); - case KeyOk: - return; - case KeyWrong: - fprint(2, "server presented public key different than expected\n"); - fprint(2, "(expected key in /sys/lib/ssh/keyring). will not continue.\n"); - error("bad server key"); - - case NoKey: - case NoKeyFile: - break; - } - - home = getenv("home"); - if(home == nil){ - fprint(2, "server %s not on keyring; will not continue.\n", c->host); - error("bad server key"); - } - - keyfile = smprint("%s/lib/keyring", home); - if(keyfile == nil) - error("out of memory"); - - switch(findkey(keyfile, c->aliases, c->hostkey)){ - default: - abort(); - case KeyOk: - return; - case KeyWrong: - fprint(2, "server %s presented public key different than expected\n", c->host); - fprint(2, "(expected key in %s). will not continue.\n", keyfile); - fprint(2, "this could be a man-in-the-middle attack.\n"); - switch(ask(c, "eri", "replace key in keyfile (r), continue without replacing key (c), or exit (e) [e]")){ - case 'e': - error("bad key"); - case 'r': - if(replacekey(keyfile, c->aliases, c->hostkey) < 0) - error("replacekey: %r"); - break; - case 'c': - break; - } - return; - case NoKey: - case NoKeyFile: - fprint(2, "server %s not on keyring.\n", c->host); - switch(ask(c, "eac", "add key to keyfile (a), continue without adding key (c), or exit (e) [e]")){ - case 'e': - error("bad key"); - case 'a': - if(appendkey(keyfile, c->aliases, c->hostkey) < 0) - error("appendkey: %r"); - break; - case 'c': - break; - } - return; - } -} - -void -sshclienthandshake(Conn *c) -{ - char buf[128], *p; - int i; - Msg *m; - - /* receive id string */ - if(readstrnl(c->fd[0], buf, sizeof buf) < 0) - error("reading server version: %r"); - - /* id string is "SSH-m.n-comment". We need m=1, n>=5. */ - if(strncmp(buf, "SSH-", 4) != 0 - || strtol(buf+4, &p, 10) != 1 - || *p != '.' - || strtol(p+1, &p, 10) < 5 - || *p != '-') - error("protocol mismatch; got %s, need SSH-1.x for x>=5", buf); - - /* send id string */ - fprint(c->fd[1], "SSH-1.5-Plan 9\n"); - - recv_ssh_smsg_public_key(c); - checkkey(c); - - for(i=0; isesskey[i] = fastrand(); - c->cipher = nil; - for(i=0; inokcipher; i++) - if((1<okcipher[i]->id) & c->ciphermask){ - c->cipher = c->okcipher[i]; - break; - } - if(c->cipher == nil) - error("can't agree on ciphers: remote side supports %#lux", c->ciphermask); - - calcsessid(c); - - send_ssh_cmsg_session_key(c); - - c->cstate = (*c->cipher->init)(c, 0); /* turns on encryption */ - m = recvmsg(c, SSH_SMSG_SUCCESS); - free(m); - - if(authuser(c) < 0) - error("client authentication failed"); -} - -static int -intgetenv(char *name, int def) -{ - char *s; - int n, val; - - val = def; - if((s = getenv(name))!=nil){ - if((n=atoi(s)) > 0) - val = n; - free(s); - } - return val; -} - -/* - * assumes that if you care, you're running under vt - * and therefore these are set. - */ -int -readgeom(int *nrow, int *ncol, int *width, int *height) -{ - static int fd = -1; - char buf[64]; - - if(fd < 0 && (fd = open("/dev/wctl", OREAD)) < 0) - return -1; - /* wait for event, but don't care what it says */ - if(read(fd, buf, sizeof buf) < 0) - return -1; - *nrow = intgetenv("LINES", 24); - *ncol = intgetenv("COLS", 80); - *width = intgetenv("XPIXELS", 640); - *height = intgetenv("YPIXELS", 480); - return 0; -} - -void -sendwindowsize(Conn *c, int nrow, int ncol, int width, int height) -{ - Msg *m; - - m = allocmsg(c, SSH_CMSG_WINDOW_SIZE, 4*4); - putlong(m, nrow); - putlong(m, ncol); - putlong(m, width); - putlong(m, height); - sendmsg(m); -} - -/* - * In each option line, the first byte is the option number - * and the second is either a boolean bit or actually an - * ASCII code. - */ -static uchar ptyopt[] = -{ - 0x01, 0x7F, /* interrupt = DEL */ - 0x02, 0x11, /* quit = ^Q */ - 0x03, 0x08, /* backspace = ^H */ - 0x04, 0x15, /* line kill = ^U */ - 0x05, 0x04, /* EOF = ^D */ - 0x20, 0x00, /* don't strip high bit */ - 0x48, 0x01, /* give us CRs */ - - 0x00, /* end options */ -}; - -static uchar rawptyopt[] = -{ - 30, 0, /* ignpar */ - 31, 0, /* parmrk */ - 32, 0, /* inpck */ - 33, 0, /* istrip */ - 34, 0, /* inlcr */ - 35, 0, /* igncr */ - 36, 0, /* icnrl */ - 37, 0, /* iuclc */ - 38, 0, /* ixon */ - 39, 1, /* ixany */ - 40, 0, /* ixoff */ - 41, 0, /* imaxbel */ - - 50, 0, /* isig: intr, quit, susp processing */ - 51, 0, /* icanon: erase and kill processing */ - 52, 0, /* xcase */ - - 53, 0, /* echo */ - - 57, 0, /* noflsh */ - 58, 0, /* tostop */ - 59, 0, /* iexten: impl defined control chars */ - - 70, 0, /* opost */ - - 0x00, -}; - -void -requestpty(Conn *c) -{ - char *term; - int nrow, ncol, width, height; - Msg *m; - - m = allocmsg(c, SSH_CMSG_REQUEST_PTY, 1024); - if((term = getenv("TERM")) == nil) - term = "9term"; - putstring(m, term); - - readgeom(&nrow, &ncol, &width, &height); - putlong(m, nrow); /* characters */ - putlong(m, ncol); - putlong(m, width); /* pixels */ - putlong(m, height); - - if(rawhack) - putbytes(m, rawptyopt, sizeof rawptyopt); - else - putbytes(m, ptyopt, sizeof ptyopt); - - sendmsg(m); - - m = recvmsg(c, 0); - switch(m->type){ - case SSH_SMSG_SUCCESS: - debug(DBG_IO, "PTY allocated\n"); - break; - case SSH_SMSG_FAILURE: - debug(DBG_IO, "PTY allocation failed\n"); - break; - default: - badmsg(m, 0); - } - free(m); -} - diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/mkfile --- a/sys/src/cmd/ssh/mkfile Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -"); - s = buf; - }else{ - snprint(buf, sizeof buf, "", m->type); - s = buf; - if(0 <= m->type && m->type < nelem(msgnames)) - s = msgnames[m->type]; - } - if(want) - error("got %s message expecting %s", s, msgnames[want]); - error("got unexpected %s message", s); -} - -Msg* -allocmsg(Conn *c, int type, int len) -{ - uchar *p; - Msg *m; - - if(len > 256*1024) - abort(); - - m = (Msg*)emalloc(sizeof(Msg)+4+8+1+len+4); - setmalloctag(m, getcallerpc(&c)); - p = (uchar*)&m[1]; - m->c = c; - m->bp = p; - m->ep = p+len; - m->wp = p; - m->type = type; - return m; -} - -void -unrecvmsg(Conn *c, Msg *m) -{ - debug(DBG_PROTO, "unreceived %s len %ld\n", msgnames[m->type], m->ep - m->rp); - free(c->unget); - c->unget = m; -} - -static Msg* -recvmsg0(Conn *c) -{ - int pad; - uchar *p, buf[4]; - ulong crc, crc0, len; - Msg *m; - - if(c->unget){ - m = c->unget; - c->unget = nil; - return m; - } - - if(readn(c->fd[0], buf, 4) != 4){ - werrstr("short net read: %r"); - return nil; - } - - len = LONG(buf); - if(len > 256*1024){ - werrstr("packet size far too big: %.8lux", len); - return nil; - } - - pad = 8 - len%8; - - m = (Msg*)emalloc(sizeof(Msg)+pad+len); - setmalloctag(m, getcallerpc(&c)); - m->c = c; - m->bp = (uchar*)&m[1]; - m->ep = m->bp + pad+len-4; /* -4: don't include crc */ - m->rp = m->bp; - - if(readn(c->fd[0], m->bp, pad+len) != pad+len){ - werrstr("short net read: %r"); - free(m); - return nil; - } - - if(c->cipher) - c->cipher->decrypt(c->cstate, m->bp, len+pad); - - crc = sum32(0, m->bp, pad+len-4); - p = m->bp + pad+len-4; - crc0 = LONG(p); - if(crc != crc0){ - werrstr("bad crc %#lux != %#lux (packet length %lud)", crc, crc0, len); - free(m); - return nil; - } - - m->rp += pad; - m->type = *m->rp++; - - return m; -} - -Msg* -recvmsg(Conn *c, int type) -{ - Msg *m; - - while((m = recvmsg0(c)) != nil){ - debug(DBG_PROTO, "received %s len %ld\n", msgnames[m->type], m->ep - m->rp); - if(m->type != SSH_MSG_DEBUG && m->type != SSH_MSG_IGNORE) - break; - if(m->type == SSH_MSG_DEBUG) - debug(DBG_PROTO, "remote DEBUG: %s\n", getstring(m)); - free(m); - } - if(type == 0){ - /* no checking */ - }else if(type == -1){ - /* must not be nil */ - if(m == nil) - error(Ehangup); - }else{ - /* must be given type */ - if(m==nil || m->type!=type) - badmsg(m, type); - } - setmalloctag(m, getcallerpc(&c)); - return m; -} - -int -sendmsg(Msg *m) -{ - int i, pad; - uchar *p; - ulong datalen, len, crc; - Conn *c; - - datalen = m->wp - m->bp; - len = datalen + 5; - pad = 8 - len%8; - - debug(DBG_PROTO, "sending %s len %lud\n", msgnames[m->type], datalen); - - p = m->bp; - memmove(m->bp+4+pad+1, m->bp, datalen); /* slide data to correct position */ - - PLONG(p, len); - p += 4; - - if(m->c->cstate){ - for(i=0; itype; - - /* data already in position */ - p += datalen; - - crc = sum32(0, m->bp+4, pad+1+datalen); - PLONG(p, crc); - p += 4; - - c = m->c; - qlock(c); - if(c->cstate) - c->cipher->encrypt(c->cstate, m->bp+4, len+pad); - - if(write(c->fd[1], m->bp, p - m->bp) != p-m->bp){ - qunlock(c); - free(m); - return -1; - } - qunlock(c); - free(m); - return 0; -} - -uchar -getbyte(Msg *m) -{ - if(m->rp >= m->ep) - error(Edecode); - return *m->rp++; -} - -ushort -getshort(Msg *m) -{ - ushort x; - - if(m->rp+2 > m->ep) - error(Edecode); - - x = SHORT(m->rp); - m->rp += 2; - return x; -} - -ulong -getlong(Msg *m) -{ - ulong x; - - if(m->rp+4 > m->ep) - error(Edecode); - - x = LONG(m->rp); - m->rp += 4; - return x; -} - -char* -getstring(Msg *m) -{ - char *p; - ulong len; - - /* overwrites length to make room for NUL */ - len = getlong(m); - if(m->rp+len > m->ep) - error(Edecode); - p = (char*)m->rp-1; - memmove(p, m->rp, len); - p[len] = '\0'; - return p; -} - -void* -getbytes(Msg *m, int n) -{ - uchar *p; - - if(m->rp+n > m->ep) - error(Edecode); - p = m->rp; - m->rp += n; - return p; -} - -mpint* -getmpint(Msg *m) -{ - int n; - - n = (getshort(m)+7)/8; /* getshort returns # bits */ - return betomp(getbytes(m, n), n, nil); -} - -RSApub* -getRSApub(Msg *m) -{ - RSApub *key; - - getlong(m); - key = rsapuballoc(); - if(key == nil) - error(Ememory); - key->ek = getmpint(m); - key->n = getmpint(m); - setmalloctag(key, getcallerpc(&m)); - return key; -} - -void -putbyte(Msg *m, uchar x) -{ - if(m->wp >= m->ep) - error(Eencode); - *m->wp++ = x; -} - -void -putshort(Msg *m, ushort x) -{ - if(m->wp+2 > m->ep) - error(Eencode); - PSHORT(m->wp, x); - m->wp += 2; -} - -void -putlong(Msg *m, ulong x) -{ - if(m->wp+4 > m->ep) - error(Eencode); - PLONG(m->wp, x); - m->wp += 4; -} - -void -putstring(Msg *m, char *s) -{ - int len; - - len = strlen(s); - putlong(m, len); - putbytes(m, s, len); -} - -void -putbytes(Msg *m, void *a, long n) -{ - if(m->wp+n > m->ep) - error(Eencode); - memmove(m->wp, a, n); - m->wp += n; -} - -void -putmpint(Msg *m, mpint *b) -{ - int bits, n; - - bits = mpsignif(b); - putshort(m, bits); - n = (bits+7)/8; - if(m->wp+n > m->ep) - error(Eencode); - mptobe(b, m->wp, n, nil); - m->wp += n; -} - -void -putRSApub(Msg *m, RSApub *key) -{ - putlong(m, mpsignif(key->n)); - putmpint(m, key->ek); - putmpint(m, key->n); -} - -static ulong crctab[256]; - -static void -initsum32(void) -{ - ulong crc, poly; - int i, j; - - poly = 0xEDB88320; - for(i = 0; i < 256; i++){ - crc = i; - for(j = 0; j < 8; j++){ - if(crc & 1) - crc = (crc >> 1) ^ poly; - else - crc >>= 1; - } - crctab[i] = crc; - } -} - -static ulong -sum32(ulong lcrc, void *buf, int n) -{ - static int first=1; - uchar *s = buf; - ulong crc = lcrc; - - if(first){ - first=0; - initsum32(); - } - while(n-- > 0) - crc = crctab[(crc^*s++)&0xff] ^ (crc>>8); - return crc; -} - -mpint* -rsapad(mpint *b, int n) -{ - int i, pad, nbuf; - uchar buf[2560]; - mpint *c; - - if(n > sizeof buf) - error("buffer too small in rsapad"); - - nbuf = (mpsignif(b)+7)/8; - pad = n - nbuf; - assert(pad >= 3); - mptobe(b, buf, nbuf, nil); - memmove(buf+pad, buf, nbuf); - - buf[0] = 0; - buf[1] = 2; - for(i=2; i sizeof buf) - error("buffer too small in rsaunpad"); - mptobe(b, buf, n, nil); - - /* the initial zero has been eaten by the betomp -> mptobe sequence */ - if(buf[0] != 2) - error("bad data in rsaunpad"); - for(i=1; i= 0); - if(n < len){ - len -= n; - memmove(buf+len, buf, n); - memset(buf, 0, len); - } -} - -mpint* -rsaencryptbuf(RSApub *key, uchar *buf, int nbuf) -{ - int n; - mpint *a, *b, *c; - - n = (mpsignif(key->n)+7)/8; - a = betomp(buf, nbuf, nil); - b = rsapad(a, n); - mpfree(a); - c = rsaencrypt(key, b, nil); - mpfree(b); - return c; -} - diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/pubkey.c --- a/sys/src/cmd/ssh/pubkey.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -#include "ssh.h" -#include -#include - -static int -parsepubkey(char *s, RSApub *key, char **sp, int base) -{ - int n; - char *host, *p, *z; - - z = nil; - n = strtoul(s, &p, 10); - host = nil; - if(n < 256 || !isspace(*p)){ /* maybe this is a host name */ - host = s; - s = strpbrk(s, " \t"); - if(s == nil) - return -1; - z = s; - *s++ = '\0'; - s += strspn(s, " \t"); - - n = strtoul(s, &p, 10); - if(n < 256 || !isspace(*p)){ - if(z) - *z = ' '; - return -1; - } - } - - if((key->ek = strtomp(p, &p, base, nil)) == nil - || (key->n = strtomp(p, &p, base, nil)) == nil - || (*p != '\0' && !isspace(*p)) - || mpsignif(key->n) < 256){ /* 256 is just a sanity check */ - mpfree(key->ek); - mpfree(key->n); - key->ek = nil; - key->n = nil; - if(z) - *z = ' '; - return -1; - } - if(host == nil){ - if(*p != '\0'){ - p += strspn(p, " \t"); - if(*p != '\0'){ - host = emalloc(strlen(p)+1); - strcpy(host, p); - } - } - free(s); - } - *sp = host; - return 0; -} - -RSApub* -readpublickey(Biobuf *b, char **sp) -{ - char *s; - RSApub *key; - - key = rsapuballoc(); - if(key == nil) - return nil; - - for(;;){ - if((s = Brdstr(b, '\n', 1)) == nil){ - rsapubfree(key); - return nil; - } - if(s[0]=='#'){ - free(s); - continue; - } - if(parsepubkey(s, key, sp, 10)==0 - || parsepubkey(s, key, sp, 16)==0) - return key; - fprint(2, "warning: skipping line '%s'; cannot parse\n", s); - free(s); - } -} - -static int -match(char *pattern, char *aliases) -{ - char *s, *snext; - char *a, *anext, *ae; - - for(s=pattern; s && *s; s=snext){ - if((snext=strchr(s, ',')) != nil) - *snext++ = '\0'; - for(a=aliases; a && *a; a=anext){ - if((anext=strchr(a, ',')) != nil){ - ae = anext; - anext++; - }else - ae = a+strlen(a); - if(ae-a == strlen(s) && memcmp(s, a, ae-a)==0) - return 0; - } - } - return 1; -} - -int -findkey(char *keyfile, char *host, RSApub *key) -{ - char *h; - Biobuf *b; - RSApub *k; - - if((b = Bopen(keyfile, OREAD)) == nil) - return NoKeyFile; - - for(;;){ - if((k = readpublickey(b, &h)) == nil){ - Bterm(b); - return NoKey; - } - if(match(h, host) != 0){ - free(h); - rsapubfree(k); - continue; - } - if(mpcmp(k->n, key->n) != 0 || mpcmp(k->ek, key->ek) != 0){ - free(h); - rsapubfree(k); - Bterm(b); - return KeyWrong; - } - free(h); - rsapubfree(k); - Bterm(b); - return KeyOk; - } -} - -int -replacekey(char *keyfile, char *host, RSApub *hostkey) -{ - char *h, *nkey, *p; - Biobuf *br, *bw; - Dir *d, nd; - RSApub *k; - - nkey = smprint("%s.new", keyfile); - if(nkey == nil) - return -1; - - if((br = Bopen(keyfile, OREAD)) == nil){ - free(nkey); - return -1; - } - if((bw = Bopen(nkey, OWRITE)) == nil){ - Bterm(br); - free(nkey); - return -1; - } - - while((k = readpublickey(br, &h)) != nil){ - if(match(h, host) != 0){ - Bprint(bw, "%s %d %.10B %.10B\n", - h, mpsignif(k->n), k->ek, k->n); - } - free(h); - rsapubfree(k); - } - Bprint(bw, "%s %d %.10B %.10B\n", host, mpsignif(hostkey->n), hostkey->ek, hostkey->n); - Bterm(bw); - Bterm(br); - - d = dirstat(nkey); - if(d == nil){ - fprint(2, "new key file disappeared?\n"); - free(nkey); - return -1; - } - - p = strrchr(d->name, '.'); - if(p==nil || strcmp(p, ".new")!=0){ - fprint(2, "new key file changed names? %s to %s\n", nkey, d->name); - free(d); - free(nkey); - return -1; - } - - *p = '\0'; - nulldir(&nd); - nd.name = d->name; - if(remove(keyfile) < 0){ - fprint(2, "error removing %s: %r\n", keyfile); - free(d); - free(nkey); - return -1; - } - if(dirwstat(nkey, &nd) < 0){ - fprint(2, "error renaming %s to %s: %r\n", nkey, d->name); - free(nkey); - free(d); - return -1; - } - free(d); - free(nkey); - return 0; -} - -int -appendkey(char *keyfile, char *host, RSApub *key) -{ - int fd; - - if((fd = open(keyfile, OWRITE)) < 0){ - fd = create(keyfile, OWRITE, 0666); - if(fd < 0){ - fprint(2, "cannot open nor create %s: %r\n", keyfile); - return -1; - } - } - if(seek(fd, 0, 2) < 0 - || fprint(fd, "%s %d %.10B %.10B\n", host, mpsignif(key->n), key->ek, key->n) < 0){ - close(fd); - return -1; - } - close(fd); - return 0; -} diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/scp.c --- a/sys/src/cmd/ssh/scp.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,799 +0,0 @@ -#include -#include -#include - -int -isatty(int fd) -{ - char buf[64]; - - buf[0] = '\0'; - fd2path(fd, buf, sizeof buf); - if(strlen(buf)>=9 && strcmp(buf+strlen(buf)-9, "/dev/cons")==0) - return 1; - return 0; -} - -#define OK 0x00 -#define ERROR 0x01 -#define FATAL 0x02 - -char *progname; - -int dflag; -int fflag; -int iflag; -int pflag; -int rflag; -int tflag; -int vflag; - -int remote; - -char *exitflag = nil; - -void scperror(int, char*, ...); -void mustbedir(char*); -void receive(char*); -char *fileaftercolon(char*); -void destislocal(char *cmd, int argc, char *argv[], char *dest); -void destisremote(char *cmd, int argc, char *argv[], char *host, char *dest); -int remotessh(char *host, char *cmd); -void send(char*); -void senddir(char*, int, Dir*); -int getresponse(void); - -char theuser[32]; - -char ssh[] = "/bin/ssh"; - -int remotefd0; -int remotefd1; - -int -runcommand(char *cmd) -{ - Waitmsg *w; - int pid; - char *argv[4]; - - if (cmd == nil) - return -1; - switch(pid = fork()){ - case -1: - return -1; - case 0: - argv[0] = "rc"; - argv[1] = "-c"; - argv[2] = cmd; - argv[3] = nil; - exec("/bin/rc", argv); - exits("exec failed"); - } - for(;;){ - w = wait(); - if(w == nil) - return -1; - if(w->pid == pid) - break; - free(w); - } - if(w->msg[0]){ - free(w); - return -1; - } - free(w); - return 1; -} - -void -vprint(char *fmt, ...) -{ - char buf[1024]; - va_list arg; - static char *name; - - if(vflag == 0) - return; - - va_start(arg, fmt); - vseprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - - if(name == nil){ - name = sysname(); - if(name == nil) - name = ""; - } - fprint(2, "%s: %s\n", name, buf); -} - -void -usage(void) -{ - fprint(2, "Usage: scp [-Iidfprtv] source ... destination\n"); - exits("usage"); -} - - -#pragma varargck type "F" int -#pragma varargck type "V" char* -static int flag; - -/* flag: if integer flag, take following char *value */ -int -flagfmt(Fmt *f) -{ - flag = va_arg(f->args, int); - return 0; -} - -/* flag: if previous integer flag, take char *value */ -int -valfmt(Fmt *f) -{ - char *value; - - value = va_arg(f->args, char*); - if(flag) - return fmtprint(f, " %s", value); - return 0; -} - -void -sendokresponse(void) -{ - char ok = OK; - - write(remotefd1, &ok, 1); -} - -void -main(int argc, char *argv[]) -{ - int i, fd; - char cmd[32]; - char *p; - - progname = argv[0]; - fmtinstall('F', flagfmt); - fmtinstall('V', valfmt); - iflag = -1; - - ARGBEGIN { - case 'I': - iflag = 0; - break; - case 'i': - iflag = 1; - break; - case 'd': - dflag++; - break; - case 'f': - fflag++; - remote++; - break; - case 'p': - pflag++; - break; - case 'r': - rflag++; - break; - case 't': - tflag++; - remote++; - break; - case 'v': - vflag++; - break; - default: - scperror(1, "unknown option %c", ARGC()); - } ARGEND - - if(iflag == -1) - iflag = isatty(0); - - remotefd0 = 0; - remotefd1 = 1; - - if(fflag){ - getresponse(); - for(i=0; i 2) - dflag = 1; - - i = 0; - fd = open("/dev/user", OREAD); - if(fd >= 0){ - i = read(fd, theuser, sizeof theuser - 1); - close(fd); - } - if(i <= 0) - scperror(1, "can't read /dev/user: %r"); - - remotefd0 = -1; - remotefd1 = -1; - - snprint(cmd, sizeof cmd, "scp%F%V%F%V%F%V%F%V", - dflag, "-d", - pflag, "-p", - rflag, "-r", - vflag, "-v"); - - p = fileaftercolon(argv[argc-1]); - if(p != nil) /* send to remote machine. */ - destisremote(cmd, argc-1, argv, argv[argc-1], p); - else{ - if(dflag) - mustbedir(argv[argc-1]); - destislocal(cmd, argc-1, argv, argv[argc-1]); - } - - exits(exitflag); -} - -void -destislocal(char *cmd, int argc, char *argv[], char *dst) -{ - int i; - char *src; - char buf[4096]; - - for(i = 0; iqid.type & QTDIR)) { - scperror(0, "%s: protocol botch: directory requrest for non-directory", dir); - return d; - } - }else{ - /* create it writeable; will fix later */ - setmodes = 1; - fd = create(dir, OREAD, DMDIR|mode|0700); - if (fd < 0){ - scperror(0, "%s: can't create: %r", dir); - return d; - } - d = dirfstat(fd); - close(fd); - if(d == nil){ - scperror(0, "%s: can't stat: %r", dir); - return d; - } - } - receive(dir); - if(settimes || setmodes){ - nulldir(&nd); - if(settimes){ - nd.atime = atime; - nd.mtime = mtime; - d->atime = nd.atime; - d->mtime = nd.mtime; - } - if(setmodes){ - nd.mode = DMDIR | (mode & 0777); - d->mode = nd.mode; - } - if(dirwstat(dir, &nd) < 0){ - scperror(0, "can't wstat %s: %r", dir); - free(d); - return nil; - } - } - return d; -} - -void -receive(char *dest) -{ - int isdir, settimes, mode; - int exists, n, i, fd, m; - int errors; - ulong atime, mtime, size; - char buf[8192], *p; - char name[1024]; - Dir *d; - Dir nd; - - mtime = 0L; - atime = 0L; - settimes = 0; - isdir = 0; - if ((d = dirstat(dest)) && (d->qid.type & QTDIR)) { - isdir = 1; - } - if(dflag && !isdir) - scperror(1, "%s: not a directory: %r", dest); - - sendokresponse(); - - for (;;) { - readhdr(buf, sizeof buf); - - switch(buf[0]){ - case ERROR: - case FATAL: - if(!remote) - fprint(2, "%s\n", buf+1); - exitflag = "bad receive"; - if(buf[0] == FATAL) - exits(exitflag); - continue; - - case 'E': - sendokresponse(); - return; - - case 'T': - settimes = 1; - p = buf + 1; - mtime = strtol(p, &p, 10); - if(*p++ != ' '){ - Badtime: - scperror(1, "bad time format: %s", buf+1); - } - strtol(p, &p, 10); - if(*p++ != ' ') - goto Badtime; - atime = strtol(p, &p, 10); - if(*p++ != ' ') - goto Badtime; - strtol(p, &p, 10); - if(*p++ != 0) - goto Badtime; - - sendokresponse(); - continue; - - case 'D': - case 'C': - p = buf + 1; - mode = strtol(p, &p, 8); - if (*p++ != ' '){ - Badmode: - scperror(1, "bad mode/size format: %s", buf+1); - } - size = strtoll(p, &p, 10); - if(*p++ != ' ') - goto Badmode; - - if(isdir){ - if(dest[0] == '\0') - snprint(name, sizeof name, "%s", p); - else - snprint(name, sizeof name, "%s/%s", dest, p); - }else - snprint(name, sizeof name, "%s", dest); - if(strlen(name) > sizeof name-UTFmax) - scperror(1, "file name too long: %s", dest); - - exists = 1; - free(d); - if((d = dirstat(name)) == nil) - exists = 0; - - if(buf[0] == 'D'){ - vprint("receive directory %s", name); - d = receivedir(name, exists, d, settimes, atime, mtime, mode); - settimes = 0; - continue; - } - - vprint("receive file %s by %s", name, getuser()); - fd = create(name, OWRITE, mode); - if(fd < 0){ - scperror(0, "can't create %s: %r", name); - continue; - } - sendokresponse(); - - /* - * Committed to receive size bytes - */ - errors = 0; - for(i = 0; i < size; i += m){ - n = sizeof buf; - if(n > size - i) - n = size - i; - m = readn(remotefd0, buf, n); - if(m <= 0) - scperror(1, "read error on connection: %r"); - if(errors == 0){ - n = write(fd, buf, m); - if(n != m) - errors = 1; - } - } - - /* if file exists, modes could be wrong */ - if(errors) - scperror(0, "%s: write error: %r", name); - else if(settimes || (exists && (d->mode&0777) != (mode&0777))){ - nulldir(&nd); - if(settimes){ - settimes = 0; - nd.atime = atime; - nd.mtime = mtime; - } - if(exists && (d->mode&0777) != (mode&0777)) - nd.mode = (d->mode & ~0777) | (mode&0777); - if(dirwstat(name, &nd) < 0) - scperror(0, "can't wstat %s: %r", name); - } - free(d); - d = nil; - close(fd); - getresponse(); - if(errors) - exits("write error"); - sendokresponse(); - break; - - default: - scperror(0, "unrecognized header type char %c", buf[0]); - scperror(1, "input line: %s", buf); - } - } -} - -/* - * Lastelem is called when we have a Dir with the final element, but if the file - * has been bound, we want the original name that was used rather than - * the contents of the stat buffer, so do this lexically. - */ -char* -lastelem(char *file) -{ - char *elem; - - elem = strrchr(file, '/'); - if(elem == nil) - return file; - return elem+1; -} - -void -send(char *file) -{ - Dir *d; - ulong i; - int m, n, fd; - char buf[8192]; - - if((fd = open(file, OREAD)) < 0){ - scperror(0, "can't open %s: %r", file); - return; - } - if((d = dirfstat(fd)) == nil){ - scperror(0, "can't fstat %s: %r", file); - goto Return; - } - - if(d->qid.type & QTDIR){ - if(rflag) - senddir(file, fd, d); - else - scperror(0, "%s: is a directory", file); - goto Return; - } - - if(pflag){ - fprint(remotefd1, "T%lud 0 %lud 0\n", d->mtime, d->atime); - if(getresponse() < 0) - goto Return; - } - - fprint(remotefd1, "C%.4luo %lld %s\n", d->mode&0777, d->length, lastelem(file)); - if(getresponse() < 0) - goto Return; - - /* - * We are now committed to send d.length bytes, regardless - */ - for(i=0; ilength; i+=m){ - n = sizeof buf; - if(n > d->length - i) - n = d->length - i; - m = readn(fd, buf, n); - if(m <= 0) - break; - write(remotefd1, buf, m); - } - - if(i == d->length) - sendokresponse(); - else{ - /* continue to send gibberish up to d.length */ - for(; ilength; i+=n){ - n = sizeof buf; - if(n > d->length - i) - n = d->length - i; - write(remotefd1, buf, n); - } - scperror(0, "%s: %r", file); - } - - getresponse(); - - Return: - free(d); - close(fd); -} - -int -getresponse(void) -{ - uchar first, byte, buf[256]; - int i; - - if (read(remotefd0, &first, 1) != 1) - scperror(1, "lost connection"); - - if(first == 0) - return 0; - - i = 0; - if(first > FATAL){ - fprint(2, "scp: unexpected response character 0x%.2ux\n", first); - buf[i++] = first; - } - - /* read error message up to newline */ - for(;;){ - if(read(remotefd0, &byte, 1) != 1) - scperror(1, "response: dropped connection"); - if(byte == '\n') - break; - if(i < sizeof buf) - buf[i++] = byte; - } - - exitflag = "bad response"; - if(!remote) - fprint(2, "%.*s\n", utfnlen((char*)buf, i), (char*)buf); - - if (first == ERROR) - return -1; - exits(exitflag); - return 0; /* not reached */ -} - -void -senddir(char *name, int fd, Dir *dirp) -{ - Dir *d, *dir; - int n; - char file[256]; - - if(pflag){ - fprint(remotefd1, "T%lud 0 %lud 0\n", dirp->mtime, dirp->atime); - if(getresponse() < 0) - return; - } - - vprint("directory %s mode: D%.4lo %d %.1024s", name, dirp->mode&0777, 0, lastelem(name)); - - fprint(remotefd1, "D%.4lo %d %.1024s\n", dirp->mode&0777, 0, dirp->name); - if(getresponse() < 0) - return; - - n = dirreadall(fd, &dir); - for(d = dir; d < &dir[n]; d++){ - /* shouldn't happen with plan 9, but worth checking anyway */ - if(strcmp(d->name, ".")==0 || strcmp(d->name, "..")==0) - continue; - if(snprint(file, sizeof file, "%s/%s", name, d->name) > sizeof file-UTFmax){ - scperror(0, "%.20s.../%s: name too long; skipping file", file, d->name); - continue; - } - send(file); - } - free(dir); - fprint(remotefd1, "E\n"); - getresponse(); -} - -int -remotessh(char *host, char *cmd) -{ - int i, p[2]; - char *arg[32]; - - vprint("remotessh: %s: %s", host, cmd); - - if(pipe(p) < 0) - scperror(1, "pipe: %r"); - - switch(fork()){ - case -1: - scperror(1, "fork: %r"); - - case 0: - /* child */ - close(p[0]); - dup(p[1], 0); - dup(p[1], 1); - for (i = 3; i < 100; i++) - close(i); - - i = 0; - arg[i++] = ssh; - arg[i++] = "-x"; - arg[i++] = "-a"; - arg[i++] = "-m"; - if(iflag) - arg[i++] = "-i"; - if(vflag) - arg[i++] = "-v"; - arg[i++] = host; - arg[i++] = cmd; - arg[i] = nil; - - exec(ssh, arg); - exits("exec failed"); - - default: - /* parent */ - close(p[1]); - remotefd0 = p[0]; - remotefd1 = p[0]; - } - return 0; -} - -void -scperror(int exit, char *fmt, ...) -{ - char buf[2048]; - va_list arg; - - - va_start(arg, fmt); - vseprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - - fprint(remotefd1, "%cscp: %s\n", ERROR, buf); - - if (!remote) - fprint(2, "scp: %s\n", buf); - exitflag = buf; - if(exit) - exits(exitflag); -} - -char * -fileaftercolon(char *file) -{ - char *c, *s; - - c = utfrune(file, ':'); - if(c == nil) - return nil; - - /* colon must be in middle of name to be a separator */ - if(c == file) - return nil; - - /* does slash occur before colon? */ - s = utfrune(file, '/'); - if(s != nil && s < c) - return nil; - - *c++ = '\0'; - if(*c == '\0') - return "."; - return c; -} - -void -mustbedir(char *file) -{ - Dir *d; - - if((d = dirstat(file)) == nil){ - scperror(1, "%s: %r", file); - return; - } - if(!(d->qid.type & QTDIR)) - scperror(1, "%s: Not a directory", file); - free(d); -} diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/smsg.c --- a/sys/src/cmd/ssh/smsg.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,285 +0,0 @@ -#include "ssh.h" -#include - -static void -send_ssh_smsg_public_key(Conn *c) -{ - int i; - Msg *m; - - m = allocmsg(c, SSH_SMSG_PUBLIC_KEY, 2048); - putbytes(m, c->cookie, COOKIELEN); - putRSApub(m, c->serverkey); - putRSApub(m, c->hostkey); - putlong(m, c->flags); - - for(i=0; inokcipher; i++) - c->ciphermask |= 1<okcipher[i]->id; - putlong(m, c->ciphermask); - for(i=0; inokauthsrv; i++) - c->authmask |= 1<okauthsrv[i]->id; - putlong(m, c->authmask); - - sendmsg(m); -} - -static mpint* -rpcdecrypt(AuthRpc *rpc, mpint *b) -{ - mpint *a; - char *p; - - p = mptoa(b, 16, nil, 0); - if(auth_rpc(rpc, "write", p, strlen(p)) != ARok) - sysfatal("factotum rsa write: %r"); - free(p); - if(auth_rpc(rpc, "read", nil, 0) != ARok) - sysfatal("factotum rsa read: %r"); - a = strtomp(rpc->arg, nil, 16, nil); - mpfree(b); - return a; -} - -static void -recv_ssh_cmsg_session_key(Conn *c, AuthRpc *rpc) -{ - int i, id, n, serverkeylen, hostkeylen; - mpint *a, *b; - uchar *buf; - Msg *m; - RSApriv *ksmall, *kbig; - - m = recvmsg(c, SSH_CMSG_SESSION_KEY); - id = getbyte(m); - c->cipher = nil; - for(i=0; inokcipher; i++) - if(c->okcipher[i]->id == id) - c->cipher = c->okcipher[i]; - if(c->cipher == nil) - sysfatal("invalid cipher selected"); - - if(memcmp(getbytes(m, COOKIELEN), c->cookie, COOKIELEN) != 0) - sysfatal("bad cookie"); - - serverkeylen = mpsignif(c->serverkey->n); - hostkeylen = mpsignif(c->hostkey->n); - ksmall = kbig = nil; - if(serverkeylen+128 <= hostkeylen){ - ksmall = c->serverpriv; - kbig = nil; - }else if(hostkeylen+128 <= serverkeylen){ - ksmall = nil; - kbig = c->serverpriv; - }else - sysfatal("server session and host keys do not differ by at least 128 bits"); - - b = getmpint(m); - - debug(DBG_CRYPTO, "encrypted with kbig is %B\n", b); - if(kbig){ - a = rsadecrypt(kbig, b, nil); - mpfree(b); - b = a; - }else - b = rpcdecrypt(rpc, b); - a = rsaunpad(b); - mpfree(b); - b = a; - - debug(DBG_CRYPTO, "encrypted with ksmall is %B\n", b); - if(ksmall){ - a = rsadecrypt(ksmall, b, nil); - mpfree(b); - b = a; - }else - b = rpcdecrypt(rpc, b); - a = rsaunpad(b); - mpfree(b); - b = a; - - debug(DBG_CRYPTO, "munged is %B\n", b); - - n = (mpsignif(b)+7)/8; - if(n > SESSKEYLEN) - sysfatal("client sent short session key"); - - buf = emalloc(SESSKEYLEN); - mptoberjust(b, buf, SESSKEYLEN); - mpfree(b); - - for(i=0; isessid[i]; - - memmove(c->sesskey, buf, SESSKEYLEN); - - debug(DBG_CRYPTO, "unmunged is %.*H\n", SESSKEYLEN, buf); - - c->flags = getlong(m); - free(m); -} - -static AuthInfo* -responselogin(char *user, char *resp) -{ - Chalstate *c; - AuthInfo *ai; - - if((c = auth_challenge("proto=p9cr user=%q role=server", user)) == nil){ - sshlog("auth_challenge failed for %s", user); - return nil; - } - c->resp = resp; - c->nresp = strlen(resp); - ai = auth_response(c); - auth_freechal(c); - return ai; -} - -static AuthInfo* -authusername(Conn *c) -{ - char *p; - AuthInfo *ai; - - /* - * hack for sam users: 'name numbers' gets tried as securid login. - */ - if(p = strchr(c->user, ' ')){ - *p++ = '\0'; - if((ai=responselogin(c->user, p)) != nil) - return ai; - *--p = ' '; - sshlog("bad response: %s", c->user); - } - return nil; -} - -static void -authsrvuser(Conn *c) -{ - int i; - char *ns, *user; - AuthInfo *ai; - Msg *m; - - m = recvmsg(c, SSH_CMSG_USER); - user = getstring(m); - c->user = emalloc(strlen(user)+1); - strcpy(c->user, user); - free(m); - - ai = authusername(c); - while(ai == nil){ - /* - * clumsy: if the client aborted the auth_tis early - * we don't send a new failure. we check this by - * looking at c->unget, which is only used in that - * case. - */ - if(c->unget != nil) - goto skipfailure; - sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0)); - skipfailure: - m = recvmsg(c, -1); - for(i=0; inokauthsrv; i++) - if(c->okauthsrv[i]->firstmsg == m->type){ - ai = (*c->okauthsrv[i]->fn)(c, m); - break; - } - if(i==c->nokauthsrv) - badmsg(m, 0); - } - sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0)); - - if(noworld(ai->cuid)) - ns = "/lib/namespace.noworld"; - else - ns = nil; - if(auth_chuid(ai, ns) < 0){ - sshlog("auth_chuid to %s: %r", ai->cuid); - sysfatal("auth_chuid: %r"); - } - sshlog("logged in as %s", ai->cuid); - auth_freeAI(ai); -} - -void -sshserverhandshake(Conn *c) -{ - char *p, buf[128]; - Biobuf *b; - Attr *a; - int i, afd; - mpint *m; - AuthRpc *rpc; - RSApub *key; - - /* - * BUG: should use `attr' to get the key attributes - * after the read, but that's not implemented yet. - */ - if((b = Bopen("/mnt/factotum/ctl", OREAD)) == nil) - sysfatal("open /mnt/factotum/ctl: %r"); - while((p = Brdline(b, '\n')) != nil){ - p[Blinelen(b)-1] = '\0'; - if(strstr(p, " proto=rsa ") && strstr(p, " service=sshserve ")) - break; - } - if(p == nil) - sysfatal("no sshserve keys found in /mnt/factotum/ctl"); - a = _parseattr(p); - Bterm(b); - key = emalloc(sizeof(*key)); - if((p = _strfindattr(a, "n")) == nil) - sysfatal("no n in sshserve key"); - if((key->n = strtomp(p, &p, 16, nil)) == nil || *p != 0) - sysfatal("bad n in sshserve key"); - if((p = _strfindattr(a, "ek")) == nil) - sysfatal("no ek in sshserve key"); - if((key->ek = strtomp(p, &p, 16, nil)) == nil || *p != 0) - sysfatal("bad ek in sshserve key"); - _freeattr(a); - - if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) - sysfatal("open /mnt/factotum/rpc: %r"); - if((rpc = auth_allocrpc(afd)) == nil) - sysfatal("auth_allocrpc: %r"); - p = "proto=rsa role=client service=sshserve"; - if(auth_rpc(rpc, "start", p, strlen(p)) != ARok) - sysfatal("auth_rpc start %s: %r", p); - if(auth_rpc(rpc, "read", nil, 0) != ARok) - sysfatal("auth_rpc read: %r"); - m = strtomp(rpc->arg, nil, 16, nil); - if(mpcmp(m, key->n) != 0) - sysfatal("key in /mnt/factotum/ctl does not match rpc key"); - mpfree(m); - c->hostkey = key; - - /* send id string */ - fprint(c->fd[0], "SSH-1.5-Plan9\n"); - - /* receive id string */ - if(readstrnl(c->fd[0], buf, sizeof buf) < 0) - sysfatal("reading server version: %r"); - - /* id string is "SSH-m.n-comment". We need m=1, n>=5. */ - if(strncmp(buf, "SSH-", 4) != 0 - || strtol(buf+4, &p, 10) != 1 - || *p != '.' - || strtol(p+1, &p, 10) < 5 - || *p != '-') - sysfatal("protocol mismatch; got %s, need SSH-1.x for x>=5", buf); - - for(i=0; icookie[i] = fastrand(); - calcsessid(c); - send_ssh_smsg_public_key(c); - recv_ssh_cmsg_session_key(c, rpc); - auth_freerpc(rpc); - close(afd); - - c->cstate = (*c->cipher->init)(c, 1); /* turns on encryption */ - sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0)); - - authsrvuser(c); -} diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/ssh.c --- a/sys/src/cmd/ssh/ssh.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,592 +0,0 @@ -#include "ssh.h" - -int cooked = 0; /* user wants cooked mode */ -int raw = 0; /* console is in raw mode */ -int crstrip; -int interactive = -1; -int usemenu = 1; -int isatty(int); -int rawhack; -int forwardagent = 0; -char *buildcmd(int, char**); -void fromnet(Conn*); -void fromstdin(Conn*); -void winchanges(Conn*); -static void sendwritemsg(Conn *c, char *buf, int n); - -Cipher *allcipher[] = { - &cipherrc4, - &cipherblowfish, - &cipher3des, - &cipherdes, - &ciphernone, - &ciphertwiddle, -}; - -Auth *allauth[] = { - &authpassword, - &authrsa, - &authtis, -}; - -char *cipherlist = "blowfish rc4 3des"; -char *authlist = "rsa password tis"; - -Cipher* -findcipher(char *name, Cipher **list, int nlist) -{ - int i; - - for(i=0; iname) == 0) - return list[i]; - error("unknown cipher %s", name); - return nil; -} - -Auth* -findauth(char *name, Auth **list, int nlist) -{ - int i; - - for(i=0; iname) == 0) - return list[i]; - error("unknown auth %s", name); - return nil; -} - -void -usage(void) -{ - fprint(2, "usage: ssh [-CiImPpRr] [-A authlist] [-c cipherlist] [user@]hostname [cmd [args]]\n"); - exits("usage"); -} - -void -main(int argc, char **argv) -{ - int i, dowinchange, fd, usepty; - char *host, *cmd, *user, *p; - char *f[16]; - Conn c; - Msg *m; - - fmtinstall('B', mpfmt); - fmtinstall('H', encodefmt); - atexit(atexitkiller); - atexitkill(getpid()); - - dowinchange = 0; - if(getenv("LINES")) - dowinchange = 1; - usepty = -1; - user = nil; - ARGBEGIN{ - case 'B': /* undocumented, debugging */ - doabort = 1; - break; - case 'D': /* undocumented, debugging */ - debuglevel = strtol(EARGF(usage()), nil, 0); - break; - case 'l': /* deprecated */ - case 'u': - user = EARGF(usage()); - break; - case 'a': /* used by Unix scp implementations; we must ignore them. */ - case 'x': - break; - - case 'A': - authlist = EARGF(usage()); - break; - case 'C': - cooked = 1; - break; - case 'c': - cipherlist = EARGF(usage()); - break; - case 'f': - forwardagent = 1; - break; - case 'I': - interactive = 0; - break; - case 'i': - interactive = 1; - break; - case 'm': - usemenu = 0; - break; - case 'P': - usepty = 0; - break; - case 'p': - usepty = 1; - break; - case 'R': - rawhack = 1; - break; - case 'r': - crstrip = 1; - break; - default: - usage(); - }ARGEND - - if(argc < 1) - usage(); - - host = argv[0]; - - cmd = nil; - if(argc > 1) - cmd = buildcmd(argc-1, argv+1); - - if((p = strchr(host, '@')) != nil){ - *p++ = '\0'; - user = host; - host = p; - } - if(user == nil) - user = getenv("user"); - if(user == nil) - sysfatal("cannot find user name"); - - privatefactotum(); - if(interactive==-1) - interactive = isatty(0); - - if((fd = dial(netmkaddr(host, "tcp", "ssh"), nil, nil, nil)) < 0) - sysfatal("dialing %s: %r", host); - - memset(&c, 0, sizeof c); - c.interactive = interactive; - c.fd[0] = c.fd[1] = fd; - c.user = user; - c.host = host; - setaliases(&c, host); - - c.nokcipher = getfields(cipherlist, f, nelem(f), 1, ", "); - c.okcipher = emalloc(sizeof(Cipher*)*c.nokcipher); - for(i=0; i=9 && strcmp(buf+strlen(buf)-9, "/dev/cons")==0) - return 1; - return 0; -} - -char* -buildcmd(int argc, char **argv) -{ - int i, len; - char *s, *t; - - len = argc-1; - for(i=0; itype){ - default: - badmsg(m, 0); - - case SSH_SMSG_EXITSTATUS: - ex = getlong(m); - if(ex==0) - exits(0); - sprint(buf, "%lud", ex); - exits(buf); - - case SSH_MSG_DISCONNECT: - s = getstring(m); - error("disconnect: %s", s); - - /* - * If we ever add reverse port forwarding, we'll have to - * revisit this. It assumes that the agent connections are - * the only ones. - */ - case SSH_SMSG_AGENT_OPEN: - if(!forwardagent) - error("server tried to use agent forwarding"); - handleagentopen(m); - break; - case SSH_MSG_CHANNEL_INPUT_EOF: - if(!forwardagent) - error("server tried to use agent forwarding"); - handleagentieof(m); - break; - case SSH_MSG_CHANNEL_OUTPUT_CLOSED: - if(!forwardagent) - error("server tried to use agent forwarding"); - handleagentoclose(m); - break; - case SSH_MSG_CHANNEL_DATA: - if(!forwardagent) - error("server tried to use agent forwarding"); - handleagentmsg(m); - break; - - case SSH_SMSG_STDOUT_DATA: - fd = 1; - goto Dataout; - case SSH_SMSG_STDERR_DATA: - fd = 2; - goto Dataout; - Dataout: - len = getlong(m); - s = (char*)getbytes(m, len); - if(crstrip){ - es = s+len; - for(r=w=s; r>> "); - for(done = 0; !done; ){ - n = read(0, buf, sizeof(buf)-1); - if(n <= 0) - return -1; - buf[n] = 0; - switch(buf[0]){ - case '!': - print(buf); - system(c, buf+1); - print("!\n"); - done = 1; - break; - case 'i': - buf[0] = 0x1c; - sendwritemsg(c, buf, 1); - done = 1; - break; - case '.': - case 'q': - done = 1; - break; - case 'r': - crstrip = 1-crstrip; - done = 1; - break; - default: - fprint(2, STDHELP); - break; - } - if(!done) - fprint(2, ">>> "); - } - - if(wasraw) - rawon(); - else - rawoff(); - return buf[0]; -} - -static void -sendwritemsg(Conn *c, char *buf, int n) -{ - Msg *m; - - if(n==0) - m = allocmsg(c, SSH_CMSG_EOF, 0); - else{ - m = allocmsg(c, SSH_CMSG_STDIN_DATA, 4+n); - putlong(m, n); - putbytes(m, buf, n); - } - sendmsg(m); -} - -/* - * run a command with the network connection as standard IO - */ -static void -system(Conn *c, char *cmd) -{ - int pid; - int p; - int pfd[2]; - int n; - int wasconsctl; - char buf[4096]; - - if(pipe(pfd) < 0){ - perror("pipe"); - return; - } - outfd1 = outfd2 = pfd[1]; - - wasconsctl = consctl; - close(consctl); - consctl = -1; - switch(pid = fork()){ - case -1: - perror("con"); - return; - case 0: - close(pfd[1]); - dup(pfd[0], 0); - dup(pfd[0], 1); - close(c->fd[0]); /* same as c->fd[1] */ - close(pfd[0]); - if(*cmd) - execl("/bin/rc", "rc", "-c", cmd, nil); - else - execl("/bin/rc", "rc", nil); - perror("con"); - exits("exec"); - break; - default: - close(pfd[0]); - while((n = read(pfd[1], buf, sizeof(buf))) > 0) - sendwritemsg(c, buf, n); - p = waitpid(); - outfd1 = 1; - outfd2 = 2; - close(pfd[1]); - if(p < 0 || p != pid) - return; - break; - } - if(wasconsctl >= 0){ - consctl = open("/dev/consctl", OWRITE); - if(consctl < 0) - error("cannot open consctl"); - } -} - -static void -cookedcatchint(void*, char *msg) -{ - if(strstr(msg, "interrupt")) - noted(NCONT); - else if(strstr(msg, "kill")) - noted(NDFLT); - else - noted(NCONT); -} - -static int -wasintr(void) -{ - char err[64]; - - rerrstr(err, sizeof err); - return strstr(err, "interrupt") != 0; -} - -void -fromstdin(Conn *c) -{ - int n; - char buf[1024]; - int pid; - int eofs; - - switch(pid = rfork(RFMEM|RFPROC|RFNOWAIT)){ - case -1: - error("fork: %r"); - case 0: - break; - default: - atexitkill(pid); - return; - } - - atexit(atexitkiller); - if(interactive) - rawon(); - - notify(cookedcatchint); - - eofs = 0; - for(;;){ - n = read(0, buf, sizeof(buf)); - if(n < 0){ - if(wasintr()){ - if(!raw){ - buf[0] = 0x7f; - n = 1; - }else - continue; - }else - break; - } - if(n == 0){ - if(!c->interactive || ++eofs > 32) - break; - }else - eofs = 0; - if(interactive && usemenu && n && memchr(buf, 0x1c, n)) { - if(menu(c)=='q'){ - sendwritemsg(c, "", 0); - exits("quit"); - } - continue; - } - if(!raw && n==0){ - buf[0] = 0x4; - n = 1; - } - sendwritemsg(c, buf, n); - } - sendwritemsg(c, "", 0); - atexitdont(atexitkiller); - exits(nil); -} - -void -winchanges(Conn *c) -{ - int nrow, ncol, width, height; - int pid; - - switch(pid = rfork(RFMEM|RFPROC|RFNOWAIT)){ - case -1: - error("fork: %r"); - case 0: - break; - default: - atexitkill(pid); - return; - } - - for(;;){ - if(readgeom(&nrow, &ncol, &width, &height) < 0) - break; - sendwindowsize(c, nrow, ncol, width, height); - } - exits(nil); -} diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/ssh.h --- a/sys/src/cmd/ssh/ssh.h Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,303 +0,0 @@ -#include -#include -#include -#include -#include - -enum /* internal debugging flags */ -{ - DBG= 1<<0, - DBG_CRYPTO= 1<<1, - DBG_PACKET= 1<<2, - DBG_AUTH= 1<<3, - DBG_PROC= 1<<4, - DBG_PROTO= 1<<5, - DBG_IO= 1<<6, - DBG_SCP= 1<<7, -}; - -enum /* protocol packet types */ -{ -/* 0 */ - SSH_MSG_NONE=0, - SSH_MSG_DISCONNECT, - SSH_SMSG_PUBLIC_KEY, - SSH_CMSG_SESSION_KEY, - SSH_CMSG_USER, - SSH_CMSG_AUTH_RHOSTS, - SSH_CMSG_AUTH_RSA, - SSH_SMSG_AUTH_RSA_CHALLENGE, - SSH_CMSG_AUTH_RSA_RESPONSE, - SSH_CMSG_AUTH_PASSWORD, - -/* 10 */ - SSH_CMSG_REQUEST_PTY, - SSH_CMSG_WINDOW_SIZE, - SSH_CMSG_EXEC_SHELL, - SSH_CMSG_EXEC_CMD, - SSH_SMSG_SUCCESS, - SSH_SMSG_FAILURE, - SSH_CMSG_STDIN_DATA, - SSH_SMSG_STDOUT_DATA, - SSH_SMSG_STDERR_DATA, - SSH_CMSG_EOF, - -/* 20 */ - SSH_SMSG_EXITSTATUS, - SSH_MSG_CHANNEL_OPEN_CONFIRMATION, - SSH_MSG_CHANNEL_OPEN_FAILURE, - SSH_MSG_CHANNEL_DATA, - SSH_MSG_CHANNEL_INPUT_EOF, - SSH_MSG_CHANNEL_OUTPUT_CLOSED, - SSH_MSG_UNIX_DOMAIN_X11_FORWARDING, /* obsolete */ - SSH_SMSG_X11_OPEN, - SSH_CMSG_PORT_FORWARD_REQUEST, - SSH_MSG_PORT_OPEN, - -/* 30 */ - SSH_CMSG_AGENT_REQUEST_FORWARDING, - SSH_SMSG_AGENT_OPEN, - SSH_MSG_IGNORE, - SSH_CMSG_EXIT_CONFIRMATION, - SSH_CMSG_X11_REQUEST_FORWARDING, - SSH_CMSG_AUTH_RHOSTS_RSA, - SSH_MSG_DEBUG, - SSH_CMSG_REQUEST_COMPRESSION, - SSH_CMSG_MAX_PACKET_SIZE, - SSH_CMSG_AUTH_TIS, - -/* 40 */ - SSH_SMSG_AUTH_TIS_CHALLENGE, - SSH_CMSG_AUTH_TIS_RESPONSE, - SSH_CMSG_AUTH_KERBEROS, - SSH_SMSG_AUTH_KERBEROS_RESPONSE, - SSH_CMSG_HAVE_KERBEROS_TGT, -}; - -enum /* protocol flags */ -{ - SSH_PROTOFLAG_SCREEN_NUMBER=1<<0, - SSH_PROTOFLAG_HOST_IN_FWD_OPEN=1<<1, -}; - -enum /* agent protocol packet types */ -{ - SSH_AGENTC_NONE = 0, - SSH_AGENTC_REQUEST_RSA_IDENTITIES, - SSH_AGENT_RSA_IDENTITIES_ANSWER, - SSH_AGENTC_RSA_CHALLENGE, - SSH_AGENT_RSA_RESPONSE, - SSH_AGENT_FAILURE, - SSH_AGENT_SUCCESS, - SSH_AGENTC_ADD_RSA_IDENTITY, - SSH_AGENTC_REMOVE_RSA_IDENTITY, -}; - -enum /* protocol constants */ -{ - SSH_MAX_DATA = 256*1024, - SSH_MAX_MSG = SSH_MAX_DATA+4, - - SESSKEYLEN = 32, - SESSIDLEN = 16, - - COOKIELEN = 8, -}; - -enum /* crypto ids */ -{ - SSH_CIPHER_NONE = 0, - SSH_CIPHER_IDEA, - SSH_CIPHER_DES, - SSH_CIPHER_3DES, - SSH_CIPHER_TSS, - SSH_CIPHER_RC4, - SSH_CIPHER_BLOWFISH, - SSH_CIPHER_TWIDDLE, /* for debugging */ -}; - -enum /* auth method ids */ -{ - SSH_AUTH_RHOSTS = 1, - SSH_AUTH_RSA = 2, - SSH_AUTH_PASSWORD = 3, - SSH_AUTH_RHOSTS_RSA = 4, - SSH_AUTH_TIS = 5, - SSH_AUTH_USER_RSA = 6, -}; - -typedef struct Auth Auth; -typedef struct Authsrv Authsrv; -typedef struct Cipher Cipher; -typedef struct CipherState CipherState; -typedef struct Conn Conn; -typedef struct Msg Msg; - -#pragma incomplete CipherState - -struct Auth -{ - int id; - char *name; - int (*fn)(Conn*); -}; - -struct Authsrv -{ - int id; - char *name; - int firstmsg; - AuthInfo *(*fn)(Conn*, Msg*); -}; - -struct Cipher -{ - int id; - char *name; - CipherState *(*init)(Conn*, int isserver); - void (*encrypt)(CipherState*, uchar*, int); - void (*decrypt)(CipherState*, uchar*, int); -}; - -struct Conn -{ - QLock; - int fd[2]; - CipherState *cstate; - uchar cookie[COOKIELEN]; - uchar sessid[SESSIDLEN]; - uchar sesskey[SESSKEYLEN]; - RSApub *serverkey; - RSApub *hostkey; - ulong flags; - ulong ciphermask; - Cipher *cipher; /* chosen cipher */ - Cipher **okcipher; /* list of acceptable ciphers */ - int nokcipher; - ulong authmask; - Auth **okauth; - int nokauth; - char *user; - char *host; - char *aliases; - int interactive; - Msg *unget; - - RSApriv *serverpriv; /* server only */ - RSApriv *hostpriv; - Authsrv **okauthsrv; - int nokauthsrv; -}; - -struct Msg -{ - Conn *c; - uchar type; - ulong len; /* output: #bytes before pos, input: #bytes after pos */ - uchar *bp; /* beginning of allocated space */ - uchar *rp; /* read pointer */ - uchar *wp; /* write pointer */ - uchar *ep; /* end of allocated space */ - Msg *link; /* for sshnet */ -}; - -#define LONG(p) (((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|((p)[3])) -#define PLONG(p, l) \ - (((p)[0]=(l)>>24),((p)[1]=(l)>>16),\ - ((p)[2]=(l)>>8),((p)[3]=(l))) -#define SHORT(p) (((p)[0]<<8)|(p)[1]) -#define PSHORT(p,l) \ - (((p)[0]=(l)>>8),((p)[1]=(l))) - -extern char Edecode[]; -extern char Eencode[]; -extern char Ememory[]; -extern char Ehangup[]; -extern int doabort; -extern int debuglevel; - -extern Auth authpassword; -extern Auth authrsa; -extern Auth authtis; - -extern Authsrv authsrvpassword; -extern Authsrv authsrvtis; - -extern Cipher cipher3des; -extern Cipher cipherblowfish; -extern Cipher cipherdes; -extern Cipher cipherrc4; -extern Cipher ciphernone; -extern Cipher ciphertwiddle; - -/* msg.c */ -Msg* allocmsg(Conn*, int, int); -void badmsg(Msg*, int); -Msg* recvmsg(Conn*, int); -void unrecvmsg(Conn*, Msg*); -int sendmsg(Msg*); -uchar getbyte(Msg*); -ushort getshort(Msg*); -ulong getlong(Msg*); -char* getstring(Msg*); -void* getbytes(Msg*, int); -mpint* getmpint(Msg*); -RSApub* getRSApub(Msg*); -void putbyte(Msg*, uchar); -void putshort(Msg*, ushort); -void putlong(Msg*, ulong); -void putstring(Msg*, char*); -void putbytes(Msg*, void*, long); -void putmpint(Msg*, mpint*); -void putRSApub(Msg*, RSApub*); -mpint* rsapad(mpint*, int); -mpint* rsaunpad(mpint*); -void mptoberjust(mpint*, uchar*, int); -mpint* rsaencryptbuf(RSApub*, uchar*, int); - -/* cmsg.c */ -void sshclienthandshake(Conn*); -void requestpty(Conn*); -int readgeom(int*, int*, int*, int*); -void sendwindowsize(Conn*, int, int, int, int); -int rawhack; - -/* smsg.c */ -void sshserverhandshake(Conn*); - -/* pubkey.c */ -enum -{ - KeyOk, - KeyWrong, - NoKey, - NoKeyFile, -}; -int appendkey(char*, char*, RSApub*); -int findkey(char*, char*, RSApub*); -int replacekey(char*, char*, RSApub*); - -/* agent.c */ -int startagent(Conn*); -void handleagentmsg(Msg*); -void handleagentopen(Msg*); -void handleagentieof(Msg*); -void handleagentoclose(Msg*); - -/* util.c */ -void debug(int, char*, ...); -void* emalloc(long); -void* erealloc(void*, long); -void error(char*, ...); -RSApriv* readsecretkey(char*); -int readstrnl(int, char*, int); -void atexitkill(int); -void atexitkiller(void); -void calcsessid(Conn*); -void sshlog(char*, ...); -void setaliases(Conn*, char*); -void privatefactotum(void); - -#pragma varargck argpos debug 2 -#pragma varargck argpos error 1 -#pragma varargck argpos sshlog 2 diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/sshnet.c --- a/sys/src/cmd/ssh/sshnet.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1110 +0,0 @@ -/* - * SSH network file system. - * Presents remote TCP stack as /net-style file system. - */ - -#include "ssh.h" -#include -#include -#include -#include -#include <9p.h> - -int rawhack = 1; -Conn *conn; -char *remoteip = ""; -char *mtpt; - -Cipher *allcipher[] = { - &cipherrc4, - &cipherblowfish, - &cipher3des, - &cipherdes, - &ciphernone, - &ciphertwiddle, -}; - -Auth *allauth[] = { - &authpassword, - &authrsa, - &authtis, -}; - -char *cipherlist = "rc4 3des"; -char *authlist = "rsa password tis"; - -Cipher* -findcipher(char *name, Cipher **list, int nlist) -{ - int i; - - for(i=0; iname) == 0) - return list[i]; - error("unknown cipher %s", name); - return nil; -} - -Auth* -findauth(char *name, Auth **list, int nlist) -{ - int i; - - for(i=0; iname) == 0) - return list[i]; - error("unknown auth %s", name); - return nil; -} - -void -usage(void) -{ - fprint(2, "usage: sshnet [-A authlist] [-c cipherlist] [-m mtpt] [user@]hostname\n"); - exits("usage"); -} - -int -isatty(int fd) -{ - char buf[64]; - - buf[0] = '\0'; - fd2path(fd, buf, sizeof buf); - if(strlen(buf)>=9 && strcmp(buf+strlen(buf)-9, "/dev/cons")==0) - return 1; - return 0; -} - -enum -{ - Qroot, - Qcs, - Qtcp, - Qclone, - Qn, - Qctl, - Qdata, - Qlocal, - Qremote, - Qstatus, -}; - -#define PATH(type, n) ((type)|((n)<<8)) -#define TYPE(path) ((int)(path) & 0xFF) -#define NUM(path) ((uint)(path)>>8) - -Channel *sshmsgchan; /* chan(Msg*) */ -Channel *fsreqchan; /* chan(Req*) */ -Channel *fsreqwaitchan; /* chan(nil) */ -Channel *fsclunkchan; /* chan(Fid*) */ -Channel *fsclunkwaitchan; /* chan(nil) */ -ulong time0; - -enum -{ - Closed, - Dialing, - Established, - Teardown, -}; - -char *statestr[] = { - "Closed", - "Dialing", - "Established", - "Teardown", -}; - -typedef struct Client Client; -struct Client -{ - int ref; - int state; - int num; - int servernum; - char *connect; - Req *rq; - Req **erq; - Msg *mq; - Msg **emq; -}; - -int nclient; -Client **client; - -int -newclient(void) -{ - int i; - Client *c; - - for(i=0; iref==0 && client[i]->state == Closed) - return i; - - if(nclient%16 == 0) - client = erealloc9p(client, (nclient+16)*sizeof(client[0])); - - c = emalloc9p(sizeof(Client)); - memset(c, 0, sizeof(*c)); - c->num = nclient; - client[nclient++] = c; - return c->num; -} - -void -queuereq(Client *c, Req *r) -{ - if(c->rq==nil) - c->erq = &c->rq; - *c->erq = r; - r->aux = nil; - c->erq = (Req**)&r->aux; -} - -void -queuemsg(Client *c, Msg *m) -{ - if(c->mq==nil) - c->emq = &c->mq; - *c->emq = m; - m->link = nil; - c->emq = (Msg**)&m->link; -} - -void -matchmsgs(Client *c) -{ - Req *r; - Msg *m; - int n, rm; - - while(c->rq && c->mq){ - r = c->rq; - c->rq = r->aux; - - rm = 0; - m = c->mq; - n = r->ifcall.count; - if(n >= m->ep - m->rp){ - n = m->ep - m->rp; - c->mq = m->link; - rm = 1; - } - memmove(r->ofcall.data, m->rp, n); - if(rm) - free(m); - else - m->rp += n; - r->ofcall.count = n; - respond(r, nil); - } -} - -Req* -findreq(Client *c, Req *r) -{ - Req **l; - - for(l=&c->rq; *l; l=(Req**)&(*l)->aux){ - if(*l == r){ - *l = r->aux; - if(*l == nil) - c->erq = l; - return r; - } - } - return nil; -} - -void -dialedclient(Client *c) -{ - Req *r; - - if(r=c->rq){ - if(r->aux != nil) - sysfatal("more than one outstanding dial request (BUG)"); - if(c->state == Established) - respond(r, nil); - else - respond(r, "connect failed"); - } - c->rq = nil; -} - -void -teardownclient(Client *c) -{ - Msg *m; - - c->state = Teardown; - m = allocmsg(conn, SSH_MSG_CHANNEL_INPUT_EOF, 4); - putlong(m, c->servernum); - sendmsg(m); -} - -void -hangupclient(Client *c) -{ - Req *r, *next; - Msg *m, *mnext; - - c->state = Closed; - for(m=c->mq; m; m=mnext){ - mnext = m->link; - free(m); - } - c->mq = nil; - for(r=c->rq; r; r=next){ - next = r->aux; - respond(r, "hangup on network connection"); - } - c->rq = nil; -} - -void -closeclient(Client *c) -{ - Msg *m, *next; - - if(--c->ref) - return; - - if(c->rq != nil) - sysfatal("ref count reached zero with requests pending (BUG)"); - - for(m=c->mq; m; m=next){ - next = m->link; - free(m); - } - c->mq = nil; - - if(c->state != Closed) - teardownclient(c); -} - - -void -sshreadproc(void *a) -{ - Conn *c; - Msg *m; - - c = a; - for(;;){ - m = recvmsg(c, -1); - if(m == nil) - sysfatal("eof on ssh connection"); - sendp(sshmsgchan, m); - } -} - -typedef struct Tab Tab; -struct Tab -{ - char *name; - ulong mode; -}; - -Tab tab[] = -{ - "/", DMDIR|0555, - "cs", 0666, - "tcp", DMDIR|0555, - "clone", 0666, - nil, DMDIR|0555, - "ctl", 0666, - "data", 0666, - "local", 0444, - "remote", 0444, - "status", 0444, -}; - -static void -fillstat(Dir *d, uvlong path) -{ - Tab *t; - - memset(d, 0, sizeof(*d)); - d->uid = estrdup9p("ssh"); - d->gid = estrdup9p("ssh"); - d->qid.path = path; - d->atime = d->mtime = time0; - t = &tab[TYPE(path)]; - if(t->name) - d->name = estrdup9p(t->name); - else{ - d->name = smprint("%ud", NUM(path)); - if(d->name == nil) - sysfatal("out of memory"); - } - d->qid.type = t->mode>>24; - d->mode = t->mode; -} - -static void -fsattach(Req *r) -{ - if(r->ifcall.aname && r->ifcall.aname[0]){ - respond(r, "invalid attach specifier"); - return; - } - r->fid->qid.path = PATH(Qroot, 0); - r->fid->qid.type = QTDIR; - r->fid->qid.vers = 0; - r->ofcall.qid = r->fid->qid; - respond(r, nil); -} - -static void -fsstat(Req *r) -{ - fillstat(&r->d, r->fid->qid.path); - respond(r, nil); -} - -static int -rootgen(int i, Dir *d, void*) -{ - i += Qroot+1; - if(i <= Qtcp){ - fillstat(d, i); - return 0; - } - return -1; -} - -static int -tcpgen(int i, Dir *d, void*) -{ - i += Qtcp+1; - if(i < Qn){ - fillstat(d, i); - return 0; - } - i -= Qn; - if(i < nclient){ - fillstat(d, PATH(Qn, i)); - return 0; - } - return -1; -} - -static int -clientgen(int i, Dir *d, void *aux) -{ - Client *c; - - c = aux; - i += Qn+1; - if(i <= Qstatus){ - fillstat(d, PATH(i, c->num)); - return 0; - } - return -1; -} - -static char* -fswalk1(Fid *fid, char *name, Qid *qid) -{ - int i, n; - char buf[32]; - ulong path; - - path = fid->qid.path; - if(!(fid->qid.type&QTDIR)) - return "walk in non-directory"; - - if(strcmp(name, "..") == 0){ - switch(TYPE(path)){ - case Qn: - qid->path = PATH(Qtcp, NUM(path)); - qid->type = tab[Qtcp].mode>>24; - return nil; - case Qtcp: - qid->path = PATH(Qroot, 0); - qid->type = tab[Qroot].mode>>24; - return nil; - case Qroot: - return nil; - default: - return "bug in fswalk1"; - } - } - - i = TYPE(path)+1; - for(; ipath = PATH(i, n); - qid->type = tab[i].mode>>24; - return nil; - } - break; - } - if(strcmp(name, tab[i].name) == 0){ - qid->path = PATH(i, NUM(path)); - qid->type = tab[i].mode>>24; - return nil; - } - if(tab[i].mode&DMDIR) - break; - } - return "directory entry not found"; -} - -typedef struct Cs Cs; -struct Cs -{ - char *resp; - int isnew; -}; - -static int -ndbfindport(char *p) -{ - char *s, *port; - int n; - static Ndb *db; - - if(*p == '\0') - return -1; - - n = strtol(p, &s, 0); - if(*s == '\0') - return n; - - if(db == nil){ - db = ndbopen("/lib/ndb/common"); - if(db == nil) - return -1; - } - - port = ndbgetvalue(db, nil, "tcp", p, "port", nil); - if(port == nil) - return -1; - n = atoi(port); - free(port); - - return n; -} - -static void -csread(Req *r) -{ - Cs *cs; - - cs = r->fid->aux; - if(cs->resp==nil){ - respond(r, "cs read without write"); - return; - } - if(r->ifcall.offset==0){ - if(!cs->isnew){ - r->ofcall.count = 0; - respond(r, nil); - return; - } - cs->isnew = 0; - } - readstr(r, cs->resp); - respond(r, nil); -} - -static void -cswrite(Req *r) -{ - int port, nf; - char err[ERRMAX], *f[4], *s, *ns; - Cs *cs; - - cs = r->fid->aux; - s = emalloc(r->ifcall.count+1); - memmove(s, r->ifcall.data, r->ifcall.count); - s[r->ifcall.count] = '\0'; - - nf = getfields(s, f, nelem(f), 0, "!"); - if(nf != 3){ - free(s); - respond(r, "can't translate"); - return; - } - if(strcmp(f[0], "tcp") != 0 && strcmp(f[0], "net") != 0){ - free(s); - respond(r, "unknown protocol"); - return; - } - port = ndbfindport(f[2]); - if(port <= 0){ - free(s); - respond(r, "no translation found"); - return; - } - - ns = smprint("%s/tcp/clone %s!%d", mtpt, f[1], port); - if(ns == nil){ - free(s); - rerrstr(err, sizeof err); - respond(r, err); - return; - } - free(s); - free(cs->resp); - cs->resp = ns; - cs->isnew = 1; - r->ofcall.count = r->ifcall.count; - respond(r, nil); -} - -static void -ctlread(Req *r, Client *c) -{ - char buf[32]; - - sprint(buf, "%d", c->num); - readstr(r, buf); - respond(r, nil); -} - -static void -ctlwrite(Req *r, Client *c) -{ - char *f[3], *s; - int nf; - Msg *m; - - s = emalloc(r->ifcall.count+1); - memmove(s, r->ifcall.data, r->ifcall.count); - s[r->ifcall.count] = '\0'; - - nf = tokenize(s, f, 3); - if(nf == 0){ - free(s); - respond(r, nil); - return; - } - - if(strcmp(f[0], "hangup") == 0){ - if(c->state != Established) - goto Badarg; - if(nf != 1) - goto Badarg; - queuereq(c, r); - teardownclient(c); - }else if(strcmp(f[0], "connect") == 0){ - if(c->state != Closed) - goto Badarg; - if(nf != 2) - goto Badarg; - c->connect = estrdup9p(f[1]); - nf = getfields(f[1], f, nelem(f), 0, "!"); - if(nf != 2){ - free(c->connect); - c->connect = nil; - goto Badarg; - } - c->state = Dialing; - m = allocmsg(conn, SSH_MSG_PORT_OPEN, 4+4+strlen(f[0])+4+4+strlen("localhost")); - putlong(m, c->num); - putstring(m, f[0]); - putlong(m, ndbfindport(f[1])); - putstring(m, "localhost"); - queuereq(c, r); - sendmsg(m); - }else{ - Badarg: - respond(r, "bad or inappropriate tcp control message"); - } - free(s); -} - -static void -dataread(Req *r, Client *c) -{ - if(c->state != Established){ - respond(r, "not connected"); - return; - } - queuereq(c, r); - matchmsgs(c); -} - -static void -datawrite(Req *r, Client *c) -{ - Msg *m; - - if(c->state != Established){ - respond(r, "not connected"); - return; - } - if(r->ifcall.count){ - m = allocmsg(conn, SSH_MSG_CHANNEL_DATA, 4+4+r->ifcall.count); - putlong(m, c->servernum); - putlong(m, r->ifcall.count); - putbytes(m, r->ifcall.data, r->ifcall.count); - sendmsg(m); - } - r->ofcall.count = r->ifcall.count; - respond(r, nil); -} - -static void -localread(Req *r) -{ - char buf[128]; - - snprint(buf, sizeof buf, "%s!%d\n", remoteip, 0); - readstr(r, buf); - respond(r, nil); -} - -static void -remoteread(Req *r, Client *c) -{ - char *s; - char buf[128]; - - s = c->connect; - if(s == nil) - s = "::!0"; - snprint(buf, sizeof buf, "%s\n", s); - readstr(r, buf); - respond(r, nil); -} - -static void -statusread(Req *r, Client *c) -{ - char buf[64]; - char *s; - - snprint(buf, sizeof buf, "%s!%d", remoteip, 0); - s = statestr[c->state]; - readstr(r, s); - respond(r, nil); -} - -static void -fsread(Req *r) -{ - char e[ERRMAX]; - ulong path; - - path = r->fid->qid.path; - switch(TYPE(path)){ - default: - snprint(e, sizeof e, "bug in fsread path=%lux", path); - respond(r, e); - break; - - case Qroot: - dirread9p(r, rootgen, nil); - respond(r, nil); - break; - - case Qcs: - csread(r); - break; - - case Qtcp: - dirread9p(r, tcpgen, nil); - respond(r, nil); - break; - - case Qn: - dirread9p(r, clientgen, client[NUM(path)]); - respond(r, nil); - break; - - case Qctl: - ctlread(r, client[NUM(path)]); - break; - - case Qdata: - dataread(r, client[NUM(path)]); - break; - - case Qlocal: - localread(r); - break; - - case Qremote: - remoteread(r, client[NUM(path)]); - break; - - case Qstatus: - statusread(r, client[NUM(path)]); - break; - } -} - -static void -fswrite(Req *r) -{ - ulong path; - char e[ERRMAX]; - - path = r->fid->qid.path; - switch(TYPE(path)){ - default: - snprint(e, sizeof e, "bug in fswrite path=%lux", path); - respond(r, e); - break; - - case Qcs: - cswrite(r); - break; - - case Qctl: - ctlwrite(r, client[NUM(path)]); - break; - - case Qdata: - datawrite(r, client[NUM(path)]); - break; - } -} - -static void -fsopen(Req *r) -{ - static int need[4] = { 4, 2, 6, 1 }; - ulong path; - int n; - Tab *t; - Cs *cs; - - /* - * lib9p already handles the blatantly obvious. - * we just have to enforce the permissions we have set. - */ - path = r->fid->qid.path; - t = &tab[TYPE(path)]; - n = need[r->ifcall.mode&3]; - if((n&t->mode) != n){ - respond(r, "permission denied"); - return; - } - - switch(TYPE(path)){ - case Qcs: - cs = emalloc(sizeof(Cs)); - r->fid->aux = cs; - respond(r, nil); - break; - case Qclone: - n = newclient(); - path = PATH(Qctl, n); - r->fid->qid.path = path; - r->ofcall.qid.path = path; - if(chatty9p) - fprint(2, "open clone => path=%lux\n", path); - t = &tab[Qctl]; - /* fall through */ - default: - if(t-tab >= Qn) - client[NUM(path)]->ref++; - respond(r, nil); - break; - } -} - -static void -fsflush(Req *r) -{ - int i; - - for(i=0; ioldreq)) - respond(r->oldreq, "interrupted"); - respond(r, nil); -} - -static void -handlemsg(Msg *m) -{ - int chan, n; - Client *c; - - switch(m->type){ - case SSH_MSG_DISCONNECT: - case SSH_CMSG_EXIT_CONFIRMATION: - sysfatal("disconnect"); - - case SSH_CMSG_STDIN_DATA: - case SSH_CMSG_EOF: - case SSH_CMSG_WINDOW_SIZE: - /* don't care */ - free(m); - break; - - case SSH_MSG_CHANNEL_DATA: - chan = getlong(m); - n = getlong(m); - if(m->rp+n != m->ep) - sysfatal("got bad channel data"); - if(chanstate==Established){ - queuemsg(c, m); - matchmsgs(c); - }else - free(m); - break; - - case SSH_MSG_CHANNEL_INPUT_EOF: - chan = getlong(m); - free(m); - if(chanservernum; - hangupclient(c); - m = allocmsg(conn, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4); - putlong(m, chan); - sendmsg(m); - } - break; - - case SSH_MSG_CHANNEL_OUTPUT_CLOSED: - chan = getlong(m); - if(chan=nclient || (c=client[chan])->state != Dialing){ - if(c) - fprint(2, "cstate %d\n", c->state); - sysfatal("got unexpected open confirmation for %d", chan); - } - c->servernum = getlong(m); - c->state = Established; - dialedclient(c); - free(m); - break; - - case SSH_MSG_CHANNEL_OPEN_FAILURE: - chan = getlong(m); - c = nil; - if(chan>=nclient || (c=client[chan])->state != Dialing) - sysfatal("got unexpected open failure"); - if(m->rp+4 <= m->ep) - c->servernum = getlong(m); - c->state = Closed; - dialedclient(c); - free(m); - break; - } -} - -void -fsnetproc(void*) -{ - ulong path; - Alt a[4]; - Cs *cs; - Fid *fid; - Req *r; - Msg *m; - - threadsetname("fsthread"); - - a[0].op = CHANRCV; - a[0].c = fsclunkchan; - a[0].v = &fid; - a[1].op = CHANRCV; - a[1].c = fsreqchan; - a[1].v = &r; - a[2].op = CHANRCV; - a[2].c = sshmsgchan; - a[2].v = &m; - a[3].op = CHANEND; - - for(;;){ - switch(alt(a)){ - case 0: - path = fid->qid.path; - switch(TYPE(path)){ - case Qcs: - cs = fid->aux; - if(cs){ - free(cs->resp); - free(cs); - } - break; - } - if(fid->omode != -1 && TYPE(path) >= Qn) - closeclient(client[NUM(path)]); - sendp(fsclunkwaitchan, nil); - break; - case 1: - switch(r->ifcall.type){ - case Tattach: - fsattach(r); - break; - case Topen: - fsopen(r); - break; - case Tread: - fsread(r); - break; - case Twrite: - fswrite(r); - break; - case Tstat: - fsstat(r); - break; - case Tflush: - fsflush(r); - break; - default: - respond(r, "bug in fsthread"); - break; - } - sendp(fsreqwaitchan, 0); - break; - case 2: - handlemsg(m); - break; - } - } -} - -static void -fssend(Req *r) -{ - sendp(fsreqchan, r); - recvp(fsreqwaitchan); /* avoids need to deal with spurious flushes */ -} - -static void -fsdestroyfid(Fid *fid) -{ - sendp(fsclunkchan, fid); - recvp(fsclunkwaitchan); -} - -void -takedown(Srv*) -{ - threadexitsall("done"); -} - -Srv fs = -{ -.attach= fssend, -.destroyfid= fsdestroyfid, -.walk1= fswalk1, -.open= fssend, -.read= fssend, -.write= fssend, -.stat= fssend, -.flush= fssend, -.end= takedown, -}; - -void -threadmain(int argc, char **argv) -{ - int i, fd; - char *host, *user, *p, *service; - char *f[16]; - Msg *m; - static Conn c; - - fmtinstall('B', mpfmt); - fmtinstall('H', encodefmt); - - mtpt = "/net"; - service = nil; - user = nil; - ARGBEGIN{ - case 'B': /* undocumented, debugging */ - doabort = 1; - break; - case 'D': /* undocumented, debugging */ - debuglevel = strtol(EARGF(usage()), nil, 0); - break; - case '9': /* undocumented, debugging */ - chatty9p++; - break; - - case 'A': - authlist = EARGF(usage()); - break; - case 'c': - cipherlist = EARGF(usage()); - break; - case 'm': - mtpt = EARGF(usage()); - break; - case 's': - service = EARGF(usage()); - break; - default: - usage(); - }ARGEND - - if(argc != 1) - usage(); - - host = argv[0]; - - if((p = strchr(host, '@')) != nil){ - *p++ = '\0'; - user = host; - host = p; - } - if(user == nil) - user = getenv("user"); - if(user == nil) - sysfatal("cannot find user name"); - - privatefactotum(); - - if((fd = dial(netmkaddr(host, "tcp", "ssh"), nil, nil, nil)) < 0) - sysfatal("dialing %s: %r", host); - - c.interactive = isatty(0); - c.fd[0] = c.fd[1] = fd; - c.user = user; - c.host = host; - setaliases(&c, host); - - c.nokcipher = getfields(cipherlist, f, nelem(f), 1, ", "); - c.okcipher = emalloc(sizeof(Cipher*)*c.nokcipher); - for(i=0; iname) == 0) - return list[i]; - error("unknown cipher %s", name); - return nil; -} - -Authsrv* -findauthsrv(char *name, Authsrv **list, int nlist) -{ - int i; - - for(i=0; iname) == 0) - return list[i]; - error("unknown authsrv %s", name); - return nil; -} - -void -usage(void) -{ - fprint(2, "usage: sshserve [-A authlist] [-c cipherlist] client-ip-address\n"); - exits("usage"); -} - -void -main(int argc, char **argv) -{ - char *f[16]; - int i; - Conn c; - - fmtinstall('B', mpfmt); - fmtinstall('H', encodefmt); - atexit(atexitkiller); - atexitkill(getpid()); - - memset(&c, 0, sizeof c); - - ARGBEGIN{ - case 'D': - debuglevel = atoi(EARGF(usage())); - break; - case 'A': - authlist = EARGF(usage()); - break; - case 'c': - cipherlist = EARGF(usage()); - break; - default: - usage(); - }ARGEND - - if(argc != 1) - usage(); - c.host = argv[0]; - - sshlog("connect from %s", c.host); - - /* limit of 768 bits in remote host key? */ - c.serverpriv = rsagen(768, 6, 0); - if(c.serverpriv == nil) - sysfatal("rsagen failed: %r"); - c.serverkey = &c.serverpriv->pub; - - c.nokcipher = getfields(cipherlist, f, nelem(f), 1, ", "); - c.okcipher = emalloc(sizeof(Cipher*)*c.nokcipher); - for(i=0; itype){ - default: - //badmsg(m, 0); - sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0)); - break; - - case SSH_MSG_DISCONNECT: - sysfatal("client disconnected"); - - case SSH_CMSG_REQUEST_PTY: - sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0)); - break; - - case SSH_CMSG_X11_REQUEST_FORWARDING: - sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0)); - break; - - case SSH_CMSG_MAX_PACKET_SIZE: - maxmsg = getlong(m); - sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0)); - break; - - case SSH_CMSG_REQUEST_COMPRESSION: - sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0)); - break; - - case SSH_CMSG_EXEC_SHELL: - startcmd(c, nil, &kidpid, &infd); - goto InteractiveMode; - - case SSH_CMSG_EXEC_CMD: - cmd = getstring(m); - startcmd(c, cmd, &kidpid, &infd); - goto InteractiveMode; - } - free(m); - } - -InteractiveMode: - for(;;){ - free(m); - m = recvmsg(c, -1); - if(m == nil) - exits(nil); - switch(m->type){ - default: - badmsg(m, 0); - - case SSH_MSG_DISCONNECT: - postnote(PNGROUP, kidpid, "hangup"); - sysfatal("client disconnected"); - - case SSH_CMSG_STDIN_DATA: - if(infd != 0){ - n = getlong(m); - write(infd, getbytes(m, n), n); - } - break; - - case SSH_CMSG_EOF: - close(infd); - infd = -1; - break; - - case SSH_CMSG_EXIT_CONFIRMATION: - /* sent by some clients as dying breath */ - exits(nil); - - case SSH_CMSG_WINDOW_SIZE: - /* we don't care */ - break; - } - } -} - -void -copyout(Conn *c, int fd, int mtype) -{ - char buf[8192]; - int n, max, pid; - Msg *m; - - max = sizeof buf; - if(max > maxmsg - 32) /* 32 is an overestimate of packet overhead */ - max = maxmsg - 32; - if(max <= 0) - sysfatal("maximum message size too small"); - - switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ - case -1: - sysfatal("fork: %r"); - case 0: - break; - default: - atexitkill(pid); - return; - } - - while((n = read(fd, buf, max)) > 0){ - m = allocmsg(c, mtype, 4+n); - putlong(m, n); - putbytes(m, buf, n); - sendmsg(m); - } - exits(nil); -} - -void -startcmd(Conn *c, char *cmd, int *kidpid, int *kidin) -{ - int i, pid, kpid; - int pfd[3][2]; - char *dir; - char *sysname, *tz; - Msg *m; - Waitmsg *w; - - for(i=0; i<3; i++) - if(pipe(pfd[i]) < 0) - sysfatal("pipe: %r"); - - sysname = getenv("sysname"); - tz = getenv("timezone"); - - switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ - case -1: - sysfatal("fork: %r"); - case 0: - switch(kpid = rfork(RFPROC|RFNOTEG|RFENVG|RFFDG)){ - case -1: - sysfatal("fork: %r"); - case 0: - for(i=0; i<3; i++){ - if(dup(pfd[i][1], i) < 0) - sysfatal("dup: %r"); - close(pfd[i][0]); - close(pfd[i][1]); - } - putenv("user", c->user); - if(sysname) - putenv("sysname", sysname); - if(tz) - putenv("tz", tz); - - dir = smprint("/usr/%s", c->user); - if(dir == nil || chdir(dir) < 0) - chdir("/"); - if(cmd){ - putenv("service", "rx"); - execl("/bin/rc", "rc", "-lc", cmd, nil); - sysfatal("cannot exec /bin/rc: %r"); - }else{ - putenv("service", "con"); - execl("/bin/ip/telnetd", "telnetd", "-tn", nil); - sysfatal("cannot exec /bin/ip/telnetd: %r"); - } - default: - *kidpid = kpid; - rendezvous(kidpid, 0); - for(;;){ - if((w = wait()) == nil) - sysfatal("wait: %r"); - if(w->pid == kpid) - break; - free(w); - } - if(w->msg[0]){ - m = allocmsg(c, SSH_MSG_DISCONNECT, 4+strlen(w->msg)); - putstring(m, w->msg); - sendmsg(m); - }else{ - m = allocmsg(c, SSH_SMSG_EXITSTATUS, 4); - putlong(m, 0); - sendmsg(m); - } - for(i=0; i<3; i++) - close(pfd[i][0]); - free(w); - exits(nil); - break; - } - default: - atexitkill(pid); - rendezvous(kidpid, 0); - break; - } - - for(i=0; i<3; i++) - close(pfd[i][1]); - - copyout(c, pfd[1][0], SSH_SMSG_STDOUT_DATA); - copyout(c, pfd[2][0], SSH_SMSG_STDERR_DATA); - *kidin = pfd[0][0]; -} diff -r 4b6ef67cbbca -r ff808386c75d sys/src/cmd/ssh/util.c --- a/sys/src/cmd/ssh/util.c Mon Sep 12 19:04:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,269 +0,0 @@ -#include "ssh.h" -#include -#include - -char Edecode[] = "error decoding input packet"; -char Eencode[] = "out of space encoding output packet (BUG)"; -char Ehangup[] = "hungup connection"; -char Ememory[] = "out of memory"; - -int debuglevel; -int doabort; - -void -error(char *fmt, ...) -{ - va_list arg; - char buf[2048]; - - va_start(arg, fmt); - vseprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - fprint(2, "%s: %s\n", argv0, buf); - if(doabort) - abort(); - exits(buf); -} - -void -debug(int level, char *fmt, ...) -{ - va_list arg; - - if((level&debuglevel) == 0) - return; - va_start(arg, fmt); - vfprint(2, fmt, arg); - va_end(arg); -} - -void* -emalloc(long n) -{ - void *a; - - a = mallocz(n, 1); - if(a == nil) - error(Ememory); - setmalloctag(a, getcallerpc(&n)); - return a; -} - -void* -erealloc(void *v, long n) -{ - v = realloc(v, n); - if(v == nil) - error(Ememory); - setrealloctag(v, getcallerpc(&v)); - return v; -} - - -static int killpid[32]; -static int nkillpid; -void -atexitkiller(void) -{ - int i, pid; - - pid = getpid(); - debug(DBG, "atexitkiller: nkillpid=%d mypid=%d\n", nkillpid, pid); - for(i=0; ihostkey->n, buf, sizeof buf, nil); - n += mptobe(c->serverkey->n, buf+n, sizeof buf-n, nil); - memmove(buf+n, c->cookie, COOKIELEN); - n += COOKIELEN; - md5(buf, n, c->sessid, nil); -} - -void -sshlog(char *f, ...) -{ - char *s; - va_list arg; - Fmt fmt; - static int pid; - - if(pid == 0) - pid = getpid(); - - va_start(arg, f); - va_end(arg); - - if(fmtstrinit(&fmt) < 0) - sysfatal("fmtstrinit: %r"); - - fmtprint(&fmt, "[%d] ", pid); - fmtvprint(&fmt, f, arg); - - s = fmtstrflush(&fmt); - if(s == nil) - sysfatal("fmtstrflush: %r"); - syslog(0, "ssh", "%s", s); - free(s); -} - -/* - * this is far too smart. - */ -static int -pstrcmp(const void *a, const void *b) -{ - return strcmp(*(char**)a, *(char**)b); -} - -static char* -trim(char *s) -{ - char *t; - int i, last, n, nf; - char **f; - char *p; - - t = emalloc(strlen(s)+1); - t[0] = '\0'; - n = 1; - for(p=s; *p; p++) - if(*p == ' ') - n++; - f = emalloc((n+1)*sizeof(f[0])); - nf = tokenize(s, f, n+1); - qsort(f, nf, sizeof(f[0]), pstrcmp); - last=-1; - for(i=0; i= 0) - strcat(t, ","); - strcat(t, f[i]); - last = i; - } - } - return t; -} - -static void -usetuple(Conn *c, Ndbtuple *t, int scanentries) -{ - int first; - Ndbtuple *l, *e; - char *s; - - first=1; - s = c->host; - for(l=t; first||l!=t; l=l->line, first=0){ - if(scanentries){ - for(e=l; e; e=e->entry){ - if(strcmp(e->val, c->host) != 0 && - (strcmp(e->attr, "ip")==0 || strcmp(e->attr, "dom")==0 || strcmp(e->attr, "sys")==0)){ - s = smprint("%s %s", s, e->val); - if(s == nil) - error("out of memory"); - } - } - } - if(strcmp(l->val, c->host) != 0 && - (strcmp(l->attr, "ip")==0 || strcmp(l->attr, "dom")==0 || strcmp(l->attr, "sys")==0)){ - s = smprint("%s %s", s, l->val); - if(s == nil) - error("out of memory"); - } - } - s = trim(s); - c->aliases = s; -} - -void -setaliases(Conn *c, char *name) -{ - char *p, *net; - char *attr[2]; - Ndbtuple *t; - - net = "/net"; - if(name[0]=='/'){ - p = strchr(name+1, '/'); - if(p){ - net = emalloc(p-name+1); - memmove(net, name, p-name); - } - } - if(p = strchr(name, '!')) - name = p+1; - - c->host = emalloc(strlen(name)+1); - strcpy(c->host, name); - - c->aliases = c->host; - attr[0] = "dom"; - attr[1] = "ip"; - t = csipinfo(nil, ipattr(name), name, attr, 2); - if(t != nil){ - usetuple(c, t, 0); - ndbfree(t); - }else{ - t = dnsquery(net, name, "ip"); - if(t != nil){ - usetuple(c, t, 1); - ndbfree(t); - } - } -} - -void -privatefactotum(void) -{ - char *user; - Dir *d; - - if((user=getuser()) && (d=dirstat("/mnt/factotum/rpc")) && strcmp(user, d->uid)!=0){ - /* grab the terminal's factotum */ - rfork(RFNAMEG); /* was RFNOTEG, which makes little sense */ - if(access("/mnt/term/mnt/factotum", AEXIST) >= 0){ -// fprint(2, "binding terminal's factotum\n"); - if(bind("/mnt/term/mnt/factotum", "/mnt/factotum", MREPL) < 0) - sysfatal("cannot find factotum"); - } - } -}