1 /* $NetBSD: ipkdb_ipkdb.c,v 1.26 2009/04/12 22:37:50 elad Exp $ */
4 * Copyright (C) 1993-2000 Wolfgang Solfrank.
5 * Copyright (C) 1993-2000 TooLs GmbH.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: ipkdb_ipkdb.c,v 1.26 2009/04/12 22:37:50 elad Exp $");
37 #include "opt_ipkdb.h"
39 #include <sys/param.h>
40 #include <sys/socket.h>
42 #include <sys/reboot.h>
43 #include <sys/systm.h>
44 #include <sys/kauth.h>
48 #include <net/if_arp.h>
49 #include <net/if_ether.h>
51 #include <netinet/in.h>
52 #include <netinet/in_systm.h>
53 #include <netinet/if_inarp.h>
54 #include <netinet/ip.h>
55 #include <netinet/ip_var.h>
56 #include <netinet/udp.h>
58 #include <machine/reg.h>
60 #include <ipkdb/ipkdb.h>
61 #include <machine/ipkdb.h>
66 #error You must specify the IPKDBKEY option to use IPKDB.
68 static char ipkdbkey
[] = IPKDBKEY
;
71 static struct ipkdb_if ipkdb_if
;
73 static kauth_listener_t ipkdb_listener
;
75 static u_char
*ipkdbaddr(u_char
*, int *, void **);
76 static void peekmem(struct ipkdb_if
*, u_char
*, void *, long);
77 static void pokemem(struct ipkdb_if
*, u_char
*, void *, long);
78 static u_int32_t
getnl(void *);
79 static u_int
getns(void *);
80 static void setnl(void *, u_int32_t
);
81 static void setns(void *, int);
82 static u_short
cksum(u_short
, void *, int);
83 static int assemble(struct ipkdb_if
*, void *);
84 static char *inpkt(struct ipkdb_if
*, char *, int);
85 static void outpkt(struct ipkdb_if
*, char *, int, int, int);
86 static void init(struct ipkdb_if
*);
87 static void *chksum(void *, int);
88 static void getpkt(struct ipkdb_if
*, char *, int *);
89 static void putpkt(struct ipkdb_if
*, const char *, int);
90 static int check_ipkdb(struct ipkdb_if
*, struct in_addr
*, char *, int);
91 static int connectipkdb(struct ipkdb_if
*, char *, int);
92 static int hmac_init(void);
95 ipkdb_listener_cb(kauth_cred_t cred
, kauth_action_t action
, void *cookie
,
96 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
98 enum kauth_system_req req
;
101 req
= (enum kauth_system_req
)arg0
;
102 result
= KAUTH_RESULT_DEFER
;
104 if ((action
!= KAUTH_SYSTEM_DEBUG
) ||
105 (req
!= KAUTH_REQ_SYSTEM_DEBUG_IPKDB
))
108 result
= KAUTH_RESULT_ALLOW
;
117 if ( ipkdbifinit(&ipkdb_if
) < 0
118 || !(ipkdb_if
.flags
&IPKDB_MYHW
)
120 /* Interface not found, drop IPKDB */
121 printf("IPKDB: No interface found!\n");
122 boothowto
&= ~RB_KDB
;
125 ipkdb_listener
= kauth_listen_scope(KAUTH_SCOPE_SYSTEM
,
126 ipkdb_listener_cb
, NULL
);
130 ipkdb_connect(int when
)
134 printf("waiting for remote debugger\n");
146 * Doesn't handle overlapping regions!
149 ipkdbcopy(const void *s
, void *d
, int n
)
159 ipkdbzero(void *d
, int n
)
168 ipkdbcmp(void *s
, void *d
, int n
)
170 char *sp
= s
, *dp
= d
;
174 return *--dp
- *--sp
;
181 static char buf
[512];
185 if (!(ipkdb_if
.flags
&IPKDB_MYHW
)) /* no interface */
186 return IPKDB_CMD_EXIT
;
188 if (ipkdbpanic
> 1) {
189 ipkdb_if
.leave(&ipkdb_if
);
190 return IPKDB_CMD_RUN
;
192 putpkt(&ipkdb_if
, "s", 1);
194 getpkt(&ipkdb_if
, buf
, &plen
);
196 if (ipkdbpanic
&& ipkdb_poll()) {
197 ipkdb_if
.leave(&ipkdb_if
);
198 return IPKDB_CMD_RUN
;
205 putpkt(&ipkdb_if
, "eunknown command", 16);
208 /* This is an allowed reconnect, ack it */
209 putpkt(&ipkdb_if
, "s", 1);
212 peekmem(&ipkdb_if
, buf
, ipkdbregs
, sizeof ipkdbregs
);
215 if (plen
!= sizeof ipkdbregs
+ 1) {
216 putpkt(&ipkdb_if
, "einvalid register size", 22);
219 pokemem(&ipkdb_if
, buf
+ 1, ipkdbregs
, sizeof ipkdbregs
);
226 if ( !(cp
= ipkdbaddr(buf
+ 1, &plen
, &addr
))
227 || !ipkdbaddr(cp
, &plen
, &len
)) {
228 putpkt(&ipkdb_if
, "einvalid peek format", 20);
231 peekmem(&ipkdb_if
, buf
, addr
, (long)len
);
239 if ( !(cp
= ipkdbaddr(buf
+ 1, &plen
, &addr
))
240 || !(cp
= ipkdbaddr(cp
, &plen
, &len
))
241 || plen
< (long)len
) {
242 putpkt(&ipkdb_if
, "einvalid poke format", 20);
245 pokemem(&ipkdb_if
, cp
, addr
, (long)len
);
249 ipkdb_if
.leave(&ipkdb_if
);
250 return IPKDB_CMD_STEP
;
252 putpkt(&ipkdb_if
, "ok",2);
253 ipkdb_if
.leave(&ipkdb_if
);
254 return IPKDB_CMD_EXIT
;
256 ipkdb_if
.leave(&ipkdb_if
);
257 return IPKDB_CMD_RUN
;
263 ipkdbaddr(u_char
*cp
, int *pl
, void **dp
)
265 /* Assume that sizeof(void *) <= sizeof(u_long) */
269 if ((*pl
-= sizeof *dp
) < 0)
271 for (i
= sizeof *dp
, l
= 0; --i
>= 0;) {
280 peekmem(struct ipkdb_if
*ifp
, u_char
*buf
, void *addr
, long len
)
282 u_char
*cp
, *p
= addr
;
287 for (l
= len
; --l
>= 0;)
288 *cp
++ = ipkdbfbyte(p
++);
289 putpkt(ifp
, buf
, len
+ 1);
293 pokemem(struct ipkdb_if
*ifp
, u_char
*cp
, void *addr
, long len
)
298 ipkdbsbyte(p
++, *cp
++);
299 putpkt(ifp
, "ok", 2);
302 inline static u_int32_t
307 return (*s
<< 24)|(s
[1] << 16)|(s
[2] << 8)|s
[3];
315 return (*s
<< 8)|s
[1];
319 setnl(void *vs
, u_int32_t l
)
330 setns(void *vs
, int l
)
339 cksum(u_short st
, void *vcp
, int l
)
344 for (s
= st
; (l
-= 2) >= 0; cp
+= 2)
345 s
+= (*cp
<< 8) + cp
[1];
349 s
= (s
&0xffff) + (s
>> 16);
350 return s
== 0xffff ? 0 : s
;
354 assemble(struct ipkdb_if
*ifp
, void *buf
)
360 ip
= (struct ip
*)buf
;
361 ipkdbcopy(ip
, &iph
, sizeof iph
);
369 if (ipkdbcmp(&iph
, ifp
->ass
, sizeof iph
)) {
372 * decide whether to keep the old
375 i
= (getns(&ip
->ip_id
)
376 ^ getns(&((struct ip
*)ifp
->ass
)->ip_id
));
377 i
^= ((i
>> 2) ^ (i
>> 4) ^ (i
>> 8) ^ (i
>> 12));
385 ipkdbzero(ifp
->assbit
, sizeof ifp
->assbit
);
386 ipkdbcopy(&iph
, ifp
->ass
, sizeof iph
);
388 off
= getns(&ip
->ip_off
);
389 len
= ((off
& IP_OFFMASK
) << 3) + getns(&ip
->ip_len
) - ip
->ip_hl
* 4;
390 if (ifp
->asslen
< len
)
392 if (ifp
->asslen
+ sizeof *ip
> sizeof ifp
->ass
) {
393 /* packet too long */
397 if (!(off
& IP_MF
)) {
399 cp
= ifp
->assbit
+ (off
>> 3);
400 for (i
= (off
& 7); i
< 8; *cp
|= 1 << i
++);
401 for (; cp
< ifp
->assbit
+ sizeof ifp
->assbit
; *cp
++ = -1);
404 cp
= ifp
->assbit
+ (off
>> 3);
405 ecp
= ifp
->assbit
+ (len
>> 6);
407 for (i
= (off
& 7); i
<= ((len
>> 3) & 7);
410 for (i
= (off
& 7); i
< 8; *cp
|= 1 << i
++);
411 for (; ++cp
< ecp
; *cp
= -1);
412 for (i
= 0; i
< ((len
>> 3) & 7); *cp
|= 1 << i
++);
415 ipkdbcopy((char *)buf
+ ip
->ip_hl
* 4,
416 ifp
->ass
+ sizeof *ip
+ (off
<< 3),
418 for (cp
= ifp
->assbit
; cp
< ifp
->assbit
+ sizeof ifp
->assbit
;)
419 if (*cp
++ != (u_char
)-1)
422 ip
= (struct ip
*)ifp
->ass
;
423 setns(&ip
->ip_len
, sizeof *ip
+ ifp
->asslen
);
429 inpkt(struct ipkdb_if
*ifp
, char *ibuf
, int poll
)
433 struct ether_header
*eh
;
440 l
= ifp
->receive(ifp
, ibuf
, poll
!= 0);
442 if (poll
== 1 || (poll
== 2 && --cnt
<= 0))
447 eh
= (struct ether_header
*)ibuf
;
448 switch (getns(&eh
->ether_type
)) {
450 ah
= (struct arphdr
*)(ibuf
+ 14);
451 if ( getns(&ah
->ar_hrd
) != ARPHRD_ETHER
452 || getns(&ah
->ar_pro
) != ETHERTYPE_IP
455 /* unsupported arp packet */
457 switch (getns(&ah
->ar_op
)) {
459 if ( (ifp
->flags
&IPKDB_MYIP
)
460 && !ipkdbcmp(ar_tpa(ah
),
462 sizeof ifp
->myinetaddr
)) {
463 /* someone requested my address */
464 ipkdbcopy(eh
->ether_shost
,
466 sizeof eh
->ether_dhost
);
467 ipkdbcopy(ifp
->myenetaddr
,
469 sizeof eh
->ether_shost
);
470 setns(&ah
->ar_op
, ARPOP_REPLY
);
471 ipkdbcopy(ar_sha(ah
),
474 ipkdbcopy(ar_spa(ah
),
477 ipkdbcopy(ifp
->myenetaddr
,
480 ipkdbcopy(ifp
->myinetaddr
,
483 ifp
->send(ifp
, ibuf
, 74);
492 ip
= (struct ip
*)(ibuf
+ 14);
493 if ( ip
->ip_v
!= IPVERSION
495 || getns(&ip
->ip_len
) + 14 > l
)
498 if (cksum(0, ip
, ip
->ip_hl
* 4))
501 if (ip
->ip_p
!= IPPROTO_UDP
)
503 if (getns(&ip
->ip_off
) & ~IP_DF
) {
504 if (!assemble(ifp
, ip
))
506 ip
= (struct ip
*)ifp
->ass
;
509 udp
= (struct udphdr
*)((char *)ip
+ ip
->ip_hl
* 4);
510 ul
= getns(&ip
->ip_len
) - ip
->ip_hl
* 4;
511 if (getns(&udp
->uh_ulen
) != ul
)
512 /* invalid UDP packet length */
514 ipkdbcopy(ip
, &ipo
, sizeof ipo
);
515 ipkdbzero(ipo
.ih_x1
, sizeof ipo
.ih_x1
);
516 ipo
.ih_len
= udp
->uh_ulen
;
518 && cksum(cksum(0, &ipo
, sizeof ipo
), udp
, ul
))
521 if (!(ifp
->flags
& IPKDB_MYIP
)) {
522 if ( getns(&udp
->uh_sport
) == 67
523 && getns(&udp
->uh_dport
) == 68
524 && *(char *)(udp
+ 1) == 2) {
525 /* this is a BOOTP reply to our ethernet address */
526 /* should check a bit more? XXX */
527 char *bootp
= (char *)(udp
+ 1);
528 ipkdbcopy(bootp
+ 16,
530 sizeof ifp
->myinetaddr
);
531 ifp
->flags
|= IPKDB_MYIP
;
533 /* give caller a chance to resend his request */
536 if ( ipkdbcmp(&ip
->ip_dst
, ifp
->myinetaddr
, sizeof ifp
->myinetaddr
)
537 || getns(&udp
->uh_dport
) != IPKDBPORT
)
539 /* so now it's a UDP packet for the debugger */
541 /* Check for reconnect packet */
544 p
= (u_char
*)(udp
+ 1);
545 if (!getnl(p
) && p
[6] == 'O') {
547 if ( l
<= ul
- sizeof *udp
- 6
548 && check_ipkdb(ifp
, &ip
->ip_src
,
550 ipkdbcopy(&ip
->ip_src
,
552 sizeof ifp
->hisinetaddr
);
553 ipkdbcopy(eh
->ether_shost
,
555 sizeof ifp
->hisenetaddr
);
556 ifp
->hisport
= getns(&udp
->uh_sport
);
557 ifp
->flags
|= IPKDB_HISHW
|IPKDB_HISIP
;
562 if ( (ifp
->flags
&IPKDB_HISIP
)
563 && ipkdbcmp(&ip
->ip_src
,
564 ifp
->hisinetaddr
, sizeof ifp
->hisinetaddr
))
565 /* It's a packet from someone else */
567 if (!(ifp
->flags
&IPKDB_HISIP
))
569 return (char *)(udp
+ 1);
578 static short ipkdb_ipid
= 0;
581 outpkt(struct ipkdb_if
*ifp
, char *in
, int l
, int srcport
, int dstport
)
583 struct ether_header
*eh
;
587 char _obuf
[ETHERMTU
+ 16];
588 #define obuf (_obuf + 2) /* align ip data in packet */
592 ipkdbzero(_obuf
, sizeof _obuf
);
593 eh
= (struct ether_header
*)obuf
;
595 * If we don't have his ethernet address, or this is a bootp request,
596 * broadcast the packet.
598 if (!(ifp
->flags
& IPKDB_HISHW
)
600 for (cp
= eh
->ether_dhost
;
601 cp
< eh
->ether_dhost
+ sizeof eh
->ether_dhost
;
604 ipkdbcopy(ifp
->hisenetaddr
, eh
->ether_dhost
, sizeof eh
->ether_dhost
);
605 ipkdbcopy(ifp
->myenetaddr
, eh
->ether_shost
, sizeof eh
->ether_shost
);
606 setns(&eh
->ether_type
, ETHERTYPE_IP
);
607 ip
= (struct ip
*)(obuf
+ 14);
608 ip
->ip_v
= IPVERSION
;
610 setns(&ip
->ip_id
, ipkdb_ipid
++);
612 ip
->ip_p
= IPPROTO_UDP
;
613 ipkdbcopy(ifp
->myinetaddr
, &ip
->ip_src
, sizeof ip
->ip_src
);
615 * If this is a bootp request, broadcast it.
618 for (cp
= (u_char
*)&ip
->ip_dst
;
619 cp
< (u_char
*)&ip
->ip_dst
+ sizeof ip
->ip_dst
;
622 ipkdbcopy(ifp
->hisinetaddr
, &ip
->ip_dst
, sizeof ip
->ip_dst
);
623 udp
= (struct udphdr
*)(ip
+ 1);
624 setns(&udp
->uh_sport
, srcport
);
625 setns(&udp
->uh_dport
, dstport
);
626 setns(&udp
->uh_ulen
, l
+ sizeof *udp
);
627 ipkdbcopy(ip
, &ipo
, sizeof ipo
);
628 ipkdbzero(ipo
.ih_x1
, sizeof ipo
.ih_x1
);
629 ipo
.ih_len
= udp
->uh_ulen
;
631 ~cksum(cksum(cksum(0, &ipo
, sizeof ipo
),
634 for (cp
= (u_char
*)(udp
+ 1), l
+= sizeof *udp
, off
= 0;
636 l
-= i
, in
+= i
, off
+= i
, cp
= (u_char
*)udp
) {
637 i
= l
> ifp
->mtu
- sizeof *ip
? ((ifp
->mtu
- sizeof *ip
) & ~7) : l
;
638 ipkdbcopy(in
, cp
, i
);
639 setns(&ip
->ip_len
, i
+ sizeof *ip
);
640 setns(&ip
->ip_off
, (l
> i
? IP_MF
: 0) | (off
>> 3));
642 setns(&ip
->ip_sum
, ~cksum(0, ip
, sizeof *ip
));
643 if (i
+ sizeof *ip
< ETHERMIN
)
644 i
= ETHERMIN
- sizeof *ip
;
645 ifp
->send(ifp
, obuf
, i
+ sizeof *ip
+ 14);
651 init(struct ipkdb_if
*ifp
)
654 u_char _ibuf
[ETHERMTU
+ 16];
655 #define ibuf (_ibuf + 2) /* align ip data in packet */
659 if (ifp
->flags
& IPKDB_MYIP
)
662 while (!(ifp
->flags
& IPKDB_MYIP
)) {
663 ipkdbzero(_ibuf
, sizeof _ibuf
);
665 *cp
++ = 1; /* BOOTP_REQUEST */
666 *cp
++ = 1; /* Ethernet hardware */
667 *cp
++ = 6; /* length of address */
668 setnl(++cp
, 0x12345678); /* some random number? */
669 setns(cp
+ 4, secs
++);
670 ipkdbcopy(ifp
->myenetaddr
, cp
+ 24, sizeof ifp
->myenetaddr
);
671 outpkt(ifp
, _ibuf
, 300, 68, 67);
673 if (ipkdbpanic
&& ipkdb_poll()) {
678 cp
= ifp
->myinetaddr
;
679 printf("My IP address is %d.%d.%d.%d\n",
680 cp
[0], cp
[1], cp
[2], cp
[3]);
684 /* HMAC Checksumming routines, see draft-ietf-ipsec-hmac-md5-00.txt */
685 #define LENCHK 16 /* Length of checksum in bytes */
688 * This code is based on the MD5 implementation as found in ssh.
689 * It's quite a bit hacked by myself, but the original has
690 * the following non-copyright comments on it:
692 /* This code has been heavily hacked by Tatu Ylonen <ylo@cs.hut.fi> to
693 make it compile on machines like Cray that don't have a 32 bit integer
696 * This code implements the MD5 message-digest algorithm.
697 * The algorithm is due to Ron Rivest. This code was
698 * written by Colin Plumb in 1993, no copyright is claimed.
699 * This code is in the public domain; do with it what you wish.
701 * Equivalent code is available from RSA Data Security, Inc.
702 * This code has been tested against that, and is equivalent,
703 * except that you don't need to include two pages of legalese
706 static struct ipkdb_MD5Context
{
710 } icontext
, ocontext
;
712 static u_int32_t
getNl(void *);
713 static void setNl(void *, u_int32_t
);
714 static void ipkdb_MD5Transform(struct ipkdb_MD5Context
*);
715 static void ipkdb_MD5Init(struct ipkdb_MD5Context
*);
716 static void ipkdb_MD5Update(struct ipkdb_MD5Context
*, u_char
*, u_int
);
717 static u_char
*ipkdb_MD5Final(struct ipkdb_MD5Context
*);
719 inline static u_int32_t
724 return *s
| (s
[1] << 8) | (s
[2] << 16) | (s
[3] << 24);
728 setNl(void *vs
, u_int32_t l
)
738 /* The four core functions - F1 is optimized somewhat */
739 /* #define F1(x, y, z) (((x) & (y)) | (~(x) & (z))) */
740 #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
741 #define F2(x, y, z) F1(z, x, y)
742 #define F3(x, y, z) ((x) ^ (y) ^ (z))
743 #define F4(x, y, z) ((y) ^ ((x) | ~(z)))
745 /* This is the central step in the MD5 algorithm. */
746 #define ipkdb_MD5STEP(f, w, x, y, z, data, s) \
747 ((w) += f(x, y, z) + (data), \
748 (w) = ((w) << (s)) | (((w) >> (32 - s)) & 0xffffffff), \
752 * The core of the MD5 algorithm, this alters an existing MD5 hash to
753 * reflect the addition of 16 longwords of new data. MD5Update blocks
754 * the data for this routine.
757 ipkdb_MD5Transform(struct ipkdb_MD5Context
*ctx
)
762 for (i
= 0; i
< 16; i
++)
763 in
[i
] = getNl(ctx
->in
+ 4 * i
);
770 ipkdb_MD5STEP(F1
, a
, b
, c
, d
, in
[0] + 0xd76aa478, 7);
771 ipkdb_MD5STEP(F1
, d
, a
, b
, c
, in
[1] + 0xe8c7b756, 12);
772 ipkdb_MD5STEP(F1
, c
, d
, a
, b
, in
[2] + 0x242070db, 17);
773 ipkdb_MD5STEP(F1
, b
, c
, d
, a
, in
[3] + 0xc1bdceee, 22);
774 ipkdb_MD5STEP(F1
, a
, b
, c
, d
, in
[4] + 0xf57c0faf, 7);
775 ipkdb_MD5STEP(F1
, d
, a
, b
, c
, in
[5] + 0x4787c62a, 12);
776 ipkdb_MD5STEP(F1
, c
, d
, a
, b
, in
[6] + 0xa8304613, 17);
777 ipkdb_MD5STEP(F1
, b
, c
, d
, a
, in
[7] + 0xfd469501, 22);
778 ipkdb_MD5STEP(F1
, a
, b
, c
, d
, in
[8] + 0x698098d8, 7);
779 ipkdb_MD5STEP(F1
, d
, a
, b
, c
, in
[9] + 0x8b44f7af, 12);
780 ipkdb_MD5STEP(F1
, c
, d
, a
, b
, in
[10] + 0xffff5bb1, 17);
781 ipkdb_MD5STEP(F1
, b
, c
, d
, a
, in
[11] + 0x895cd7be, 22);
782 ipkdb_MD5STEP(F1
, a
, b
, c
, d
, in
[12] + 0x6b901122, 7);
783 ipkdb_MD5STEP(F1
, d
, a
, b
, c
, in
[13] + 0xfd987193, 12);
784 ipkdb_MD5STEP(F1
, c
, d
, a
, b
, in
[14] + 0xa679438e, 17);
785 ipkdb_MD5STEP(F1
, b
, c
, d
, a
, in
[15] + 0x49b40821, 22);
787 ipkdb_MD5STEP(F2
, a
, b
, c
, d
, in
[1] + 0xf61e2562, 5);
788 ipkdb_MD5STEP(F2
, d
, a
, b
, c
, in
[6] + 0xc040b340, 9);
789 ipkdb_MD5STEP(F2
, c
, d
, a
, b
, in
[11] + 0x265e5a51, 14);
790 ipkdb_MD5STEP(F2
, b
, c
, d
, a
, in
[0] + 0xe9b6c7aa, 20);
791 ipkdb_MD5STEP(F2
, a
, b
, c
, d
, in
[5] + 0xd62f105d, 5);
792 ipkdb_MD5STEP(F2
, d
, a
, b
, c
, in
[10] + 0x02441453, 9);
793 ipkdb_MD5STEP(F2
, c
, d
, a
, b
, in
[15] + 0xd8a1e681, 14);
794 ipkdb_MD5STEP(F2
, b
, c
, d
, a
, in
[4] + 0xe7d3fbc8, 20);
795 ipkdb_MD5STEP(F2
, a
, b
, c
, d
, in
[9] + 0x21e1cde6, 5);
796 ipkdb_MD5STEP(F2
, d
, a
, b
, c
, in
[14] + 0xc33707d6, 9);
797 ipkdb_MD5STEP(F2
, c
, d
, a
, b
, in
[3] + 0xf4d50d87, 14);
798 ipkdb_MD5STEP(F2
, b
, c
, d
, a
, in
[8] + 0x455a14ed, 20);
799 ipkdb_MD5STEP(F2
, a
, b
, c
, d
, in
[13] + 0xa9e3e905, 5);
800 ipkdb_MD5STEP(F2
, d
, a
, b
, c
, in
[2] + 0xfcefa3f8, 9);
801 ipkdb_MD5STEP(F2
, c
, d
, a
, b
, in
[7] + 0x676f02d9, 14);
802 ipkdb_MD5STEP(F2
, b
, c
, d
, a
, in
[12] + 0x8d2a4c8a, 20);
804 ipkdb_MD5STEP(F3
, a
, b
, c
, d
, in
[5] + 0xfffa3942, 4);
805 ipkdb_MD5STEP(F3
, d
, a
, b
, c
, in
[8] + 0x8771f681, 11);
806 ipkdb_MD5STEP(F3
, c
, d
, a
, b
, in
[11] + 0x6d9d6122, 16);
807 ipkdb_MD5STEP(F3
, b
, c
, d
, a
, in
[14] + 0xfde5380c, 23);
808 ipkdb_MD5STEP(F3
, a
, b
, c
, d
, in
[1] + 0xa4beea44, 4);
809 ipkdb_MD5STEP(F3
, d
, a
, b
, c
, in
[4] + 0x4bdecfa9, 11);
810 ipkdb_MD5STEP(F3
, c
, d
, a
, b
, in
[7] + 0xf6bb4b60, 16);
811 ipkdb_MD5STEP(F3
, b
, c
, d
, a
, in
[10] + 0xbebfbc70, 23);
812 ipkdb_MD5STEP(F3
, a
, b
, c
, d
, in
[13] + 0x289b7ec6, 4);
813 ipkdb_MD5STEP(F3
, d
, a
, b
, c
, in
[0] + 0xeaa127fa, 11);
814 ipkdb_MD5STEP(F3
, c
, d
, a
, b
, in
[3] + 0xd4ef3085, 16);
815 ipkdb_MD5STEP(F3
, b
, c
, d
, a
, in
[6] + 0x04881d05, 23);
816 ipkdb_MD5STEP(F3
, a
, b
, c
, d
, in
[9] + 0xd9d4d039, 4);
817 ipkdb_MD5STEP(F3
, d
, a
, b
, c
, in
[12] + 0xe6db99e5, 11);
818 ipkdb_MD5STEP(F3
, c
, d
, a
, b
, in
[15] + 0x1fa27cf8, 16);
819 ipkdb_MD5STEP(F3
, b
, c
, d
, a
, in
[2] + 0xc4ac5665, 23);
821 ipkdb_MD5STEP(F4
, a
, b
, c
, d
, in
[0] + 0xf4292244, 6);
822 ipkdb_MD5STEP(F4
, d
, a
, b
, c
, in
[7] + 0x432aff97, 10);
823 ipkdb_MD5STEP(F4
, c
, d
, a
, b
, in
[14] + 0xab9423a7, 15);
824 ipkdb_MD5STEP(F4
, b
, c
, d
, a
, in
[5] + 0xfc93a039, 21);
825 ipkdb_MD5STEP(F4
, a
, b
, c
, d
, in
[12] + 0x655b59c3, 6);
826 ipkdb_MD5STEP(F4
, d
, a
, b
, c
, in
[3] + 0x8f0ccc92, 10);
827 ipkdb_MD5STEP(F4
, c
, d
, a
, b
, in
[10] + 0xffeff47d, 15);
828 ipkdb_MD5STEP(F4
, b
, c
, d
, a
, in
[1] + 0x85845dd1, 21);
829 ipkdb_MD5STEP(F4
, a
, b
, c
, d
, in
[8] + 0x6fa87e4f, 6);
830 ipkdb_MD5STEP(F4
, d
, a
, b
, c
, in
[15] + 0xfe2ce6e0, 10);
831 ipkdb_MD5STEP(F4
, c
, d
, a
, b
, in
[6] + 0xa3014314, 15);
832 ipkdb_MD5STEP(F4
, b
, c
, d
, a
, in
[13] + 0x4e0811a1, 21);
833 ipkdb_MD5STEP(F4
, a
, b
, c
, d
, in
[4] + 0xf7537e82, 6);
834 ipkdb_MD5STEP(F4
, d
, a
, b
, c
, in
[11] + 0xbd3af235, 10);
835 ipkdb_MD5STEP(F4
, c
, d
, a
, b
, in
[2] + 0x2ad7d2bb, 15);
836 ipkdb_MD5STEP(F4
, b
, c
, d
, a
, in
[9] + 0xeb86d391, 21);
845 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
846 * initialization constants.
849 ipkdb_MD5Init(struct ipkdb_MD5Context
*ctx
)
851 ctx
->buf
[0] = 0x67452301;
852 ctx
->buf
[1] = 0xefcdab89;
853 ctx
->buf
[2] = 0x98badcfe;
854 ctx
->buf
[3] = 0x10325476;
861 * Update context to reflect the concatenation of another buffer full
865 ipkdb_MD5Update(struct ipkdb_MD5Context
*ctx
, u_char
*buf
, unsigned len
)
869 /* Update bitcount */
871 if ((ctx
->bits
[0] = (t
+ (len
<< 3)) & 0xffffffff) < t
)
872 ctx
->bits
[1]++; /* Carry from low to high */
873 ctx
->bits
[1] += (len
>> 29) & 0xffffffff;
875 t
= (t
>> 3) & 0x3f; /* Bytes already in ctx->in */
877 /* Handle any leading odd-sized chunks */
879 u_char
*p
= ctx
->in
+ t
;
883 ipkdbcopy(buf
, p
, len
);
886 ipkdbcopy(buf
, p
, t
);
887 ipkdb_MD5Transform(ctx
);
892 /* Process data in 64-byte chunks */
894 ipkdbcopy(buf
, ctx
->in
, 64);
895 ipkdb_MD5Transform(ctx
);
900 /* Handle any remaining bytes of data. */
901 ipkdbcopy(buf
, ctx
->in
, len
);
905 * Final wrapup - pad to 64-byte boundary with the bit pattern
906 * 1 0* (64-bit count of bits processed, LSB-first)
909 ipkdb_MD5Final(struct ipkdb_MD5Context
*ctx
)
911 static u_char digest
[16];
915 /* Compute number of bytes mod 64 */
916 count
= (ctx
->bits
[0] >> 3) & 0x3f;
918 /* Set the first char of padding to 0x80. This is safe since there is
919 always at least one byte free */
923 /* Bytes of padding needed to make 64 bytes */
924 count
= 64 - 1 - count
;
926 /* Pad out to 56 mod 64 */
928 /* Two lots of padding: Pad the first block to 64 bytes */
930 ipkdb_MD5Transform(ctx
);
932 /* Now fill the next block with 56 bytes */
933 ipkdbzero(ctx
->in
, 56);
935 /* Pad block to 56 bytes */
936 ipkdbzero(p
, count
- 8);
938 /* Append length in bits and transform */
939 setNl(ctx
->in
+ 56, ctx
->bits
[0]);
940 setNl(ctx
->in
+ 60, ctx
->bits
[1]);
942 ipkdb_MD5Transform(ctx
);
943 setNl(digest
, ctx
->buf
[0]);
944 setNl(digest
+ 4, ctx
->buf
[1]);
945 setNl(digest
+ 8, ctx
->buf
[2]);
946 setNl(digest
+ 12, ctx
->buf
[3]);
952 * The following code is more or less stolen from the hmac_md5
953 * function in the Appendix of the HMAC IETF draft, but is
954 * optimized as suggested in this same paper.
961 u_char
*key
= ipkdbkey
;
962 int key_len
= strlen(key
);
965 /* Require key to be at least 16 bytes long */
967 printf("IPKDBKEY must be at least 16 bytes long!\n");
968 ipkdbzero(key
, key_len
); /* XXX */
972 /* if key is longer than 64 bytes reset it to key=MD5(key) */
974 ipkdb_MD5Init(&icontext
);
975 ipkdb_MD5Update(&icontext
, key
, key_len
);
976 ipkdbcopy(ipkdb_MD5Final(&icontext
), tk
, 16);
977 ipkdbzero(key
, key_len
); /* XXX */
983 * the HMAC_MD5 transform looks like:
985 * MD5(K XOR opad, MD5(K XOR ipad, text))
987 * where K is and n byte key
988 * ipad is the byte 0x36 repeated 64 times
989 * opad is the byte 0x5c repeated 64 times
990 * and text is the data being protected
993 * We do the initial part of MD5(K XOR ipad)
994 * and MD5(K XOR opad) here, in order to
995 * speed up the computation later on.
997 ipkdbzero(pad
, sizeof pad
);
998 ipkdbcopy(key
, pad
, key_len
);
999 for (i
= 0; i
< 64; i
++)
1001 ipkdb_MD5Init(&icontext
);
1002 ipkdb_MD5Update(&icontext
, pad
, 64);
1004 ipkdbzero(pad
, sizeof pad
);
1005 ipkdbcopy(key
, pad
, key_len
);
1006 for (i
= 0; i
< 64; i
++)
1008 ipkdb_MD5Init(&ocontext
);
1009 ipkdb_MD5Update(&ocontext
, pad
, 64);
1011 /* Zero out the key XXX */
1012 ipkdbzero(key
, key_len
);
1018 * This is more or less hmac_md5 from the HMAC IETF draft, Appendix.
1021 chksum(void *buf
, int len
)
1024 struct ipkdb_MD5Context context
;
1027 * the HMAC_MD5 transform looks like:
1029 * MD5(K XOR opad, MD5(K XOR ipad, text))
1031 * where K is an n byte key
1032 * ipad is the byte 0x36 repeated 64 times
1033 * opad is the byte 0x5c repeated 64 times
1034 * and text is the data being protected
1037 * Since we've already done the precomputation,
1038 * we can now stuff the data into the relevant
1039 * preinitialized contexts to get the result.
1044 ipkdbcopy(&icontext
, &context
, sizeof context
);
1045 ipkdb_MD5Update(&context
, buf
, len
);
1046 digest
= ipkdb_MD5Final(&context
);
1050 ipkdbcopy(&ocontext
, &context
, sizeof context
);
1051 ipkdb_MD5Update(&context
, digest
, 16);
1052 return ipkdb_MD5Final(&context
);
1056 getpkt(struct ipkdb_if
*ifp
, char *buf
, int *lp
)
1060 char _ibuf
[ETHERMTU
+ 16];
1061 #define ibuf (_ibuf + 2) /* align ip data in packet */
1065 if (!(got
= inpkt(ifp
, ibuf
, ipkdbpanic
!= 0))) {
1069 if ( ifp
->seq
== getnl(got
)
1072 && (l
= getns(got
+ 4))
1073 && !ipkdbcmp(chksum(got
, l
+ 6), got
+ l
+ 6, LENCHK
)) {
1074 ipkdbcopy(got
+ 6, buf
, *lp
= l
);
1078 && ((ifp
->flags
& (IPKDB_MYIP
| IPKDB_HISIP
| IPKDB_CONNECTED
))
1079 == (IPKDB_MYIP
| IPKDB_HISIP
| IPKDB_CONNECTED
)))
1080 outpkt(ifp
, ifp
->pkt
, ifp
->pktlen
, IPKDBPORT
, ifp
->hisport
);
1086 putpkt(struct ipkdb_if
*ifp
, const char *buf
, int l
)
1088 setnl(ifp
->pkt
, ifp
->seq
++);
1089 setns(ifp
->pkt
+ 4, l
);
1090 ipkdbcopy(buf
, ifp
->pkt
+ 6, l
);
1091 ipkdbcopy(chksum(ifp
->pkt
, l
+ 6), ifp
->pkt
+ 6 + l
, LENCHK
);
1092 ifp
->pktlen
= l
+ 6 + LENCHK
;
1093 if ( (ifp
->flags
& (IPKDB_MYIP
| IPKDB_HISIP
| IPKDB_CONNECTED
))
1094 != (IPKDB_MYIP
| IPKDB_HISIP
| IPKDB_CONNECTED
))
1096 outpkt(ifp
, ifp
->pkt
, ifp
->pktlen
, IPKDBPORT
, ifp
->hisport
);
1100 check_ipkdb(struct ipkdb_if
*ifp
, struct in_addr
*shost
, char *p
, int l
)
1108 if (kauth_authorize_system(curlwp
->l_cred
, KAUTH_SYSTEM_DEBUG
,
1109 KAUTH_REQ_SYSTEM_DEBUG_IPKDB
, NULL
, NULL
, NULL
))
1112 if (ipkdbcmp(chksum(p
, l
), p
+ l
, LENCHK
))
1114 ipkdbcopy(ifp
->hisenetaddr
, hisenet
, sizeof hisenet
);
1115 ipkdbcopy(ifp
->hisinetaddr
, hisinet
, sizeof hisinet
);
1116 hisport
= ifp
->hisport
;
1118 ipkdbcopy(shost
, ifp
->hisinetaddr
, sizeof ifp
->hisinetaddr
);
1119 ifp
->flags
&= ~IPKDB_HISHW
;
1120 ifp
->flags
|= IPKDB_HISIP
;
1121 if (connectipkdb(ifp
, p
+ 6, l
- 6) < 0) {
1122 ipkdbcopy(hisenet
, ifp
->hisenetaddr
, sizeof ifp
->hisenetaddr
);
1123 ipkdbcopy(hisinet
, ifp
->hisinetaddr
, sizeof ifp
->hisinetaddr
);
1124 ifp
->hisport
= hisport
;
1132 * Should check whether packet came across the correct interface. XXX
1135 checkipkdb(struct in_addr
*shost
, u_short sport
, u_short dport
, struct mbuf
*m
, int off
, int len
)
1139 char ibuf
[ETHERMTU
+50];
1141 if (dport
!= IPKDBPORT
)
1143 if (len
> sizeof ibuf
)
1145 m_copydata(m
, off
, len
, ibuf
);
1147 if (getnl(p
) || p
[6] != 'O')
1150 if (l
> len
- 6 || !check_ipkdb(&ipkdb_if
, shost
, p
, l
+ 6))
1152 ipkdb_if
.hisport
= sport
;
1158 connectipkdb(struct ipkdb_if
*ifp
, char *buf
, int l
)
1165 if (getnl(buf
+ 1) == ifp
->id
)
1166 /* It's a retry of a connect packet, ignore it */
1168 ip
= ifp
->hisinetaddr
;
1169 printf("debugged by ");
1170 l
-= 1 + sizeof(u_int32_t
);
1171 for (cp
= buf
+ 1 + sizeof(u_int32_t
); --l
>= 0; printf("%c", *cp
++));
1172 printf(" (%d.%d.%d.%d)\n", ip
[0], ip
[1], ip
[2], ip
[3]);
1173 ifp
->flags
|= IPKDB_CONNECTED
;
1176 ifp
->id
= getnl(buf
+ 1);