⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 agent.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "ssh.h"#include <bio.h>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; 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 intlistkeys(Key **kp){	Biobuf *b;	Key *k;	int nk;	char *p, *f[20];	int nf;	mpint *mod, *ek;		*kp = nil;	if((b = Bopen("/mnt/factotum/ctl", OREAD)) == nil)		return -1;		k = nil;	nk = 0;	while((p = Brdline(b, '\n')) != nil){		p[Blinelen(b)-1] = '\0';		nf = tokenize(p, f, nelem(f));		if(nf == 0 || strcmp(f[0], "key") != 0)			continue;		p = find(f, nf, "proto");		if(p == nil || strcmp(p, "rsa") != 0)			continue;		p = find(f, nf, "n");		if(p == nil || (mod = strtomp(p, nil, 16, nil)) == nil)			continue;		p = find(f, nf, "ek");		if(p == nil || (ek = strtomp(p, nil, 16, nil)) == nil){			mpfree(mod);			continue;		}		p = find(f, nf, "comment");		if(p == nil)			p = "";		k = erealloc(k, (nk+1)*sizeof(k[0]));		k[nk].mod = mod;		k[nk].ek = ek;		k[nk].comment = emalloc(strlen(p)+1);		strcpy(k[nk].comment, p);		nk++;	}	Bterm(b);	*kp = k;	return nk;	}static intdorsa(mpint *mod, mpint *exp, mpint *chal, uchar chalbuf[32]){	int afd;	AuthRpc *rpc;	mpint *m;	char buf[4096], *p;	mpint *decr, *unpad;	USED(exp);	snprint(buf, sizeof buf, "proto=rsa service=ssh role=client");	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;	}	if(auth_rpc(rpc, "start", buf, strlen(buf)) != ARok){		debug(DBG_AUTH, "auth_rpc start failed: %r\n");	Die:		auth_freerpc(rpc);		close(afd);		return -1;	}	m = nil;	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);		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;}intstartagent(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*);voidhandleagentmsg(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", 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;		}	}}voidhandlefullmsg(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; i<nk; i++){			len += 4;			len += 2+(mpsignif(k[i].ek)+7)/8;			len += 2+(mpsignif(k[i].mod)+7)/8;			len += 4+strlen(k[i].comment);		}		r = allocmsg(m->c, 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; i<nk; i++){			debug(DBG_AUTH, "\t%B %B %s\n", k[i].ek, k[i].mod, k[i].comment);			putlong(r, mpsignif(k[i].mod));			putmpint(r, k[i].ek);			putmpint(r, k[i].mod);			putstring(r, k[i].comment);			mpfree(k[i].ek);			mpfree(k[i].mod);			free(k[i].comment);		}		free(k);		sendmsg(r);		break;	case SSH_AGENTC_RSA_CHALLENGE:		n = getlong(m);		USED(n);	/* number of bits in key; who cares? */		ek = getmpint(m);		mod = getmpint(m);		chal = getmpint(m);		memmove(sessid, getbytes(m, 16), 16);		rt = getlong(m);		debug(DBG_AUTH, "agent challenge %B %B %B %ud (%p %p)\n",			ek, mod, chal, rt, m->rp, 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;*/	}}voidhandleagentopen(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; i<nelem(achan); i++)		if(achan[i].open == 0 && achan[i].needeof == 0 && achan[i].needclosed == 0)			break;	if(i == nelem(achan)){		m = allocmsg(m->c, 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);}voidhandleagentieof(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);		}	}}voidhandleagentoclose(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);		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -