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

📄 esp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	"ip.h"#include	"libsec.h"typedef struct Esphdr Esphdr;typedef struct Esptail Esptail;typedef struct Userhdr Userhdr;typedef struct Esppriv Esppriv;typedef struct Espcb Espcb;typedef struct Algorithm Algorithm;typedef struct Esprc4 Esprc4;#define DPRINT if(0)printenum{	IP_ESPPROTO	= 50,	EsphdrSize	= 28,	// includes IP header	IphdrSize	= 20,	// options have been striped	EsptailSize	= 2,	// does not include pad or auth data	UserhdrSize	= 4,	// user visable header size - if enabled};struct Esphdr{	/* ip header */	uchar	vihl;		/* Version and header length */	uchar	tos;		/* Type of service */	uchar	length[2];	/* packet length */	uchar	id[2];		/* Identification */	uchar	frag[2];	/* Fragment information */	uchar	Unused;		uchar	espproto;	/* Protocol */	uchar	espplen[2];	/* Header plus data length */	uchar	espsrc[4];	/* Ip source */	uchar	espdst[4];	/* Ip destination */	/* esp header */	uchar	espspi[4];	/* Security parameter index */	uchar	espseq[4];	/* Sequence number */};struct Esptail{	uchar	pad;	uchar	nexthdr;};/* header as seen by the user */struct Userhdr{	uchar	nexthdr;	// next protocol	uchar	unused[3];};struct Esppriv{	ulong	in;	ulong	inerrors;};/* *  protocol specific part of Conv */struct Espcb{	int	incoming;	int	header;		// user user level header	ulong	spi;	ulong	seq;		// last seq sent	ulong	window;		// for replay attacks	char	*espalg;	void	*espstate;	// other state for esp	int	espivlen;	// in bytes	int	espblklen;	int	(*cipher)(Espcb*, uchar *buf, int len);	char	*ahalg;	void	*ahstate;	// other state for esp	int	ahlen;		// auth data length in bytes	int	ahblklen;	int	(*auth)(Espcb*, uchar *buf, int len, uchar *hash);};struct Algorithm{	char 	*name;	int	keylen;		// in bits	void	(*init)(Espcb*, char* name, uchar *key, int keylen);};enum {	RC4forward	= 10*1024*1024,	// maximum skip forward	RC4back = 100*1024,		// maximum look back};struct Esprc4{	ulong cseq;	// current byte sequence number	RC4state current;	int ovalid;	// old is valid	ulong lgseq; // last good sequence	ulong oseq;	// old byte sequence number	RC4state old;};static	Conv* convlookup(Proto *esp, ulong spi);static	char *setalg(Espcb *ecb, char **f, int n, Algorithm *alg);static	void nullespinit(Espcb*, char*, uchar *key, int keylen);static	void nullahinit(Espcb*, char*, uchar *key, int keylen);static	void shaahinit(Espcb*, char*, uchar *key, int keylen);static	void md5ahinit(Espcb*, char*, uchar *key, int keylen);static	void desespinit(Espcb *ecb, char *name, uchar *k, int n);static	void rc4espinit(Espcb *ecb, char *name, uchar *k, int n);static	void espkick(void *x);static Algorithm espalg[] ={	"null",			0,	nullespinit,	"des_56_cbc",		64,	desespinit,	"rc4_128",		128,	rc4espinit,	nil,			0,	nil,};static Algorithm ahalg[] ={	"null",			0,	nullahinit,	"hmac_sha1_96",		128,	shaahinit,	"hmac_md5_96",		128,	md5ahinit,	nil,			0,	nil,};static char*espconnect(Conv *c, char **argv, int argc){	char *p, *pp;	char *e = nil;	ulong spi;	Espcb *ecb = (Espcb*)c->ptcl;	switch(argc) {	default:		e = "bad args to connect";		break;	case 2:		p = strchr(argv[1], '!');		if(p == nil){			e = "malformed address";			break;		}		*p++ = 0;		parseip(c->raddr, argv[1]);		findlocalip(c->p->f, c->laddr, c->raddr);		ecb->incoming = 0;		ecb->seq = 0;		if(strcmp(p, "*") == 0) {			qlock(c->p);			for(;;) {				spi = nrand(1<<16) + 256;				if(convlookup(c->p, spi) == nil)					break;			}			qunlock(c->p);			ecb->spi = spi;			ecb->incoming = 1;			qhangup(c->wq, nil);		} else {			spi = strtoul(p, &pp, 10);			if(pp == p) {				e = "malformed address";				break;			}			ecb->spi = spi;			qhangup(c->rq, nil);		}		nullespinit(ecb, "null", nil, 0);		nullahinit(ecb, "null", nil, 0);	}	Fsconnected(c, e);	return e;}static intespstate(Conv *c, char *state, int n){	return snprint(state, n, "%s", c->inuse?"Open\n":"Closed\n");}static voidespcreate(Conv *c){	c->rq = qopen(64*1024, Qmsg, 0, 0);	c->wq = qopen(64*1024, Qkick, espkick, c);}static voidespclose(Conv *c){	Espcb *ecb;	qclose(c->rq);	qclose(c->wq);	qclose(c->eq);	ipmove(c->laddr, IPnoaddr);	ipmove(c->raddr, IPnoaddr);	ecb = (Espcb*)c->ptcl;	free(ecb->espstate);	free(ecb->ahstate);	memset(ecb, 0, sizeof(Espcb));}static voidespkick(void *x){	Conv *c = x;	Esphdr *eh;	Esptail *et;	Userhdr *uh;	Espcb *ecb;	Block *bp;	int nexthdr;	int payload;	int pad;	int align;	uchar *auth;	bp = qget(c->wq);	if(bp == nil)		return;	qlock(c);	ecb = c->ptcl;	if(ecb->header) {		/* make sure the message has a User header */		bp = pullupblock(bp, UserhdrSize);		if(bp == nil) {			qunlock(c);			return;		}		uh = (Userhdr*)bp->rp;		nexthdr = uh->nexthdr;		bp->rp += UserhdrSize;	} else {		nexthdr = 0;  // what should this be?	}	payload = BLEN(bp) + ecb->espivlen;	/* Make space to fit ip header */	bp = padblock(bp, EsphdrSize + ecb->espivlen);	align = 4;	if(ecb->espblklen > align)		align = ecb->espblklen;	if(align % ecb->ahblklen != 0)		panic("espkick: ahblklen is important after all");	pad = (align-1) - (payload + EsptailSize-1)%align;	/*	 * Make space for tail	 * this is done by calling padblock with a negative size	 * Padblock does not change bp->wp!	 */	bp = padblock(bp, -(pad+EsptailSize+ecb->ahlen));	bp->wp += pad+EsptailSize+ecb->ahlen;	eh = (Esphdr *)(bp->rp);	et = (Esptail*)(bp->rp + EsphdrSize + payload + pad);	// fill in tail	et->pad = pad;	et->nexthdr = nexthdr;	ecb->cipher(ecb, bp->rp+EsphdrSize, payload+pad+EsptailSize);	auth = bp->rp + EsphdrSize + payload + pad + EsptailSize;	// fill in head	eh->vihl = IP_VER4;	hnputl(eh->espspi, ecb->spi);	hnputl(eh->espseq, ++ecb->seq);	v6tov4(eh->espsrc, c->laddr);	v6tov4(eh->espdst, c->raddr);	eh->espproto = IP_ESPPROTO;	eh->frag[0] = 0;	eh->frag[1] = 0;	ecb->auth(ecb, bp->rp+IphdrSize, (EsphdrSize-IphdrSize)+payload+pad+EsptailSize, auth);	qunlock(c);	//print("esp: pass down: %uld\n", BLEN(bp));	ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);}voidespiput(Proto *esp, Ipifc*, Block *bp){	Esphdr *eh;	Esptail *et;	Userhdr *uh;	Conv *c;	Espcb *ecb;	uchar raddr[IPaddrlen], laddr[IPaddrlen];	Fs *f;	uchar *auth;	ulong spi;	int payload, nexthdr;	f = esp->f;	bp = pullupblock(bp, EsphdrSize+EsptailSize);	if(bp == nil) {		netlog(f, Logesp, "esp: short packet\n");		return;	}	eh = (Esphdr*)(bp->rp);	spi = nhgetl(eh->espspi);	v4tov6(raddr, eh->espsrc);	v4tov6(laddr, eh->espdst);	qlock(esp);	/* Look for a conversation structure for this port */	c = convlookup(esp, spi);	if(c == nil) {		qunlock(esp);		netlog(f, Logesp, "esp: no conv %I -> %I!%d\n", raddr,			laddr, spi);		icmpnoconv(f, bp);		freeblist(bp);		return;	}	qlock(c);	qunlock(esp);	ecb = c->ptcl;	// too hard to do decryption/authentication on block lists	if(bp->next)		bp = concatblock(bp);	if(BLEN(bp) < EsphdrSize + ecb->espivlen + EsptailSize + ecb->ahlen) {		qunlock(c);		netlog(f, Logesp, "esp: short block %I -> %I!%d\n", raddr,			laddr, spi);		freeb(bp);		return;	}	eh = (Esphdr*)(bp->rp);	auth = bp->wp - ecb->ahlen;	if(!ecb->auth(ecb, eh->espspi, auth-eh->espspi, auth)) {		qunlock(c);print("esp: bad auth %I -> %I!%ld\n", raddr, laddr, spi);		netlog(f, Logesp, "esp: bad auth %I -> %I!%d\n", raddr,			laddr, spi);		freeb(bp);		return;	}	payload = BLEN(bp)-EsphdrSize-ecb->ahlen;	if(payload<=0 || payload%4 != 0 || payload%ecb->espblklen!=0) {		qunlock(c);		netlog(f, Logesp, "esp: bad length %I -> %I!%d payload=%d BLEN=%d\n", raddr,			laddr, spi, payload, BLEN(bp));		freeb(bp);		return;	}	if(!ecb->cipher(ecb, bp->rp+EsphdrSize, payload)) {		qunlock(c);print("esp: cipher failed %I -> %I!%ld: %r\n", raddr, laddr, spi);		netlog(f, Logesp, "esp: cipher failed %I -> %I!%d: %r\n", raddr,			laddr, spi);		freeb(bp);		return;	}	payload -= EsptailSize;	et = (Esptail*)(bp->rp + EsphdrSize + payload);	payload -= et->pad + ecb->espivlen;	nexthdr = et->nexthdr;	if(payload <= 0) {		qunlock(c);		netlog(f, Logesp, "esp: short packet after decrypt %I -> %I!%d\n", raddr,			laddr, spi);		freeb(bp);		return;	}	// trim packet	bp->rp += EsphdrSize + ecb->espivlen;	bp->wp = bp->rp + payload;	if(ecb->header) {		// assume UserhdrSize < EsphdrSize		bp->rp -= UserhdrSize;		uh = (Userhdr*)bp->rp;		memset(uh, 0, UserhdrSize);		uh->nexthdr = nexthdr;	}	if(qfull(c->rq)){		netlog(f, Logesp, "esp: qfull %I -> %I.%uld\n", raddr,			laddr, spi);		freeblist(bp);	}else {//print("esp: pass up: %uld\n", BLEN(bp));		qpass(c->rq, bp);	}	qunlock(c);}char*espctl(Conv *c, char **f, int n){	Espcb *ecb = c->ptcl;	char *e = nil;	if(strcmp(f[0], "esp") == 0)		e = setalg(ecb, f, n, espalg);	else if(strcmp(f[0], "ah") == 0)		e = setalg(ecb, f, n, ahalg);	else if(strcmp(f[0], "header") == 0)

⌨️ 快捷键说明

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