1066 lines · 17.9 KB · C
RawDownload
/* * 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.