Ejemplo n.º 1
0
Archivo: esp.c Proyecto: npe9/harvey
static char*
espconnect(Conv *c, char **argv, int argc)
{
	char *p, *pp, *e = nil;
	uint32_t 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;
		if (parseip(c->raddr, argv[1]) == -1) {
			e = Ebadip;
			break;
		}
		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;
}
Ejemplo n.º 2
0
Archivo: esp.c Proyecto: npe9/harvey
/* called from icmp(v6) for unreachable hosts, time exceeded, etc. */
void
espadvise(Proto *esp, Block *bp, char *msg)
{
	Conv *c;
	Versdep vers;

	getverslens(pktipvers(esp->f, &bp), &vers);
	getpktspiaddrs(bp->rp, &vers);

	qlock(esp);
	c = convlookup(esp, vers.spi);
	if(c != nil) {
		qhangup(c->rq, msg);
		qhangup(c->wq, msg);
	}
	qunlock(esp);
	freeblist(bp);
}
Ejemplo n.º 3
0
Archivo: esp.c Proyecto: 8l/inferno
void
espadvise(Proto *esp, Block *bp, char *msg)
{
	Esphdr *h;
	Conv *c;
	ulong spi;

	h = (Esphdr*)(bp->rp);

	spi = nhgets(h->espspi);
	qlock(esp);
	c = convlookup(esp, spi);
	if(c != nil) {
		qhangup(c->rq, msg);
		qhangup(c->wq, msg);
	}
	qunlock(esp);
	freeblist(bp);
}
Ejemplo n.º 4
0
Archivo: esp.c Proyecto: npe9/harvey
/*
 * decapsulate IP packet from IP/ESP packet in bp and
 * pass the result up the spi's Conv's read queue.
 */
void
espiput(Proto *esp, Ipifc *ipifc, Block *bp)
{
	Mach *m = machp();
	int payload, nexthdr;
	uint8_t *auth, *espspi;
	Conv *c;
	Espcb *ecb;
	Esptail *et;
	Fs *f;
	Userhdr *uh;
	Versdep vers;

	f = esp->f;

	getverslens(pktipvers(f, &bp), &vers);

	bp = pullupblock(bp, vers.hdrlen + Esptaillen);
	if(bp == nil) {
		netlog(f, Logesp, "esp: short packet\n");
		return;
	}
	getpktspiaddrs(bp->rp, &vers);

	qlock(esp);
	/* Look for a conversation structure for this port */
	c = convlookup(esp, vers.spi);
	if(c == nil) {
		qunlock(esp);
		netlog(f, Logesp, "esp: no conv %I -> %I!%lud\n", vers.raddr,
			vers.laddr, vers.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) < vers.hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) {
		qunlock(c);
		netlog(f, Logesp, "esp: short block %I -> %I!%lud\n", vers.raddr,
			vers.laddr, vers.spi);
		freeb(bp);
		return;
	}

	auth = bp->wp - ecb->ahlen;
	espspi = vers.version == V4?	((Esp4hdr*)bp->rp)->espspi:
					((Esp6hdr*)bp->rp)->espspi;

	/* compute secure hash and authenticate */
	if(!ecb->auth(ecb, espspi, auth - espspi, auth)) {
		qunlock(c);
print("esp: bad auth %I -> %I!%ld\n", vers.raddr, vers.laddr, vers.spi);
		netlog(f, Logesp, "esp: bad auth %I -> %I!%lud\n", vers.raddr,
			vers.laddr, vers.spi);
		freeb(bp);
		return;
	}

	payload = BLEN(bp) - vers.hdrlen - ecb->ahlen;
	if(payload <= 0 || payload % 4 != 0 || payload % ecb->espblklen != 0) {
		qunlock(c);
		netlog(f, Logesp, "esp: bad length %I -> %I!%lud payload=%d BLEN=%lud\n",
			vers.raddr, vers.laddr, vers.spi, payload, BLEN(bp));
		freeb(bp);
		return;
	}

	/* decrypt payload */
	if(!ecb->cipher(ecb, bp->rp + vers.hdrlen, payload)) {
		qunlock(c);
print("esp: cipher failed %I -> %I!%ld: %s\n", vers.raddr, vers.laddr, vers.spi, m->externup->errstr);
		netlog(f, Logesp, "esp: cipher failed %I -> %I!%lud: %s\n",
			vers.raddr, vers.laddr, vers.spi, m->externup->errstr);
		freeb(bp);
		return;
	}

	payload -= Esptaillen;
	et = (Esptail*)(bp->rp + vers.hdrlen + payload);
	payload -= et->pad + ecb->espivlen;
	nexthdr = et->nexthdr;
	if(payload <= 0) {
		qunlock(c);
		netlog(f, Logesp, "esp: short packet after decrypt %I -> %I!%lud\n",
			vers.raddr, vers.laddr, vers.spi);
		freeb(bp);
		return;
	}

	/* trim packet */
	bp->rp += vers.hdrlen + ecb->espivlen; /* toss original IP & ESP hdrs */
	bp->wp = bp->rp + payload;
	if(ecb->header) {
		/* assume Userhdrlen < Esp4hdrlen < Esp6hdrlen */
		bp->rp -= Userhdrlen;
		uh = (Userhdr*)bp->rp;
		memset(uh, 0, Userhdrlen);
		uh->nexthdr = nexthdr;
	}

	/* ingress filtering here? */

	if(qfull(c->rq)){
		netlog(f, Logesp, "esp: qfull %I -> %I.%uld\n", vers.raddr,
			vers.laddr, vers.spi);
		freeblist(bp);
	}else {
//		print("esp: pass up: %uld\n", BLEN(bp));
		qpass(c->rq, bp);	/* pass packet up the read queue */
	}

	qunlock(c);
}
Ejemplo n.º 5
0
Archivo: esp.c Proyecto: 8l/inferno
void
espiput(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);
}