~kris/9p

9hist

05490cdb1d38889d0d0e0fed6e5e48ee209cd86f — David du Colombier 25 years ago 63d5e56
Plan 9 from Bell Labs 2001-04-07
1 files changed, 95 insertions(+), 75 deletions(-)

M port/devtls.c
M port/devtls.c => port/devtls.c +95 -75
@@ 14,11 14,12 @@ typedef struct OneWay OneWay;
typedef struct Secret Secret;

enum {
	/* buffer limits */
	MaxRecLen	= 1<<14,	/* max payload length of a record layer message */
	MaxCipherRecLen	= MaxRecLen + 2048,

//ZZZ
	RecHdrLen	= 5,

	/* protocol versions we can accept */
	TLSVersion	= 0x0301,
	SSL3Version	= 0x0300,
	ProtocolVersion	= 0x0301,	/* maximum version we speak */


@@ 26,13 27,13 @@ enum {
	MaxProtoVersion	= 0x03ff,

	/* connection states */
	SHandshake	= 1 << 0,		// doing handshake
	SOpen		= 1 << 1,		// application data can be sent
	SRClose		= 1 << 2,		// remote side has closed down
	SLClose		= 1 << 3,		// sent a close notify alert
	SAlert		= 1 << 5,		// sending or sent a fatal alert
	SError		= 1 << 6,		// some sort of error has occured
	SClosed		= 1 << 7,		// it is all over
	SHandshake	= 1 << 0,	/* doing handshake */
	SOpen		= 1 << 1,	/* application data can be sent */
	SRClose		= 1 << 2,	/* remote side has closed down */
	SLClose		= 1 << 3,	/* sent a close notify alert */
	SAlert		= 1 << 5,	/* sending or sent a fatal alert */
	SError		= 1 << 6,	/* some sort of error has occured */
	SClosed		= 1 << 7,	/* it is all over */

	/* record types */
	RChangeCipherSpec = 20,


@@ 89,12 90,12 @@ struct OneWay
typedef struct TlsRec TlsRec;
struct TlsRec
{
	Chan		*c;			/* io channel */
	int		ref;			/* serialized by dslock for atomic destroy */
	int		version;		/* version of the protocol we are speaking */
	char		verset;			/* version has been set */
	char		opened;			/* opened command every issued? */
	char		err[ERRLEN];		/* error message to return to handshake requests */
	Chan		*c;		/* io channel */
	int		ref;		/* serialized by tdlock for atomic destroy */
	int		version;	/* version of the protocol we are speaking */
	char		verset;		/* version has been set */
	char		opened;		/* opened command every issued? */
	char		err[ERRLEN];	/* error message to return to handshake requests */

	Lock		statelk;
	int		state;


@@ 104,13 105,15 @@ struct TlsRec

	/* input side -- protected by in.io */
	OneWay		in;
	Block		*processed;			/* next bunch of application data */
	Block		*unprocessed;			/* data read from c but not parsed into records */
	Block		*processed;	/* next bunch of application data */
	Block		*unprocessed;	/* data read from c but not parsed into records */

	/* handshake queue */
	Lock		hqlock;
	Lock		hqlock;		/* protects hqref, alloc & free of handq, hprocessed */
	int		hqref;
	Queue		*handq;				/* queue of handshake messages */
	Queue		*handq;		/* queue of handshake messages */
	Block		*hprocessed;	/* remainder of last block read from handq */
	QLock		hqread;		/* protects reads for hprocessed, handq */

	/* output side */
	OneWay		out;


@@ 178,18 181,18 @@ static TlsErrs tlserrs[] = {
		0, "handshake canceled by user"},
	{ENoRenegotiation,		EUnexpectedMessage,		ENoRenegotiation,
		0, "no renegotiation"},
	{-1},
};

enum
{
	Maxdstate	= 64,
	/* max. open tls connections */
	MaxTlsDevs	= 1024
};

static	Lock	dslock;
static	int	dshiwat;
static	int	maxdstate = 128;
static	TlsRec** dstate;
static	Lock	tdlock;
static	int	tdhiwat;
static	int	maxtlsdevs = 128;
static	TlsRec	**tlsdevs;
static	char	*encalgs;
static	char	*hashalgs;



@@ 206,7 209,7 @@ enum{
};

#define TYPE(x) 	((x).path & 0xf)
#define CONV(x) 	(((x).path >> 5)&(Maxdstate-1))
#define CONV(x) 	(((x).path >> 5)&(MaxTlsDevs-1))
#define QID(c, y) 	(((c)<<5) | (y))

static void	checkstate(TlsRec *, int, int);


@@ 270,10 273,10 @@ tlsgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp)
			devdir(c, q, ".", 0, eve, CHDIR|0555, dp);
			return 1;
		}
		if(s < dshiwat) {
		if(s < tdhiwat) {
			sprint(name, "%d", s);
			q.path = QID(s, Qconvdir)|CHDIR;
			ds = dstate[s];
			ds = tlsdevs[s];
			if(ds != 0)
				nm = ds->user;
			else


@@ 281,7 284,7 @@ tlsgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp)
			devdir(c, q, name, 0, nm, CHDIR|0555, dp);
			return 1;
		}
		if(s > dshiwat)
		if(s > tdhiwat)
			return -1;
		q.path = QID(0, Qclonus);
		devdir(c, q, "clone", 0, eve, 0555, dp);


@@ 292,7 295,7 @@ tlsgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp)
			devdir(c, q, "tls", 0, eve, CHDIR|0555, dp);
			return 1;
		}
		ds = dstate[CONV(c->qid)];
		ds = tlsdevs[CONV(c->qid)];
		if(ds != 0)
			nm = ds->user;
		else


@@ 327,7 330,7 @@ tlsgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp)
		devdir(c, c->qid, tlsnames[TYPE(c->qid)], 0, eve, 0555, dp);
		return 1;
	default:
		ds = dstate[CONV(c->qid)];
		ds = tlsdevs[CONV(c->qid)];
		devdir(c, c->qid, tlsnames[TYPE(c->qid)], 0, ds->user, 0660, dp);
		return 1;
	}


@@ 396,11 399,11 @@ tlsopen(Chan *c, int omode)
	case Qdata:
	case Qhand:
		if(waserror()) {
			unlock(&dslock);
			unlock(&tdlock);
			nexterror();
		}
		lock(&dslock);
		pp = &dstate[CONV(c->qid)];
		lock(&tdlock);
		pp = &tlsdevs[CONV(c->qid)];
		tr = *pp;
		if(tr == nil)
			error("must open connection using clone");


@@ 425,7 428,7 @@ tlsopen(Chan *c, int omode)
			poperror();
		}
		tr->ref++;
		unlock(&dslock);
		unlock(&tdlock);
		poperror();
		break;
	case Qencalgs:


@@ 448,7 451,7 @@ tlswstat(Chan *c, char *dp)

	convM2D(dp, &d);

	tr = dstate[CONV(c->qid)];
	tr = tlsdevs[CONV(c->qid)];
	if(tr == nil)
		error(Ebadusefd);
	if(strcmp(tr->user, up->user) != 0)


@@ 463,9 466,15 @@ static void
dechandq(TlsRec *tr)
{
	lock(&tr->hqlock);
	if(--tr->hqref == 0 && tr->handq != nil){
		qfree(tr->handq);
		tr->handq = nil;
	if(--tr->hqref == 0){
		if(tr->handq != nil){
			qfree(tr->handq);
			tr->handq = nil;
		}
		if(tr->hprocessed != nil){
			freeb(tr->hprocessed);
			tr->hprocessed = nil;
		}
	}
	unlock(&tr->hqlock);
}


@@ 484,20 493,20 @@ tlsclose(Chan *c)
		if((c->flag & COPEN) == 0)
			break;

		tr = dstate[CONV(c->qid)];
		tr = tlsdevs[CONV(c->qid)];
		if(tr == nil)
			break;

		if(t == Qhand)
			dechandq(tr);

		lock(&dslock);
		lock(&tdlock);
		if(--tr->ref > 0) {
			unlock(&dslock);
			unlock(&tdlock);
			return;
		}
		dstate[CONV(c->qid)] = nil;
		unlock(&dslock);
		tlsdevs[CONV(c->qid)] = nil;
		unlock(&tdlock);

		if(tr->c != nil && !waserror()){
			checkstate(tr, 0, SOpen|SHandshake|SRClose);


@@ 943,7 952,7 @@ tlsbread(Chan *c, long n, ulong offset)
		break;
	}

	tr = dstate[CONV(c->qid)];
	tr = tlsdevs[CONV(c->qid)];
	if(tr == nil)
		panic("tlsbread");



@@ 969,17 978,30 @@ tlsbread(Chan *c, long n, ulong offset)
		 * since it only protects reading records,
		 * and we have that tr->in.io held.
		 */
		while(!tr->opened && !qcanread(tr->handq))
		while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq))
			tlsrecread(tr);

		qunlock(&tr->in.io);
		poperror();
		b = qbread(tr->handq, n);
		if(*b->rp++ == RAlert){
			strncpy(up->error, (char*)b->rp, ERRLEN - 1);
			up->error[ERRLEN - 1] = '\0';
			error(up->error);

		if(waserror()){
			qunlock(&tr->hqread);
			nexterror();
		}
		qlock(&tr->hqread);
		if(tr->hprocessed == nil){
			b = qbread(tr->handq, MaxRecLen + 1);
			if(*b->rp++ == RAlert){
				strncpy(up->error, (char*)b->rp, ERRLEN - 1);
				up->error[ERRLEN - 1] = '\0';
				freeb(b);
				error(up->error);
			}
			tr->hprocessed = b;
		}
		b = qremove(&tr->hprocessed, n, 0);
		poperror();
		qunlock(&tr->hqread);
	}

	return b;


@@ 1156,7 1178,7 @@ tlsbwrite(Chan *c, Block *b, ulong offset)

	n = BLEN(b);

	tr = dstate[CONV(c->qid)];
	tr = tlsdevs[CONV(c->qid)];
	if(tr == nil)
		panic("tlsbread");



@@ 1261,7 1283,7 @@ tlswrite(Chan *c, void *a, long n, vlong off)
	uchar *volatile x;
	ulong offset = off;

	tr = dstate[CONV(c->qid)];
	tr = tlsdevs[CONV(c->qid)];
	if(tr == nil)
		panic("tlswrite");



@@ 1305,7 1327,6 @@ tlswrite(Chan *c, void *a, long n, vlong off)
		error("short control request");

	/* mutex with operations using what we're about to change */
//ZZZ check this locking
	if(waserror()){
		qunlock(&tr->in.seclock);
		qunlock(&tr->out.seclock);


@@ 1418,8 1439,7 @@ tlswrite(Chan *c, void *a, long n, vlong off)
		lock(&tr->statelk);
		if(tr->state != SHandshake && tr->state != SOpen){
			unlock(&tr->statelk);
//ZZZ bad error message
			error("can't set open state");
			error("can't enable data messages");
		}
		tr->state = SOpen;
		unlock(&tr->statelk);


@@ 1463,7 1483,7 @@ tlsinit(void)
	int n;
	char *cp;

	if((dstate = smalloc(sizeof(TlsRec*) * maxdstate)) == 0)
	if((tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs)) == 0)
		panic("tlsinit");

	n = 1;


@@ 1618,39 1638,39 @@ newtls(Chan *ch)
	int t, newmax;

	if(waserror()) {
		unlock(&dslock);
		unlock(&tdlock);
		nexterror();
	}
	lock(&dslock);
	ep = &dstate[maxdstate];
	for(pp = dstate; pp < ep; pp++)
	lock(&tdlock);
	ep = &tlsdevs[maxtlsdevs];
	for(pp = tlsdevs; pp < ep; pp++)
		if(*pp == nil)
			break;
	if(pp >= ep) {
		if(maxdstate >= Maxdstate) {
			unlock(&dslock);
		if(maxtlsdevs >= MaxTlsDevs) {
			unlock(&tdlock);
			poperror();
			return nil;
		}
		newmax = 2 * maxdstate;
		if(newmax > Maxdstate)
			newmax = Maxdstate;
		newmax = 2 * maxtlsdevs;
		if(newmax > MaxTlsDevs)
			newmax = MaxTlsDevs;
		np = smalloc(sizeof(TlsRec*) * newmax);
		memmove(np, dstate, sizeof(TlsRec*) * maxdstate);
		dstate = np;
		pp = &dstate[maxdstate];
		memset(pp, 0, sizeof(TlsRec*)*(newmax - maxdstate));
		maxdstate = newmax;
		memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs);
		tlsdevs = np;
		pp = &tlsdevs[maxtlsdevs];
		memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs));
		maxtlsdevs = newmax;
	}
	*pp = mktlsrec();
	if(pp - dstate >= dshiwat)
		dshiwat++;
	if(pp - tlsdevs >= tdhiwat)
		tdhiwat++;
	t = TYPE(ch->qid);
	if(t == Qclonus)
		t = Qctl;
	ch->qid.path = QID(pp - dstate, t);
	ch->qid.path = QID(pp - tlsdevs, t);
	ch->qid.vers = 0;
	unlock(&dslock);
	unlock(&tdlock);
	poperror();
	return *pp;
}