245 lines · 4.5 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <mp.h>#include <fcall.h>#include <thread.h>#include <9p.h>#include <libsec.h>#include <ip.h>#include "netssh.h" extern Cipher *cryptos[]; Packet *new_packet(Conn *c){	Packet *p; 	p = emalloc9p(sizeof(Packet));	init_packet(p);	p->c = c;	return p;} voidinit_packet(Packet *p){	memset(p, 0, sizeof(Packet));	p->rlength = 1;} voidadd_byte(Packet *p, char c){	p->payload[p->rlength-1] = c;	p->rlength++;} voidadd_uint32(Packet *p, ulong l){	hnputl(p->payload+p->rlength-1, l);	p->rlength += 4;} ulongget_uint32(Packet *, uchar **data){	ulong x;	x = nhgetl(*data);	*data += 4;	return x;} intadd_packet(Packet *p, void *data, int len){	if(p->rlength + len > Maxpayload)		return -1;	memmove(p->payload + p->rlength - 1, data, len);	p->rlength += len;	return 0;} voidadd_block(Packet *p, void *data, int len){	hnputl(p->payload + p->rlength - 1, len);	p->rlength += 4;	add_packet(p, data, len);} void add_string(Packet *p, char *s){	uchar *q;	int n;	uchar nn[4]; 	n = strlen(s);	hnputl(nn, n);	q = p->payload + p->rlength - 1;	memmove(q, nn, 4);	memmove(q+4, s, n);	p->rlength += n + 4;} uchar *get_string(Packet *p, uchar *q, char *s, int lim, int *len){	int n, m; 	if (p && q > p->payload + p->rlength)		s[0] = '\0';	m = nhgetl(q);	q += 4;	if(m < lim)		n = m;	else		n = lim - 1;	memmove(s, q, n);	s[n] = '\0';	q += m;	if(len)		*len = n;	return q;} voidadd_mp(Packet *p, mpint *x){	uchar *q;	int n; 	q = p->payload + p->rlength - 1;	n = mptobe(x, q + 4, Maxpktpay - p->rlength + 1 - 4, nil);	if(q[4] & 0x80){		memmove(q + 5, q + 4, n);		q[4] = 0;		n++;	}	hnputl(q, n);	p->rlength += n + 4;} mpint *get_mp(uchar *q){	return betomp(q + 4, nhgetl(q), nil);} intfinish_packet(Packet *p){	Conn *c;	uchar *q, *buf;	int blklen, i, n2, n1, maclen; 	c = p->c;	blklen = 8;	if(c && debug > 1)		fprint(2, "%s: in finish_packet: enc %d outmac %d len %ld\n",			argv0, c->encrypt, c->outmac, p->rlength);	if(c && c->encrypt != -1){		blklen = cryptos[c->encrypt]->blklen;		if(blklen < 8)			blklen = 8;	}	n1 = p->rlength - 1;	n2 = blklen - (n1 + 5) % blklen;	if(n2 < 4)		n2 += blklen;	p->pad_len = n2;	for(i = 0, q = p->payload + n1; i < n2; ++i, ++q)		*q = fastrand();	p->rlength = n1 + n2 + 1;	hnputl(p->nlength, p->rlength);	maclen = 0;	if(c && c->outmac != -1){		maclen = SHA1dlen;		buf = emalloc9p(Maxpktpay);		hnputl(buf, c->outseq);		memmove(buf + 4, p->nlength, p->rlength + 4);		hmac_sha1(buf, p->rlength + 8, c->outik, maclen, q, nil);		free(buf);	}	if(c && c->encrypt != -1)		cryptos[c->encrypt]->encrypt(c->enccs, p->nlength, p->rlength + 4);	if (c)		c->outseq++;	if(debug > 1)		fprint(2, "%s: leaving finish packet: len %ld n1 %d n2 %d maclen %d\n",			argv0, p->rlength, n1, n2, maclen);	return p->rlength + 4 + maclen;} /* * The first blklen bytes are already decrypted so we could find the * length. */intundo_packet(Packet *p){	Conn *c;	long nlength;	int nb;	uchar rmac[SHA1dlen], *buf; 	c = p->c;	nb = 4;	if(c->decrypt != -1)		nb = cryptos[c->decrypt]->blklen;	if(c->inmac != -1)		p->rlength -= SHA1dlen;			/* was magic 20 */	nlength = nhgetl(p->nlength);	if(c->decrypt != -1)		cryptos[c->decrypt]->decrypt(c->deccs, p->nlength + nb,			p->rlength + 4 - nb);	if(c->inmac != -1){		buf = emalloc9p(Maxpktpay);		hnputl(buf, c->inseq);		memmove(buf + 4, p->nlength, nlength + 4);		hmac_sha1(buf, nlength + 8, c->inik, SHA1dlen, rmac, nil);		free(buf);		if(memcmp(rmac, p->payload + nlength - 1, SHA1dlen) != 0){			fprint(2, "%s: received MAC verification failed: seq=%d\n",				argv0, c->inseq);			return -1;		}	}	c->inseq++;	p->rlength -= p->pad_len;	p->pad_len = 0;	return p->rlength - 1;} voiddump_packet(Packet *p){	int i;	char *buf, *q, *e; 	fprint(2, "Length: %ld, Padding length: %d\n", p->rlength, p->pad_len);	q = buf = emalloc9p(Copybufsz);	e = buf + Copybufsz;	for(i = 0; i < p->rlength - 1; ++i){		q = seprint(q, e, " %02x", p->payload[i]);		if(i % 16 == 15)			q = seprint(q, e, "\n");		if(q - buf > Copybufsz - 4){			fprint(2, "%s", buf);			q = buf;		}	}	fprint(2, "%s\n", buf);	free(buf);}