2009-10-03 02:05:52 +04:00
|
|
|
/* $NetBSD: ipkdb_ipkdb.c,v 1.27 2009/10/02 22:05:52 elad Exp $ */
|
1997-06-26 11:21:44 +04:00
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
/*
|
2000-03-22 23:58:25 +03:00
|
|
|
* Copyright (C) 1993-2000 Wolfgang Solfrank.
|
|
|
|
* Copyright (C) 1993-2000 TooLs GmbH.
|
1996-09-30 20:16:45 +04:00
|
|
|
* 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>
|
2009-10-03 02:05:52 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: ipkdb_ipkdb.c,v 1.27 2009/10/02 22:05:52 elad Exp $");
|
2001-11-13 01:54:03 +03:00
|
|
|
|
2000-03-22 23:58:25 +03:00
|
|
|
#include "opt_ipkdb.h"
|
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
#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>
|
2007-10-19 15:59:34 +04:00
|
|
|
#include <sys/cpu.h>
|
1996-09-30 20:16:45 +04:00
|
|
|
|
|
|
|
#include <net/if.h>
|
1997-04-19 05:52:15 +04:00
|
|
|
#include <net/if_arp.h>
|
1997-03-15 21:09:08 +03:00
|
|
|
#include <net/if_ether.h>
|
1996-09-30 20:16:45 +04:00
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
1997-03-15 21:09:08 +03:00
|
|
|
#include <netinet/if_inarp.h>
|
1996-09-30 20:16:45 +04:00
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <netinet/ip_var.h>
|
|
|
|
#include <netinet/udp.h>
|
|
|
|
|
|
|
|
#include <machine/reg.h>
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
#include <ipkdb/ipkdb.h>
|
|
|
|
#include <machine/ipkdb.h>
|
1996-09-30 20:16:45 +04:00
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
int ipkdbpanic = 0;
|
1996-09-30 20:16:45 +04:00
|
|
|
|
2002-10-11 04:50:30 +04:00
|
|
|
#ifndef IPKDBKEY
|
|
|
|
#error You must specify the IPKDBKEY option to use IPKDB.
|
|
|
|
#else
|
2007-01-13 21:54:43 +03:00
|
|
|
static char ipkdbkey[] = IPKDBKEY;
|
2002-10-11 04:50:30 +04:00
|
|
|
#endif
|
2000-03-22 23:58:25 +03:00
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
static struct ipkdb_if ipkdb_if;
|
1996-09-30 20:16:45 +04:00
|
|
|
|
2009-10-03 02:05:52 +04:00
|
|
|
static kauth_listener_t ipkdb_listener;
|
|
|
|
|
2009-03-14 17:45:51 +03:00
|
|
|
static u_char *ipkdbaddr(u_char *, int *, void **);
|
|
|
|
static void peekmem(struct ipkdb_if *, u_char *, void *, long);
|
|
|
|
static void pokemem(struct ipkdb_if *, u_char *, void *, long);
|
|
|
|
static u_int32_t getnl(void *);
|
|
|
|
static u_int getns(void *);
|
|
|
|
static void setnl(void *, u_int32_t);
|
|
|
|
static void setns(void *, int);
|
|
|
|
static u_short cksum(u_short, void *, int);
|
|
|
|
static int assemble(struct ipkdb_if *, void *);
|
|
|
|
static char *inpkt(struct ipkdb_if *, char *, int);
|
|
|
|
static void outpkt(struct ipkdb_if *, char *, int, int, int);
|
|
|
|
static void init(struct ipkdb_if *);
|
|
|
|
static void *chksum(void *, int);
|
|
|
|
static void getpkt(struct ipkdb_if *, char *, int *);
|
|
|
|
static void putpkt(struct ipkdb_if *, const char *, int);
|
|
|
|
static int check_ipkdb(struct ipkdb_if *, struct in_addr *, char *, int);
|
|
|
|
static int connectipkdb(struct ipkdb_if *, char *, int);
|
|
|
|
static int hmac_init(void);
|
1996-09-30 20:16:45 +04:00
|
|
|
|
2009-10-03 02:05:52 +04:00
|
|
|
static int
|
|
|
|
ipkdb_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
|
|
|
|
void *arg0, void *arg1, void *arg2, void *arg3)
|
|
|
|
{
|
|
|
|
enum kauth_system_req req;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
req = (enum kauth_system_req)arg0;
|
|
|
|
result = KAUTH_RESULT_DEFER;
|
|
|
|
|
|
|
|
if ((action != KAUTH_SYSTEM_DEBUG) ||
|
|
|
|
(req != KAUTH_REQ_SYSTEM_DEBUG_IPKDB))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
result = KAUTH_RESULT_ALLOW;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
void
|
2009-03-18 13:22:21 +03:00
|
|
|
ipkdb_init(void)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbinit();
|
2000-03-22 23:58:25 +03:00
|
|
|
if ( ipkdbifinit(&ipkdb_if) < 0
|
|
|
|
|| !(ipkdb_if.flags&IPKDB_MYHW)
|
|
|
|
|| !hmac_init()) {
|
1996-10-16 23:32:08 +04:00
|
|
|
/* Interface not found, drop IPKDB */
|
|
|
|
printf("IPKDB: No interface found!\n");
|
1996-09-30 20:16:45 +04:00
|
|
|
boothowto &= ~RB_KDB;
|
|
|
|
}
|
2009-10-03 02:05:52 +04:00
|
|
|
|
|
|
|
ipkdb_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
|
|
|
|
ipkdb_listener_cb, NULL);
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-03-14 18:35:58 +03:00
|
|
|
ipkdb_connect(int when)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
boothowto |= RB_KDB;
|
|
|
|
if (when == 0)
|
1996-10-16 23:32:08 +04:00
|
|
|
printf("waiting for remote debugger\n");
|
|
|
|
ipkdb_trap();
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-03-18 13:22:21 +03:00
|
|
|
ipkdb_panic(void)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbpanic = 1;
|
|
|
|
ipkdb_trap();
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
|
2000-03-22 23:58:25 +03:00
|
|
|
/*
|
|
|
|
* Doesn't handle overlapping regions!
|
|
|
|
*/
|
|
|
|
void
|
2009-03-14 18:35:58 +03:00
|
|
|
ipkdbcopy(const void *s, void *d, int n)
|
2000-03-22 23:58:25 +03:00
|
|
|
{
|
2007-01-13 21:54:43 +03:00
|
|
|
const char *sp = s;
|
|
|
|
char *dp = d;
|
2000-03-22 23:58:25 +03:00
|
|
|
|
|
|
|
while (--n >= 0)
|
|
|
|
*dp++ = *sp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-03-14 18:35:58 +03:00
|
|
|
ipkdbzero(void *d, int n)
|
2000-03-22 23:58:25 +03:00
|
|
|
{
|
|
|
|
char *dp = d;
|
|
|
|
|
|
|
|
while (--n >= 0)
|
|
|
|
*dp++ = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2009-03-15 00:04:01 +03:00
|
|
|
ipkdbcmp(void *s, void *d, int n)
|
2000-03-22 23:58:25 +03:00
|
|
|
{
|
|
|
|
char *sp = s, *dp = d;
|
|
|
|
|
|
|
|
while (--n >= 0)
|
|
|
|
if (*sp++ != *dp++)
|
|
|
|
return *--dp - *--sp;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
int
|
2009-03-18 13:22:21 +03:00
|
|
|
ipkdbcmds(void)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
static char buf[512];
|
|
|
|
char *cp;
|
|
|
|
int plen;
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
if (!(ipkdb_if.flags&IPKDB_MYHW)) /* no interface */
|
2000-03-22 23:58:25 +03:00
|
|
|
return IPKDB_CMD_EXIT;
|
1996-10-16 23:32:08 +04:00
|
|
|
init(&ipkdb_if);
|
|
|
|
if (ipkdbpanic > 1) {
|
|
|
|
ipkdb_if.leave(&ipkdb_if);
|
2000-03-22 23:58:25 +03:00
|
|
|
return IPKDB_CMD_RUN;
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
1996-10-16 23:32:08 +04:00
|
|
|
putpkt(&ipkdb_if, "s", 1);
|
1996-09-30 20:16:45 +04:00
|
|
|
while (1) {
|
1996-10-16 23:32:08 +04:00
|
|
|
getpkt(&ipkdb_if, buf, &plen);
|
1996-09-30 20:16:45 +04:00
|
|
|
if (!plen) {
|
1996-10-16 23:32:08 +04:00
|
|
|
if (ipkdbpanic && ipkdb_poll()) {
|
|
|
|
ipkdb_if.leave(&ipkdb_if);
|
2000-03-22 23:58:25 +03:00
|
|
|
return IPKDB_CMD_RUN;
|
1996-09-30 20:16:45 +04:00
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
} else
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbpanic = 0;
|
1996-09-30 20:16:45 +04:00
|
|
|
switch (*buf) {
|
|
|
|
default:
|
1996-10-16 23:32:08 +04:00
|
|
|
putpkt(&ipkdb_if, "eunknown command", 16);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
case 'O':
|
|
|
|
/* This is an allowed reconnect, ack it */
|
1996-10-16 23:32:08 +04:00
|
|
|
putpkt(&ipkdb_if, "s", 1);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
case 'R':
|
1996-10-16 23:32:08 +04:00
|
|
|
peekmem(&ipkdb_if, buf, ipkdbregs, sizeof ipkdbregs);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
case 'W':
|
1996-10-16 23:32:08 +04:00
|
|
|
if (plen != sizeof ipkdbregs + 1) {
|
|
|
|
putpkt(&ipkdb_if, "einvalid register size", 22);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
}
|
1996-10-16 23:32:08 +04:00
|
|
|
pokemem(&ipkdb_if, buf + 1, ipkdbregs, sizeof ipkdbregs);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
void *addr, *len;
|
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
plen--;
|
1996-10-16 23:32:08 +04:00
|
|
|
if ( !(cp = ipkdbaddr(buf + 1, &plen, &addr))
|
|
|
|
|| !ipkdbaddr(cp, &plen, &len)) {
|
|
|
|
putpkt(&ipkdb_if, "einvalid peek format", 20);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
}
|
1996-10-16 23:32:08 +04:00
|
|
|
peekmem(&ipkdb_if, buf, addr, (long)len);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'N':
|
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
void *addr, *len;
|
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
plen--;
|
1996-10-16 23:32:08 +04:00
|
|
|
if ( !(cp = ipkdbaddr(buf + 1, &plen, &addr))
|
|
|
|
|| !(cp = ipkdbaddr(cp, &plen, &len))
|
|
|
|
|| plen < (long)len) {
|
|
|
|
putpkt(&ipkdb_if, "einvalid poke format", 20);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
}
|
1996-10-16 23:32:08 +04:00
|
|
|
pokemem(&ipkdb_if, cp, addr, (long)len);
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'S':
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdb_if.leave(&ipkdb_if);
|
2000-03-22 23:58:25 +03:00
|
|
|
return IPKDB_CMD_STEP;
|
1996-09-30 20:16:45 +04:00
|
|
|
case 'X':
|
1996-10-16 23:32:08 +04:00
|
|
|
putpkt(&ipkdb_if, "ok",2);
|
|
|
|
ipkdb_if.leave(&ipkdb_if);
|
2000-03-22 23:58:25 +03:00
|
|
|
return IPKDB_CMD_EXIT;
|
1996-09-30 20:16:45 +04:00
|
|
|
case 'C':
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdb_if.leave(&ipkdb_if);
|
2000-03-22 23:58:25 +03:00
|
|
|
return IPKDB_CMD_RUN;
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static u_char *
|
2009-03-14 18:35:58 +03:00
|
|
|
ipkdbaddr(u_char *cp, int *pl, void **dp)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
/* Assume that sizeof(void *) <= sizeof(u_long) */
|
|
|
|
u_long l;
|
1996-09-30 20:16:45 +04:00
|
|
|
int i;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
|
|
|
if ((*pl -= sizeof *dp) < 0)
|
1996-09-30 20:16:45 +04:00
|
|
|
return 0;
|
1996-10-16 23:32:08 +04:00
|
|
|
for (i = sizeof *dp, l = 0; --i >= 0;) {
|
1996-09-30 20:16:45 +04:00
|
|
|
l <<= 8;
|
|
|
|
l |= *cp++;
|
|
|
|
}
|
|
|
|
*dp = (void *)l;
|
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-03-14 18:35:58 +03:00
|
|
|
peekmem(struct ipkdb_if *ifp, u_char *buf, void *addr, long len)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
u_char *cp, *p = addr;
|
1996-09-30 20:16:45 +04:00
|
|
|
int l;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
cp = buf;
|
|
|
|
*cp++ = 'p';
|
|
|
|
for (l = len; --l >= 0;)
|
1996-10-16 23:32:08 +04:00
|
|
|
*cp++ = ipkdbfbyte(p++);
|
1996-09-30 20:16:45 +04:00
|
|
|
putpkt(ifp, buf, len + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-03-14 18:35:58 +03:00
|
|
|
pokemem(struct ipkdb_if *ifp, u_char *cp, void *addr, long len)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
u_char *p = addr;
|
1996-09-30 20:16:45 +04:00
|
|
|
|
|
|
|
while (--len >= 0)
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbsbyte(p++, *cp++);
|
1996-09-30 20:16:45 +04:00
|
|
|
putpkt(ifp, "ok", 2);
|
|
|
|
}
|
|
|
|
|
2005-12-24 23:45:08 +03:00
|
|
|
inline static u_int32_t
|
2009-03-14 18:35:58 +03:00
|
|
|
getnl(void *vs)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
u_char *s = vs;
|
|
|
|
|
|
|
|
return (*s << 24)|(s[1] << 16)|(s[2] << 8)|s[3];
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
1996-10-16 23:32:08 +04:00
|
|
|
|
2005-12-24 23:45:08 +03:00
|
|
|
inline static u_int
|
2009-03-14 18:35:58 +03:00
|
|
|
getns(void *vs)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
u_char *s = vs;
|
|
|
|
|
|
|
|
return (*s << 8)|s[1];
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
|
2005-12-24 23:45:08 +03:00
|
|
|
inline static void
|
2009-03-14 18:35:58 +03:00
|
|
|
setnl(void *vs, u_int32_t l)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
u_char *s = vs;
|
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
*s++ = l >> 24;
|
|
|
|
*s++ = l >> 16;
|
|
|
|
*s++ = l >> 8;
|
|
|
|
*s = l;
|
|
|
|
}
|
|
|
|
|
2005-12-24 23:45:08 +03:00
|
|
|
inline static void
|
2009-03-14 18:35:58 +03:00
|
|
|
setns(void *vs, int l)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
u_char *s = vs;
|
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
*s++ = l >> 8;
|
|
|
|
*s = l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u_short
|
2009-03-14 18:35:58 +03:00
|
|
|
cksum(u_short st, void *vcp, int l)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1996-10-16 23:32:08 +04:00
|
|
|
u_char *cp = vcp;
|
|
|
|
u_long s;
|
|
|
|
|
|
|
|
for (s = st; (l -= 2) >= 0; cp += 2)
|
1996-09-30 20:16:45 +04:00
|
|
|
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
|
2009-03-14 18:35:58 +03:00
|
|
|
assemble(struct ipkdb_if *ifp, void *buf)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
struct ip *ip, iph;
|
|
|
|
int off, len, i;
|
|
|
|
u_char *cp, *ecp;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
ip = (struct ip *)buf;
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(ip, &iph, sizeof iph);
|
1996-09-30 20:16:45 +04:00
|
|
|
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) {
|
1996-10-16 23:32:08 +04:00
|
|
|
if (ipkdbcmp(&iph, ifp->ass, sizeof iph)) {
|
1996-09-30 20:16:45 +04:00
|
|
|
/*
|
|
|
|
* different packet
|
|
|
|
* decide whether to keep the old
|
|
|
|
* or start a new one
|
|
|
|
*/
|
2000-03-22 23:58:25 +03:00
|
|
|
i = (getns(&ip->ip_id)
|
|
|
|
^ getns(&((struct ip *)ifp->ass)->ip_id));
|
|
|
|
i ^= ((i >> 2) ^ (i >> 4) ^ (i >> 8) ^ (i >> 12));
|
|
|
|
if (i & 1)
|
1996-09-30 20:16:45 +04:00
|
|
|
/* keep the old */
|
|
|
|
return 0;
|
|
|
|
ifp->asslen = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ifp->asslen) {
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbzero(ifp->assbit, sizeof ifp->assbit);
|
|
|
|
ipkdbcopy(&iph, ifp->ass, sizeof iph);
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
off = getns(&ip->ip_off);
|
2000-03-22 23:58:25 +03:00
|
|
|
len = ((off & IP_OFFMASK) << 3) + getns(&ip->ip_len) - ip->ip_hl * 4;
|
1996-09-30 20:16:45 +04:00
|
|
|
if (ifp->asslen < len)
|
|
|
|
ifp->asslen = len;
|
|
|
|
if (ifp->asslen + sizeof *ip > sizeof ifp->ass) {
|
|
|
|
/* packet too long */
|
|
|
|
ifp->asslen = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
2000-03-22 23:58:25 +03:00
|
|
|
if (!(off & IP_MF)) {
|
1996-09-30 20:16:45 +04:00
|
|
|
off &= IP_OFFMASK;
|
|
|
|
cp = ifp->assbit + (off >> 3);
|
2000-03-22 23:58:25 +03:00
|
|
|
for (i = (off & 7); i < 8; *cp |= 1 << i++);
|
1996-09-30 20:16:45 +04:00
|
|
|
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)
|
2000-03-22 23:58:25 +03:00
|
|
|
for (i = (off & 7); i <= ((len >> 3) & 7);
|
|
|
|
*cp |= 1 << i++);
|
1996-09-30 20:16:45 +04:00
|
|
|
else {
|
2000-03-22 23:58:25 +03:00
|
|
|
for (i = (off & 7); i < 8; *cp |= 1 << i++);
|
1996-09-30 20:16:45 +04:00
|
|
|
for (; ++cp < ecp; *cp = -1);
|
2000-03-22 23:58:25 +03:00
|
|
|
for (i = 0; i < ((len >> 3) & 7); *cp |= 1 << i++);
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
}
|
2000-03-22 23:58:25 +03:00
|
|
|
ipkdbcopy((char *)buf + ip->ip_hl * 4,
|
1996-10-16 23:32:08 +04:00
|
|
|
ifp->ass + sizeof *ip + (off << 3),
|
|
|
|
len - (off << 3));
|
1996-09-30 20:16:45 +04:00
|
|
|
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 *
|
2009-03-14 18:35:58 +03:00
|
|
|
inpkt(struct ipkdb_if *ifp, char *ibuf, int poll)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
int cnt = 1000000;
|
|
|
|
int l, ul;
|
|
|
|
struct ether_header *eh;
|
1997-04-19 05:52:15 +04:00
|
|
|
struct arphdr *ah;
|
1996-09-30 20:16:45 +04:00
|
|
|
struct ip *ip;
|
|
|
|
struct udphdr *udp;
|
|
|
|
struct ipovly ipo;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
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:
|
1997-04-19 05:52:15 +04:00
|
|
|
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)
|
1996-09-30 20:16:45 +04:00
|
|
|
/* unsupported arp packet */
|
|
|
|
break;
|
1997-04-19 05:52:15 +04:00
|
|
|
switch (getns(&ah->ar_op)) {
|
1996-09-30 20:16:45 +04:00
|
|
|
case ARPOP_REQUEST:
|
1996-10-16 23:32:08 +04:00
|
|
|
if ( (ifp->flags&IPKDB_MYIP)
|
1997-04-19 05:52:15 +04:00
|
|
|
&& !ipkdbcmp(ar_tpa(ah),
|
1996-10-16 23:32:08 +04:00
|
|
|
ifp->myinetaddr,
|
|
|
|
sizeof ifp->myinetaddr)) {
|
1996-09-30 20:16:45 +04:00
|
|
|
/* someone requested my address */
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(eh->ether_shost,
|
|
|
|
eh->ether_dhost,
|
|
|
|
sizeof eh->ether_dhost);
|
|
|
|
ipkdbcopy(ifp->myenetaddr,
|
|
|
|
eh->ether_shost,
|
|
|
|
sizeof eh->ether_shost);
|
1997-04-19 05:52:15 +04:00
|
|
|
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);
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(ifp->myenetaddr,
|
1997-04-19 05:52:15 +04:00
|
|
|
ar_sha(ah),
|
|
|
|
ah->ar_hln);
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(ifp->myinetaddr,
|
2000-03-22 23:58:25 +03:00
|
|
|
ar_spa(ah),
|
1997-04-19 05:52:15 +04:00
|
|
|
ah->ar_pln);
|
1996-09-30 20:16:45 +04:00
|
|
|
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;
|
2000-03-22 23:58:25 +03:00
|
|
|
if (getns(&ip->ip_off) & ~IP_DF) {
|
1996-09-30 20:16:45 +04:00
|
|
|
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;
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(ip, &ipo, sizeof ipo);
|
|
|
|
ipkdbzero(ipo.ih_x1, sizeof ipo.ih_x1);
|
1996-09-30 20:16:45 +04:00
|
|
|
ipo.ih_len = udp->uh_ulen;
|
|
|
|
if ( udp->uh_sum
|
|
|
|
&& cksum(cksum(0, &ipo, sizeof ipo), udp, ul))
|
|
|
|
/* wrong checksum */
|
|
|
|
break;
|
2000-03-22 23:58:25 +03:00
|
|
|
if (!(ifp->flags & IPKDB_MYIP)) {
|
1996-09-30 20:16:45 +04:00
|
|
|
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 */
|
2000-03-22 23:58:25 +03:00
|
|
|
char *bootp = (char *)(udp + 1);
|
|
|
|
ipkdbcopy(bootp + 16,
|
1996-10-16 23:32:08 +04:00
|
|
|
ifp->myinetaddr,
|
|
|
|
sizeof ifp->myinetaddr);
|
|
|
|
ifp->flags |= IPKDB_MYIP;
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
/* give caller a chance to resend his request */
|
|
|
|
return 0;
|
|
|
|
}
|
1996-10-16 23:32:08 +04:00
|
|
|
if ( ipkdbcmp(&ip->ip_dst, ifp->myinetaddr, sizeof ifp->myinetaddr)
|
|
|
|
|| getns(&udp->uh_dport) != IPKDBPORT)
|
1996-09-30 20:16:45 +04:00
|
|
|
break;
|
|
|
|
/* so now it's a UDP packet for the debugger */
|
|
|
|
{
|
|
|
|
/* Check for reconnect packet */
|
|
|
|
u_char *p;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
p = (u_char *)(udp + 1);
|
|
|
|
if (!getnl(p) && p[6] == 'O') {
|
|
|
|
l = getns(p + 4);
|
1996-10-16 23:32:08 +04:00
|
|
|
if ( l <= ul - sizeof *udp - 6
|
2000-03-22 23:58:25 +03:00
|
|
|
&& check_ipkdb(ifp, &ip->ip_src,
|
|
|
|
p, l + 6)) {
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(&ip->ip_src,
|
|
|
|
ifp->hisinetaddr,
|
|
|
|
sizeof ifp->hisinetaddr);
|
|
|
|
ipkdbcopy(eh->ether_shost,
|
|
|
|
ifp->hisenetaddr,
|
|
|
|
sizeof ifp->hisenetaddr);
|
2000-03-22 23:58:25 +03:00
|
|
|
ifp->hisport = getns(&udp->uh_sport);
|
1996-10-16 23:32:08 +04:00
|
|
|
ifp->flags |= IPKDB_HISHW|IPKDB_HISIP;
|
1996-09-30 20:16:45 +04:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1996-10-16 23:32:08 +04:00
|
|
|
if ( (ifp->flags&IPKDB_HISIP)
|
|
|
|
&& ipkdbcmp(&ip->ip_src,
|
|
|
|
ifp->hisinetaddr, sizeof ifp->hisinetaddr))
|
1996-09-30 20:16:45 +04:00
|
|
|
/* It's a packet from someone else */
|
|
|
|
break;
|
2000-03-23 23:33:37 +03:00
|
|
|
if (!(ifp->flags&IPKDB_HISIP))
|
|
|
|
break;
|
1996-09-30 20:16:45 +04:00
|
|
|
return (char *)(udp + 1);
|
|
|
|
default:
|
|
|
|
/* unknown type */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-10-16 23:32:08 +04:00
|
|
|
static short ipkdb_ipid = 0;
|
1996-09-30 20:16:45 +04:00
|
|
|
|
|
|
|
static void
|
2009-03-15 00:04:01 +03:00
|
|
|
outpkt(struct ipkdb_if *ifp, char *in, int l, int srcport, int dstport)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
struct ether_header *eh;
|
|
|
|
struct ip *ip;
|
|
|
|
struct udphdr *udp;
|
|
|
|
u_char *cp;
|
2000-03-22 23:58:25 +03:00
|
|
|
char _obuf[ETHERMTU + 16];
|
|
|
|
#define obuf (_obuf + 2) /* align ip data in packet */
|
1996-09-30 20:16:45 +04:00
|
|
|
struct ipovly ipo;
|
|
|
|
int i, off;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
2000-03-22 23:58:25 +03:00
|
|
|
ipkdbzero(_obuf, sizeof _obuf);
|
1996-09-30 20:16:45 +04:00
|
|
|
eh = (struct ether_header *)obuf;
|
2000-03-22 23:58:25 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
1996-09-30 20:16:45 +04:00
|
|
|
else
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(ifp->hisenetaddr, eh->ether_dhost, sizeof eh->ether_dhost);
|
|
|
|
ipkdbcopy(ifp->myenetaddr, eh->ether_shost, sizeof eh->ether_shost);
|
1996-09-30 20:16:45 +04:00
|
|
|
setns(&eh->ether_type, ETHERTYPE_IP);
|
|
|
|
ip = (struct ip *)(obuf + 14);
|
|
|
|
ip->ip_v = IPVERSION;
|
|
|
|
ip->ip_hl = 5;
|
1996-10-16 23:32:08 +04:00
|
|
|
setns(&ip->ip_id, ipkdb_ipid++);
|
1996-09-30 20:16:45 +04:00
|
|
|
ip->ip_ttl = 255;
|
|
|
|
ip->ip_p = IPPROTO_UDP;
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(ifp->myinetaddr, &ip->ip_src, sizeof ip->ip_src);
|
2000-03-22 23:58:25 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
1996-09-30 20:16:45 +04:00
|
|
|
udp = (struct udphdr *)(ip + 1);
|
|
|
|
setns(&udp->uh_sport, srcport);
|
|
|
|
setns(&udp->uh_dport, dstport);
|
|
|
|
setns(&udp->uh_ulen, l + sizeof *udp);
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(ip, &ipo, sizeof ipo);
|
|
|
|
ipkdbzero(ipo.ih_x1, sizeof ipo.ih_x1);
|
1996-09-30 20:16:45 +04:00
|
|
|
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) {
|
2000-03-22 23:58:25 +03:00
|
|
|
i = l > ifp->mtu - sizeof *ip ? ((ifp->mtu - sizeof *ip) & ~7) : l;
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(in, cp, i);
|
1996-09-30 20:16:45 +04:00
|
|
|
setns(&ip->ip_len, i + sizeof *ip);
|
2000-03-22 23:58:25 +03:00
|
|
|
setns(&ip->ip_off, (l > i ? IP_MF : 0) | (off >> 3));
|
1996-09-30 20:16:45 +04:00
|
|
|
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);
|
|
|
|
}
|
2000-03-22 23:58:25 +03:00
|
|
|
#undef obuf
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-03-14 18:35:58 +03:00
|
|
|
init(struct ipkdb_if *ifp)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
u_char *cp;
|
2000-03-22 23:58:25 +03:00
|
|
|
u_char _ibuf[ETHERMTU + 16];
|
|
|
|
#define ibuf (_ibuf + 2) /* align ip data in packet */
|
1996-09-30 20:16:45 +04:00
|
|
|
int secs = 0;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
ifp->start(ifp);
|
2000-03-22 23:58:25 +03:00
|
|
|
if (ifp->flags & IPKDB_MYIP)
|
1996-09-30 20:16:45 +04:00
|
|
|
return;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
2000-03-22 23:58:25 +03:00
|
|
|
while (!(ifp->flags & IPKDB_MYIP)) {
|
|
|
|
ipkdbzero(_ibuf, sizeof _ibuf);
|
|
|
|
cp = _ibuf;
|
1996-09-30 20:16:45 +04:00
|
|
|
*cp++ = 1; /* BOOTP_REQUEST */
|
|
|
|
*cp++ = 1; /* Ethernet hardware */
|
|
|
|
*cp++ = 6; /* length of address */
|
|
|
|
setnl(++cp, 0x12345678); /* some random number? */
|
|
|
|
setns(cp + 4, secs++);
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(ifp->myenetaddr, cp + 24, sizeof ifp->myenetaddr);
|
2000-03-22 23:58:25 +03:00
|
|
|
outpkt(ifp, _ibuf, 300, 68, 67);
|
|
|
|
inpkt(ifp, ibuf, 2);
|
1996-10-16 23:32:08 +04:00
|
|
|
if (ipkdbpanic && ipkdb_poll()) {
|
|
|
|
ipkdbpanic++;
|
1996-09-30 20:16:45 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cp = ifp->myinetaddr;
|
1996-10-16 23:32:08 +04:00
|
|
|
printf("My IP address is %d.%d.%d.%d\n",
|
|
|
|
cp[0], cp[1], cp[2], cp[3]);
|
2000-03-22 23:58:25 +03:00
|
|
|
#undef ibuf
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
|
1997-04-19 05:52:15 +04:00
|
|
|
/* HMAC Checksumming routines, see draft-ietf-ipsec-hmac-md5-00.txt */
|
|
|
|
#define LENCHK 16 /* Length of checksum in bytes */
|
|
|
|
|
1997-06-26 04:53:03 +04:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2009-03-14 17:45:51 +03:00
|
|
|
static u_int32_t getNl(void *);
|
|
|
|
static void setNl(void *, u_int32_t);
|
|
|
|
static void ipkdb_MD5Transform(struct ipkdb_MD5Context *);
|
|
|
|
static void ipkdb_MD5Init(struct ipkdb_MD5Context *);
|
|
|
|
static void ipkdb_MD5Update(struct ipkdb_MD5Context *, u_char *, u_int);
|
|
|
|
static u_char *ipkdb_MD5Final(struct ipkdb_MD5Context *);
|
2000-03-22 23:58:25 +03:00
|
|
|
|
2005-12-24 23:45:08 +03:00
|
|
|
inline static u_int32_t
|
2009-03-14 18:35:58 +03:00
|
|
|
getNl(void *vs)
|
1997-06-26 04:53:03 +04:00
|
|
|
{
|
|
|
|
u_char *s = vs;
|
|
|
|
|
2000-03-22 23:58:25 +03:00
|
|
|
return *s | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
|
1997-06-26 04:53:03 +04:00
|
|
|
}
|
|
|
|
|
2005-12-24 23:45:08 +03:00
|
|
|
inline static void
|
2009-03-14 18:35:58 +03:00
|
|
|
setNl(void *vs, u_int32_t l)
|
1997-06-26 04:53:03 +04:00
|
|
|
{
|
|
|
|
u_char *s = vs;
|
|
|
|
|
|
|
|
*s++ = l;
|
|
|
|
*s++ = l >> 8;
|
|
|
|
*s++ = l >> 16;
|
|
|
|
*s = l >> 24;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The four core functions - F1 is optimized somewhat */
|
2000-03-22 23:58:25 +03:00
|
|
|
/* #define F1(x, y, z) (((x) & (y)) | (~(x) & (z))) */
|
|
|
|
#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
1997-06-26 04:53:03 +04:00
|
|
|
#define F2(x, y, z) F1(z, x, y)
|
2000-03-22 23:58:25 +03:00
|
|
|
#define F3(x, y, z) ((x) ^ (y) ^ (z))
|
|
|
|
#define F4(x, y, z) ((y) ^ ((x) | ~(z)))
|
1997-06-26 04:53:03 +04:00
|
|
|
|
|
|
|
/* This is the central step in the MD5 algorithm. */
|
|
|
|
#define ipkdb_MD5STEP(f, w, x, y, z, data, s) \
|
2000-03-22 23:58:25 +03:00
|
|
|
((w) += f(x, y, z) + (data), \
|
2000-03-23 23:33:37 +03:00
|
|
|
(w) = ((w) << (s)) | (((w) >> (32 - s)) & 0xffffffff), \
|
2000-03-22 23:58:25 +03:00
|
|
|
(w) += (x))
|
1997-06-26 04:53:03 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2000-03-22 23:58:25 +03:00
|
|
|
static void
|
2009-03-14 18:35:58 +03:00
|
|
|
ipkdb_MD5Transform(struct ipkdb_MD5Context *ctx)
|
1997-06-26 04:53:03 +04:00
|
|
|
{
|
2000-03-23 23:33:37 +03:00
|
|
|
u_int a, b, c, d, i;
|
|
|
|
u_int in[16];
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04:00
|
|
|
for (i = 0; i < 16; i++)
|
|
|
|
in[i] = getNl(ctx->in + 4 * i);
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04: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
|
2009-03-14 18:35:58 +03:00
|
|
|
ipkdb_MD5Init(struct ipkdb_MD5Context *ctx)
|
1997-06-26 04:53:03 +04:00
|
|
|
{
|
|
|
|
ctx->buf[0] = 0x67452301;
|
|
|
|
ctx->buf[1] = 0xefcdab89;
|
|
|
|
ctx->buf[2] = 0x98badcfe;
|
|
|
|
ctx->buf[3] = 0x10325476;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04:00
|
|
|
ctx->bits[0] = 0;
|
|
|
|
ctx->bits[1] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update context to reflect the concatenation of another buffer full
|
|
|
|
* of bytes.
|
|
|
|
*/
|
|
|
|
static void
|
2009-03-14 18:35:58 +03:00
|
|
|
ipkdb_MD5Update(struct ipkdb_MD5Context *ctx, u_char *buf, unsigned len)
|
1997-06-26 04:53:03 +04:00
|
|
|
{
|
|
|
|
u_int t;
|
|
|
|
|
|
|
|
/* Update bitcount */
|
|
|
|
t = ctx->bits[0];
|
|
|
|
if ((ctx->bits[0] = (t + (len << 3)) & 0xffffffff) < t)
|
2000-03-23 23:33:37 +03:00
|
|
|
ctx->bits[1]++; /* Carry from low to high */
|
1997-06-26 04:53:03 +04:00
|
|
|
ctx->bits[1] += (len >> 29) & 0xffffffff;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04:00
|
|
|
t = (t >> 3) & 0x3f; /* Bytes already in ctx->in */
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04:00
|
|
|
/* Handle any leading odd-sized chunks */
|
|
|
|
if (t) {
|
|
|
|
u_char *p = ctx->in + t;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04: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
|
|
|
|
1997-06-26 04:53:03 +04: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
|
|
|
|
1997-06-26 04:53:03 +04: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 *
|
2009-03-14 18:35:58 +03:00
|
|
|
ipkdb_MD5Final(struct ipkdb_MD5Context *ctx)
|
1997-06-26 04:53:03 +04:00
|
|
|
{
|
|
|
|
static u_char digest[16];
|
|
|
|
unsigned count;
|
|
|
|
u_char *p;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04:00
|
|
|
/* Compute number of bytes mod 64 */
|
|
|
|
count = (ctx->bits[0] >> 3) & 0x3f;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04: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
|
|
|
|
1997-06-26 04:53:03 +04:00
|
|
|
/* Bytes of padding needed to make 64 bytes */
|
|
|
|
count = 64 - 1 - count;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-06-26 04:53:03 +04: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
|
|
|
|
1997-06-26 04:53:03 +04: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
|
|
|
|
1997-06-26 04:53:03 +04: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
|
|
|
|
1997-06-26 04:53:03 +04: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;
|
|
|
|
}
|
1997-04-19 05:52:15 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
1996-09-30 20:16:45 +04:00
|
|
|
static int
|
2009-03-18 13:22:21 +03:00
|
|
|
hmac_init(void)
|
1997-04-19 05:52:15 +04:00
|
|
|
{
|
|
|
|
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) {
|
1997-06-26 04:53:03 +04:00
|
|
|
ipkdb_MD5Init(&icontext);
|
|
|
|
ipkdb_MD5Update(&icontext, key, key_len);
|
|
|
|
ipkdbcopy(ipkdb_MD5Final(&icontext), tk, 16);
|
1997-04-19 05:52:15 +04:00
|
|
|
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;
|
1997-06-26 04:53:03 +04:00
|
|
|
ipkdb_MD5Init(&icontext);
|
|
|
|
ipkdb_MD5Update(&icontext, pad, 64);
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-04-19 05:52:15 +04:00
|
|
|
ipkdbzero(pad, sizeof pad);
|
|
|
|
ipkdbcopy(key, pad, key_len);
|
|
|
|
for (i = 0; i < 64; i++)
|
|
|
|
pad[i] ^= 0x5c;
|
1997-06-26 04:53:03 +04:00
|
|
|
ipkdb_MD5Init(&ocontext);
|
|
|
|
ipkdb_MD5Update(&ocontext, pad, 64);
|
1997-04-19 05:52:15 +04:00
|
|
|
|
|
|
|
/* 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 *
|
2009-03-14 18:35:58 +03:00
|
|
|
chksum(void *buf, int len)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
1997-06-26 04:53:03 +04:00
|
|
|
u_char *digest;
|
|
|
|
struct ipkdb_MD5Context context;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
1997-04-19 05:52:15 +04: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);
|
1997-06-26 04:53:03 +04:00
|
|
|
ipkdb_MD5Update(&context, buf, len);
|
|
|
|
digest = ipkdb_MD5Final(&context);
|
1997-04-19 05:52:15 +04:00
|
|
|
/*
|
|
|
|
* perform outer MD5
|
|
|
|
*/
|
|
|
|
ipkdbcopy(&ocontext, &context, sizeof context);
|
1997-06-26 04:53:03 +04:00
|
|
|
ipkdb_MD5Update(&context, digest, 16);
|
|
|
|
return ipkdb_MD5Final(&context);
|
1997-04-19 05:52:15 +04:00
|
|
|
}
|
1996-09-30 20:16:45 +04:00
|
|
|
|
|
|
|
static void
|
2009-03-14 18:35:58 +03:00
|
|
|
getpkt(struct ipkdb_if *ifp, char *buf, int *lp)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
char *got;
|
|
|
|
int l;
|
2000-03-22 23:58:25 +03:00
|
|
|
char _ibuf[ETHERMTU + 16];
|
|
|
|
#define ibuf (_ibuf + 2) /* align ip data in packet */
|
1996-10-16 23:32:08 +04:00
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
*lp = 0;
|
|
|
|
while (1) {
|
1996-10-16 23:32:08 +04:00
|
|
|
if (!(got = inpkt(ifp, ibuf, ipkdbpanic != 0))) {
|
1996-09-30 20:16:45 +04:00
|
|
|
*lp = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( ifp->seq == getnl(got)
|
|
|
|
&& got[6] >= 'A'
|
|
|
|
&& got[6] <= 'Z'
|
|
|
|
&& (l = getns(got + 4))
|
1997-04-19 05:52:15 +04:00
|
|
|
&& !ipkdbcmp(chksum(got, l + 6), got + l + 6, LENCHK)) {
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(got + 6, buf, *lp = l);
|
1996-09-30 20:16:45 +04:00
|
|
|
return;
|
|
|
|
}
|
1996-10-16 23:32:08 +04:00
|
|
|
if ( ifp->pktlen
|
2000-03-22 23:58:25 +03:00
|
|
|
&& ((ifp->flags & (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
|
|
|
|
== (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED)))
|
|
|
|
outpkt(ifp, ifp->pkt, ifp->pktlen, IPKDBPORT, ifp->hisport);
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
2000-03-22 23:58:25 +03:00
|
|
|
#undef ibuf
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-03-14 18:35:58 +03:00
|
|
|
putpkt(struct ipkdb_if *ifp, const char *buf, int l)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
setnl(ifp->pkt, ifp->seq++);
|
|
|
|
setns(ifp->pkt + 4, l);
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdbcopy(buf, ifp->pkt + 6, l);
|
1997-04-19 05:52:15 +04:00
|
|
|
ipkdbcopy(chksum(ifp->pkt, l + 6), ifp->pkt + 6 + l, LENCHK);
|
|
|
|
ifp->pktlen = l + 6 + LENCHK;
|
2000-03-22 23:58:25 +03:00
|
|
|
if ( (ifp->flags & (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
|
|
|
|
!= (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
|
1996-09-30 20:16:45 +04:00
|
|
|
return;
|
2000-03-22 23:58:25 +03:00
|
|
|
outpkt(ifp, ifp->pkt, ifp->pktlen, IPKDBPORT, ifp->hisport);
|
1996-09-30 20:16:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2009-03-14 18:35:58 +03:00
|
|
|
check_ipkdb(struct ipkdb_if *ifp, struct in_addr *shost, char *p, int l)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
u_char hisenet[6];
|
|
|
|
u_char hisinet[4];
|
2000-03-22 23:58:25 +03:00
|
|
|
u_int16_t hisport;
|
1996-09-30 20:16:45 +04:00
|
|
|
char save;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
1997-04-19 05:52:15 +04:00
|
|
|
#ifndef IPKDBSECURE
|
2007-11-24 17:20:41 +03:00
|
|
|
if (kauth_authorize_system(curlwp->l_cred, KAUTH_SYSTEM_DEBUG,
|
2009-04-13 02:37:50 +04:00
|
|
|
KAUTH_REQ_SYSTEM_DEBUG_IPKDB, NULL, NULL, NULL))
|
1997-04-19 05:52:15 +04:00
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
if (ipkdbcmp(chksum(p, l), p + l, LENCHK))
|
1996-09-30 20:16:45 +04:00
|
|
|
return 0;
|
2000-03-22 23:58:25 +03:00
|
|
|
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;
|
1997-04-19 05:52:15 +04:00
|
|
|
if (connectipkdb(ifp, p + 6, l - 6) < 0) {
|
2000-03-22 23:58:25 +03:00
|
|
|
ipkdbcopy(hisenet, ifp->hisenetaddr, sizeof ifp->hisenetaddr);
|
|
|
|
ipkdbcopy(hisinet, ifp->hisinetaddr, sizeof ifp->hisinetaddr);
|
|
|
|
ifp->hisport = hisport;
|
|
|
|
ifp->flags = save;
|
1996-09-30 20:16:45 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-03-22 23:58:25 +03:00
|
|
|
* Should check whether packet came across the correct interface. XXX
|
1996-09-30 20:16:45 +04:00
|
|
|
*/
|
|
|
|
int
|
2009-03-15 00:04:01 +03:00
|
|
|
checkipkdb(struct in_addr *shost, u_short sport, u_short dport, struct mbuf *m, int off, int len)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
int l;
|
|
|
|
char ibuf[ETHERMTU+50];
|
1996-10-16 23:32:08 +04:00
|
|
|
|
2000-03-22 23:58:25 +03:00
|
|
|
if (dport != IPKDBPORT)
|
|
|
|
return 0;
|
|
|
|
if (len > sizeof ibuf)
|
|
|
|
return 0;
|
1996-09-30 20:16:45 +04:00
|
|
|
m_copydata(m, off, len, ibuf);
|
|
|
|
p = ibuf;
|
|
|
|
if (getnl(p) || p[6] != 'O')
|
|
|
|
return 0;
|
|
|
|
l = getns(p + 4);
|
2000-03-22 23:58:25 +03:00
|
|
|
if (l > len - 6 || !check_ipkdb(&ipkdb_if, shost, p, l + 6))
|
1996-09-30 20:16:45 +04:00
|
|
|
return 0;
|
2000-03-22 23:58:25 +03:00
|
|
|
ipkdb_if.hisport = sport;
|
1996-10-16 23:32:08 +04:00
|
|
|
ipkdb_connect(1);
|
1996-09-30 20:16:45 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2009-03-14 18:35:58 +03:00
|
|
|
connectipkdb(struct ipkdb_if *ifp, char *buf, int l)
|
1996-09-30 20:16:45 +04:00
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
u_char *ip;
|
1996-10-16 23:32:08 +04:00
|
|
|
|
1996-09-30 20:16:45 +04:00
|
|
|
if (*buf != 'O')
|
|
|
|
return -1;
|
1996-10-16 23:32:08 +04:00
|
|
|
if (getnl(buf + 1) == ifp->id)
|
|
|
|
/* It's a retry of a connect packet, ignore it */
|
|
|
|
return -1;
|
1996-09-30 20:16:45 +04:00
|
|
|
ip = ifp->hisinetaddr;
|
1997-04-19 05:52:15 +04:00
|
|
|
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]);
|
1996-10-16 23:32:08 +04:00
|
|
|
ifp->flags |= IPKDB_CONNECTED;
|
1996-09-30 20:16:45 +04:00
|
|
|
ifp->seq = 0;
|
|
|
|
ifp->pktlen = 0;
|
1996-10-16 23:32:08 +04:00
|
|
|
ifp->id = getnl(buf + 1);
|
1996-09-30 20:16:45 +04:00
|
|
|
return 0;
|
|
|
|
}
|