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