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

📄 devtls.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 3 页
字号:
static longtlswrite(Chan *c, void *a, long n, vlong off){	Encalg *ea;	Hashalg *ha;	TlsRec *volatile tr;	Secret *volatile tos, *volatile toc;	Block *volatile b;	Cmdbuf *volatile cb;	int m, ty;	char *p, *e;	uchar *volatile x;	ulong offset = off;	tr = tlsdevs[CONV(c->qid)];	if(tr == nil)		panic("tlswrite");	ty = TYPE(c->qid);	switch(ty){	case Qdata:	case Qhand:		p = a;		e = p + n;		do{			m = e - p;			if(m > MaxRecLen)				m = MaxRecLen;			b = allocb(m);			if(waserror()){				freeb(b);				nexterror();			}			memmove(b->wp, p, m);			poperror();			b->wp += m;			tlsbwrite(c, b, offset);			p += m;		}while(p < e);		return n;	case Qctl:		break;	default:		error(Ebadusefd);		return -1;	}	cb = parsecmd(a, n);	if(waserror()){		free(cb);		nexterror();	}	if(cb->nf < 1)		error("short control request");	/* mutex with operations using what we're about to change */	if(waserror()){		qunlock(&tr->in.seclock);		qunlock(&tr->out.seclock);		nexterror();	}	qlock(&tr->in.seclock);	qlock(&tr->out.seclock);	if(strcmp(cb->f[0], "fd") == 0){		if(cb->nf != 3)			error("usage: fd open-fd version");		if(tr->c != nil)			error(Einuse);		m = strtol(cb->f[2], nil, 0);		if(m < MinProtoVersion || m > MaxProtoVersion)			error("unsupported version");		tr->c = buftochan(cb->f[1]);		tr->version = m;		tlsSetState(tr, SHandshake, SClosed);	}else if(strcmp(cb->f[0], "version") == 0){		if(cb->nf != 2)			error("usage: version vers");		if(tr->c == nil)			error("must set fd before version");		if(tr->verset)			error("version already set");		m = strtol(cb->f[1], nil, 0);		if(m == SSL3Version)			tr->packMac = sslPackMac;		else if(m == TLSVersion)			tr->packMac = tlsPackMac;		else			error("unsupported version");		tr->verset = 1;		tr->version = m;	}else if(strcmp(cb->f[0], "secret") == 0){		if(cb->nf != 5)			error("usage: secret hashalg encalg isclient secretdata");		if(tr->c == nil || !tr->verset)			error("must set fd and version before secrets");		if(tr->in.new != nil){			freeSec(tr->in.new);			tr->in.new = nil;		}		if(tr->out.new != nil){			freeSec(tr->out.new);			tr->out.new = nil;		}		ha = parsehashalg(cb->f[1]);		ea = parseencalg(cb->f[2]);		p = cb->f[4];		m = (strlen(p)*3)/2;		x = smalloc(m);		tos = nil;		toc = nil;		if(waserror()){			freeSec(tos);			freeSec(toc);			free(x);			nexterror();		}		m = dec64(x, m, p, strlen(p));		if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen)			error("not enough secret data provided");		tos = smalloc(sizeof(Secret));		toc = smalloc(sizeof(Secret));		if(!ha->initkey || !ea->initkey)			error("misimplemented secret algorithm");		(*ha->initkey)(ha, tr->version, tos, &x[0]);		(*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);		(*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);		(*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);		if(!tos->mac || !tos->enc || !tos->dec		|| !toc->mac || !toc->enc || !toc->dec)			error("missing algorithm implementations");		if(strtol(cb->f[3], nil, 0) == 0){			tr->in.new = tos;			tr->out.new = toc;		}else{			tr->in.new = toc;			tr->out.new = tos;		}		if(tr->version == SSL3Version){			toc->unpad = sslunpad;			tos->unpad = sslunpad;		}else{			toc->unpad = tlsunpad;			tos->unpad = tlsunpad;		}		toc->encalg = ea->name;		toc->hashalg = ha->name;		tos->encalg = ea->name;		tos->hashalg = ha->name;		free(x);		poperror();	}else if(strcmp(cb->f[0], "changecipher") == 0){		if(cb->nf != 1)			error("usage: changecipher");		if(tr->out.new == nil)			error("cannot change cipher spec without setting secret");		qunlock(&tr->in.seclock);		qunlock(&tr->out.seclock);		poperror();		free(cb);		poperror();		/*		 * the real work is done as the message is written		 * so the stream is encrypted in sync.		 */		b = allocb(1);		*b->wp++ = 1;		tlsrecwrite(tr, RChangeCipherSpec, b);		return n;	}else if(strcmp(cb->f[0], "opened") == 0){		if(cb->nf != 1)			error("usage: opened");		if(tr->in.sec == nil || tr->out.sec == nil)			error("cipher must be configured before enabling data messages");		lock(&tr->statelk);		if(tr->state != SHandshake && tr->state != SOpen){			unlock(&tr->statelk);			error("cannot enable data messages");		}		tr->state = SOpen;		unlock(&tr->statelk);		tr->opened = 1;	}else if(strcmp(cb->f[0], "alert") == 0){		if(cb->nf != 2)			error("usage: alert n");		if(tr->c == nil)			error("must set fd before sending alerts");		m = strtol(cb->f[1], nil, 0);		qunlock(&tr->in.seclock);		qunlock(&tr->out.seclock);		poperror();		free(cb);		poperror();		sendAlert(tr, m);		if(m == ECloseNotify)			tlsclosed(tr, SLClose);		return n;	} else if(strcmp(cb->f[0], "debug") == 0){		if(cb->nf == 2){			if(strcmp(cb->f[1], "on") == 0)				tr->debug = 1;			else				tr->debug = 0;		} else			tr->debug = 1;	} else		error(Ebadarg);	qunlock(&tr->in.seclock);	qunlock(&tr->out.seclock);	poperror();	free(cb);	poperror();	return n;}static voidtlsinit(void){	struct Encalg *e;	struct Hashalg *h;	int n;	char *cp;	static int already;	if(!already){		fmtinstall('H', encodefmt);		already = 1;	}	tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs);	trnames = smalloc((sizeof *trnames) * maxtlsdevs);	n = 1;	for(e = encrypttab; e->name != nil; e++)		n += strlen(e->name) + 1;	cp = encalgs = smalloc(n);	for(e = encrypttab;;){		strcpy(cp, e->name);		cp += strlen(e->name);		e++;		if(e->name == nil)			break;		*cp++ = ' ';	}	*cp = 0;	n = 1;	for(h = hashtab; h->name != nil; h++)		n += strlen(h->name) + 1;	cp = hashalgs = smalloc(n);	for(h = hashtab;;){		strcpy(cp, h->name);		cp += strlen(h->name);		h++;		if(h->name == nil)			break;		*cp++ = ' ';	}	*cp = 0;}Dev tlsdevtab = {	'a',	"tls",	devreset,	tlsinit,	devshutdown,	tlsattach,	tlswalk,	tlsstat,	tlsopen,	devcreate,	tlsclose,	tlsread,	tlsbread,	tlswrite,	tlsbwrite,	devremove,	tlswstat,};/* get channel associated with an fd */static Chan*buftochan(char *p){	Chan *c;	int fd;	if(p == 0)		error(Ebadarg);	fd = strtoul(p, 0, 0);	if(fd < 0)		error(Ebadarg);	c = fdtochan(fd, -1, 0, 1);	/* error check and inc ref */	return c;}static voidsendAlert(TlsRec *tr, int err){	Block *b;	int i, fatal;	char *msg;if(tr->debug)pprint("sendAlert %d\n", err);	fatal = 1;	msg = "tls unknown alert";	for(i=0; i < nelem(tlserrs); i++) {		if(tlserrs[i].err == err) {			msg = tlserrs[i].msg;			if(tr->version == SSL3Version)				err = tlserrs[i].sslerr;			else				err = tlserrs[i].tlserr;			fatal = tlserrs[i].fatal;			break;		}	}	if(!waserror()){		b = allocb(2);		*b->wp++ = fatal + 1;		*b->wp++ = err;		if(fatal)			tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose);		tlsrecwrite(tr, RAlert, b);		poperror();	}	if(fatal)		tlsError(tr, msg);}static voidtlsError(TlsRec *tr, char *msg){	int s;if(tr->debug)pprint("tleError %s\n", msg);	lock(&tr->statelk);	s = tr->state;	tr->state = SError;	if(s != SError){		strncpy(tr->err, msg, ERRMAX - 1);		tr->err[ERRMAX - 1] = '\0';	}	unlock(&tr->statelk);	if(s != SError)		alertHand(tr, msg);}static voidtlsSetState(TlsRec *tr, int new, int old){	lock(&tr->statelk);	if(tr->state & old)		tr->state = new;	unlock(&tr->statelk);}/* hand up a digest connection */static voidtlshangup(TlsRec *tr){	Block *b;	qlock(&tr->in.io);	for(b = tr->processed; b; b = tr->processed){		tr->processed = b->next;		freeb(b);	}	if(tr->unprocessed != nil){		freeb(tr->unprocessed);		tr->unprocessed = nil;	}	qunlock(&tr->in.io);	tlsSetState(tr, SClosed, ~0);}static TlsRec*newtls(Chan *ch){	TlsRec **pp, **ep, **np;	char **nmp;	int t, newmax;	if(waserror()) {		unlock(&tdlock);		nexterror();	}	lock(&tdlock);	ep = &tlsdevs[maxtlsdevs];	for(pp = tlsdevs; pp < ep; pp++)		if(*pp == nil)			break;	if(pp >= ep) {		if(maxtlsdevs >= MaxTlsDevs) {			unlock(&tdlock);			poperror();			return nil;		}		newmax = 2 * maxtlsdevs;		if(newmax > MaxTlsDevs)			newmax = MaxTlsDevs;		np = smalloc(sizeof(TlsRec*) * newmax);		memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs);		tlsdevs = np;		pp = &tlsdevs[maxtlsdevs];		memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs));		nmp = smalloc(sizeof *nmp * newmax);		memmove(nmp, trnames, sizeof *nmp * maxtlsdevs);		trnames = nmp;		maxtlsdevs = newmax;	}	*pp = mktlsrec();	if(pp - tlsdevs >= tdhiwat)		tdhiwat++;	t = TYPE(ch->qid);	if(t == Qclonus)		t = Qctl;	ch->qid.path = QID(pp - tlsdevs, t);	ch->qid.vers = 0;	unlock(&tdlock);	poperror();	return *pp;}static TlsRec *mktlsrec(void){	TlsRec *tr;	tr = mallocz(sizeof(*tr), 1);	if(tr == nil)		error(Enomem);	tr->state = SClosed;	tr->ref = 1;	kstrdup(&tr->user, up->user);	tr->perm = 0660;	return tr;}static char*tlsstate(int s){	switch(s){	case SHandshake:		return "Handshaking";	case SOpen:		return "Established";	case SRClose:		return "RemoteClosed";	case SLClose:		return "LocalClosed";	case SAlert:		return "Alerting";	case SError:		return "Errored";	case SClosed:		return "Closed";	}	return "Unknown";}static voidfreeSec(Secret *s){	if(s != nil){		free(s->enckey);		free(s);	}}static intnoenc(Secret *s, uchar *u, int n){	return n;}static intrc4enc(Secret *sec, uchar *buf, int n){	rc4(sec->enckey, buf, n);	return n;}static inttlsunpad(uchar *buf, int n, int block){	int pad, nn;	pad = buf[n - 1];	nn = n - 1 - pad;	if(nn <= 0 || n % block)		return -1;	while(--n > nn)		if(pad != buf[n - 1])			return -1;	return nn;}static intsslunpad(uchar *buf, int n, int block){	int pad, nn;	pad = buf[n - 1];	nn = n - 1 - pad;	if(nn <= 0 || n % block)		return -1;	return nn;}static intblockpad(uchar *buf, int n, int block){	int pad, nn;	nn = n + block;	nn -= nn % block;	pad = nn - (n + 1);	while(n < nn)		buf[n++] = pad;	return nn;}		static intdes3enc(Secret *sec, uchar *buf, int n){	n = blockpad(buf, n, 8);	des3CBCencrypt(buf, n, sec->enckey);	return n;}static intdes3dec(Secret *sec, uchar *buf, int n){	des3CBCdecrypt(buf, n, sec->enckey);	return (*sec->unpad)(buf, n, 8);}static DigestState*nomac(uchar *a, ulong b, uchar *c, ulong d, uchar *e, DigestState *f){	return nil;}/* * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac. */static DigestState*sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,	DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen){	int i;	uchar pad[48], innerdigest[20];	if(xlen > sizeof(innerdigest)	|| padlen > sizeof(pad))		return nil;	if(klen>64)		return nil;	/* first time through */	if(s == nil){		for(i=0; i<padlen; i++)			pad[i] = 0x36;		s = (*x)(key, klen, nil, nil);		s = (*x)(pad, padlen, nil, s);		if(s == nil)			return nil;	}	s = (*x)(p, len, nil, s);	if(digest == nil)		return s;	/* last time through */	for(i=0; i<padlen; i++)		pad[i] = 0x5c;	(*x)(nil, 0, innerdigest, s);	s = (*x)(key, klen, nil, nil);	s = (*x)(pad, padlen, nil, s);	(*x)(innerdigest, xlen, digest, s);	return nil;}static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s){	return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);}static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s){	return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);}static voidsslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac){	DigestState *s;	uchar buf[11];	memmove(buf, seq, 8);	buf[8] = header[0];	buf[9] = header[3];	buf[10] = header[4];	s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0);	(*sec->mac)(body, len, mackey, sec->maclen, mac, s);}static voidtlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac){	DigestState *s;	uchar buf[13];	memmove(buf, seq, 8);	memmove(&buf[8], header, 5);	s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0);	(*sec->mac)(body, len, mackey, sec->maclen, mac, s);}static voidput32(uchar *p, u32int x){	p[0] = x>>24;	p[1] = x>>16;	p[2] = x>>8;	p[3] = x;}static voidput64(uchar *p, vlong x){	put32(p, (u32int)(x >> 32));	put32(p+4, (u32int)x);}static voidput24(uchar *p, int x){	p[0] = x>>16;	p[1] = x>>8;	p[2] = x;}static voidput16(uchar *p, int x){	p[0] = x>>8;	p[1] = x;}#if 0static u32intget32(uchar *p){	return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];}#endifstatic intget16(uchar *p){	return (p[0]<<8)|p[1];}static char *charmap = "0123456789abcdef";static voidpdump(int len, void *a, char *tag){	uchar *p;	int i;	char buf[65+32];	char *q;	p = a;	strcpy(buf, tag);	while(len > 0){		q = buf + strlen(tag);		for(i = 0; len > 0 && i < 32; i++){			if(*p >= ' ' && *p < 0x7f){				*q++ = ' ';				*q++ = *p;			} else {				*q++ = charmap[*p>>4];				*q++ = charmap[*p & 0xf];			}			len--;			p++;		}		*q = 0;		if(len > 0)			pprint("%s...\n", buf);		else			pprint("%s\n", buf);	}}

⌨️ 快捷键说明

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