~kris/9p

9hist

22b4419718fe23075553c15dcd9b4180f6009968 — David du Colombier 24 years ago 8b850f5
Plan 9 from Bell Labs 2002-03-07
1 files changed, 160 insertions(+), 133 deletions(-)

M port/devssl.c
M port/devssl.c => port/devssl.c +160 -133
@@ 111,6 111,7 @@ static Chan*	buftochan(char*);
static void	sslhangup(Dstate*);
static Dstate*	dsclone(Chan *c);
static void	dsnew(Chan *c, Dstate **);
static long	sslput(Dstate *s, Block * volatile b);

char *sslnames[] = {
[Qclonus]	"clone",


@@ 542,40 543,40 @@ qtake(Block **l, int n, int discard)
static Block*
sslbread(Chan *c, long n, ulong)
{
	volatile struct { Dstate *s; } s;
	Dstate * volatile s;
	Block *b;
	uchar consumed[3], *p;
	int toconsume;
	int len, pad;

	s.s = dstate[CONV(c->qid)];
	if(s.s == 0)
	s = dstate[CONV(c->qid)];
	if(s == 0)
		panic("sslbread");
	if(s.s->state == Sincomplete)
	if(s->state == Sincomplete)
		error(Ebadusefd);

	qlock(&s.s->in.q);
	qlock(&s->in.q);
	if(waserror()){
		qunlock(&s.s->in.q);
		qunlock(&s->in.q);
		nexterror();
	}

	if(s.s->processed == 0){
	if(s->processed == 0){
		/*
		 * Read in the whole message.  Until we've got it all,
		 * it stays on s.s->unprocessed, so that if we get Eintr,
		 * it stays on s->unprocessed, so that if we get Eintr,
		 * we'll pick up where we left off.
		 */
		ensure(s.s, &s.s->unprocessed, 3);
		s.s->unprocessed = pullupblock(s.s->unprocessed, 2);
		p = s.s->unprocessed->rp;
		ensure(s, &s->unprocessed, 3);
		s->unprocessed = pullupblock(s->unprocessed, 2);
		p = s->unprocessed->rp;
		if(p[0] & 0x80){
			len = ((p[0] & 0x7f)<<8) | p[1];
			ensure(s.s, &s.s->unprocessed, len);
			ensure(s, &s->unprocessed, len);
			pad = 0;
			toconsume = 2;
		} else {
			s.s->unprocessed = pullupblock(s.s->unprocessed, 3);
			s->unprocessed = pullupblock(s->unprocessed, 3);
			len = ((p[0] & 0x3f)<<8) | p[1];
			pad = p[2];
			if(pad > len){


@@ 584,7 585,7 @@ sslbread(Chan *c, long n, ulong)
			}
			toconsume = 3;
		}
		ensure(s.s, &s.s->unprocessed, toconsume+len);
		ensure(s, &s->unprocessed, toconsume+len);

		/*
		 * Now we have a full SSL packet in the unprocessed list.


@@ 600,61 601,61 @@ sslbread(Chan *c, long n, ulong)
		}

		/* skip header */
		consume(&s.s->unprocessed, consumed, toconsume);
		consume(&s->unprocessed, consumed, toconsume);

		/* grab the next message and decode/decrypt it */
		b = qtake(&s.s->unprocessed, len, 0);
		b = qtake(&s->unprocessed, len, 0);

		if(blocklen(b) != len)
			print("devssl: sslbread got wrong count %d != %d", blocklen(b), len);

		if(waserror()){
			qunlock(&s.s->in.ctlq);
			qunlock(&s->in.ctlq);
			if(b != nil)
				freeb(b);
			nexterror();
		}
		qlock(&s.s->in.ctlq);
		switch(s.s->state){
		qlock(&s->in.ctlq);
		switch(s->state){
		case Sencrypting:
			if(b == nil)
				error("ssl message too short (encrypting)");
			b = decryptb(s.s, b);
			b = decryptb(s, b);
			break;
		case Sdigesting:
			b = pullupblock(b, s.s->diglen);
			b = pullupblock(b, s->diglen);
			if(b == nil)
				error("ssl message too short (digesting)");
			checkdigestb(s.s, b);
			b->rp += s.s->diglen;
			checkdigestb(s, b);
			b->rp += s->diglen;
			break;
		case Sdigenc:
			b = decryptb(s.s, b);
			b = pullupblock(b, s.s->diglen);
			b = decryptb(s, b);
			b = pullupblock(b, s->diglen);
			if(b == nil)
				error("ssl message too short (dig+enc)");
			checkdigestb(s.s, b);
			b->rp += s.s->diglen;
			len -= s.s->diglen;
			checkdigestb(s, b);
			b->rp += s->diglen;
			len -= s->diglen;
			break;
		}

		/* remove pad */
		if(pad)
			s.s->processed = qtake(&b, len - pad, 1);
			s->processed = qtake(&b, len - pad, 1);
		else
			s.s->processed = b;
			s->processed = b;
		b = nil;
		s.s->in.mid++;
		qunlock(&s.s->in.ctlq);
		s->in.mid++;
		qunlock(&s->in.ctlq);
		poperror();
		poperror();
	}

	/* return at most what was asked for */
	b = qtake(&s.s->processed, n, 0);
	b = qtake(&s->processed, n, 0);

	qunlock(&s.s->in.q);
	qunlock(&s->in.q);
	poperror();

	return b;


@@ 663,7 664,7 @@ sslbread(Chan *c, long n, ulong)
static long
sslread(Chan *c, void *a, long n, vlong off)
{
	volatile struct { Block *b; } b;
	Block * volatile b;
	Block *nb;
	uchar *va;
	int i;


@@ 683,7 684,7 @@ sslread(Chan *c, void *a, long n, vlong off)
		sprint(buf, "%d", ft);
		return readstr(offset, a, n, buf);
	case Qdata:
		b.b = sslbread(c, n, offset);
		b = sslbread(c, n, offset);
		break;
	case Qencalgs:
		return readstr(offset, a, n, encalgs);


@@ 694,19 695,19 @@ sslread(Chan *c, void *a, long n, vlong off)
	}

	if(waserror()){
		freeblist(b.b);
		freeblist(b);
		nexterror();
	}

	n = 0;
	va = a;
	for(nb = b.b; nb; nb = nb->next){
	for(nb = b; nb; nb = nb->next){
		i = BLEN(nb);
		memmove(va+n, nb->rp, i);
		n += i;
	}

	freeblist(b.b);
	freeblist(b);
	poperror();

	return n;


@@ 723,6 724,36 @@ randfill(uchar *buf, int len)
		*buf++ = nrand(256);
}

static long
sslbwrite(Chan *c, Block *b, ulong)
{
	Dstate * volatile s;
	long rv;

	s = dstate[CONV(c->qid)];
	if(s == nil)
		panic("sslbwrite");

	if(s->state == Sincomplete){
		freeb(b);
		error(Ebadusefd);
	}

	/* lock so split writes won't interleave */
	if(waserror()){
		qunlock(&s->out.q);
		nexterror();
	}
	qlock(&s->out.q);

	rv = sslput(s, b);

	poperror();
	qunlock(&s->out.q);

	return rv;
}

/*
 *  use SSL record format, add in count, digest and/or encrypt.
 *  the write is interruptable.  if it is interrupted, we'll


@@ 730,48 761,36 @@ randfill(uchar *buf, int len)
 *  it since we don't know if any bytes have been written.
 */
static long
sslbwrite(Chan *c, Block *b, ulong offset)
sslput(Dstate *s, Block * volatile b)
{
	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);
	}
	int offset;

	if(waserror()){
		qunlock(&s.s->out.q);
		if(bb.b != nil)
			freeb(bb.b);
		if(b != nil)
			free(b);
		nexterror();
	}
	qlock(&s.s->out.q);

	rv = 0;
	while(bb.b){
		m = n = BLEN(bb.b);
		h = s.s->diglen + 2;
	while(b != nil){
		m = n = BLEN(b);
		h = 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(m > s->max){
			m = s->max;
		} else if(s->blocklen != 1){
			pad = (m + s->diglen)%s->blocklen;
			if(pad){
				if(m > s.s->maxpad){
				if(m > s->maxpad){
					pad = 0;
					m = s.s->maxpad;
					m = s->maxpad;
				} else {
					pad = s.s->blocklen - pad;
					pad = s->blocklen - pad;
					h++;
				}
			}


@@ 780,15 799,15 @@ sslbwrite(Chan *c, Block *b, ulong offset)
		rv += m;
		if(m != n){
			nb = allocb(m + h + pad);
			memmove(nb->wp + h, bb.b->rp, m);
			memmove(nb->wp + h, b->rp, m);
			nb->wp += m + h;
			bb.b->rp += m;
			b->rp += m;
		} else {
			/* add header space */
			nb = padblock(bb.b, h);
			bb.b = 0;
			nb = padblock(b, h);
			b = 0;
		}
		m += s.s->diglen;
		m += s->diglen;

		/* SSL style count */
		if(pad){


@@ 809,28 828,27 @@ sslbwrite(Chan *c, Block *b, ulong offset)
			offset = 2;
		}

		switch(s.s->state){
		switch(s->state){
		case Sencrypting:
			nb = encryptb(s.s, nb, offset);
			nb = encryptb(s, nb, offset);
			break;
		case Sdigesting:
			nb = digestb(s.s, nb, offset);
			nb = digestb(s, nb, offset);
			break;
		case Sdigenc:
			nb = digestb(s.s, nb, offset);
			nb = encryptb(s.s, nb, offset);
			nb = digestb(s, nb, offset);
			nb = encryptb(s, nb, offset);
			break;
		}

		s.s->out.mid++;
		s->out.mid++;

		m = BLEN(nb);
		devtab[s.s->c->type]->bwrite(s.s->c, nb, s.s->c->offset);
		s.s->c->offset += m;
		devtab[s->c->type]->bwrite(s->c, nb, s->c->offset);
		s->c->offset += m;
	}
	qunlock(&s.s->out.q);
	poperror();

	poperror();
	return rv;
}



@@ 1033,64 1051,73 @@ parseencryptalg(char *p, Dstate *s)
}

static long
sslwrite(Chan *c, void *a, long n, vlong off)
sslwrite(Chan *c, void *a, long n, vlong)
{
	volatile struct { Dstate *s; } s;
	volatile struct { Block *b; } b;
	Dstate * volatile s;
	Block * volatile b;
	int m, t;
	char *p, *np, *e, buf[128];
	uchar *x;
	ulong offset = off;

	s.s = dstate[CONV(c->qid)];
	if(s.s == 0)
	s = dstate[CONV(c->qid)];
	if(s == 0)
		panic("sslwrite");

	t = TYPE(c->qid);
	if(t == Qdata){
		if(s.s->state == Sincomplete)
		if(s->state == Sincomplete)
			error(Ebadusefd);

		/* lock should a write gets split over multiple records */
		if(waserror()){
			qunlock(&s->out.q);
			nexterror();
		}
		qlock(&s->out.q);

		p = a;
		e = p + n;
		do {
			m = e - p;
			if(m > s.s->max)
				m = s.s->max;
			if(m > s->max)
				m = s->max;

			b.b = allocb(m);
			b = allocb(m);
			if(waserror()){
				freeb(b.b);
				freeb(b);
				nexterror();
			}
			memmove(b.b->wp, p, m);
			memmove(b->wp, p, m);
			poperror();
			b.b->wp += m;
			b->wp += m;

			sslbwrite(c, b.b, offset);
			sslput(s, b);

			p += m;
		} while(p < e);

		poperror();
		qunlock(&s->out.q);
		return n;
	}

	/* mutex with operations using what we're about to change */
	if(waserror()){
		qunlock(&s.s->in.ctlq);
		qunlock(&s.s->out.q);
		qunlock(&s->in.ctlq);
		qunlock(&s->out.q);
		nexterror();
	}
	qlock(&s.s->in.ctlq);
	qlock(&s.s->out.q);
	qlock(&s->in.ctlq);
	qlock(&s->out.q);

	switch(t){
	default:
		panic("sslwrite");
	case Qsecretin:
		setsecret(&s.s->in, a, n);
		setsecret(&s->in, a, n);
		goto out;
	case Qsecretout:
		setsecret(&s.s->out, a, n);
		setsecret(&s->out, a, n);
		goto out;
	case Qctl:
		break;


@@ 1108,46 1135,46 @@ sslwrite(Chan *c, void *a, long n, vlong off)
		*p++ = 0;

	if(strcmp(buf, "fd") == 0){
		s.s->c = buftochan(p);
		s->c = buftochan(p);

		/* default is clear (msg delimiters only) */
		s.s->state = Sclear;
		s.s->blocklen = 1;
		s.s->diglen = 0;
		s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1;
		s.s->in.mid = 0;
		s.s->out.mid = 0;
		s->state = Sclear;
		s->blocklen = 1;
		s->diglen = 0;
		s->maxpad = s->max = (1<<15) - s->diglen - 1;
		s->in.mid = 0;
		s->out.mid = 0;
	} else if(strcmp(buf, "alg") == 0 && p != 0){
		s.s->blocklen = 1;
		s.s->diglen = 0;
		s->blocklen = 1;
		s->diglen = 0;

		if(s.s->c == 0)
		if(s->c == 0)
			error("must set fd before algorithm");

		s.s->state = Sclear;
		s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1;
		s->state = Sclear;
		s->maxpad = s->max = (1<<15) - s->diglen - 1;
		if(strcmp(p, "clear") == 0){
			goto out;
		}

		if(s.s->in.secret && s.s->out.secret == 0)
			setsecret(&s.s->out, s.s->in.secret, s.s->in.slen);
		if(s.s->out.secret && s.s->in.secret == 0)
			setsecret(&s.s->in, s.s->out.secret, s.s->out.slen);
		if(s.s->in.secret == 0 || s.s->out.secret == 0)
		if(s->in.secret && s->out.secret == 0)
			setsecret(&s->out, s->in.secret, s->in.slen);
		if(s->out.secret && s->in.secret == 0)
			setsecret(&s->in, s->out.secret, s->out.slen);
		if(s->in.secret == 0 || s->out.secret == 0)
			error("algorithm but no secret");

		s.s->hf = 0;
		s.s->encryptalg = Noencryption;
		s.s->blocklen = 1;
		s->hf = 0;
		s->encryptalg = Noencryption;
		s->blocklen = 1;

		for(;;){
			np = strchr(p, ' ');
			if(np)
				*np++ = 0;

			if(parsehashalg(p, s.s) < 0)
			if(parseencryptalg(p, s.s) < 0)
			if(parsehashalg(p, s) < 0)
			if(parseencryptalg(p, s) < 0)
				error("bad algorithm");

			if(np == 0)


@@ 1155,34 1182,34 @@ sslwrite(Chan *c, void *a, long n, vlong off)
			p = np;
		}

		if(s.s->hf == 0 && s.s->encryptalg == Noencryption)
		if(s->hf == 0 && s->encryptalg == Noencryption)
			error("bad algorithm");

		if(s.s->blocklen != 1){
			s.s->max = (1<<15) - s.s->diglen - 1;
			s.s->max -= s.s->max % s.s->blocklen;
			s.s->maxpad = (1<<14) - s.s->diglen - 1;
			s.s->maxpad -= s.s->maxpad % s.s->blocklen;
		if(s->blocklen != 1){
			s->max = (1<<15) - s->diglen - 1;
			s->max -= s->max % s->blocklen;
			s->maxpad = (1<<14) - s->diglen - 1;
			s->maxpad -= s->maxpad % s->blocklen;
		} else
			s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1;
			s->maxpad = s->max = (1<<15) - s->diglen - 1;
	} else if(strcmp(buf, "secretin") == 0 && p != 0) {
		m = (strlen(p)*3)/2;
		x = smalloc(m);
		t = dec64(x, m, p, strlen(p));
		setsecret(&s.s->in, x, t);
		setsecret(&s->in, x, t);
		free(x);
	} else if(strcmp(buf, "secretout") == 0 && p != 0) {
		m = (strlen(p)*3)/2 + 1;
		x = smalloc(m);
		t = dec64(x, m, p, strlen(p));
		setsecret(&s.s->out, x, t);
		setsecret(&s->out, x, t);
		free(x);
	} else
		error(Ebadarg);

out:
	qunlock(&s.s->in.ctlq);
	qunlock(&s.s->out.q);
	qunlock(&s->in.ctlq);
	qunlock(&s->out.q);
	poperror();
	return n;
}