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

📄 devtls.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 3 页
字号:
{	OneWay *volatile in;	Block *volatile b;	uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen];	int volatile nconsumed;	int len, type, ver, unpad_len;	nconsumed = 0;	if(waserror()){		if(strcmp(up->errstr, Eintr) == 0 && !waserror()){			regurgitate(tr, header, nconsumed);			poperror();		}else			tlsError(tr, "channel error");		nexterror();	}	ensure(tr, &tr->unprocessed, RecHdrLen);	consume(&tr->unprocessed, header, RecHdrLen);if(tr->debug)pprint("consumed %d header\n", RecHdrLen);	nconsumed = RecHdrLen;	if((tr->handin == 0) && (header[0] & 0x80)){		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.			This is sent by some clients that we must interoperate			with, such as Java's JSSE and Microsoft's Internet Explorer. */		len = (get16(header) & ~0x8000) - 3;		type = header[2];		ver = get16(header + 3);		if(type != SSL2ClientHello || len < 22)			rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");	}else{  /* normal SSL3 record format */		type = header[0];		ver = get16(header+1);		len = get16(header+3);	}	if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))		rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",			tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);	if(len > MaxCipherRecLen || len < 0)		rcvError(tr, ERecordOverflow, "record message too long %d", len);	ensure(tr, &tr->unprocessed, len);	nconsumed = 0;	poperror();	/*	 * If an Eintr happens after this, we'll get out of sync.	 * Make sure nothing we call can sleep.	 * Errors are ok, as they kill the connection.	 * Luckily, allocb won't sleep, it'll just error out.	 */	b = nil;	if(waserror()){		if(b != nil)			freeb(b);		tlsError(tr, "channel error");		nexterror();	}	b = qgrab(&tr->unprocessed, len);if(tr->debug) pprint("consumed unprocessed %d\n", len);	in = &tr->in;	if(waserror()){		qunlock(&in->seclock);		nexterror();	}	qlock(&in->seclock);	p = b->rp;	if(in->sec != nil) {		/* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here		        should look alike, including timing of the response. */		unpad_len = (*in->sec->dec)(in->sec, p, len);		if(unpad_len >= in->sec->maclen)			len = unpad_len - in->sec->maclen;if(tr->debug) pprint("decrypted %d\n", unpad_len);if(tr->debug) pdump(unpad_len, p, "decrypted:");		/* update length */		put16(header+3, len);		put64(seq, in->seq);		in->seq++;		(*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);		if(unpad_len < in->sec->maclen)			rcvError(tr, EBadRecordMac, "short record mac");		if(memcmp(hmac, p+len, in->sec->maclen) != 0)			rcvError(tr, EBadRecordMac, "record mac mismatch");		b->wp = b->rp + len;	}	qunlock(&in->seclock);	poperror();	if(len < 0)		rcvError(tr, EDecodeError, "runt record message");	switch(type) {	default:		rcvError(tr, EIllegalParameter, "invalid record message 0x%x", type);		break;	case RChangeCipherSpec:		if(len != 1 || p[0] != 1)			rcvError(tr, EDecodeError, "invalid change cipher spec");		qlock(&in->seclock);		if(in->new == nil){			qunlock(&in->seclock);			rcvError(tr, EUnexpectedMessage, "unexpected change cipher spec");		}		freeSec(in->sec);		in->sec = in->new;		in->new = nil;		in->seq = 0;		qunlock(&in->seclock);		break;	case RAlert:		if(len != 2)			rcvError(tr, EDecodeError, "invalid alert");		if(p[0] == 2)			rcvAlert(tr, p[1]);		if(p[0] != 1)			rcvError(tr, EIllegalParameter, "invalid alert fatal code");		/*		 * propate non-fatal alerts to handshaker		 */		if(p[1] == ECloseNotify) {			tlsclosed(tr, SRClose);			if(tr->opened)				error("tls hungup");			error("close notify");		}		if(p[1] == ENoRenegotiation)			alertHand(tr, "no renegotiation");		else if(p[1] == EUserCanceled)			alertHand(tr, "handshake canceled by user");		else			rcvError(tr, EIllegalParameter, "invalid alert code");		break;	case RHandshake:		/*		 * don't worry about dropping the block		 * qbwrite always queues even if flow controlled and interrupted.		 *		 * if there isn't any handshaker, ignore the request,		 * but notify the other side we are doing so.		 */		lock(&tr->hqlock);		if(tr->handq != nil){			tr->hqref++;			unlock(&tr->hqlock);			if(waserror()){				dechandq(tr);				nexterror();			}			b = padblock(b, 1);			*b->rp = RHandshake;			qbwrite(tr->handq, b);			b = nil;			poperror();			dechandq(tr);		}else{			unlock(&tr->hqlock);			if(tr->verset && tr->version != SSL3Version && !waserror()){				sendAlert(tr, ENoRenegotiation);				poperror();			}		}		break;	case SSL2ClientHello:		lock(&tr->hqlock);		if(tr->handq != nil){			tr->hqref++;			unlock(&tr->hqlock);			if(waserror()){				dechandq(tr);				nexterror();			}			/* Pass the SSL2 format data, so that the handshake code can compute				the correct checksums.  HSSL2ClientHello = HandshakeType 9 is				unused in RFC2246. */			b = padblock(b, 8);			b->rp[0] = RHandshake;			b->rp[1] = HSSL2ClientHello;			put24(&b->rp[2], len+3);			b->rp[5] = SSL2ClientHello;			put16(&b->rp[6], ver);			qbwrite(tr->handq, b);			b = nil;			poperror();			dechandq(tr);		}else{			unlock(&tr->hqlock);			if(tr->verset && tr->version != SSL3Version && !waserror()){				sendAlert(tr, ENoRenegotiation);				poperror();			}		}		break;	case RApplication:		if(!tr->opened)			rcvError(tr, EUnexpectedMessage, "application message received before handshake completed");		if(BLEN(b) > 0){			tr->processed = b;			b = nil;		}		break;	}	if(b != nil)		freeb(b);	poperror();}/* * got a fatal alert message */static voidrcvAlert(TlsRec *tr, int err){	char *s;	int i;	s = "unknown error";	for(i=0; i < nelem(tlserrs); i++){		if(tlserrs[i].err == err){			s = tlserrs[i].msg;			break;		}	}if(tr->debug) pprint("rcvAlert: %s\n", s);	tlsError(tr, s);	if(!tr->opened)		error(s);	error("tls error");}/* * found an error while decoding the input stream */static voidrcvError(TlsRec *tr, int err, char *fmt, ...){	char msg[ERRMAX];	va_list arg;	va_start(arg, fmt);	vseprint(msg, msg+sizeof(msg), fmt, arg);	va_end(arg);if(tr->debug) pprint("rcvError: %s\n", msg);	sendAlert(tr, err);	if(!tr->opened)		error(msg);	error("tls error");}/* * make sure the next hand operation returns with a 'msg' error */static voidalertHand(TlsRec *tr, char *msg){	Block *b;	int n;	lock(&tr->hqlock);	if(tr->handq == nil){		unlock(&tr->hqlock);		return;	}	tr->hqref++;	unlock(&tr->hqlock);	n = strlen(msg);	if(waserror()){		dechandq(tr);		nexterror();	}	b = allocb(n + 2);	*b->wp++ = RAlert;	memmove(b->wp, msg, n + 1);	b->wp += n + 1;	qbwrite(tr->handq, b);	poperror();	dechandq(tr);}static voidcheckstate(TlsRec *tr, int ishand, int ok){	int state;	lock(&tr->statelk);	state = tr->state;	unlock(&tr->statelk);	if(state & ok)		return;	switch(state){	case SHandshake:	case SOpen:		break;	case SError:	case SAlert:		if(ishand)			error(tr->err);		error("tls error");	case SRClose:	case SLClose:	case SClosed:		error("tls hungup");	}	error("tls improperly configured");}static Block*tlsbread(Chan *c, long n, ulong offset){	int ty;	Block *b;	TlsRec *volatile tr;	ty = TYPE(c->qid);	switch(ty) {	default:		return devbread(c, n, offset);	case Qhand:	case Qdata:		break;	}	tr = tlsdevs[CONV(c->qid)];	if(tr == nil)		panic("tlsbread");	if(waserror()){		qunlock(&tr->in.io);		nexterror();	}	qlock(&tr->in.io);	if(ty == Qdata){		checkstate(tr, 0, SOpen);		while(tr->processed == nil)			tlsrecread(tr);		/* return at most what was asked for */		b = qgrab(&tr->processed, n);if(tr->debug) pprint("consumed processed %d\n", BLEN(b));if(tr->debug) pdump(BLEN(b), b->rp, "consumed:");		qunlock(&tr->in.io);		poperror();		tr->datain += BLEN(b);	}else{		checkstate(tr, 1, SOpen|SHandshake|SLClose);		/*		 * it's ok to look at state without the lock		 * since it only protects reading records,		 * and we have that tr->in.io held.		 */		while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq))			tlsrecread(tr);		qunlock(&tr->in.io);		poperror();		if(waserror()){			qunlock(&tr->hqread);			nexterror();		}		qlock(&tr->hqread);		if(tr->hprocessed == nil){			b = qbread(tr->handq, MaxRecLen + 1);			if(*b->rp++ == RAlert){				kstrcpy(up->errstr, (char*)b->rp, ERRMAX);				freeb(b);				nexterror();			}			tr->hprocessed = b;		}		b = qgrab(&tr->hprocessed, n);		poperror();		qunlock(&tr->hqread);		tr->handin += BLEN(b);	}	return b;}static longtlsread(Chan *c, void *a, long n, vlong off){	Block *volatile b;	Block *nb;	uchar *va;	int i, ty;	char *buf, *s, *e;	ulong offset = off;	TlsRec * tr;	if(c->qid.type & QTDIR)		return devdirread(c, a, n, 0, 0, tlsgen);	tr = tlsdevs[CONV(c->qid)];	ty = TYPE(c->qid);	switch(ty) {	default:		error(Ebadusefd);	case Qstatus:		buf = smalloc(Statlen);		qlock(&tr->in.seclock);		qlock(&tr->out.seclock);		s = buf;		e = buf + Statlen;		s = seprint(s, e, "State: %s\n", tlsstate(tr->state));		s = seprint(s, e, "Version: 0x%x\n", tr->version);		if(tr->in.sec != nil)			s = seprint(s, e, "EncIn: %s\nHashIn: %s\n", tr->in.sec->encalg, tr->in.sec->hashalg);		if(tr->in.new != nil)			s = seprint(s, e, "NewEncIn: %s\nNewHashIn: %s\n", tr->in.new->encalg, tr->in.new->hashalg);		if(tr->out.sec != nil)			s = seprint(s, e, "EncOut: %s\nHashOut: %s\n", tr->out.sec->encalg, tr->out.sec->hashalg);		if(tr->out.new != nil)			seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg);		qunlock(&tr->in.seclock);		qunlock(&tr->out.seclock);		n = readstr(offset, a, n, buf);		free(buf);		return n;	case Qstats:		buf = smalloc(Statlen);		s = buf;		e = buf + Statlen;		s = seprint(s, e, "DataIn: %lld\n", tr->datain);		s = seprint(s, e, "DataOut: %lld\n", tr->dataout);		s = seprint(s, e, "HandIn: %lld\n", tr->handin);		seprint(s, e, "HandOut: %lld\n", tr->handout);		n = readstr(offset, a, n, buf);		free(buf);		return n;	case Qctl:		buf = smalloc(Statlen);		snprint(buf, Statlen, "%llud", CONV(c->qid));		n = readstr(offset, a, n, buf);		free(buf);		return n;	case Qdata:	case Qhand:		b = tlsbread(c, n, offset);		break;	case Qencalgs:		return readstr(offset, a, n, encalgs);	case Qhashalgs:		return readstr(offset, a, n, hashalgs);	}	if(waserror()){		freeblist(b);		nexterror();	}	n = 0;	va = a;	for(nb = b; nb; nb = nb->next){		i = BLEN(nb);		memmove(va+n, nb->rp, i);		n += i;	}	freeblist(b);	poperror();	return n;}/* *  write a block in tls records */static voidtlsrecwrite(TlsRec *tr, int type, Block *b){	Block *volatile bb;	Block *nb;	uchar *p, seq[8];	OneWay *volatile out;	int n, maclen, pad, ok;	out = &tr->out;	bb = b;	if(waserror()){		qunlock(&out->io);		if(bb != nil)			freeb(bb);		nexterror();	}	qlock(&out->io);if(tr->debug)pprint("send %d\n", BLEN(b));if(tr->debug)pdump(BLEN(b), b->rp, "sent:");	ok = SHandshake|SOpen|SRClose;	if(type == RAlert)		ok |= SAlert;	while(bb != nil){		checkstate(tr, type != RApplication, ok);		/*		 * get at most one maximal record's input,		 * with padding on the front for header and		 * back for mac and maximal block padding.		 */		if(waserror()){			qunlock(&out->seclock);			nexterror();		}		qlock(&out->seclock);		maclen = 0;		pad = 0;		if(out->sec != nil){			maclen = out->sec->maclen;			pad = maclen + out->sec->block;		}		n = BLEN(bb);		if(n > MaxRecLen){			n = MaxRecLen;			nb = allocb(n + pad + RecHdrLen);			memmove(nb->wp + RecHdrLen, bb->rp, n);			bb->rp += n;		}else{			/*			 * carefully reuse bb so it will get freed if we're out of memory			 */			bb = padblock(bb, RecHdrLen);			if(pad)				nb = padblock(bb, -pad);			else				nb = bb;			bb = nil;		}		p = nb->rp;		p[0] = type;		put16(p+1, tr->version);		put16(p+3, n);		if(out->sec != nil){			put64(seq, out->seq);			out->seq++;			(*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n);			n += maclen;			/* encrypt */			n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);			nb->wp = p + RecHdrLen + n;			/* update length */			put16(p+3, n);		}		if(type == RChangeCipherSpec){			if(out->new == nil)				error("change cipher without a new cipher");			freeSec(out->sec);			out->sec = out->new;			out->new = nil;			out->seq = 0;		}		qunlock(&out->seclock);		poperror();		/*		 * if bwrite error's, we assume the block is queued.		 * if not, we're out of sync with the receiver and will not recover.		 */		if(waserror()){			if(strcmp(up->errstr, "interrupted") != 0)				tlsError(tr, "channel error");			nexterror();		}		devtab[tr->c->type]->bwrite(tr->c, nb, 0);		poperror();	}	qunlock(&out->io);	poperror();}static longtlsbwrite(Chan *c, Block *b, ulong offset){	int ty;	ulong n;	TlsRec *tr;	n = BLEN(b);	tr = tlsdevs[CONV(c->qid)];	if(tr == nil)		panic("tlsbread");	ty = TYPE(c->qid);	switch(ty) {	default:		return devbwrite(c, b, offset);	case Qhand:		tlsrecwrite(tr, RHandshake, b);		tr->handout += n;		break;	case Qdata:		checkstate(tr, 0, SOpen);		tlsrecwrite(tr, RApplication, b);		tr->dataout += n;		break;	}	return n;}typedef struct Hashalg Hashalg;struct Hashalg{	char	*name;	int	maclen;	void	(*initkey)(Hashalg *, int, Secret *, uchar*);};static voidinitmd5key(Hashalg *ha, int version, Secret *s, uchar *p){	s->maclen = ha->maclen;	if(version == SSL3Version)		s->mac = sslmac_md5;	else		s->mac = hmac_md5;	memmove(s->mackey, p, ha->maclen);}static voidinitclearmac(Hashalg *h, int i, Secret *s, uchar *u){	s->maclen = 0;	s->mac = nomac;}static voidinitsha1key(Hashalg *ha, int version, Secret *s, uchar *p){	s->maclen = ha->maclen;	if(version == SSL3Version)		s->mac = sslmac_sha1;	else		s->mac = hmac_sha1;	memmove(s->mackey, p, ha->maclen);}static Hashalg hashtab[] ={	{ "clear", 0, initclearmac, },	{ "md5", MD5dlen, initmd5key, },	{ "sha1", SHA1dlen, initsha1key, },	{ 0 }};static Hashalg*parsehashalg(char *p){	Hashalg *ha;	for(ha = hashtab; ha->name; ha++)		if(strcmp(p, ha->name) == 0)			return ha;	error("unsupported hash algorithm");	return nil;}typedef struct Encalg Encalg;struct Encalg{	char	*name;	int	keylen;	int	ivlen;	void	(*initkey)(Encalg *ea, Secret *, uchar*, uchar*);};static voidinitRC4key(Encalg *ea, Secret *s, uchar *p, uchar *u){	s->enckey = smalloc(sizeof(RC4state));	s->enc = rc4enc;	s->dec = rc4enc;	s->block = 0;	setupRC4state(s->enckey, p, ea->keylen);}static voidinitDES3key(Encalg *ea, Secret *s, uchar *p, uchar *iv){	s->enckey = smalloc(sizeof(DES3state));	s->enc = des3enc;	s->dec = des3dec;	s->block = 8;	setupDES3state(s->enckey, (uchar(*)[8])p, iv);}static voidinitclearenc(Encalg *ea, Secret *s, uchar *u, uchar *uu){	s->enc = noenc;	s->dec = noenc;	s->block = 0;}static Encalg encrypttab[] ={	{ "clear", 0, 0, initclearenc },	{ "rc4_128", 128/8, 0, initRC4key },	{ "3des_ede_cbc", 3 * 8, 8, initDES3key },	{ 0 }};static Encalg*parseencalg(char *p){	Encalg *ea;	for(ea = encrypttab; ea->name; ea++)		if(strcmp(p, ea->name) == 0)			return ea;	error("unsupported encryption algorithm");	return nil;}

⌨️ 快捷键说明

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