NetBSD/sys/ipkdb/ipkdb_ipkdb.c

1220 lines
30 KiB
C
Raw Normal View History

First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
/* $NetBSD: ipkdb_ipkdb.c,v 1.16 2006/09/08 20:58:57 elad Exp $ */
1997-06-26 11:21:44 +04:00
/*
* Copyright (C) 1993-2000 Wolfgang Solfrank.
* Copyright (C) 1993-2000 TooLs GmbH.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
2001-11-13 01:54:03 +03:00
#include <sys/cdefs.h>
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
__KERNEL_RCSID(0, "$NetBSD: ipkdb_ipkdb.c,v 1.16 2006/09/08 20:58:57 elad Exp $");
2001-11-13 01:54:03 +03:00
#include "opt_ipkdb.h"
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/mbuf.h>
#include <sys/reboot.h>
#include <sys/systm.h>
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
#include <sys/kauth.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_ether.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_inarp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <machine/cpu.h>
#include <machine/reg.h>
#include <ipkdb/ipkdb.h>
#include <machine/ipkdb.h>
int ipkdbpanic = 0;
#ifndef IPKDBKEY
#error You must specify the IPKDBKEY option to use IPKDB.
#else
static char *ipkdbkey = IPKDBKEY;
#endif
static struct ipkdb_if ipkdb_if;
static u_char *ipkdbaddr __P((u_char *, int *, void **));
static void peekmem __P((struct ipkdb_if *, u_char *, void *, long));
static void pokemem __P((struct ipkdb_if *, u_char *, void *, long));
static u_int32_t getnl __P((void *));
static u_int getns __P((void *));
static void setnl __P((void *, u_int32_t));
static void setns __P((void *, int));
static u_short cksum __P((u_short, void *, int));
static int assemble __P((struct ipkdb_if *, void *));
static char *inpkt __P((struct ipkdb_if *, char *, int));
static void outpkt __P((struct ipkdb_if *, char *, int, int, int));
static void init __P((struct ipkdb_if *));
static void *chksum __P((void *, int));
static void getpkt __P((struct ipkdb_if *, char *, int *));
static void putpkt __P((struct ipkdb_if *, char *, int));
static int check_ipkdb __P((struct ipkdb_if *, struct in_addr *, char *, int));
static int connectipkdb __P((struct ipkdb_if *, char *, int));
static int hmac_init __P((void));
void
ipkdb_init()
{
ipkdbinit();
if ( ipkdbifinit(&ipkdb_if) < 0
|| !(ipkdb_if.flags&IPKDB_MYHW)
|| !hmac_init()) {
/* Interface not found, drop IPKDB */
printf("IPKDB: No interface found!\n");
boothowto &= ~RB_KDB;
}
}
void
ipkdb_connect(when)
int when;
{
boothowto |= RB_KDB;
if (when == 0)
printf("waiting for remote debugger\n");
ipkdb_trap();
}
void
ipkdb_panic()
{
ipkdbpanic = 1;
ipkdb_trap();
}
/*
* Doesn't handle overlapping regions!
*/
void
ipkdbcopy(s, d, n)
void *s, *d;
int n;
{
char *sp = s, *dp = d;
while (--n >= 0)
*dp++ = *sp++;
}
void
ipkdbzero(d, n)
void *d;
int n;
{
char *dp = d;
while (--n >= 0)
*dp++ = 0;
}
int
ipkdbcmp(s, d, n)
void *s, *d;
int n;
{
char *sp = s, *dp = d;
while (--n >= 0)
if (*sp++ != *dp++)
return *--dp - *--sp;
return 0;
}
int
ipkdbcmds()
{
static char buf[512];
char *cp;
int plen;
if (!(ipkdb_if.flags&IPKDB_MYHW)) /* no interface */
return IPKDB_CMD_EXIT;
init(&ipkdb_if);
if (ipkdbpanic > 1) {
ipkdb_if.leave(&ipkdb_if);
return IPKDB_CMD_RUN;
}
putpkt(&ipkdb_if, "s", 1);
while (1) {
getpkt(&ipkdb_if, buf, &plen);
if (!plen) {
if (ipkdbpanic && ipkdb_poll()) {
ipkdb_if.leave(&ipkdb_if);
return IPKDB_CMD_RUN;
} else
continue;
} else
ipkdbpanic = 0;
switch (*buf) {
default:
putpkt(&ipkdb_if, "eunknown command", 16);
break;
case 'O':
/* This is an allowed reconnect, ack it */
putpkt(&ipkdb_if, "s", 1);
break;
case 'R':
peekmem(&ipkdb_if, buf, ipkdbregs, sizeof ipkdbregs);
break;
case 'W':
if (plen != sizeof ipkdbregs + 1) {
putpkt(&ipkdb_if, "einvalid register size", 22);
break;
}
pokemem(&ipkdb_if, buf + 1, ipkdbregs, sizeof ipkdbregs);
break;
case 'M':
{
void *addr, *len;
plen--;
if ( !(cp = ipkdbaddr(buf + 1, &plen, &addr))
|| !ipkdbaddr(cp, &plen, &len)) {
putpkt(&ipkdb_if, "einvalid peek format", 20);
break;
}
peekmem(&ipkdb_if, buf, addr, (long)len);
break;
}
case 'N':
{
void *addr, *len;
plen--;
if ( !(cp = ipkdbaddr(buf + 1, &plen, &addr))
|| !(cp = ipkdbaddr(cp, &plen, &len))
|| plen < (long)len) {
putpkt(&ipkdb_if, "einvalid poke format", 20);
break;
}
pokemem(&ipkdb_if, cp, addr, (long)len);
break;
}
case 'S':
ipkdb_if.leave(&ipkdb_if);
return IPKDB_CMD_STEP;
case 'X':
putpkt(&ipkdb_if, "ok",2);
ipkdb_if.leave(&ipkdb_if);
return IPKDB_CMD_EXIT;
case 'C':
ipkdb_if.leave(&ipkdb_if);
return IPKDB_CMD_RUN;
}
}
}
static u_char *
ipkdbaddr(cp, pl, dp)
u_char *cp;
int *pl;
void **dp;
{
/* Assume that sizeof(void *) <= sizeof(u_long) */
u_long l;
int i;
if ((*pl -= sizeof *dp) < 0)
return 0;
for (i = sizeof *dp, l = 0; --i >= 0;) {
l <<= 8;
l |= *cp++;
}
*dp = (void *)l;
return cp;
}
static void
peekmem(ifp, buf, addr, len)
struct ipkdb_if *ifp;
u_char *buf;
void *addr;
long len;
{
u_char *cp, *p = addr;
int l;
cp = buf;
*cp++ = 'p';
for (l = len; --l >= 0;)
*cp++ = ipkdbfbyte(p++);
putpkt(ifp, buf, len + 1);
}
static void
pokemem(ifp, cp, addr, len)
struct ipkdb_if *ifp;
u_char *cp;
void *addr;
long len;
{
u_char *p = addr;
while (--len >= 0)
ipkdbsbyte(p++, *cp++);
putpkt(ifp, "ok", 2);
}
inline static u_int32_t
getnl(vs)
void *vs;
{
u_char *s = vs;
return (*s << 24)|(s[1] << 16)|(s[2] << 8)|s[3];
}
inline static u_int
getns(vs)
void *vs;
{
u_char *s = vs;
return (*s << 8)|s[1];
}
inline static void
setnl(vs, l)
void *vs;
u_int32_t l;
{
u_char *s = vs;
*s++ = l >> 24;
*s++ = l >> 16;
*s++ = l >> 8;
*s = l;
}
inline static void
setns(vs, l)
void *vs;
int l;
{
u_char *s = vs;
*s++ = l >> 8;
*s = l;
}
static u_short
cksum(st, vcp, l)
u_short st;
void *vcp;
int l;
{
u_char *cp = vcp;
u_long s;
for (s = st; (l -= 2) >= 0; cp += 2)
s += (*cp << 8) + cp[1];
if (l == -1)
s += *cp << 8;
while (s&0xffff0000)
s = (s&0xffff) + (s >> 16);
return s == 0xffff ? 0 : s;
}
static int
assemble(ifp, buf)
struct ipkdb_if *ifp;
void *buf;
{
struct ip *ip, iph;
int off, len, i;
u_char *cp, *ecp;
ip = (struct ip *)buf;
ipkdbcopy(ip, &iph, sizeof iph);
iph.ip_hl = 5;
iph.ip_tos = 0;
iph.ip_len = 0;
iph.ip_off = 0;
iph.ip_ttl = 0;
iph.ip_sum = 0;
if (ifp->asslen) {
if (ipkdbcmp(&iph, ifp->ass, sizeof iph)) {
/*
* different packet
* decide whether to keep the old
* or start a new one
*/
i = (getns(&ip->ip_id)
^ getns(&((struct ip *)ifp->ass)->ip_id));
i ^= ((i >> 2) ^ (i >> 4) ^ (i >> 8) ^ (i >> 12));
if (i & 1)
/* keep the old */
return 0;
ifp->asslen = 0;
}
}
if (!ifp->asslen) {
ipkdbzero(ifp->assbit, sizeof ifp->assbit);
ipkdbcopy(&iph, ifp->ass, sizeof iph);
}
off = getns(&ip->ip_off);
len = ((off & IP_OFFMASK) << 3) + getns(&ip->ip_len) - ip->ip_hl * 4;
if (ifp->asslen < len)
ifp->asslen = len;
if (ifp->asslen + sizeof *ip > sizeof ifp->ass) {
/* packet too long */
ifp->asslen = 0;
return 0;
}
if (!(off & IP_MF)) {
off &= IP_OFFMASK;
cp = ifp->assbit + (off >> 3);
for (i = (off & 7); i < 8; *cp |= 1 << i++);
for (; cp < ifp->assbit + sizeof ifp->assbit; *cp++ = -1);
} else {
off &= IP_OFFMASK;
cp = ifp->assbit + (off >> 3);
ecp = ifp->assbit + (len >> 6);
if (cp == ecp)
for (i = (off & 7); i <= ((len >> 3) & 7);
*cp |= 1 << i++);
else {
for (i = (off & 7); i < 8; *cp |= 1 << i++);
for (; ++cp < ecp; *cp = -1);
for (i = 0; i < ((len >> 3) & 7); *cp |= 1 << i++);
}
}
ipkdbcopy((char *)buf + ip->ip_hl * 4,
ifp->ass + sizeof *ip + (off << 3),
len - (off << 3));
for (cp = ifp->assbit; cp < ifp->assbit + sizeof ifp->assbit;)
if (*cp++ != (u_char)-1)
/* not complete */
return 0;
ip = (struct ip *)ifp->ass;
setns(&ip->ip_len, sizeof *ip + ifp->asslen);
/* complete */
return 1;
}
static char *
inpkt(ifp, ibuf, poll)
struct ipkdb_if *ifp;
char *ibuf;
int poll;
{
int cnt = 1000000;
int l, ul;
struct ether_header *eh;
struct arphdr *ah;
struct ip *ip;
struct udphdr *udp;
struct ipovly ipo;
while (1) {
l = ifp->receive(ifp, ibuf, poll != 0);
if (!l) {
if (poll == 1 || (poll == 2 && --cnt <= 0))
break;
else
continue;
}
eh = (struct ether_header *)ibuf;
switch (getns(&eh->ether_type)) {
case ETHERTYPE_ARP:
ah = (struct arphdr *)(ibuf + 14);
if ( getns(&ah->ar_hrd) != ARPHRD_ETHER
|| getns(&ah->ar_pro) != ETHERTYPE_IP
|| ah->ar_hln != 6
|| ah->ar_pln != 4)
/* unsupported arp packet */
break;
switch (getns(&ah->ar_op)) {
case ARPOP_REQUEST:
if ( (ifp->flags&IPKDB_MYIP)
&& !ipkdbcmp(ar_tpa(ah),
ifp->myinetaddr,
sizeof ifp->myinetaddr)) {
/* someone requested my address */
ipkdbcopy(eh->ether_shost,
eh->ether_dhost,
sizeof eh->ether_dhost);
ipkdbcopy(ifp->myenetaddr,
eh->ether_shost,
sizeof eh->ether_shost);
setns(&ah->ar_op, ARPOP_REPLY);
ipkdbcopy(ar_sha(ah),
ar_tha(ah),
ah->ar_hln);
ipkdbcopy(ar_spa(ah),
ar_tpa(ah),
ah->ar_pln);
ipkdbcopy(ifp->myenetaddr,
ar_sha(ah),
ah->ar_hln);
ipkdbcopy(ifp->myinetaddr,
ar_spa(ah),
ah->ar_pln);
ifp->send(ifp, ibuf, 74);
continue;
}
break;
default:
break;
}
break;
case ETHERTYPE_IP:
ip = (struct ip *)(ibuf + 14);
if ( ip->ip_v != IPVERSION
|| ip->ip_hl < 5
|| getns(&ip->ip_len) + 14 > l)
/* invalid packet */
break;
if (cksum(0, ip, ip->ip_hl * 4))
/* wrong checksum */
break;
if (ip->ip_p != IPPROTO_UDP)
break;
if (getns(&ip->ip_off) & ~IP_DF) {
if (!assemble(ifp, ip))
break;
ip = (struct ip *)ifp->ass;
ifp->asslen = 0;
}
udp = (struct udphdr *)((char *)ip + ip->ip_hl * 4);
ul = getns(&ip->ip_len) - ip->ip_hl * 4;
if (getns(&udp->uh_ulen) != ul)
/* invalid UDP packet length */
break;
ipkdbcopy(ip, &ipo, sizeof ipo);
ipkdbzero(ipo.ih_x1, sizeof ipo.ih_x1);
ipo.ih_len = udp->uh_ulen;
if ( udp->uh_sum
&& cksum(cksum(0, &ipo, sizeof ipo), udp, ul))
/* wrong checksum */
break;
if (!(ifp->flags & IPKDB_MYIP)) {
if ( getns(&udp->uh_sport) == 67
&& getns(&udp->uh_dport) == 68
&& *(char *)(udp + 1) == 2) {
/* this is a BOOTP reply to our ethernet address */
/* should check a bit more? XXX */
char *bootp = (char *)(udp + 1);
ipkdbcopy(bootp + 16,
ifp->myinetaddr,
sizeof ifp->myinetaddr);
ifp->flags |= IPKDB_MYIP;
}
/* give caller a chance to resend his request */
return 0;
}
if ( ipkdbcmp(&ip->ip_dst, ifp->myinetaddr, sizeof ifp->myinetaddr)
|| getns(&udp->uh_dport) != IPKDBPORT)
break;
/* so now it's a UDP packet for the debugger */
{
/* Check for reconnect packet */
u_char *p;
p = (u_char *)(udp + 1);
if (!getnl(p) && p[6] == 'O') {
l = getns(p + 4);
if ( l <= ul - sizeof *udp - 6
&& check_ipkdb(ifp, &ip->ip_src,
p, l + 6)) {
ipkdbcopy(&ip->ip_src,
ifp->hisinetaddr,
sizeof ifp->hisinetaddr);
ipkdbcopy(eh->ether_shost,
ifp->hisenetaddr,
sizeof ifp->hisenetaddr);
ifp->hisport = getns(&udp->uh_sport);
ifp->flags |= IPKDB_HISHW|IPKDB_HISIP;
return p;
}
}
}
if ( (ifp->flags&IPKDB_HISIP)
&& ipkdbcmp(&ip->ip_src,
ifp->hisinetaddr, sizeof ifp->hisinetaddr))
/* It's a packet from someone else */
break;
if (!(ifp->flags&IPKDB_HISIP))
break;
return (char *)(udp + 1);
default:
/* unknown type */
break;
}
}
return 0;
}
static short ipkdb_ipid = 0;
static void
outpkt(ifp, in, l, srcport, dstport)
struct ipkdb_if *ifp;
char *in;
int l;
int srcport, dstport;
{
struct ether_header *eh;
struct ip *ip;
struct udphdr *udp;
u_char *cp;
char _obuf[ETHERMTU + 16];
#define obuf (_obuf + 2) /* align ip data in packet */
struct ipovly ipo;
int i, off;
ipkdbzero(_obuf, sizeof _obuf);
eh = (struct ether_header *)obuf;
/*
* If we don't have his ethernet address, or this is a bootp request,
* broadcast the packet.
*/
if (!(ifp->flags & IPKDB_HISHW)
|| dstport == 67)
for (cp = eh->ether_dhost;
cp < eh->ether_dhost + sizeof eh->ether_dhost;
*cp++ = -1);
else
ipkdbcopy(ifp->hisenetaddr, eh->ether_dhost, sizeof eh->ether_dhost);
ipkdbcopy(ifp->myenetaddr, eh->ether_shost, sizeof eh->ether_shost);
setns(&eh->ether_type, ETHERTYPE_IP);
ip = (struct ip *)(obuf + 14);
ip->ip_v = IPVERSION;
ip->ip_hl = 5;
setns(&ip->ip_id, ipkdb_ipid++);
ip->ip_ttl = 255;
ip->ip_p = IPPROTO_UDP;
ipkdbcopy(ifp->myinetaddr, &ip->ip_src, sizeof ip->ip_src);
/*
* If this is a bootp request, broadcast it.
*/
if (dstport == 67)
for (cp = (u_char *)&ip->ip_dst;
cp < (u_char *)&ip->ip_dst + sizeof ip->ip_dst;
*cp++ = -1);
else
ipkdbcopy(ifp->hisinetaddr, &ip->ip_dst, sizeof ip->ip_dst);
udp = (struct udphdr *)(ip + 1);
setns(&udp->uh_sport, srcport);
setns(&udp->uh_dport, dstport);
setns(&udp->uh_ulen, l + sizeof *udp);
ipkdbcopy(ip, &ipo, sizeof ipo);
ipkdbzero(ipo.ih_x1, sizeof ipo.ih_x1);
ipo.ih_len = udp->uh_ulen;
setns(&udp->uh_sum,
~cksum(cksum(cksum(0, &ipo, sizeof ipo),
udp, sizeof *udp),
in, l));
for (cp = (u_char *)(udp + 1), l += sizeof *udp, off = 0;
l > 0;
l -= i, in += i, off += i, cp = (u_char *)udp) {
i = l > ifp->mtu - sizeof *ip ? ((ifp->mtu - sizeof *ip) & ~7) : l;
ipkdbcopy(in, cp, i);
setns(&ip->ip_len, i + sizeof *ip);
setns(&ip->ip_off, (l > i ? IP_MF : 0) | (off >> 3));
ip->ip_sum = 0;
setns(&ip->ip_sum, ~cksum(0, ip, sizeof *ip));
if (i + sizeof *ip < ETHERMIN)
i = ETHERMIN - sizeof *ip;
ifp->send(ifp, obuf, i + sizeof *ip + 14);
}
#undef obuf
}
static void
init(ifp)
struct ipkdb_if *ifp;
{
u_char *cp;
u_char _ibuf[ETHERMTU + 16];
#define ibuf (_ibuf + 2) /* align ip data in packet */
int secs = 0;
ifp->start(ifp);
if (ifp->flags & IPKDB_MYIP)
return;
while (!(ifp->flags & IPKDB_MYIP)) {
ipkdbzero(_ibuf, sizeof _ibuf);
cp = _ibuf;
*cp++ = 1; /* BOOTP_REQUEST */
*cp++ = 1; /* Ethernet hardware */
*cp++ = 6; /* length of address */
setnl(++cp, 0x12345678); /* some random number? */
setns(cp + 4, secs++);
ipkdbcopy(ifp->myenetaddr, cp + 24, sizeof ifp->myenetaddr);
outpkt(ifp, _ibuf, 300, 68, 67);
inpkt(ifp, ibuf, 2);
if (ipkdbpanic && ipkdb_poll()) {
ipkdbpanic++;
return;
}
}
cp = ifp->myinetaddr;
printf("My IP address is %d.%d.%d.%d\n",
cp[0], cp[1], cp[2], cp[3]);
#undef ibuf
}
/* HMAC Checksumming routines, see draft-ietf-ipsec-hmac-md5-00.txt */
#define LENCHK 16 /* Length of checksum in bytes */
/*
* This code is based on the MD5 implementation as found in ssh.
* It's quite a bit hacked by myself, but the original has
* the following non-copyright comments on it:
*/
/* This code has been heavily hacked by Tatu Ylonen <ylo@cs.hut.fi> to
make it compile on machines like Cray that don't have a 32 bit integer
type. */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*/
static struct ipkdb_MD5Context {
u_int buf[4];
u_int bits[2];
u_char in[64];
} icontext, ocontext;
static u_int32_t getNl __P((void *));
static void setNl __P((void *, u_int32_t));
static void ipkdb_MD5Transform __P((struct ipkdb_MD5Context *));
static void ipkdb_MD5Init __P((struct ipkdb_MD5Context *));
static void ipkdb_MD5Update __P((struct ipkdb_MD5Context *, u_char *, u_int));
static u_char *ipkdb_MD5Final __P((struct ipkdb_MD5Context *));
inline static u_int32_t
getNl(vs)
void *vs;
{
u_char *s = vs;
return *s | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
}
inline static void
setNl(vs, l)
void *vs;
u_int32_t l;
{
u_char *s = vs;
*s++ = l;
*s++ = l >> 8;
*s++ = l >> 16;
*s = l >> 24;
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (((x) & (y)) | (~(x) & (z))) */
#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) ((x) ^ (y) ^ (z))
#define F4(x, y, z) ((y) ^ ((x) | ~(z)))
/* This is the central step in the MD5 algorithm. */
#define ipkdb_MD5STEP(f, w, x, y, z, data, s) \
((w) += f(x, y, z) + (data), \
(w) = ((w) << (s)) | (((w) >> (32 - s)) & 0xffffffff), \
(w) += (x))
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data for this routine.
*/
static void
ipkdb_MD5Transform(ctx)
struct ipkdb_MD5Context *ctx;
{
u_int a, b, c, d, i;
u_int in[16];
2005-02-27 01:58:54 +03:00
for (i = 0; i < 16; i++)
in[i] = getNl(ctx->in + 4 * i);
2005-02-27 01:58:54 +03:00
a = ctx->buf[0];
b = ctx->buf[1];
c = ctx->buf[2];
d = ctx->buf[3];
ipkdb_MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
ipkdb_MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
ipkdb_MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
ipkdb_MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
ipkdb_MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
ipkdb_MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
ipkdb_MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
ipkdb_MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
ipkdb_MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
ipkdb_MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
ipkdb_MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
ipkdb_MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
ipkdb_MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
ipkdb_MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
ipkdb_MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
ipkdb_MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
ipkdb_MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
ipkdb_MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
ipkdb_MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
ipkdb_MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
ipkdb_MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
ipkdb_MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
ipkdb_MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
ipkdb_MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
ipkdb_MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
ipkdb_MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
ipkdb_MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
ipkdb_MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
ipkdb_MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
ipkdb_MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
ipkdb_MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
ipkdb_MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
ipkdb_MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
ipkdb_MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
ipkdb_MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
ipkdb_MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
ipkdb_MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
ipkdb_MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
ipkdb_MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
ipkdb_MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
ipkdb_MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
ipkdb_MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
ipkdb_MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
ipkdb_MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
ipkdb_MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
ipkdb_MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
ipkdb_MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
ipkdb_MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
ipkdb_MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
ipkdb_MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
ipkdb_MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
ipkdb_MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
ipkdb_MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
ipkdb_MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
ipkdb_MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
ipkdb_MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
ipkdb_MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
ipkdb_MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
ipkdb_MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
ipkdb_MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
ipkdb_MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
ipkdb_MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
ipkdb_MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
ipkdb_MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
ctx->buf[0] += a;
ctx->buf[1] += b;
ctx->buf[2] += c;
ctx->buf[3] += d;
}
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
static void
ipkdb_MD5Init(ctx)
struct ipkdb_MD5Context *ctx;
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
2005-02-27 01:58:54 +03:00
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
static void
ipkdb_MD5Update(ctx, buf, len)
struct ipkdb_MD5Context *ctx;
u_char *buf;
unsigned len;
{
u_int t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = (t + (len << 3)) & 0xffffffff) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += (len >> 29) & 0xffffffff;
2005-02-27 01:58:54 +03:00
t = (t >> 3) & 0x3f; /* Bytes already in ctx->in */
2005-02-27 01:58:54 +03:00
/* Handle any leading odd-sized chunks */
if (t) {
u_char *p = ctx->in + t;
2005-02-27 01:58:54 +03:00
t = 64 - t;
if (len < t) {
ipkdbcopy(buf, p, len);
return;
}
ipkdbcopy(buf, p, t);
ipkdb_MD5Transform(ctx);
buf += t;
len -= t;
}
2005-02-27 01:58:54 +03:00
/* Process data in 64-byte chunks */
while (len >= 64) {
ipkdbcopy(buf, ctx->in, 64);
ipkdb_MD5Transform(ctx);
buf += 64;
len -= 64;
}
2005-02-27 01:58:54 +03:00
/* Handle any remaining bytes of data. */
ipkdbcopy(buf, ctx->in, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, LSB-first)
*/
static u_char *
ipkdb_MD5Final(ctx)
struct ipkdb_MD5Context *ctx;
{
static u_char digest[16];
unsigned count;
u_char *p;
2005-02-27 01:58:54 +03:00
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3f;
2005-02-27 01:58:54 +03:00
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
2005-02-27 01:58:54 +03:00
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
2005-02-27 01:58:54 +03:00
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
ipkdbzero(p, count);
ipkdb_MD5Transform(ctx);
2005-02-27 01:58:54 +03:00
/* Now fill the next block with 56 bytes */
ipkdbzero(ctx->in, 56);
} else
/* Pad block to 56 bytes */
ipkdbzero(p, count - 8);
2005-02-27 01:58:54 +03:00
/* Append length in bits and transform */
setNl(ctx->in + 56, ctx->bits[0]);
setNl(ctx->in + 60, ctx->bits[1]);
2005-02-27 01:58:54 +03:00
ipkdb_MD5Transform(ctx);
setNl(digest, ctx->buf[0]);
setNl(digest + 4, ctx->buf[1]);
setNl(digest + 8, ctx->buf[2]);
setNl(digest + 12, ctx->buf[3]);
return digest;
}
/*
* The following code is more or less stolen from the hmac_md5
* function in the Appendix of the HMAC IETF draft, but is
* optimized as suggested in this same paper.
*/
static int
hmac_init()
{
char pad[64];
char tk[16];
u_char *key = ipkdbkey;
int key_len = strlen(key);
int i;
/* Require key to be at least 16 bytes long */
if (key_len < 16) {
printf("IPKDBKEY must be at least 16 bytes long!\n");
ipkdbzero(key, key_len); /* XXX */
return 0;
}
/* if key is longer than 64 bytes reset it to key=MD5(key) */
if (key_len > 64) {
ipkdb_MD5Init(&icontext);
ipkdb_MD5Update(&icontext, key, key_len);
ipkdbcopy(ipkdb_MD5Final(&icontext), tk, 16);
ipkdbzero(key, key_len); /* XXX */
key = tk;
key_len = 16;
}
/*
* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is and n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/*
* We do the initial part of MD5(K XOR ipad)
* and MD5(K XOR opad) here, in order to
* speed up the computation later on.
*/
ipkdbzero(pad, sizeof pad);
ipkdbcopy(key, pad, key_len);
for (i = 0; i < 64; i++)
pad[i] ^= 0x36;
ipkdb_MD5Init(&icontext);
ipkdb_MD5Update(&icontext, pad, 64);
2005-02-27 01:58:54 +03:00
ipkdbzero(pad, sizeof pad);
ipkdbcopy(key, pad, key_len);
for (i = 0; i < 64; i++)
pad[i] ^= 0x5c;
ipkdb_MD5Init(&ocontext);
ipkdb_MD5Update(&ocontext, pad, 64);
/* Zero out the key XXX */
ipkdbzero(key, key_len);
return 1;
}
/*
* This is more or less hmac_md5 from the HMAC IETF draft, Appendix.
*/
static void *
chksum(buf, len)
void *buf;
int len;
{
u_char *digest;
struct ipkdb_MD5Context context;
2005-02-27 01:58:54 +03:00
/*
* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/*
* Since we've already done the precomputation,
* we can now stuff the data into the relevant
* preinitialized contexts to get the result.
*/
/*
* perform inner MD5
*/
ipkdbcopy(&icontext, &context, sizeof context);
ipkdb_MD5Update(&context, buf, len);
digest = ipkdb_MD5Final(&context);
/*
* perform outer MD5
*/
ipkdbcopy(&ocontext, &context, sizeof context);
ipkdb_MD5Update(&context, digest, 16);
return ipkdb_MD5Final(&context);
}
static void
getpkt(ifp, buf, lp)
struct ipkdb_if *ifp;
char *buf;
int *lp;
{
char *got;
int l;
char _ibuf[ETHERMTU + 16];
#define ibuf (_ibuf + 2) /* align ip data in packet */
*lp = 0;
while (1) {
if (!(got = inpkt(ifp, ibuf, ipkdbpanic != 0))) {
*lp = 0;
return;
}
if ( ifp->seq == getnl(got)
&& got[6] >= 'A'
&& got[6] <= 'Z'
&& (l = getns(got + 4))
&& !ipkdbcmp(chksum(got, l + 6), got + l + 6, LENCHK)) {
ipkdbcopy(got + 6, buf, *lp = l);
return;
}
if ( ifp->pktlen
&& ((ifp->flags & (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
== (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED)))
outpkt(ifp, ifp->pkt, ifp->pktlen, IPKDBPORT, ifp->hisport);
}
#undef ibuf
}
static void
putpkt(ifp, buf, l)
struct ipkdb_if *ifp;
char *buf;
int l;
{
setnl(ifp->pkt, ifp->seq++);
setns(ifp->pkt + 4, l);
ipkdbcopy(buf, ifp->pkt + 6, l);
ipkdbcopy(chksum(ifp->pkt, l + 6), ifp->pkt + 6 + l, LENCHK);
ifp->pktlen = l + 6 + LENCHK;
if ( (ifp->flags & (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
!= (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
return;
outpkt(ifp, ifp->pkt, ifp->pktlen, IPKDBPORT, ifp->hisport);
}
static int
check_ipkdb(ifp, shost, p, l)
struct ipkdb_if *ifp;
struct in_addr *shost;
char *p;
int l;
{
u_char hisenet[6];
u_char hisinet[4];
u_int16_t hisport;
char save;
#ifndef IPKDBSECURE
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
if (kauth_authorize_system(curlwp->l_cred, KAUTH_SYSTEM_IPKDB,
NULL, NULL, NULL, NULL) != KAUTH_RESULT_ALLOW)
return 0;
#endif
if (ipkdbcmp(chksum(p, l), p + l, LENCHK))
return 0;
ipkdbcopy(ifp->hisenetaddr, hisenet, sizeof hisenet);
ipkdbcopy(ifp->hisinetaddr, hisinet, sizeof hisinet);
hisport = ifp->hisport;
save = ifp->flags;
ipkdbcopy(shost, ifp->hisinetaddr, sizeof ifp->hisinetaddr);
ifp->flags &= ~IPKDB_HISHW;
ifp->flags |= IPKDB_HISIP;
if (connectipkdb(ifp, p + 6, l - 6) < 0) {
ipkdbcopy(hisenet, ifp->hisenetaddr, sizeof ifp->hisenetaddr);
ipkdbcopy(hisinet, ifp->hisinetaddr, sizeof ifp->hisinetaddr);
ifp->hisport = hisport;
ifp->flags = save;
return 0;
}
return 1;
}
/*
* Should check whether packet came across the correct interface. XXX
*/
int
checkipkdb(shost, sport, dport, m, off, len)
struct in_addr *shost;
u_short sport, dport;
struct mbuf *m;
int off, len;
{
char *p;
int l;
char ibuf[ETHERMTU+50];
if (dport != IPKDBPORT)
return 0;
if (len > sizeof ibuf)
return 0;
m_copydata(m, off, len, ibuf);
p = ibuf;
if (getnl(p) || p[6] != 'O')
return 0;
l = getns(p + 4);
if (l > len - 6 || !check_ipkdb(&ipkdb_if, shost, p, l + 6))
return 0;
ipkdb_if.hisport = sport;
ipkdb_connect(1);
return 1;
}
static int
connectipkdb(ifp, buf, l)
struct ipkdb_if *ifp;
char *buf;
int l;
{
char *cp;
u_char *ip;
if (*buf != 'O')
return -1;
if (getnl(buf + 1) == ifp->id)
/* It's a retry of a connect packet, ignore it */
return -1;
ip = ifp->hisinetaddr;
printf("debugged by ");
l -= 1 + sizeof(u_int32_t);
for (cp = buf + 1 + sizeof(u_int32_t); --l >= 0; printf("%c", *cp++));
printf(" (%d.%d.%d.%d)\n", ip[0], ip[1], ip[2], ip[3]);
ifp->flags |= IPKDB_CONNECTED;
ifp->seq = 0;
ifp->pktlen = 0;
ifp->id = getnl(buf + 1);
return 0;
}