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

📄 devssl.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  devssl - secure sockets layer emulation */#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	<libsec.h>#define NOSPOOKS 1typedef struct OneWay OneWay;struct OneWay{	QLock	q;	QLock	ctlq;	void	*state;		/* encryption state */	int	slen;		/* hash data length */	uchar	*secret;	/* secret */	ulong	mid;		/* message id */};enum{	/* connection states */	Sincomplete=	0,	Sclear=		1,	Sencrypting=	2,	Sdigesting=	4,	Sdigenc=	Sencrypting|Sdigesting,	/* encryption algorithms */	Noencryption=	0,	DESCBC=		1,	DESECB=		2,	RC4=		3};typedef struct Dstate Dstate;struct Dstate{	Chan	*c;		/* io channel */	uchar	state;		/* state of connection */	int	ref;		/* serialized by dslock for atomic destroy */	uchar	encryptalg;	/* encryption algorithm */	ushort	blocklen;	/* blocking length */	ushort	diglen;		/* length of digest */	DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);	/* hash func */	/* for SSL format */	int	max;		/* maximum unpadded data per msg */	int	maxpad;		/* maximum padded data per msg */	/* input side */	OneWay	in;	Block	*processed;	Block	*unprocessed;	/* output side */	OneWay	out;	/* protections */	char	user[NAMELEN];	int	perm;};Lock	dslock;int	dshiwat;int	maxdstate = 20;Dstate** dstate;char	*encalgs;char	*hashalgs;enum{	Maxdmsg=	1<<16,	Maxdstate=	64};enum{	Qtopdir		= 1,	/* top level directory */	Qprotodir,	Qclonus,	Qconvdir,		/* directory for a conversation */	Qdata,	Qctl,	Qsecretin,	Qsecretout,	Qencalgs,	Qhashalgs,};#define TYPE(x) 	((x).path & 0xf)#define CONV(x) 	(((x).path >> 5)&(Maxdstate-1))#define QID(c, y) 	(((c)<<5) | (y))static void	ensure(Dstate*, Block**, int);static void	consume(Block**, uchar*, int);static void	setsecret(OneWay*, uchar*, int);static Block*	encryptb(Dstate*, Block*, int);static Block*	decryptb(Dstate*, Block*);static Block*	digestb(Dstate*, Block*, int);static void	checkdigestb(Dstate*, Block*);static Chan*	buftochan(char*);static void	sslhangup(Dstate*);static Dstate*	dsclone(Chan *c);static void	dsnew(Chan *c, Dstate **);char *sslnames[] = {[Qclonus]	"clone",[Qdata]		"data",[Qctl]		"ctl",[Qsecretin]	"secretin",[Qsecretout]	"secretout",[Qencalgs]	"encalgs",[Qhashalgs]	"hashalgs",};static intsslgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp){	Qid q;	Dstate *ds;	char name[16], *p, *nm;	USED(nd);	USED(d);	q.vers = 0;	switch(TYPE(c->qid)) {	case Qtopdir:		if(s == DEVDOTDOT){			q.path = QID(0, Qtopdir)|CHDIR;			devdir(c, q, "#D", 0, eve, CHDIR|0555, dp);			return 1;		}		if(s > 0)			return -1;		q.path = QID(0, Qprotodir)|CHDIR;		devdir(c, q, "ssl", 0, eve, CHDIR|0555, dp);		return 1;	case Qprotodir:		if(s == DEVDOTDOT){			q.path = QID(0, Qtopdir)|CHDIR;			devdir(c, q, ".", 0, eve, CHDIR|0555, dp);			return 1;		}		if(s < dshiwat) {			sprint(name, "%d", s);			q.path = QID(s, Qconvdir)|CHDIR;			ds = dstate[s];			if(ds != 0)				nm = ds->user;			else				nm = eve;			devdir(c, q, name, 0, nm, CHDIR|0555, dp);			return 1;		}		if(s > dshiwat)			return -1;		q.path = QID(0, Qclonus);		devdir(c, q, "clone", 0, eve, 0555, dp);		return 1;	case Qconvdir:		if(s == DEVDOTDOT){			q.path = QID(0, Qprotodir)|CHDIR;			devdir(c, q, "ssl", 0, eve, CHDIR|0555, dp);			return 1;		}		ds = dstate[CONV(c->qid)];		if(ds != 0)			nm = ds->user;		else			nm = eve;		switch(s) {		default:			return -1;		case 0:			q.path = QID(CONV(c->qid), Qctl);			p = "ctl";			break;		case 1:			q.path = QID(CONV(c->qid), Qdata);			p = "data";			break;		case 2:			q.path = QID(CONV(c->qid), Qsecretin);			p = "secretin";			break;		case 3:			q.path = QID(CONV(c->qid), Qsecretout);			p = "secretout";			break;		case 4:			q.path = QID(CONV(c->qid), Qencalgs);			p = "encalgs";			break;		case 5:			q.path = QID(CONV(c->qid), Qhashalgs);			p = "hashalgs";			break;		}		devdir(c, q, p, 0, nm, 0660, dp);		return 1;	case Qclonus:		devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp);		return 1;	default:		ds = dstate[CONV(c->qid)];		devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, ds->user, 0660, dp);		return 1;	}	return -1;}static Chan*sslattach(char *spec){	Chan *c;	c = devattach('D', spec);	c->qid.path = QID(0, Qtopdir)|CHDIR;	c->qid.vers = 0;	return c;}static intsslwalk(Chan *c, char *name){	return devwalk(c, name, 0, 0, sslgen);}static voidsslstat(Chan *c, char *db){	devstat(c, db, 0, 0, sslgen);}static Chan*sslopen(Chan *c, int omode){	Dstate *s, **pp;	int perm;	perm = 0;	omode &= 3;	switch(omode) {	case OREAD:		perm = 4;		break;	case OWRITE:		perm = 2;		break;	case ORDWR:		perm = 6;		break;	}	switch(TYPE(c->qid)) {	default:		panic("sslopen");	case Qtopdir:	case Qprotodir:	case Qconvdir:		if(omode != OREAD)			error(Eperm);		break;	case Qclonus:		s = dsclone(c);		if(s == 0)			error(Enodev);		break;	case Qctl:	case Qdata:	case Qsecretin:	case Qsecretout:		if(waserror()) {			unlock(&dslock);			nexterror();		}		lock(&dslock);		pp = &dstate[CONV(c->qid)];		s = *pp;		if(s == 0)			dsnew(c, pp);		else {			if((perm & (s->perm>>6)) != perm			   && (strcmp(up->user, s->user) != 0			     || (perm & s->perm) != perm))				error(Eperm);			s->ref++;		}		unlock(&dslock);		poperror();		break;	case Qencalgs:	case Qhashalgs:		if(omode != OREAD)			error(Eperm);		break;	}	c->mode = openmode(omode);	c->flag |= COPEN;	c->offset = 0;	return c;}static voidsslwstat(Chan *c, char *dp){	Dir d;	Dstate *s;	convM2D(dp, &d);	s = dstate[CONV(c->qid)];	if(s == 0)		error(Ebadusefd);	if(strcmp(s->user, up->user) != 0)		error(Eperm);	memmove(s->user, d.uid, NAMELEN);	s->perm = d.mode;}static voidsslclose(Chan *c){	Dstate *s;	switch(TYPE(c->qid)) {	case Qctl:	case Qdata:	case Qsecretin:	case Qsecretout:		if((c->flag & COPEN) == 0)			break;		s = dstate[CONV(c->qid)];		if(s == 0)			break;		lock(&dslock);		if(--s->ref > 0) {			unlock(&dslock);			break;		}		dstate[CONV(c->qid)] = 0;		unlock(&dslock);		sslhangup(s);		if(s->c)			cclose(s->c);		if(s->in.secret)			free(s->in.secret);		if(s->out.secret)			free(s->out.secret);		if(s->in.state)			free(s->in.state);		if(s->out.state)			free(s->out.state);		free(s);	}}/* *  make sure we have at least 'n' bytes in list 'l' */static voidensure(Dstate *s, Block **l, int n){	int sofar, i;	Block *b, *bl;	sofar = 0;	for(b = *l; b; b = b->next){		sofar += BLEN(b);		if(sofar >= n)			return;		l = &b->next;	}	while(sofar < n){		bl = devtab[s->c->type]->bread(s->c, Maxdmsg, 0);		if(bl == 0)			error(Ehungup);		*l = bl;		i = 0;		for(b = bl; b; b = b->next){			i += BLEN(b);			l = &b->next;		}		if(i == 0)			error(Ehungup);		sofar += i;	}}/* *  copy 'n' bytes from 'l' into 'p' and free *  the bytes in 'l' */static voidconsume(Block **l, uchar *p, int n){	Block *b;	int i;	for(; *l && n > 0; n -= i){		b = *l;		i = BLEN(b);		if(i > n)			i = n;		memmove(p, b->rp, i);		b->rp += i;		p += i;		if(BLEN(b) < 0)			panic("consume");		if(BLEN(b))			break;		*l = b->next;		freeb(b);	}}/* *  remove at most n bytes from the queue, if discard is set *  dump the remainder */static Block*qremove(Block **l, int n, int discard){	Block *nb, *b, *first;	int i;	first = *l;	for(b = first; b; b = b->next){		i = BLEN(b);		if(i == n){			if(discard){				freeblist(b->next);				*l = 0;			} else				*l = b->next;			b->next = 0;			return first;		} else if(i > n){			i -= n;			if(discard){				freeblist(b->next);				b->wp -= i;				*l = 0;			} else {				nb = allocb(i);				memmove(nb->wp, b->rp+n, i);				nb->wp += i;				b->wp -= i;				nb->next = b->next;				*l = nb;			}			b->next = 0;			if(BLEN(b) < 0)				panic("qremove");			return first;		} else			n -= i;		if(BLEN(b) < 0)			panic("qremove");	}	*l = 0;	return first;}static Block*sslbread(Chan *c, long n, ulong){	volatile struct { Dstate *s; } s;	Block *b;	uchar count[2];	int len, pad;	s.s = dstate[CONV(c->qid)];	if(s.s == 0)		panic("sslbread");	if(s.s->state == Sincomplete)		error(Ebadusefd);	if(waserror()){		qunlock(&s.s->in.q);		sslhangup(s.s);		nexterror();	}	qlock(&s.s->in.q);	if(s.s->processed == 0){		/* read in the whole message */		ensure(s.s, &s.s->unprocessed, 2);		consume(&s.s->unprocessed, count, 2);		if(count[0] & 0x80){			len = ((count[0] & 0x7f)<<8) | count[1];			ensure(s.s, &s.s->unprocessed, len);			pad = 0;		} else {			len = ((count[0] & 0x3f)<<8) | count[1];			ensure(s.s, &s.s->unprocessed, len+1);			consume(&s.s->unprocessed, count, 1);			pad = count[0];			if(pad > len){				print("pad %d buf len %d\n", pad, len);				error("bad pad in ssl message");			}		}		/* put extra on unprocessed queue */		s.s->processed = qremove(&s.s->unprocessed, len, 0);		if(waserror()){			qunlock(&s.s->in.ctlq);			nexterror();		}		qlock(&s.s->in.ctlq);		switch(s.s->state){		case Sencrypting:			s.s->processed = decryptb(s.s, s.s->processed);			break;		case Sdigesting:			s.s->processed = pullupblock(s.s->processed, s.s->diglen);			if(s.s->processed == 0)				error("ssl message too short");			checkdigestb(s.s, s.s->processed);			s.s->processed->rp += s.s->diglen;			break;		case Sdigenc:			s.s->processed = decryptb(s.s, s.s->processed);			s.s->processed = pullupblock(s.s->processed, s.s->diglen);			if(s.s->processed == 0)				error("ssl message too short");			checkdigestb(s.s, s.s->processed);			s.s->processed->rp += s.s->diglen;			len -= s.s->diglen;			break;		}		s.s->in.mid++;		qunlock(&s.s->in.ctlq);		poperror();		/* remove pad */		if(pad)			s.s->processed = qremove(&s.s->processed, len - pad, 1);	}	/* return at most what was asked for */	b = qremove(&s.s->processed, n, 0);	qunlock(&s.s->in.q);	poperror();	return b;}static longsslread(Chan *c, void *a, long n, vlong off){	volatile struct { Block *b; } b;	Block *nb;	uchar *va;	int i;	char buf[128];	ulong offset = off;	if(c->qid.path & CHDIR)		return devdirread(c, a, n, 0, 0, sslgen);	switch(TYPE(c->qid)) {	default:		error(Ebadusefd);	case Qctl:		sprint(buf, "%lud", CONV(c->qid));		return readstr(offset, a, n, buf);	case Qdata:		b.b = sslbread(c, n, offset);		break;	case Qencalgs:		return readstr(offset, a, n, encalgs);		break;	case Qhashalgs:		return readstr(offset, a, n, hashalgs);		break;	}	if(waserror()){		freeblist(b.b);		nexterror();	}	n = 0;	va = a;	for(nb = b.b; nb; nb = nb->next){		i = BLEN(nb);		memmove(va+n, nb->rp, i);		n += i;	}	freeblist(b.b);	poperror();	return n;}/* *  this algorithm doesn't have to be great since we're just *  trying to obscure the block fill */static voidrandfill(uchar *buf, int len){	while(len-- > 0)		*buf++ = nrand(256);}/* *  use SSL record format, add in count and digest or encrypt */static longsslbwrite(Chan *c, Block *b, ulong offset){	volatile struct { Dstate *s; } s;	volatile struct { Block *b; } bb;	Block *nb;	int h, n, m, pad, rv;	uchar *p;	bb.b = b;	s.s = dstate[CONV(c->qid)];	if(s.s == 0)		panic("sslbwrite");	if(s.s->state == Sincomplete){		freeb(b);		error(Ebadusefd);	}	if(waserror()){		qunlock(&s.s->out.q);		if(bb.b)			freeb(bb.b);		sslhangup(s.s);		nexterror();	}	qlock(&s.s->out.q);	rv = 0;	while(bb.b){		m = n = BLEN(bb.b);		h = s.s->diglen + 2;		/* trim to maximum block size */		pad = 0;		if(m > s.s->max){			m = s.s->max;		} else if(s.s->blocklen != 1){			pad = (m + s.s->diglen)%s.s->blocklen;			if(pad){				if(m > s.s->maxpad){					pad = 0;					m = s.s->maxpad;				} else {					pad = s.s->blocklen - pad;					h++;				}			}		}		rv += m;		if(m != n){			nb = allocb(m + h + pad);			memmove(nb->wp + h, bb.b->rp, m);			nb->wp += m + h;			bb.b->rp += m;		} else {			/* add header space */			nb = padblock(bb.b, h);			bb.b = 0;		}		m += s.s->diglen;		/* SSL style count */		if(pad){			nb = padblock(nb, -pad);			randfill(nb->wp, pad);			nb->wp += pad;			m += pad;			p = nb->rp;			p[0] = (m>>8);			p[1] = m;			p[2] = pad;

⌨️ 快捷键说明

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