1 /* $NetBSD: ipkdb_ipkdb.c,v 1.17 2006/09/13 10:07:42 elad Exp $ */
2
3 /*
4 * Copyright (C) 1993-2000 Wolfgang Solfrank.
5 * Copyright (C) 1993-2000 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
21 *
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.
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: ipkdb_ipkdb.c,v 1.17 2006/09/13 10:07:42 elad Exp $");
36
37 #include "opt_ipkdb.h"
38
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <sys/mbuf.h>
42 #include <sys/reboot.h>
43 #include <sys/systm.h>
44 #include <sys/kauth.h>
45
46 #include <net/if.h>
47 #include <net/if_arp.h>
48 #include <net/if_ether.h>
49
50 #include <netinet/in.h>
51 #include <netinet/in_systm.h>
52 #include <netinet/if_inarp.h>
53 #include <netinet/in.h>
54 #include <netinet/ip.h>
55 #include <netinet/ip_var.h>
56 #include <netinet/udp.h>
57
58 #include <machine/cpu.h>
59 #include <machine/reg.h>
60
61 #include <ipkdb/ipkdb.h>
62 #include <machine/ipkdb.h>
63
64 int ipkdbpanic = 0;
65
66 #ifndef IPKDBKEY
67 #error You must specify the IPKDBKEY option to use IPKDB.
68 #else
69 static char *ipkdbkey = IPKDBKEY;
70 #endif
71
72 static struct ipkdb_if ipkdb_if;
73
74 static u_char *ipkdbaddr __P((u_char *, int *, void **));
75 static void peekmem __P((struct ipkdb_if *, u_char *, void *, long));
76 static void pokemem __P((struct ipkdb_if *, u_char *, void *, long));
77 static u_int32_t getnl __P((void *));
78 static u_int getns __P((void *));
79 static void setnl __P((void *, u_int32_t));
80 static void setns __P((void *, int));
81 static u_short cksum __P((u_short, void *, int));
82 static int assemble __P((struct ipkdb_if *, void *));
83 static char *inpkt __P((struct ipkdb_if *, char *, int));
84 static void outpkt __P((struct ipkdb_if *, char *, int, int, int));
85 static void init __P((struct ipkdb_if *));
86 static void *chksum __P((void *, int));
87 static void getpkt __P((struct ipkdb_if *, char *, int *));
88 static void putpkt __P((struct ipkdb_if *, char *, int));
89 static int check_ipkdb __P((struct ipkdb_if *, struct in_addr *, char *, int));
90 static int connectipkdb __P((struct ipkdb_if *, char *, int));
91 static int hmac_init __P((void));
92
93 void
94 ipkdb_init()
95 {
96 ipkdbinit();
97 if ( ipkdbifinit(&ipkdb_if) < 0
98 || !(ipkdb_if.flags&IPKDB_MYHW)
99 || !hmac_init()) {
100 /* Interface not found, drop IPKDB */
101 printf("IPKDB: No interface found!\n");
102 boothowto &= ~RB_KDB;
103 }
104 }
105
106 void
107 ipkdb_connect(when)
108 int when;
109 {
110 boothowto |= RB_KDB;
111 if (when == 0)
112 printf("waiting for remote debugger\n");
113 ipkdb_trap();
114 }
115
116 void
117 ipkdb_panic()
118 {
119 ipkdbpanic = 1;
120 ipkdb_trap();
121 }
122
123 /*
124 * Doesn't handle overlapping regions!
125 */
126 void
127 ipkdbcopy(s, d, n)
128 void *s, *d;
129 int n;
130 {
131 char *sp = s, *dp = d;
132
133 while (--n >= 0)
134 *dp++ = *sp++;
135 }
136
137 void
138 ipkdbzero(d, n)
139 void *d;
140 int n;
141 {
142 char *dp = d;
143
144 while (--n >= 0)
145 *dp++ = 0;
146 }
147
148 int
149 ipkdbcmp(s, d, n)
150 void *s, *d;
151 int n;
152 {
153 char *sp = s, *dp = d;
154
155 while (--n >= 0)
156 if (*sp++ != *dp++)
157 return *--dp - *--sp;
158 return 0;
159 }
160
161 int
162 ipkdbcmds()
163 {
164 static char buf[512];
165 char *cp;
166 int plen;
167
168 if (!(ipkdb_if.flags&IPKDB_MYHW)) /* no interface */
169 return IPKDB_CMD_EXIT;
170 init(&ipkdb_if);
171 if (ipkdbpanic > 1) {
172 ipkdb_if.leave(&ipkdb_if);
173 return IPKDB_CMD_RUN;
174 }
175 putpkt(&ipkdb_if, "s", 1);
176 while (1) {
177 getpkt(&ipkdb_if, buf, &plen);
178 if (!plen) {
179 if (ipkdbpanic && ipkdb_poll()) {
180 ipkdb_if.leave(&ipkdb_if);
181 return IPKDB_CMD_RUN;
182 } else
183 continue;
184 } else
185 ipkdbpanic = 0;
186 switch (*buf) {
187 default:
188 putpkt(&ipkdb_if, "eunknown command", 16);
189 break;
190 case 'O':
191 /* This is an allowed reconnect, ack it */
192 putpkt(&ipkdb_if, "s", 1);
193 break;
194 case 'R':
195 peekmem(&ipkdb_if, buf, ipkdbregs, sizeof ipkdbregs);
196 break;
197 case 'W':
198 if (plen != sizeof ipkdbregs + 1) {
199 putpkt(&ipkdb_if, "einvalid register size", 22);
200 break;
201 }
202 pokemem(&ipkdb_if, buf + 1, ipkdbregs, sizeof ipkdbregs);
203 break;
204 case 'M':
205 {
206 void *addr, *len;
207
208 plen--;
209 if ( !(cp = ipkdbaddr(buf + 1, &plen, &addr))
210 || !ipkdbaddr(cp, &plen, &len)) {
211 putpkt(&ipkdb_if, "einvalid peek format", 20);
212 break;
213 }
214 peekmem(&ipkdb_if, buf, addr, (long)len);
215 break;
216 }
217 case 'N':
218 {
219 void *addr, *len;
220
221 plen--;
222 if ( !(cp = ipkdbaddr(buf + 1, &plen, &addr))
223 || !(cp = ipkdbaddr(cp, &plen, &len))
224 || plen < (long)len) {
225 putpkt(&ipkdb_if, "einvalid poke format", 20);
226 break;
227 }
228 pokemem(&ipkdb_if, cp, addr, (long)len);
229 break;
230 }
231 case 'S':
232 ipkdb_if.leave(&ipkdb_if);
233 return IPKDB_CMD_STEP;
234 case 'X':
235 putpkt(&ipkdb_if, "ok",2);
236 ipkdb_if.leave(&ipkdb_if);
237 return IPKDB_CMD_EXIT;
238 case 'C':
239 ipkdb_if.leave(&ipkdb_if);
240 return IPKDB_CMD_RUN;
241 }
242 }
243 }
244
245 static u_char *
246 ipkdbaddr(cp, pl, dp)
247 u_char *cp;
248 int *pl;
249 void **dp;
250 {
251 /* Assume that sizeof(void *) <= sizeof(u_long) */
252 u_long l;
253 int i;
254
255 if ((*pl -= sizeof *dp) < 0)
256 return 0;
257 for (i = sizeof *dp, l = 0; --i >= 0;) {
258 l <<= 8;
259 l |= *cp++;
260 }
261 *dp = (void *)l;
262 return cp;
263 }
264
265 static void
266 peekmem(ifp, buf, addr, len)
267 struct ipkdb_if *ifp;
268 u_char *buf;
269 void *addr;
270 long len;
271 {
272 u_char *cp, *p = addr;
273 int l;
274
275 cp = buf;
276 *cp++ = 'p';
277 for (l = len; --l >= 0;)
278 *cp++ = ipkdbfbyte(p++);
279 putpkt(ifp, buf, len + 1);
280 }
281
282 static void
283 pokemem(ifp, cp, addr, len)
284 struct ipkdb_if *ifp;
285 u_char *cp;
286 void *addr;
287 long len;
288 {
289 u_char *p = addr;
290
291 while (--len >= 0)
292 ipkdbsbyte(p++, *cp++);
293 putpkt(ifp, "ok", 2);
294 }
295
296 inline static u_int32_t
297 getnl(vs)
298 void *vs;
299 {
300 u_char *s = vs;
301
302 return (*s << 24)|(s[1] << 16)|(s[2] << 8)|s[3];
303 }
304
305 inline static u_int
306 getns(vs)
307 void *vs;
308 {
309 u_char *s = vs;
310
311 return (*s << 8)|s[1];
312 }
313
314 inline static void
315 setnl(vs, l)
316 void *vs;
317 u_int32_t l;
318 {
319 u_char *s = vs;
320
321 *s++ = l >> 24;
322 *s++ = l >> 16;
323 *s++ = l >> 8;
324 *s = l;
325 }
326
327 inline static void
328 setns(vs, l)
329 void *vs;
330 int l;
331 {
332 u_char *s = vs;
333
334 *s++ = l >> 8;
335 *s = l;
336 }
337
338 static u_short
339 cksum(st, vcp, l)
340 u_short st;
341 void *vcp;
342 int l;
343 {
344 u_char *cp = vcp;
345 u_long s;
346
347 for (s = st; (l -= 2) >= 0; cp += 2)
348 s += (*cp << 8) + cp[1];
349 if (l == -1)
350 s += *cp << 8;
351 while (s&0xffff0000)
352 s = (s&0xffff) + (s >> 16);
353 return s == 0xffff ? 0 : s;
354 }
355
356 static int
357 assemble(ifp, buf)
358 struct ipkdb_if *ifp;
359 void *buf;
360 {
361 struct ip *ip, iph;
362 int off, len, i;
363 u_char *cp, *ecp;
364
365 ip = (struct ip *)buf;
366 ipkdbcopy(ip, &iph, sizeof iph);
367 iph.ip_hl = 5;
368 iph.ip_tos = 0;
369 iph.ip_len = 0;
370 iph.ip_off = 0;
371 iph.ip_ttl = 0;
372 iph.ip_sum = 0;
373 if (ifp->asslen) {
374 if (ipkdbcmp(&iph, ifp->ass, sizeof iph)) {
375 /*
376 * different packet
377 * decide whether to keep the old
378 * or start a new one
379 */
380 i = (getns(&ip->ip_id)
381 ^ getns(&((struct ip *)ifp->ass)->ip_id));
382 i ^= ((i >> 2) ^ (i >> 4) ^ (i >> 8) ^ (i >> 12));
383 if (i & 1)
384 /* keep the old */
385 return 0;
386 ifp->asslen = 0;
387 }
388 }
389 if (!ifp->asslen) {
390 ipkdbzero(ifp->assbit, sizeof ifp->assbit);
391 ipkdbcopy(&iph, ifp->ass, sizeof iph);
392 }
393 off = getns(&ip->ip_off);
394 len = ((off & IP_OFFMASK) << 3) + getns(&ip->ip_len) - ip->ip_hl * 4;
395 if (ifp->asslen < len)
396 ifp->asslen = len;
397 if (ifp->asslen + sizeof *ip > sizeof ifp->ass) {
398 /* packet too long */
399 ifp->asslen = 0;
400 return 0;
401 }
402 if (!(off & IP_MF)) {
403 off &= IP_OFFMASK;
404 cp = ifp->assbit + (off >> 3);
405 for (i = (off & 7); i < 8; *cp |= 1 << i++);
406 for (; cp < ifp->assbit + sizeof ifp->assbit; *cp++ = -1);
407 } else {
408 off &= IP_OFFMASK;
409 cp = ifp->assbit + (off >> 3);
410 ecp = ifp->assbit + (len >> 6);
411 if (cp == ecp)
412 for (i = (off & 7); i <= ((len >> 3) & 7);
413 *cp |= 1 << i++);
414 else {
415 for (i = (off & 7); i < 8; *cp |= 1 << i++);
416 for (; ++cp < ecp; *cp = -1);
417 for (i = 0; i < ((len >> 3) & 7); *cp |= 1 << i++);
418 }
419 }
420 ipkdbcopy((char *)buf + ip->ip_hl * 4,
421 ifp->ass + sizeof *ip + (off << 3),
422 len - (off << 3));
423 for (cp = ifp->assbit; cp < ifp->assbit + sizeof ifp->assbit;)
424 if (*cp++ != (u_char)-1)
425 /* not complete */
426 return 0;
427 ip = (struct ip *)ifp->ass;
428 setns(&ip->ip_len, sizeof *ip + ifp->asslen);
429 /* complete */
430 return 1;
431 }
432
433 static char *
434 inpkt(ifp, ibuf, poll)
435 struct ipkdb_if *ifp;
436 char *ibuf;
437 int poll;
438 {
439 int cnt = 1000000;
440 int l, ul;
441 struct ether_header *eh;
442 struct arphdr *ah;
443 struct ip *ip;
444 struct udphdr *udp;
445 struct ipovly ipo;
446
447 while (1) {
448 l = ifp->receive(ifp, ibuf, poll != 0);
449 if (!l) {
450 if (poll == 1 || (poll == 2 && --cnt <= 0))
451 break;
452 else
453 continue;
454 }
455 eh = (struct ether_header *)ibuf;
456 switch (getns(&eh->ether_type)) {
457 case ETHERTYPE_ARP:
458 ah = (struct arphdr *)(ibuf + 14);
459 if ( getns(&ah->ar_hrd) != ARPHRD_ETHER
460 || getns(&ah->ar_pro) != ETHERTYPE_IP
461 || ah->ar_hln != 6
462 || ah->ar_pln != 4)
463 /* unsupported arp packet */
464 break;
465 switch (getns(&ah->ar_op)) {
466 case ARPOP_REQUEST:
467 if ( (ifp->flags&IPKDB_MYIP)
468 && !ipkdbcmp(ar_tpa(ah),
469 ifp->myinetaddr,
470 sizeof ifp->myinetaddr)) {
471 /* someone requested my address */
472 ipkdbcopy(eh->ether_shost,
473 eh->ether_dhost,
474 sizeof eh->ether_dhost);
475 ipkdbcopy(ifp->myenetaddr,
476 eh->ether_shost,
477 sizeof eh->ether_shost);
478 setns(&ah->ar_op, ARPOP_REPLY);
479 ipkdbcopy(ar_sha(ah),
480 ar_tha(ah),
481 ah->ar_hln);
482 ipkdbcopy(ar_spa(ah),
483 ar_tpa(ah),
484 ah->ar_pln);
485 ipkdbcopy(ifp->myenetaddr,
486 ar_sha(ah),
487 ah->ar_hln);
488 ipkdbcopy(ifp->myinetaddr,
489 ar_spa(ah),
490 ah->ar_pln);
491 ifp->send(ifp, ibuf, 74);
492 continue;
493 }
494 break;
495 default:
496 break;
497 }
498 break;
499 case ETHERTYPE_IP:
500 ip = (struct ip *)(ibuf + 14);
501 if ( ip->ip_v != IPVERSION
502 || ip->ip_hl < 5
503 || getns(&ip->ip_len) + 14 > l)
504 /* invalid packet */
505 break;
506 if (cksum(0, ip, ip->ip_hl * 4))
507 /* wrong checksum */
508 break;
509 if (ip->ip_p != IPPROTO_UDP)
510 break;
511 if (getns(&ip->ip_off) & ~IP_DF) {
512 if (!assemble(ifp, ip))
513 break;
514 ip = (struct ip *)ifp->ass;
515 ifp->asslen = 0;
516 }
517 udp = (struct udphdr *)((char *)ip + ip->ip_hl * 4);
518 ul = getns(&ip->ip_len) - ip->ip_hl * 4;
519 if (getns(&udp->uh_ulen) != ul)
520 /* invalid UDP packet length */
521 break;
522 ipkdbcopy(ip, &ipo, sizeof ipo);
523 ipkdbzero(ipo.ih_x1, sizeof ipo.ih_x1);
524 ipo.ih_len = udp->uh_ulen;
525 if ( udp->uh_sum
526 && cksum(cksum(0, &ipo, sizeof ipo), udp, ul))
527 /* wrong checksum */
528 break;
529 if (!(ifp->flags & IPKDB_MYIP)) {
530 if ( getns(&udp->uh_sport) == 67
531 && getns(&udp->uh_dport) == 68
532 && *(char *)(udp + 1) == 2) {
533 /* this is a BOOTP reply to our ethernet address */
534 /* should check a bit more? XXX */
535 char *bootp = (char *)(udp + 1);
536 ipkdbcopy(bootp + 16,
537 ifp->myinetaddr,
538 sizeof ifp->myinetaddr);
539 ifp->flags |= IPKDB_MYIP;
540 }
541 /* give caller a chance to resend his request */
542 return 0;
543 }
544 if ( ipkdbcmp(&ip->ip_dst, ifp->myinetaddr, sizeof ifp->myinetaddr)
545 || getns(&udp->uh_dport) != IPKDBPORT)
546 break;
547 /* so now it's a UDP packet for the debugger */
548 {
549 /* Check for reconnect packet */
550 u_char *p;
551
552 p = (u_char *)(udp + 1);
553 if (!getnl(p) && p[6] == 'O') {
554 l = getns(p + 4);
555 if ( l <= ul - sizeof *udp - 6
556 && check_ipkdb(ifp, &ip->ip_src,
557 p, l + 6)) {
558 ipkdbcopy(&ip->ip_src,
559 ifp->hisinetaddr,
560 sizeof ifp->hisinetaddr);
561 ipkdbcopy(eh->ether_shost,
562 ifp->hisenetaddr,
563 sizeof ifp->hisenetaddr);
564 ifp->hisport = getns(&udp->uh_sport);
565 ifp->flags |= IPKDB_HISHW|IPKDB_HISIP;
566 return p;
567 }
568 }
569 }
570 if ( (ifp->flags&IPKDB_HISIP)
571 && ipkdbcmp(&ip->ip_src,
572 ifp->hisinetaddr, sizeof ifp->hisinetaddr))
573 /* It's a packet from someone else */
574 break;
575 if (!(ifp->flags&IPKDB_HISIP))
576 break;
577 return (char *)(udp + 1);
578 default:
579 /* unknown type */
580 break;
581 }
582 }
583 return 0;
584 }
585
586 static short ipkdb_ipid = 0;
587
588 static void
589 outpkt(ifp, in, l, srcport, dstport)
590 struct ipkdb_if *ifp;
591 char *in;
592 int l;
593 int srcport, dstport;
594 {
595 struct ether_header *eh;
596 struct ip *ip;
597 struct udphdr *udp;
598 u_char *cp;
599 char _obuf[ETHERMTU + 16];
600 #define obuf (_obuf + 2) /* align ip data in packet */
601 struct ipovly ipo;
602 int i, off;
603
604 ipkdbzero(_obuf, sizeof _obuf);
605 eh = (struct ether_header *)obuf;
606 /*
607 * If we don't have his ethernet address, or this is a bootp request,
608 * broadcast the packet.
609 */
610 if (!(ifp->flags & IPKDB_HISHW)
611 || dstport == 67)
612 for (cp = eh->ether_dhost;
613 cp < eh->ether_dhost + sizeof eh->ether_dhost;
614 *cp++ = -1);
615 else
616 ipkdbcopy(ifp->hisenetaddr, eh->ether_dhost, sizeof eh->ether_dhost);
617 ipkdbcopy(ifp->myenetaddr, eh->ether_shost, sizeof eh->ether_shost);
618 setns(&eh->ether_type, ETHERTYPE_IP);
619 ip = (struct ip *)(obuf + 14);
620 ip->ip_v = IPVERSION;
621 ip->ip_hl = 5;
622 setns(&ip->ip_id, ipkdb_ipid++);
623 ip->ip_ttl = 255;
624 ip->ip_p = IPPROTO_UDP;
625 ipkdbcopy(ifp->myinetaddr, &ip->ip_src, sizeof ip->ip_src);
626 /*
627 * If this is a bootp request, broadcast it.
628 */
629 if (dstport == 67)
630 for (cp = (u_char *)&ip->ip_dst;
631 cp < (u_char *)&ip->ip_dst + sizeof ip->ip_dst;
632 *cp++ = -1);
633 else
634 ipkdbcopy(ifp->hisinetaddr, &ip->ip_dst, sizeof ip->ip_dst);
635 udp = (struct udphdr *)(ip + 1);
636 setns(&udp->uh_sport, srcport);
637 setns(&udp->uh_dport, dstport);
638 setns(&udp->uh_ulen, l + sizeof *udp);
639 ipkdbcopy(ip, &ipo, sizeof ipo);
640 ipkdbzero(ipo.ih_x1, sizeof ipo.ih_x1);
641 ipo.ih_len = udp->uh_ulen;
642 setns(&udp->uh_sum,
643 ~cksum(cksum(cksum(0, &ipo, sizeof ipo),
644 udp, sizeof *udp),
645 in, l));
646 for (cp = (u_char *)(udp + 1), l += sizeof *udp, off = 0;
647 l > 0;
648 l -= i, in += i, off += i, cp = (u_char *)udp) {
649 i = l > ifp->mtu - sizeof *ip ? ((ifp->mtu - sizeof *ip) & ~7) : l;
650 ipkdbcopy(in, cp, i);
651 setns(&ip->ip_len, i + sizeof *ip);
652 setns(&ip->ip_off, (l > i ? IP_MF : 0) | (off >> 3));
653 ip->ip_sum = 0;
654 setns(&ip->ip_sum, ~cksum(0, ip, sizeof *ip));
655 if (i + sizeof *ip < ETHERMIN)
656 i = ETHERMIN - sizeof *ip;
657 ifp->send(ifp, obuf, i + sizeof *ip + 14);
658 }
659 #undef obuf
660 }
661
662 static void
663 init(ifp)
664 struct ipkdb_if *ifp;
665 {
666 u_char *cp;
667 u_char _ibuf[ETHERMTU + 16];
668 #define ibuf (_ibuf + 2) /* align ip data in packet */
669 int secs = 0;
670
671 ifp->start(ifp);
672 if (ifp->flags & IPKDB_MYIP)
673 return;
674
675 while (!(ifp->flags & IPKDB_MYIP)) {
676 ipkdbzero(_ibuf, sizeof _ibuf);
677 cp = _ibuf;
678 *cp++ = 1; /* BOOTP_REQUEST */
679 *cp++ = 1; /* Ethernet hardware */
680 *cp++ = 6; /* length of address */
681 setnl(++cp, 0x12345678); /* some random number? */
682 setns(cp + 4, secs++);
683 ipkdbcopy(ifp->myenetaddr, cp + 24, sizeof ifp->myenetaddr);
684 outpkt(ifp, _ibuf, 300, 68, 67);
685 inpkt(ifp, ibuf, 2);
686 if (ipkdbpanic && ipkdb_poll()) {
687 ipkdbpanic++;
688 return;
689 }
690 }
691 cp = ifp->myinetaddr;
692 printf("My IP address is %d.%d.%d.%d\n",
693 cp[0], cp[1], cp[2], cp[3]);
694 #undef ibuf
695 }
696
697 /* HMAC Checksumming routines, see draft-ietf-ipsec-hmac-md5-00.txt */
698 #define LENCHK 16 /* Length of checksum in bytes */
699
700 /*
701 * This code is based on the MD5 implementation as found in ssh.
702 * It's quite a bit hacked by myself, but the original has
703 * the following non-copyright comments on it:
704 */
705 /* This code has been heavily hacked by Tatu Ylonen <ylo@cs.hut.fi> to
706 make it compile on machines like Cray that don't have a 32 bit integer
707 type. */
708 /*
709 * This code implements the MD5 message-digest algorithm.
710 * The algorithm is due to Ron Rivest. This code was
711 * written by Colin Plumb in 1993, no copyright is claimed.
712 * This code is in the public domain; do with it what you wish.
713 *
714 * Equivalent code is available from RSA Data Security, Inc.
715 * This code has been tested against that, and is equivalent,
716 * except that you don't need to include two pages of legalese
717 * with every copy.
718 */
719 static struct ipkdb_MD5Context {
720 u_int buf[4];
721 u_int bits[2];
722 u_char in[64];
723 } icontext, ocontext;
724
725 static u_int32_t getNl __P((void *));
726 static void setNl __P((void *, u_int32_t));
727 static void ipkdb_MD5Transform __P((struct ipkdb_MD5Context *));
728 static void ipkdb_MD5Init __P((struct ipkdb_MD5Context *));
729 static void ipkdb_MD5Update __P((struct ipkdb_MD5Context *, u_char *, u_int));
730 static u_char *ipkdb_MD5Final __P((struct ipkdb_MD5Context *));
731
732 inline static u_int32_t
733 getNl(vs)
734 void *vs;
735 {
736 u_char *s = vs;
737
738 return *s | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
739 }
740
741 inline static void
742 setNl(vs, l)
743 void *vs;
744 u_int32_t l;
745 {
746 u_char *s = vs;
747
748 *s++ = l;
749 *s++ = l >> 8;
750 *s++ = l >> 16;
751 *s = l >> 24;
752 }
753
754 /* The four core functions - F1 is optimized somewhat */
755 /* #define F1(x, y, z) (((x) & (y)) | (~(x) & (z))) */
756 #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
757 #define F2(x, y, z) F1(z, x, y)
758 #define F3(x, y, z) ((x) ^ (y) ^ (z))
759 #define F4(x, y, z) ((y) ^ ((x) | ~(z)))
760
761 /* This is the central step in the MD5 algorithm. */
762 #define ipkdb_MD5STEP(f, w, x, y, z, data, s) \
763 ((w) += f(x, y, z) + (data), \
764 (w) = ((w) << (s)) | (((w) >> (32 - s)) & 0xffffffff), \
765 (w) += (x))
766
767 /*
768 * The core of the MD5 algorithm, this alters an existing MD5 hash to
769 * reflect the addition of 16 longwords of new data. MD5Update blocks
770 * the data for this routine.
771 */
772 static void
773 ipkdb_MD5Transform(ctx)
774 struct ipkdb_MD5Context *ctx;
775 {
776 u_int a, b, c, d, i;
777 u_int in[16];
778
779 for (i = 0; i < 16; i++)
780 in[i] = getNl(ctx->in + 4 * i);
781
782 a = ctx->buf[0];
783 b = ctx->buf[1];
784 c = ctx->buf[2];
785 d = ctx->buf[3];
786
787 ipkdb_MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
788 ipkdb_MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
789 ipkdb_MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
790 ipkdb_MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
791 ipkdb_MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
792 ipkdb_MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
793 ipkdb_MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
794 ipkdb_MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
795 ipkdb_MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
796 ipkdb_MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
797 ipkdb_MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
798 ipkdb_MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
799 ipkdb_MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
800 ipkdb_MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
801 ipkdb_MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
802 ipkdb_MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
803
804 ipkdb_MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
805 ipkdb_MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
806 ipkdb_MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
807 ipkdb_MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
808 ipkdb_MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
809 ipkdb_MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
810 ipkdb_MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
811 ipkdb_MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
812 ipkdb_MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
813 ipkdb_MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
814 ipkdb_MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
815 ipkdb_MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
816 ipkdb_MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
817 ipkdb_MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
818 ipkdb_MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
819 ipkdb_MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
820
821 ipkdb_MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
822 ipkdb_MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
823 ipkdb_MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
824 ipkdb_MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
825 ipkdb_MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
826 ipkdb_MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
827 ipkdb_MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
828 ipkdb_MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
829 ipkdb_MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
830 ipkdb_MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
831 ipkdb_MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
832 ipkdb_MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
833 ipkdb_MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
834 ipkdb_MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
835 ipkdb_MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
836 ipkdb_MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
837
838 ipkdb_MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
839 ipkdb_MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
840 ipkdb_MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
841 ipkdb_MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
842 ipkdb_MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
843 ipkdb_MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
844 ipkdb_MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
845 ipkdb_MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
846 ipkdb_MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
847 ipkdb_MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
848 ipkdb_MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
849 ipkdb_MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
850 ipkdb_MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
851 ipkdb_MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
852 ipkdb_MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
853 ipkdb_MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
854
855 ctx->buf[0] += a;
856 ctx->buf[1] += b;
857 ctx->buf[2] += c;
858 ctx->buf[3] += d;
859 }
860
861 /*
862 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
863 * initialization constants.
864 */
865 static void
866 ipkdb_MD5Init(ctx)
867 struct ipkdb_MD5Context *ctx;
868 {
869 ctx->buf[0] = 0x67452301;
870 ctx->buf[1] = 0xefcdab89;
871 ctx->buf[2] = 0x98badcfe;
872 ctx->buf[3] = 0x10325476;
873
874 ctx->bits[0] = 0;
875 ctx->bits[1] = 0;
876 }
877
878 /*
879 * Update context to reflect the concatenation of another buffer full
880 * of bytes.
881 */
882 static void
883 ipkdb_MD5Update(ctx, buf, len)
884 struct ipkdb_MD5Context *ctx;
885 u_char *buf;
886 unsigned len;
887 {
888 u_int t;
889
890 /* Update bitcount */
891 t = ctx->bits[0];
892 if ((ctx->bits[0] = (t + (len << 3)) & 0xffffffff) < t)
893 ctx->bits[1]++; /* Carry from low to high */
894 ctx->bits[1] += (len >> 29) & 0xffffffff;
895
896 t = (t >> 3) & 0x3f; /* Bytes already in ctx->in */
897
898 /* Handle any leading odd-sized chunks */
899 if (t) {
900 u_char *p = ctx->in + t;
901
902 t = 64 - t;
903 if (len < t) {
904 ipkdbcopy(buf, p, len);
905 return;
906 }
907 ipkdbcopy(buf, p, t);
908 ipkdb_MD5Transform(ctx);
909 buf += t;
910 len -= t;
911 }
912
913 /* Process data in 64-byte chunks */
914 while (len >= 64) {
915 ipkdbcopy(buf, ctx->in, 64);
916 ipkdb_MD5Transform(ctx);
917 buf += 64;
918 len -= 64;
919 }
920
921 /* Handle any remaining bytes of data. */
922 ipkdbcopy(buf, ctx->in, len);
923 }
924
925 /*
926 * Final wrapup - pad to 64-byte boundary with the bit pattern
927 * 1 0* (64-bit count of bits processed, LSB-first)
928 */
929 static u_char *
930 ipkdb_MD5Final(ctx)
931 struct ipkdb_MD5Context *ctx;
932 {
933 static u_char digest[16];
934 unsigned count;
935 u_char *p;
936
937 /* Compute number of bytes mod 64 */
938 count = (ctx->bits[0] >> 3) & 0x3f;
939
940 /* Set the first char of padding to 0x80. This is safe since there is
941 always at least one byte free */
942 p = ctx->in + count;
943 *p++ = 0x80;
944
945 /* Bytes of padding needed to make 64 bytes */
946 count = 64 - 1 - count;
947
948 /* Pad out to 56 mod 64 */
949 if (count < 8) {
950 /* Two lots of padding: Pad the first block to 64 bytes */
951 ipkdbzero(p, count);
952 ipkdb_MD5Transform(ctx);
953
954 /* Now fill the next block with 56 bytes */
955 ipkdbzero(ctx->in, 56);
956 } else
957 /* Pad block to 56 bytes */
958 ipkdbzero(p, count - 8);
959
960 /* Append length in bits and transform */
961 setNl(ctx->in + 56, ctx->bits[0]);
962 setNl(ctx->in + 60, ctx->bits[1]);
963
964 ipkdb_MD5Transform(ctx);
965 setNl(digest, ctx->buf[0]);
966 setNl(digest + 4, ctx->buf[1]);
967 setNl(digest + 8, ctx->buf[2]);
968 setNl(digest + 12, ctx->buf[3]);
969
970 return digest;
971 }
972
973 /*
974 * The following code is more or less stolen from the hmac_md5
975 * function in the Appendix of the HMAC IETF draft, but is
976 * optimized as suggested in this same paper.
977 */
978 static int
979 hmac_init()
980 {
981 char pad[64];
982 char tk[16];
983 u_char *key = ipkdbkey;
984 int key_len = strlen(key);
985 int i;
986
987 /* Require key to be at least 16 bytes long */
988 if (key_len < 16) {
989 printf("IPKDBKEY must be at least 16 bytes long!\n");
990 ipkdbzero(key, key_len); /* XXX */
991 return 0;
992 }
993
994 /* if key is longer than 64 bytes reset it to key=MD5(key) */
995 if (key_len > 64) {
996 ipkdb_MD5Init(&icontext);
997 ipkdb_MD5Update(&icontext, key, key_len);
998 ipkdbcopy(ipkdb_MD5Final(&icontext), tk, 16);
999 ipkdbzero(key, key_len); /* XXX */
1000 key = tk;
1001 key_len = 16;
1002 }
1003
1004 /*
1005 * the HMAC_MD5 transform looks like:
1006 *
1007 * MD5(K XOR opad, MD5(K XOR ipad, text))
1008 *
1009 * where K is and n byte key
1010 * ipad is the byte 0x36 repeated 64 times
1011 * opad is the byte 0x5c repeated 64 times
1012 * and text is the data being protected
1013 */
1014 /*
1015 * We do the initial part of MD5(K XOR ipad)
1016 * and MD5(K XOR opad) here, in order to
1017 * speed up the computation later on.
1018 */
1019 ipkdbzero(pad, sizeof pad);
1020 ipkdbcopy(key, pad, key_len);
1021 for (i = 0; i < 64; i++)
1022 pad[i] ^= 0x36;
1023 ipkdb_MD5Init(&icontext);
1024 ipkdb_MD5Update(&icontext, pad, 64);
1025
1026 ipkdbzero(pad, sizeof pad);
1027 ipkdbcopy(key, pad, key_len);
1028 for (i = 0; i < 64; i++)
1029 pad[i] ^= 0x5c;
1030 ipkdb_MD5Init(&ocontext);
1031 ipkdb_MD5Update(&ocontext, pad, 64);
1032
1033 /* Zero out the key XXX */
1034 ipkdbzero(key, key_len);
1035
1036 return 1;
1037 }
1038
1039 /*
1040 * This is more or less hmac_md5 from the HMAC IETF draft, Appendix.
1041 */
1042 static void *
1043 chksum(buf, len)
1044 void *buf;
1045 int len;
1046 {
1047 u_char *digest;
1048 struct ipkdb_MD5Context context;
1049
1050 /*
1051 * the HMAC_MD5 transform looks like:
1052 *
1053 * MD5(K XOR opad, MD5(K XOR ipad, text))
1054 *
1055 * where K is an n byte key
1056 * ipad is the byte 0x36 repeated 64 times
1057 * opad is the byte 0x5c repeated 64 times
1058 * and text is the data being protected
1059 */
1060 /*
1061 * Since we've already done the precomputation,
1062 * we can now stuff the data into the relevant
1063 * preinitialized contexts to get the result.
1064 */
1065 /*
1066 * perform inner MD5
1067 */
1068 ipkdbcopy(&icontext, &context, sizeof context);
1069 ipkdb_MD5Update(&context, buf, len);
1070 digest = ipkdb_MD5Final(&context);
1071 /*
1072 * perform outer MD5
1073 */
1074 ipkdbcopy(&ocontext, &context, sizeof context);
1075 ipkdb_MD5Update(&context, digest, 16);
1076 return ipkdb_MD5Final(&context);
1077 }
1078
1079 static void
1080 getpkt(ifp, buf, lp)
1081 struct ipkdb_if *ifp;
1082 char *buf;
1083 int *lp;
1084 {
1085 char *got;
1086 int l;
1087 char _ibuf[ETHERMTU + 16];
1088 #define ibuf (_ibuf + 2) /* align ip data in packet */
1089
1090 *lp = 0;
1091 while (1) {
1092 if (!(got = inpkt(ifp, ibuf, ipkdbpanic != 0))) {
1093 *lp = 0;
1094 return;
1095 }
1096 if ( ifp->seq == getnl(got)
1097 && got[6] >= 'A'
1098 && got[6] <= 'Z'
1099 && (l = getns(got + 4))
1100 && !ipkdbcmp(chksum(got, l + 6), got + l + 6, LENCHK)) {
1101 ipkdbcopy(got + 6, buf, *lp = l);
1102 return;
1103 }
1104 if ( ifp->pktlen
1105 && ((ifp->flags & (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
1106 == (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED)))
1107 outpkt(ifp, ifp->pkt, ifp->pktlen, IPKDBPORT, ifp->hisport);
1108 }
1109 #undef ibuf
1110 }
1111
1112 static void
1113 putpkt(ifp, buf, l)
1114 struct ipkdb_if *ifp;
1115 char *buf;
1116 int l;
1117 {
1118 setnl(ifp->pkt, ifp->seq++);
1119 setns(ifp->pkt + 4, l);
1120 ipkdbcopy(buf, ifp->pkt + 6, l);
1121 ipkdbcopy(chksum(ifp->pkt, l + 6), ifp->pkt + 6 + l, LENCHK);
1122 ifp->pktlen = l + 6 + LENCHK;
1123 if ( (ifp->flags & (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
1124 != (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
1125 return;
1126 outpkt(ifp, ifp->pkt, ifp->pktlen, IPKDBPORT, ifp->hisport);
1127 }
1128
1129 static int
1130 check_ipkdb(ifp, shost, p, l)
1131 struct ipkdb_if *ifp;
1132 struct in_addr *shost;
1133 char *p;
1134 int l;
1135 {
1136 u_char hisenet[6];
1137 u_char hisinet[4];
1138 u_int16_t hisport;
1139 char save;
1140
1141 #ifndef IPKDBSECURE
1142 if (kauth_authorize_system(curlwp->l_cred, KAUTH_SYSTEM_IPKDB,
1143 NULL, NULL, NULL, NULL))
1144 return 0;
1145 #endif
1146 if (ipkdbcmp(chksum(p, l), p + l, LENCHK))
1147 return 0;
1148 ipkdbcopy(ifp->hisenetaddr, hisenet, sizeof hisenet);
1149 ipkdbcopy(ifp->hisinetaddr, hisinet, sizeof hisinet);
1150 hisport = ifp->hisport;
1151 save = ifp->flags;
1152 ipkdbcopy(shost, ifp->hisinetaddr, sizeof ifp->hisinetaddr);
1153 ifp->flags &= ~IPKDB_HISHW;
1154 ifp->flags |= IPKDB_HISIP;
1155 if (connectipkdb(ifp, p + 6, l - 6) < 0) {
1156 ipkdbcopy(hisenet, ifp->hisenetaddr, sizeof ifp->hisenetaddr);
1157 ipkdbcopy(hisinet, ifp->hisinetaddr, sizeof ifp->hisinetaddr);
1158 ifp->hisport = hisport;
1159 ifp->flags = save;
1160 return 0;
1161 }
1162 return 1;
1163 }
1164
1165 /*
1166 * Should check whether packet came across the correct interface. XXX
1167 */
1168 int
1169 checkipkdb(shost, sport, dport, m, off, len)
1170 struct in_addr *shost;
1171 u_short sport, dport;
1172 struct mbuf *m;
1173 int off, len;
1174 {
1175 char *p;
1176 int l;
1177 char ibuf[ETHERMTU+50];
1178
1179 if (dport != IPKDBPORT)
1180 return 0;
1181 if (len > sizeof ibuf)
1182 return 0;
1183 m_copydata(m, off, len, ibuf);
1184 p = ibuf;
1185 if (getnl(p) || p[6] != 'O')
1186 return 0;
1187 l = getns(p + 4);
1188 if (l > len - 6 || !check_ipkdb(&ipkdb_if, shost, p, l + 6))
1189 return 0;
1190 ipkdb_if.hisport = sport;
1191 ipkdb_connect(1);
1192 return 1;
1193 }
1194
1195 static int
1196 connectipkdb(ifp, buf, l)
1197 struct ipkdb_if *ifp;
1198 char *buf;
1199 int l;
1200 {
1201 char *cp;
1202 u_char *ip;
1203
1204 if (*buf != 'O')
1205 return -1;
1206 if (getnl(buf + 1) == ifp->id)
1207 /* It's a retry of a connect packet, ignore it */
1208 return -1;
1209 ip = ifp->hisinetaddr;
1210 printf("debugged by ");
1211 l -= 1 + sizeof(u_int32_t);
1212 for (cp = buf + 1 + sizeof(u_int32_t); --l >= 0; printf("%c", *cp++));
1213 printf(" (%d.%d.%d.%d)\n", ip[0], ip[1], ip[2], ip[3]);
1214 ifp->flags |= IPKDB_CONNECTED;
1215 ifp->seq = 0;
1216 ifp->pktlen = 0;
1217 ifp->id = getnl(buf + 1);
1218 return 0;
1219 }
Cache object: 6d7ce9326ca7633798e64cc71e8b6636
|