/* * Present factotum in ssh agent clothing. */#include <u.h>#include <libc.h>#include <mp.h>#include <libsec.h>#include <auth.h>#include <thread.h>#include <9pclient.h> enum{ STACK = 65536};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, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES, SSH2_AGENTC_REQUEST_IDENTITIES = 11, SSH2_AGENT_IDENTITIES_ANSWER, SSH2_AGENTC_SIGN_REQUEST, SSH2_AGENT_SIGN_RESPONSE, SSH2_AGENTC_ADD_IDENTITY = 17, SSH2_AGENTC_REMOVE_IDENTITY, SSH2_AGENTC_REMOVE_ALL_IDENTITIES, SSH2_AGENTC_ADD_SMARTCARD_KEY, SSH2_AGENTC_REMOVE_SMARTCARD_KEY, SSH_AGENTC_LOCK, SSH_AGENTC_UNLOCK, SSH_AGENTC_ADD_RSA_ID_CONSTRAINED, SSH2_AGENTC_ADD_ID_CONSTRAINED, SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED, SSH_AGENT_CONSTRAIN_LIFETIME = 1, SSH_AGENT_CONSTRAIN_CONFIRM = 2, SSH2_AGENT_FAILURE = 30, SSH_COM_AGENT2_FAILURE = 102, SSH_AGENT_OLD_SIGNATURE = 0x01}; typedef struct Aconn Aconn;struct Aconn{ uchar *data; uint ndata; int ctl; int fd; char dir[40];}; typedef struct Msg Msg;struct Msg{ uchar *bp; uchar *p; uchar *ep; int bpalloc;}; char adir[40];int afd;int chatty;char *factotum = "factotum"; void agentproc(void *v);void* emalloc(int n);void* erealloc(void *v, int n);void listenproc(void *v);int runmsg(Aconn *a);void listkeystext(void); voidusage(void){ fprint(2, "usage: 9 ssh-agent [-D] [factotum]\n"); threadexitsall("usage");} voidthreadmain(int argc, char **argv){ int fd, pid, export, dotextlist; char dir[100], *ns; char sock[200], addr[200]; uvlong x; export = 0; dotextlist = 0; pid = getpid(); fmtinstall('B', mpfmt); fmtinstall('H', encodefmt); fmtinstall('[', encodefmt); ARGBEGIN{ case '9': chatty9pclient++; break; case 'D': chatty++; break; case 'e': export = 1; break; case 'l': dotextlist = 1; break; default: usage(); }ARGEND if(argc > 1) usage(); if(argc == 1) factotum = argv[0]; if(dotextlist) listkeystext(); ns = getns(); snprint(sock, sizeof sock, "%s/ssh-agent.socket", ns); if(0){ x = ((uvlong)fastrand()<<32) | fastrand(); x ^= ((uvlong)fastrand()<<32) | fastrand(); snprint(dir, sizeof dir, "/tmp/ssh-%llux", x); if((fd = create(dir, OREAD, DMDIR|0700)) < 0) sysfatal("mkdir %s: %r", dir); close(fd); snprint(sock, sizeof sock, "%s/agent.%d", dir, pid); } snprint(addr, sizeof addr, "unix!%s", sock); if((afd = announce(addr, adir)) < 0) sysfatal("announce %s: %r", addr); print("SSH_AUTH_SOCK=%s;\n", sock); if(export) print("export SSH_AUTH_SOCK;\n"); print("SSH_AGENT_PID=%d;\n", pid); if(export) print("export SSH_AGENT_PID;\n"); close(1); rfork(RFNOTEG); proccreate(listenproc, nil, STACK); threadexits(0);} voidlistenproc(void *v){ Aconn *a; USED(v); for(;;){ a = emalloc(sizeof *a); a->ctl = listen(adir, a->dir); if(a->ctl < 0) sysfatal("listen: %r"); proccreate(agentproc, a, STACK); }} voidagentproc(void *v){ Aconn *a; int n; a = v; a->fd = accept(a->ctl, a->dir); close(a->ctl); a->ctl = -1; for(;;){ a->data = erealloc(a->data, a->ndata+1024); n = read(a->fd, a->data+a->ndata, 1024); if(n <= 0) break; a->ndata += n; while(runmsg(a)) ; } close(a->fd); free(a); threadexits(nil);} intget1(Msg *m){ if(m->p >= m->ep) return 0; return *m->p++;} intget2(Msg *m){ uint x; if(m->p+2 > m->ep) return 0; x = (m->p[0]<<8)|m->p[1]; m->p += 2; return x;} intget4(Msg *m){ uint x; if(m->p+4 > m->ep) return 0; x = (m->p[0]<<24)|(m->p[1]<<16)|(m->p[2]<<8)|m->p[3]; m->p += 4; return x;} uchar*getn(Msg *m, uint n){ uchar *p; if(m->p+n > m->ep) return nil; p = m->p; m->p += n; return p;} char*getstr(Msg *m){ uint n; uchar *p; n = get4(m); p = getn(m, n); if(p == nil) return nil; p--; memmove(p, p+1, n); p[n] = 0; return (char*)p;} mpint*getmp(Msg *m){ int n; uchar *p; n = (get2(m)+7)/8; if((p=getn(m, n)) == nil) return nil; return betomp(p, n, nil);} mpint*getmp2(Msg *m){ int n; uchar *p; n = get4(m); if((p = getn(m, n)) == nil) return nil; return betomp(p, n, nil);} voidnewmsg(Msg *m){ memset(m, 0, sizeof *m);} voidmreset(Msg *m){ if(m->bpalloc){ memset(m->bp, 0, m->ep-m->bp); free(m->bp); } memset(m, 0, sizeof *m);} Msg*getm(Msg *m, Msg *mm){ uint n; uchar *p; n = get4(m); if((p = getn(m, n)) == nil) return nil; mm->bp = p; mm->p = p; mm->ep = p+n; mm->bpalloc = 0; return mm;} uchar*ensure(Msg *m, int n){ int len; uchar *p; uchar *obp; if(m->bp == nil) m->bpalloc = 1; if(!m->bpalloc){ p = emalloc(m->ep - m->bp); memmove(p, m->bp, m->ep - m->bp); obp = m->bp; m->bp = p; m->ep += m->bp - obp; m->p += m->bp - obp; m->bpalloc = 1; } len = m->ep - m->bp; if(m->p+n > m->ep){ obp = m->bp; m->bp = erealloc(m->bp, len+n+1024); m->p += m->bp - obp; m->ep += m->bp - obp; m->ep += n+1024; } p = m->p; m->p += n; return p;} voidput4(Msg *m, uint n){ uchar *p; p = ensure(m, 4); p[0] = (n>>24)&0xFF; p[1] = (n>>16)&0xFF; p[2] = (n>>8)&0xFF; p[3] = n&0xFF;} voidput2(Msg *m, uint n){ uchar *p; p = ensure(m, 2); p[0] = (n>>8)&0xFF; p[1] = n&0xFF;} voidput1(Msg *m, uint n){ uchar *p; p = ensure(m, 1); p[0] = n&0xFF;} voidputn(Msg *m, void *a, uint n){ uchar *p; p = ensure(m, n); memmove(p, a, n);} voidputmp(Msg *m, mpint *b){ int bits, n; uchar *p; bits = mpsignif(b); put2(m, bits); n = (bits+7)/8; p = ensure(m, n); mptobe(b, p, n, nil);} voidputmp2(Msg *m, mpint *b){ int bits, n; uchar *p; if(mpcmp(b, mpzero) == 0){ put4(m, 0); return; } bits = mpsignif(b); n = (bits+7)/8; if(bits%8 == 0){ put4(m, n+1); put1(m, 0); }else put4(m, n); p = ensure(m, n); mptobe(b, p, n, nil);} voidputstr(Msg *m, char *s){ int n; n = strlen(s); put4(m, n); putn(m, s, n);} voidputm(Msg *m, Msg *mm){ uint n; n = mm->p - mm->bp; put4(m, n); putn(m, mm->bp, n);} voidnewreply(Msg *m, int type){ memset(m, 0, sizeof *m); put4(m, 0); put1(m, type);} voidreply(Aconn *a, Msg *m){ uint n; uchar *p; n = (m->p - m->bp) - 4; p = m->bp; p[0] = (n>>24)&0xFF; p[1] = (n>>16)&0xFF; p[2] = (n>>8)&0xFF; p[3] = n&0xFF; if(chatty) fprint(2, "respond %d t=%d: %.*H\n", n, p[4], n, m->bp+4); write(a->fd, p, n+4); mreset(m);} typedef struct Key Key;struct Key{ mpint *mod; mpint *ek; char *comment;}; static char*find(char **f, int nf, char *k){ int i, len; len = strlen(k); for(i=1; i<nf; i++) /* i=1: f[0] is "key" */ if(strncmp(f[i], k, len) == 0 && f[i][len] == '=') return f[i]+len+1; return nil;} static intputrsa1(Msg *m, char **f, int nf){ char *p; mpint *mod, *ek; p = find(f, nf, "n"); if(p == nil || (mod = strtomp(p, nil, 16, nil)) == nil) return -1; p = find(f, nf, "ek"); if(p == nil || (ek = strtomp(p, nil, 16, nil)) == nil){ mpfree(mod); return -1; } p = find(f, nf, "comment");Lines 1–500 of 1066. Load more
/* * Present factotum in ssh agent clothing. */ #include <u.h> #include <libc.h> #include <mp.h> #include <libsec.h> #include <auth.h> #include <thread.h> #include <9pclient.h> enum { STACK = 65536 }; 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, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES, SSH2_AGENTC_REQUEST_IDENTITIES = 11, SSH2_AGENT_IDENTITIES_ANSWER, SSH2_AGENTC_SIGN_REQUEST, SSH2_AGENT_SIGN_RESPONSE, SSH2_AGENTC_ADD_IDENTITY = 17, SSH2_AGENTC_REMOVE_IDENTITY, SSH2_AGENTC_REMOVE_ALL_IDENTITIES, SSH2_AGENTC_ADD_SMARTCARD_KEY, SSH2_AGENTC_REMOVE_SMARTCARD_KEY, SSH_AGENTC_LOCK, SSH_AGENTC_UNLOCK, SSH_AGENTC_ADD_RSA_ID_CONSTRAINED, SSH2_AGENTC_ADD_ID_CONSTRAINED, SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED, SSH_AGENT_CONSTRAIN_LIFETIME = 1, SSH_AGENT_CONSTRAIN_CONFIRM = 2, SSH2_AGENT_FAILURE = 30, SSH_COM_AGENT2_FAILURE = 102, SSH_AGENT_OLD_SIGNATURE = 0x01 }; typedef struct Aconn Aconn; struct Aconn { uchar *data; uint ndata; int ctl; int fd; char dir[40]; }; typedef struct Msg Msg; struct Msg { uchar *bp; uchar *p; uchar *ep; int bpalloc; }; char adir[40]; int afd; int chatty; char *factotum = "factotum"; void agentproc(void *v); void* emalloc(int n); void* erealloc(void *v, int n); void listenproc(void *v); int runmsg(Aconn *a); void listkeystext(void); void usage(void) { fprint(2, "usage: 9 ssh-agent [-D] [factotum]\n"); threadexitsall("usage"); } void threadmain(int argc, char **argv) { int fd, pid, export, dotextlist; char dir[100], *ns; char sock[200], addr[200]; uvlong x; export = 0; dotextlist = 0; pid = getpid(); fmtinstall('B', mpfmt); fmtinstall('H', encodefmt); fmtinstall('[', encodefmt); ARGBEGIN{ case '9': chatty9pclient++; break; case 'D': chatty++; break; case 'e': export = 1; break; case 'l': dotextlist = 1; break; default: usage(); }ARGEND if(argc > 1) usage(); if(argc == 1) factotum = argv[0]; if(dotextlist) listkeystext(); ns = getns(); snprint(sock, sizeof sock, "%s/ssh-agent.socket", ns); if(0){ x = ((uvlong)fastrand()<<32) | fastrand(); x ^= ((uvlong)fastrand()<<32) | fastrand(); snprint(dir, sizeof dir, "/tmp/ssh-%llux", x); if((fd = create(dir, OREAD, DMDIR|0700)) < 0) sysfatal("mkdir %s: %r", dir); close(fd); snprint(sock, sizeof sock, "%s/agent.%d", dir, pid); } snprint(addr, sizeof addr, "unix!%s", sock); if((afd = announce(addr, adir)) < 0) sysfatal("announce %s: %r", addr); print("SSH_AUTH_SOCK=%s;\n", sock); if(export) print("export SSH_AUTH_SOCK;\n"); print("SSH_AGENT_PID=%d;\n", pid); if(export) print("export SSH_AGENT_PID;\n"); close(1); rfork(RFNOTEG); proccreate(listenproc, nil, STACK); threadexits(0); } void listenproc(void *v) { Aconn *a; USED(v); for(;;){ a = emalloc(sizeof *a); a->ctl = listen(adir, a->dir); if(a->ctl < 0) sysfatal("listen: %r"); proccreate(agentproc, a, STACK); } } void agentproc(void *v) { Aconn *a; int n; a = v; a->fd = accept(a->ctl, a->dir); close(a->ctl); a->ctl = -1; for(;;){ a->data = erealloc(a->data, a->ndata+1024); n = read(a->fd, a->data+a->ndata, 1024); if(n <= 0) break; a->ndata += n; while(runmsg(a)) ; } close(a->fd); free(a); threadexits(nil); } int get1(Msg *m) { if(m->p >= m->ep) return 0; return *m->p++; } int get2(Msg *m) { uint x; if(m->p+2 > m->ep) return 0; x = (m->p[0]<<8)|m->p[1]; m->p += 2; return x; } int get4(Msg *m) { uint x; if(m->p+4 > m->ep) return 0; x = (m->p[0]<<24)|(m->p[1]<<16)|(m->p[2]<<8)|m->p[3]; m->p += 4; return x; } uchar* getn(Msg *m, uint n) { uchar *p; if(m->p+n > m->ep) return nil; p = m->p; m->p += n; return p; } char* getstr(Msg *m) { uint n; uchar *p; n = get4(m); p = getn(m, n); if(p == nil) return nil; p--; memmove(p, p+1, n); p[n] = 0; return (char*)p; } mpint* getmp(Msg *m) { int n; uchar *p; n = (get2(m)+7)/8; if((p=getn(m, n)) == nil) return nil; return betomp(p, n, nil); } mpint* getmp2(Msg *m) { int n; uchar *p; n = get4(m); if((p = getn(m, n)) == nil) return nil; return betomp(p, n, nil); } void newmsg(Msg *m) { memset(m, 0, sizeof *m); } void mreset(Msg *m) { if(m->bpalloc){ memset(m->bp, 0, m->ep-m->bp); free(m->bp); } memset(m, 0, sizeof *m); } Msg* getm(Msg *m, Msg *mm) { uint n; uchar *p; n = get4(m); if((p = getn(m, n)) == nil) return nil; mm->bp = p; mm->p = p; mm->ep = p+n; mm->bpalloc = 0; return mm; } uchar* ensure(Msg *m, int n) { int len; uchar *p; uchar *obp; if(m->bp == nil) m->bpalloc = 1; if(!m->bpalloc){ p = emalloc(m->ep - m->bp); memmove(p, m->bp, m->ep - m->bp); obp = m->bp; m->bp = p; m->ep += m->bp - obp; m->p += m->bp - obp; m->bpalloc = 1; } len = m->ep - m->bp; if(m->p+n > m->ep){ obp = m->bp; m->bp = erealloc(m->bp, len+n+1024); m->p += m->bp - obp; m->ep += m->bp - obp; m->ep += n+1024; } p = m->p; m->p += n; return p; } void put4(Msg *m, uint n) { uchar *p; p = ensure(m, 4); p[0] = (n>>24)&0xFF; p[1] = (n>>16)&0xFF; p[2] = (n>>8)&0xFF; p[3] = n&0xFF; } void put2(Msg *m, uint n) { uchar *p; p = ensure(m, 2); p[0] = (n>>8)&0xFF; p[1] = n&0xFF; } void put1(Msg *m, uint n) { uchar *p; p = ensure(m, 1); p[0] = n&0xFF; } void putn(Msg *m, void *a, uint n) { uchar *p; p = ensure(m, n); memmove(p, a, n); } void putmp(Msg *m, mpint *b) { int bits, n; uchar *p; bits = mpsignif(b); put2(m, bits); n = (bits+7)/8; p = ensure(m, n); mptobe(b, p, n, nil); } void putmp2(Msg *m, mpint *b) { int bits, n; uchar *p; if(mpcmp(b, mpzero) == 0){ put4(m, 0); return; } bits = mpsignif(b); n = (bits+7)/8; if(bits%8 == 0){ put4(m, n+1); put1(m, 0); }else put4(m, n); p = ensure(m, n); mptobe(b, p, n, nil); } void putstr(Msg *m, char *s) { int n; n = strlen(s); put4(m, n); putn(m, s, n); } void putm(Msg *m, Msg *mm) { uint n; n = mm->p - mm->bp; put4(m, n); putn(m, mm->bp, n); } void newreply(Msg *m, int type) { memset(m, 0, sizeof *m); put4(m, 0); put1(m, type); } void reply(Aconn *a, Msg *m) { uint n; uchar *p; n = (m->p - m->bp) - 4; p = m->bp; p[0] = (n>>24)&0xFF; p[1] = (n>>16)&0xFF; p[2] = (n>>8)&0xFF; p[3] = n&0xFF; if(chatty) fprint(2, "respond %d t=%d: %.*H\n", n, p[4], n, m->bp+4); write(a->fd, p, n+4); mreset(m); } typedef struct Key Key; struct Key { mpint *mod; mpint *ek; char *comment; }; static char* find(char **f, int nf, char *k) { int i, len; len = strlen(k); for(i=1; i<nf; i++) /* i=1: f[0] is "key" */ if(strncmp(f[i], k, len) == 0 && f[i][len] == '=') return f[i]+len+1; return nil; } static int putrsa1(Msg *m, char **f, int nf) { char *p; mpint *mod, *ek; p = find(f, nf, "n"); if(p == nil || (mod = strtomp(p, nil, 16, nil)) == nil) return -1; p = find(f, nf, "ek"); if(p == nil || (ek = strtomp(p, nil, 16, nil)) == nil){ mpfree(mod); return -1; } p = find(f, nf, "comment");