]> The Tcpdump Group git mirrors - tcpdump/blob - print-isakmp.c
CERT and SIG payload. fix IPsec-AH transform value. (from KAME)
[tcpdump] / print-isakmp.c
1 /*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31 #ifndef lint
32 static const char rcsid[] =
33 "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.11 2000-04-24 12:49:11 itojun Exp $ (LBL)";
34 #endif
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <string.h>
41 #include <ctype.h>
42 #include <sys/param.h>
43 #include <sys/time.h>
44 #include <sys/socket.h>
45
46 #if __STDC__
47 struct mbuf;
48 struct rtentry;
49 #endif
50 #include <net/if.h>
51
52 #include <netinet/in.h>
53 #include <netinet/if_ether.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #include <netinet/ip_var.h>
57 #include <netinet/udp.h>
58 #include <netinet/udp_var.h>
59 #include <netinet/tcp.h>
60
61 #ifdef INET6
62 #include <netinet/ip6.h>
63 #endif
64
65 #include <stdio.h>
66 #include <netdb.h>
67
68 #include "isakmp.h"
69 #include "ipsec_doi.h"
70 #include "oakley.h"
71 #include "interface.h"
72 #include "addrtoname.h"
73 #include "extract.h" /* must come after interface.h */
74
75 #ifndef HAVE_SOCKADDR_STORAGE
76 #define sockaddr_storage sockaddr
77 #endif
78
79 static u_char *isakmp_sa_print __P((struct isakmp_gen *, u_char *, u_int32_t,
80 u_int32_t, u_int32_t));
81 static u_char *isakmp_p_print __P((struct isakmp_gen *, u_char *, u_int32_t,
82 u_int32_t, u_int32_t));
83 static u_char *isakmp_t_print __P((struct isakmp_gen *, u_char *, u_int32_t,
84 u_int32_t, u_int32_t));
85 static u_char *isakmp_ke_print __P((struct isakmp_gen *, u_char *, u_int32_t,
86 u_int32_t, u_int32_t));
87 static u_char *isakmp_id_print __P((struct isakmp_gen *, u_char *, u_int32_t,
88 u_int32_t, u_int32_t));
89 static u_char *isakmp_cert_print __P((struct isakmp_gen *, u_char *, u_int32_t,
90 u_int32_t, u_int32_t));
91 static u_char *isakmp_sig_print __P((struct isakmp_gen *, u_char *, u_int32_t,
92 u_int32_t, u_int32_t));
93 static u_char *isakmp_hash_print __P((struct isakmp_gen *, u_char *,
94 u_int32_t, u_int32_t, u_int32_t));
95 static u_char *isakmp_nonce_print __P((struct isakmp_gen *, u_char *,
96 u_int32_t, u_int32_t, u_int32_t));
97 static u_char *isakmp_n_print __P((struct isakmp_gen *, u_char *, u_int32_t,
98 u_int32_t, u_int32_t));
99 static u_char *isakmp_d_print __P((struct isakmp_gen *, u_char *, u_int32_t,
100 u_int32_t, u_int32_t));
101 static u_char *isakmp_vid_print __P((struct isakmp_gen *, u_char *, u_int32_t,
102 u_int32_t, u_int32_t));
103 static u_char *isakmp_sub0_print __P((u_char, struct isakmp_gen *, u_char *,
104 u_int32_t, u_int32_t, u_int32_t));
105 static u_char *isakmp_sub_print __P((u_char, struct isakmp_gen *, u_char *,
106 u_int32_t, u_int32_t, u_int32_t));
107 static char *numstr __P((int));
108
109 #define MAXINITIATORS 20
110 int ninitiator = 0;
111 struct {
112 cookie_t initiator;
113 struct sockaddr_storage iaddr;
114 struct sockaddr_storage raddr;
115 } cookiecache[MAXINITIATORS];
116
117 /* protocol id */
118 static char *protoidstr[] = {
119 NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
120 };
121
122 /* isakmp->np */
123 static char *npstr[] = {
124 "none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash",
125 "sig", "nonce", "n", "d", "vid"
126 };
127
128 /* isakmp->np */
129 static u_char *(*npfunc[]) __P((struct isakmp_gen *, u_char *, u_int32_t,
130 u_int32_t, u_int32_t)) = {
131 NULL,
132 isakmp_sa_print,
133 isakmp_p_print,
134 isakmp_t_print,
135 isakmp_ke_print,
136 isakmp_id_print,
137 isakmp_cert_print,
138 isakmp_cert_print,
139 isakmp_hash_print,
140 isakmp_sig_print,
141 isakmp_nonce_print,
142 isakmp_n_print,
143 isakmp_d_print,
144 isakmp_vid_print,
145 };
146
147 /* isakmp->etype */
148 static char *etypestr[] = {
149 "none", "base", "ident", "auth", "agg", "inf", NULL, NULL,
150 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
151 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
152 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
153 "oakley-quick", "oakley-newgroup",
154 };
155
156 #define STR_OR_ID(x, tab) \
157 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
158 #define PROTOIDSTR(x) STR_OR_ID(x, protoidstr)
159 #define NPSTR(x) STR_OR_ID(x, npstr)
160 #define ETYPESTR(x) STR_OR_ID(x, etypestr)
161
162 #define NPFUNC(x) \
163 (((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
164 ? npfunc[(x)] : NULL)
165
166 static int
167 iszero(u_char *p, size_t l)
168 {
169 while (l--) {
170 if (*p++)
171 return 0;
172 }
173 return 1;
174 }
175
176 /* find cookie from initiator cache */
177 static int
178 cookie_find(cookie_t *in)
179 {
180 int i;
181
182 for (i = 0; i < MAXINITIATORS; i++) {
183 if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
184 return i;
185 }
186
187 return -1;
188 }
189
190 /* record initiator */
191 static void
192 cookie_record(cookie_t *in, const u_char *bp2)
193 {
194 int i;
195 struct ip *ip;
196 struct sockaddr_in *sin;
197 #ifdef INET6
198 struct ip6_hdr *ip6;
199 struct sockaddr_in6 *sin6;
200 #endif
201
202 i = cookie_find(in);
203 if (0 <= i) {
204 ninitiator = (i + 1) % MAXINITIATORS;
205 return;
206 }
207
208 ip = (struct ip *)bp2;
209 switch (ip->ip_v) {
210 case 4:
211 memset(&cookiecache[ninitiator].iaddr, 0,
212 sizeof(cookiecache[ninitiator].iaddr));
213 memset(&cookiecache[ninitiator].raddr, 0,
214 sizeof(cookiecache[ninitiator].raddr));
215
216 sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr;
217 #ifdef HAVE_SOCKADDR_SA_LEN
218 sin->sin_len = sizeof(struct sockaddr_in);
219 #endif
220 sin->sin_family = AF_INET;
221 memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
222 sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr;
223 #ifdef HAVE_SOCKADDR_SA_LEN
224 sin->sin_len = sizeof(struct sockaddr_in);
225 #endif
226 sin->sin_family = AF_INET;
227 memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
228 break;
229 #ifdef INET6
230 case 6:
231 memset(&cookiecache[ninitiator].iaddr, 0,
232 sizeof(cookiecache[ninitiator].iaddr));
233 memset(&cookiecache[ninitiator].raddr, 0,
234 sizeof(cookiecache[ninitiator].raddr));
235
236 ip6 = (struct ip6_hdr *)bp2;
237 sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr;
238 #ifdef HAVE_SOCKADDR_SA_LEN
239 sin6->sin6_len = sizeof(struct sockaddr_in6);
240 #endif
241 sin6->sin6_family = AF_INET6;
242 memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
243 sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr;
244 #ifdef HAVE_SOCKADDR_SA_LEN
245 sin6->sin6_len = sizeof(struct sockaddr_in6);
246 #endif
247 sin6->sin6_family = AF_INET6;
248 memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
249 break;
250 #endif
251 default:
252 return;
253 }
254 memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in));
255 ninitiator = (ninitiator + 1) % MAXINITIATORS;
256 }
257
258 #define cookie_isinitiator(x, y) cookie_sidecheck((x), (y), 1)
259 #define cookie_isresponder(x, y) cookie_sidecheck((x), (y), 0)
260 static int
261 cookie_sidecheck(int i, const u_char *bp2, int initiator)
262 {
263 struct sockaddr_storage ss;
264 struct sockaddr *sa;
265 struct ip *ip;
266 struct sockaddr_in *sin;
267 #ifdef INET6
268 struct ip6_hdr *ip6;
269 struct sockaddr_in6 *sin6;
270 #endif
271 int salen;
272
273 memset(&ss, 0, sizeof(ss));
274 ip = (struct ip *)bp2;
275 switch (ip->ip_v) {
276 case 4:
277 sin = (struct sockaddr_in *)&ss;
278 #ifdef HAVE_SOCKADDR_SA_LEN
279 sin->sin_len = sizeof(struct sockaddr_in);
280 #endif
281 sin->sin_family = AF_INET;
282 memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src));
283 break;
284 #ifdef INET6
285 case 6:
286 ip6 = (struct ip6_hdr *)bp2;
287 sin6 = (struct sockaddr_in6 *)&ss;
288 #ifdef HAVE_SOCKADDR_SA_LEN
289 sin6->sin6_len = sizeof(struct sockaddr_in6);
290 #endif
291 sin6->sin6_family = AF_INET6;
292 memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src));
293 break;
294 #endif
295 default:
296 return 0;
297 }
298
299 sa = (struct sockaddr *)&ss;
300 if (initiator) {
301 if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].iaddr)->sa_family)
302 return 0;
303 #ifdef HAVE_SOCKADDR_SA_LEN
304 salen = sa->sa_len;
305 #else
306 #ifdef INET6
307 if (sa->sa_family == AF_INET6)
308 salen = sizeof(struct sockaddr_in6);
309 else
310 salen = sizeof(struct sockaddr);
311 #else
312 salen = sizeof(struct sockaddr);
313 #endif
314 #endif
315 if (memcmp(&ss, &cookiecache[i].iaddr, salen) == 0)
316 return 1;
317 } else {
318 if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].raddr)->sa_family)
319 return 0;
320 #ifdef HAVE_SOCKADDR_SA_LEN
321 salen = sa->sa_len;
322 #else
323 #ifdef INET6
324 if (sa->sa_family == AF_INET6)
325 salen = sizeof(struct sockaddr_in6);
326 else
327 salen = sizeof(struct sockaddr);
328 #else
329 salen = sizeof(struct sockaddr);
330 #endif
331 #endif
332 if (memcmp(&ss, &cookiecache[i].raddr, salen) == 0)
333 return 1;
334 }
335 return 0;
336 }
337
338 static void
339 rawprint(caddr_t loc, size_t len)
340 {
341 static u_char *p;
342 int i;
343
344 p = (u_char *)loc;
345 for (i = 0; i < len; i++)
346 printf("%02x", p[i] & 0xff);
347 }
348
349 struct attrmap {
350 char *type;
351 int nvalue;
352 char *value[30]; /*XXX*/
353 };
354
355 static u_char *
356 isakmp_attrmap_print(u_char *p, u_char *ep, struct attrmap *map, size_t nmap)
357 {
358 u_short *q;
359 int totlen;
360 u_int32_t t, v;
361
362 q = (u_short *)p;
363 if (p[0] & 0x80)
364 totlen = 4;
365 else
366 totlen = 4 + ntohs(q[1]);
367 if (ep < p + totlen) {
368 printf("[|attr]");
369 return ep + 1;
370 }
371
372 printf("(");
373 t = ntohs(q[0]) & 0x7fff;
374 if (map && t < nmap && map[t].type)
375 printf("type=%s ", map[t].type);
376 else
377 printf("type=#%d ", t);
378 if (p[0] & 0x80) {
379 printf("value=");
380 v = ntohs(q[1]);
381 if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
382 printf("%s", map[t].value[v]);
383 else
384 rawprint((caddr_t)&q[1], 2);
385 } else {
386 printf("len=%d value=", ntohs(q[1]));
387 rawprint((caddr_t)&p[4], ntohs(q[1]));
388 }
389 printf(")");
390 return p + totlen;
391 }
392
393 static u_char *
394 isakmp_attr_print(u_char *p, u_char *ep)
395 {
396 u_short *q;
397 int totlen;
398 u_int32_t t;
399
400 q = (u_short *)p;
401 if (p[0] & 0x80)
402 totlen = 4;
403 else
404 totlen = 4 + ntohs(q[1]);
405 if (ep < p + totlen) {
406 printf("[|attr]");
407 return ep + 1;
408 }
409
410 printf("(");
411 t = ntohs(q[0]) & 0x7fff;
412 printf("type=#%d ", t);
413 if (p[0] & 0x80) {
414 printf("value=");
415 t = q[1];
416 rawprint((caddr_t)&q[1], 2);
417 } else {
418 printf("len=%d value=", ntohs(q[1]));
419 rawprint((caddr_t)&p[2], ntohs(q[1]));
420 }
421 printf(")");
422 return p + totlen;
423 }
424
425 static u_char *
426 isakmp_sa_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
427 u_int32_t doi0, u_int32_t proto0)
428 {
429 struct isakmp_pl_sa *p;
430 u_int32_t *q;
431 u_int32_t doi;
432 u_int32_t sit;
433 u_char *cp;
434 int t;
435
436 printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
437
438 p = (struct isakmp_pl_sa *)ext;
439 doi = ntohl(p->doi);
440 if (doi != 1) {
441 printf(" doi=%d", doi);
442 printf(" situation=%u", (u_int32_t)ntohl(p->sit));
443 return (u_char *)(p + 1);
444 }
445
446 printf(" doi=ipsec");
447 q = (u_int32_t *)&p->sit;
448 printf(" situation=");
449 t = 0;
450 if (ntohl(*q) & 0x01) {
451 printf("identity");
452 t++;
453 }
454 if (ntohl(*q) & 0x02) {
455 printf("%ssecrecy", t ? "+" : "");
456 t++;
457 }
458 if (ntohl(*q) & 0x04)
459 printf("%sintegrity", t ? "+" : "");
460 sit = htonl(*q++);
461
462 if (sit != 0x01)
463 printf(" ident=%u", (u_int32_t)ntohl(*q++));
464
465 ext = (struct isakmp_gen *)q;
466
467 cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0);
468
469 return cp;
470 }
471
472 static u_char *
473 isakmp_p_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
474 u_int32_t doi0, u_int32_t proto0)
475 {
476 struct isakmp_pl_p *p;
477 u_char *cp;
478
479 printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
480
481 p = (struct isakmp_pl_p *)ext;
482 printf(" #%d protoid=%s transform=%d",
483 p->p_no, PROTOIDSTR(p->prot_id), p->num_t);
484 if (p->spi_size) {
485 printf(" spi=");
486 rawprint((caddr_t)(p + 1), p->spi_size);
487 }
488
489 ext = (struct isakmp_gen *)((u_char *)(p + 1) + p->spi_size);
490
491 cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
492 p->prot_id);
493
494 return cp;
495 }
496
497 static char *isakmp_p_map[] = {
498 NULL, "ike",
499 };
500
501 static char *ah_p_map[] = {
502 NULL, "(reserved)", "md5", "sha", "1des",
503 };
504
505 static char *esp_p_map[] = {
506 NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
507 "blowfish", "3idea", "1des-iv32", "rc4", "null"
508 };
509
510 static char *ipcomp_p_map[] = {
511 NULL, "oui", "deflate", "lzs",
512 };
513
514 struct attrmap ipsec_t_map[] = {
515 { NULL, 0, },
516 { "lifetype", 3, { NULL, "sec", "kb", }, },
517 { "life", 0, },
518 { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155",
519 "EC2N 2^185", }, },
520 { "enc mode", 3, { NULL, "tunnel", "transport", }, },
521 { "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
522 { "keylen", 0, },
523 { "rounds", 0, },
524 { "dictsize", 0, },
525 { "privalg", 0, },
526 };
527
528 struct attrmap oakley_t_map[] = {
529 { NULL, 0 },
530 { "enc", 7, { NULL, "1des", "idea", "blowfish", "rc5",
531 "3des", "cast"}, },
532 { "hash", 4, { NULL, "md5", "sha1", "tiger", }, },
533 { "auth", 6, { NULL, "preshared", "dss", "rsa sig", "rsa enc",
534 "rsa enc revised", }, },
535 { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155",
536 "EC2N 2^185", }, },
537 { "group type", 4, { NULL, "MODP", "ECP", "EC2N", }, },
538 { "group prime", 0, },
539 { "group gen1", 0, },
540 { "group gen2", 0, },
541 { "group curve A", 0, },
542 { "group curve B", 0, },
543 { "lifetype", 3, { NULL, "sec", "kb", }, },
544 { "lifeduration", 0, },
545 { "prf", 0, },
546 { "keylen", 0, },
547 { "field", 0, },
548 { "order", 0, },
549 };
550
551 static u_char *
552 isakmp_t_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
553 u_int32_t doi, u_int32_t proto)
554 {
555 struct isakmp_pl_t *p;
556 u_char *cp;
557 char *idstr;
558 struct attrmap *map;
559 size_t nmap;
560 u_char *ep2;
561
562 printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
563
564 p = (struct isakmp_pl_t *)ext;
565
566 switch (proto) {
567 case 1:
568 idstr = STR_OR_ID(p->t_id, isakmp_p_map);
569 map = oakley_t_map;
570 nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
571 break;
572 case 2:
573 idstr = STR_OR_ID(p->t_id, ah_p_map);
574 map = ipsec_t_map;
575 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
576 break;
577 case 3:
578 idstr = STR_OR_ID(p->t_id, esp_p_map);
579 map = ipsec_t_map;
580 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
581 break;
582 case 4:
583 idstr = STR_OR_ID(p->t_id, ipcomp_p_map);
584 map = ipsec_t_map;
585 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
586 break;
587 default:
588 idstr = NULL;
589 map = NULL;
590 nmap = 0;
591 break;
592 }
593
594 if (idstr)
595 printf(" #%d id=%s ", p->t_no, idstr);
596 else
597 printf(" #%d id=%d ", p->t_no, p->t_id);
598 cp = (u_char *)(p + 1);
599 ep2 = (u_char *)p + ntohs(ext->len);
600 while (cp < ep && cp < ep2) {
601 if (map && nmap) {
602 cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
603 map, nmap);
604 } else
605 cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
606 }
607 if (ep < ep2)
608 printf("...");
609 return cp;
610 }
611
612 static u_char *
613 isakmp_ke_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
614 u_int32_t doi, u_int32_t proto)
615 {
616 printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
617
618 printf(" key len=%d", ntohs(ext->len) - 4);
619 if (2 < vflag && 4 < ntohs(ext->len)) {
620 printf(" ");
621 rawprint((caddr_t)(ext + 1), ntohs(ext->len) - 4);
622 }
623 return (u_char *)ext + ntohs(ext->len);
624 }
625
626 static u_char *
627 isakmp_id_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
628 u_int32_t doi, u_int32_t proto)
629 {
630 #define USE_IPSECDOI_IN_PHASE1 1
631 struct isakmp_pl_id *p;
632 static char *idtypestr[] = {
633 "IPv4", "IPv4net", "IPv6", "IPv6net",
634 };
635 static char *ipsecidtypestr[] = {
636 NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
637 "IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
638 "keyid",
639 };
640 int len;
641 u_char *data;
642
643 printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
644
645 p = (struct isakmp_pl_id *)ext;
646 if (sizeof(*p) < ext->len)
647 data = (u_char *)(p + 1);
648 else
649 data = NULL;
650 len = ntohs(ext->len) - sizeof(*p);
651
652 #if 0 /*debug*/
653 printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
654 #endif
655 switch (phase) {
656 #ifndef USE_IPSECDOI_IN_PHASE1
657 case 1:
658 #endif
659 default:
660 printf(" idtype=%s", STR_OR_ID(p->d.id_type, idtypestr));
661 printf(" doi_data=%u",
662 (u_int32_t)(ntohl(p->d.doi_data) & 0xffffff));
663 break;
664
665 #ifdef USE_IPSECDOI_IN_PHASE1
666 case 1:
667 #endif
668 case 2:
669 {
670 struct ipsecdoi_id *p;
671 struct protoent *pe;
672
673 p = (struct ipsecdoi_id *)ext;
674 printf(" idtype=%s", STR_OR_ID(p->type, ipsecidtypestr));
675 setprotoent(1);
676 pe = getprotobynumber(p->proto_id);
677 if (pe)
678 printf(" protoid=%s", pe->p_name);
679 else
680 printf(" protoid=%s", PROTOIDSTR(p->proto_id));
681 endprotoent();
682 printf(" port=%d", ntohs(p->port));
683 if (!len)
684 break;
685 switch (p->type) {
686 case IPSECDOI_ID_IPV4_ADDR:
687 printf(" len=%d %s", len, ipaddr_string(data));
688 len = 0;
689 break;
690 case IPSECDOI_ID_FQDN:
691 case IPSECDOI_ID_USER_FQDN:
692 {
693 int i;
694 printf(" len=%d ", len);
695 for (i = 0; i < len; i++) {
696 if (isprint(data[i]))
697 printf("%c", data[i]);
698 else
699 printf("\\%03o", data[i]);
700 }
701 len = 0;
702 break;
703 }
704 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
705 {
706 u_char *mask;
707 mask = data + sizeof(struct in_addr);
708 printf(" len=%d %s/%u.%u.%u.%u", len,
709 ipaddr_string(data),
710 mask[0], mask[1], mask[2], mask[3]);
711 len = 0;
712 break;
713 }
714 #ifdef INET6
715 case IPSECDOI_ID_IPV6_ADDR:
716 printf(" len=%d %s", len, ip6addr_string(data));
717 len = 0;
718 break;
719 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
720 {
721 u_int32_t *mask;
722 mask = (u_int32_t *)(data + sizeof(struct in6_addr));
723 /*XXX*/
724 printf(" len=%d %s/0x%08x%08x%08x%08x", len,
725 ip6addr_string(data),
726 mask[0], mask[1], mask[2], mask[3]);
727 len = 0;
728 break;
729 }
730 #endif /*INET6*/
731 case IPSECDOI_ID_IPV4_ADDR_RANGE:
732 printf(" len=%d %s-%s", len, ipaddr_string(data),
733 ipaddr_string(data + sizeof(struct in_addr)));
734 len = 0;
735 break;
736 #ifdef INET6
737 case IPSECDOI_ID_IPV6_ADDR_RANGE:
738 printf(" len=%d %s-%s", len, ip6addr_string(data),
739 ip6addr_string(data + sizeof(struct in6_addr)));
740 len = 0;
741 break;
742 #endif /*INET6*/
743 case IPSECDOI_ID_DER_ASN1_DN:
744 case IPSECDOI_ID_DER_ASN1_GN:
745 case IPSECDOI_ID_KEY_ID:
746 break;
747 }
748 break;
749 }
750 }
751 if (data && len) {
752 len -= sizeof(*p);
753 printf(" len=%d", len);
754 if (2 < vflag) {
755 printf(" ");
756 rawprint((caddr_t)data, len);
757 }
758 }
759 return (u_char *)ext + ntohs(ext->len);
760 }
761
762 static u_char *
763 isakmp_cert_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
764 u_int32_t doi0, u_int32_t proto0)
765 {
766 struct isakmp_pl_cert *p;
767 static char *certstr[] = {
768 "none", "pkcs7", "pgp", "dns",
769 "x509sign", "x509ke", "kerberos", "crl",
770 "arl", "spki", "x509attr",
771 };
772
773 printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
774
775 p = (struct isakmp_pl_cert *)ext;
776 printf(" len=%d", ntohs(ext->len) - 4);
777 printf(" type=%s", STR_OR_ID((p->encode), certstr));
778 if (2 < vflag && 4 < ntohs(ext->len)) {
779 printf(" ");
780 rawprint((caddr_t)(ext + 1), ntohs(ext->len) - 4);
781 }
782 return (u_char *)ext + ntohs(ext->len);
783 }
784
785 static u_char *
786 isakmp_hash_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
787 u_int32_t doi, u_int32_t proto)
788 {
789 printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
790
791 printf(" len=%d", ntohs(ext->len) - 4);
792 if (2 < vflag && 4 < ntohs(ext->len)) {
793 printf(" ");
794 rawprint((caddr_t)(ext + 1), ntohs(ext->len) - 4);
795 }
796 return (u_char *)ext + ntohs(ext->len);
797 }
798
799 static u_char *
800 isakmp_sig_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
801 u_int32_t doi, u_int32_t proto)
802 {
803 printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
804
805 printf(" len=%d", ntohs(ext->len) - 4);
806 if (2 < vflag && 4 < ntohs(ext->len)) {
807 printf(" ");
808 rawprint((caddr_t)(ext + 1), ntohs(ext->len) - 4);
809 }
810 return (u_char *)ext + ntohs(ext->len);
811 }
812
813 static u_char *
814 isakmp_nonce_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
815 u_int32_t doi, u_int32_t proto)
816 {
817 printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
818
819 printf(" n len=%d", ntohs(ext->len) - 4);
820 if (2 < vflag && 4 < ntohs(ext->len)) {
821 printf(" ");
822 rawprint((caddr_t)(ext + 1), ntohs(ext->len) - 4);
823 }
824 return (u_char *)ext + ntohs(ext->len);
825 }
826
827 static u_char *
828 isakmp_n_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
829 u_int32_t doi0, u_int32_t proto0)
830 {
831 struct isakmp_pl_n *p;
832 u_char *cp;
833 u_char *ep2;
834 u_int32_t doi;
835 u_int32_t proto;
836 static char *notifystr[] = {
837 NULL, "INVALID-PAYLOAD-TYPE",
838 "DOI-NOT-SUPPORTED", "SITUATION-NOT-SUPPORTED",
839 "INVALID-COOKIE", "INVALID-MAJOR-VERSION",
840 "INVALID-MINOR-VERSION", "INVALID-EXCHANGE-TYPE",
841 "INVALID-FLAGS", "INVALID-MESSAGE-ID",
842 "INVALID-PROTOCOL-ID", "INVALID-SPI",
843 "INVALID-TRANSFORM-ID", "ATTRIBUTES-NOT-SUPPORTED",
844 "NO-PROPOSAL-CHOSEN", "BAD-PROPOSAL-SYNTAX",
845 "PAYLOAD-MALFORMED", "INVALID-KEY-INFORMATION",
846 "INVALID-ID-INFORMATION", "INVALID-CERT-ENCODING",
847 "INVALID-CERTIFICATE", "CERT-TYPE-UNSUPPORTED",
848 "INVALID-CERT-AUTHORITY", "INVALID-HASH-INFORMATION",
849 "AUTHENTICATION-FAILED", "INVALID-SIGNATURE",
850 "ADDRESS-NOTIFICATION", "NOTIFY-SA-LIFETIME",
851 "CERTIFICATE-UNAVAILABLE", "UNSUPPORTED-EXCHANGE-TYPE",
852 "UNEQUAL-PAYLOAD-LENGTHS",
853 };
854 static char *ipsecnotifystr[] = {
855 "RESPONDER-LIFETIME", "REPLAY-STATUS",
856 "INITIAL-CONTACT",
857 };
858 /* NOTE: these macro must be called with x in proper range */
859 #define NOTIFYSTR(x) \
860 (((x) == 16384) ? "CONNECTED" : STR_OR_ID((x), notifystr))
861 #define IPSECNOTIFYSTR(x) \
862 (((x) == 8192) ? "RESERVED" : STR_OR_ID(((x) - 24576), ipsecnotifystr))
863
864 printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
865
866 p = (struct isakmp_pl_n *)ext;
867 doi = ntohl(p->doi);
868 proto = p->prot_id;
869 if (doi != 1) {
870 printf(" doi=%d", doi);
871 printf(" proto=%d", proto);
872 printf(" type=%s", NOTIFYSTR(ntohs(p->type)));
873 if (p->spi_size) {
874 printf(" spi=");
875 rawprint((caddr_t)(p + 1), p->spi_size);
876 }
877 return (u_char *)(p + 1) + p->spi_size;
878 }
879
880 printf(" doi=ipsec");
881 printf(" proto=%s", PROTOIDSTR(proto));
882 if (ntohs(p->type) < 8192)
883 printf(" type=%s", NOTIFYSTR(ntohs(p->type)));
884 else if (ntohs(p->type) < 16384)
885 printf(" type=%s", IPSECNOTIFYSTR(ntohs(p->type)));
886 else if (ntohs(p->type) < 24576)
887 printf(" type=%s", NOTIFYSTR(ntohs(p->type)));
888 else if (ntohs(p->type) < 40960)
889 printf(" type=%s", IPSECNOTIFYSTR(ntohs(p->type)));
890 else
891 printf(" type=%s", NOTIFYSTR(ntohs(p->type)));
892 if (p->spi_size) {
893 printf(" spi=");
894 rawprint((caddr_t)(p + 1), p->spi_size);
895 }
896
897 cp = (u_char *)(p + 1) + p->spi_size;
898 ep2 = (u_char *)p + ntohs(ext->len);
899
900 if (cp < ep) {
901 printf(" orig=(");
902 switch (ntohs(p->type)) {
903 case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
904 {
905 struct attrmap *map = oakley_t_map;
906 size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
907 while (cp < ep && cp < ep2) {
908 cp = isakmp_attrmap_print(cp,
909 (ep < ep2) ? ep : ep2, map, nmap);
910 }
911 break;
912 }
913 case IPSECDOI_NTYPE_REPLAY_STATUS:
914 printf("replay detection %sabled",
915 (*(u_int32_t *)cp) ? "en" : "dis");
916 break;
917 case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
918 isakmp_sub_print(ISAKMP_NPTYPE_SA,
919 (struct isakmp_gen *)cp, ep, phase, doi, proto);
920 break;
921 default:
922 /* NULL is dummy */
923 isakmp_print(cp,
924 ntohs(ext->len) - sizeof(*p) - p->spi_size,
925 NULL);
926 }
927 printf(")");
928 }
929 return (u_char *)ext + ntohs(ext->len);
930 }
931
932 static u_char *
933 isakmp_d_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
934 u_int32_t doi0, u_int32_t proto0)
935 {
936 struct isakmp_pl_d *p;
937 u_int8_t *q;
938 u_int32_t doi;
939 u_int32_t proto;
940 int i;
941
942 printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
943
944 p = (struct isakmp_pl_d *)ext;
945 doi = ntohl(p->doi);
946 proto = p->prot_id;
947 if (doi != 1) {
948 printf(" doi=%u", doi);
949 printf(" proto=%u", proto);
950 } else {
951 printf(" doi=ipsec");
952 printf(" proto=%s", PROTOIDSTR(proto));
953 }
954 printf(" spilen=%u", p->spi_size);
955 printf(" nspi=%u", ntohs(p->num_spi));
956 printf(" spi=");
957 q = (u_int8_t *)(p + 1);
958 for (i = 0; i < ntohs(p->num_spi); i++) {
959 if (i != 0)
960 printf(",");
961 rawprint((caddr_t)q, p->spi_size);
962 q += p->spi_size;
963 }
964 return q;
965 }
966
967 static u_char *
968 isakmp_vid_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
969 u_int32_t doi, u_int32_t proto)
970 {
971 printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
972
973 printf(" len=%d", ntohs(ext->len) - 4);
974 if (2 < vflag && 4 < ntohs(ext->len)) {
975 printf(" ");
976 rawprint((caddr_t)(ext + 1), ntohs(ext->len) - 4);
977 }
978 return (u_char *)ext + ntohs(ext->len);
979 }
980
981 static u_char *
982 isakmp_sub0_print(u_char np, struct isakmp_gen *ext, u_char *ep,
983 u_int32_t phase, u_int32_t doi, u_int32_t proto)
984 {
985 u_char *cp;
986
987 cp = (u_char *)ext;
988
989 if (NPFUNC(np))
990 cp = (*NPFUNC(np))(ext, ep, phase, doi, proto);
991 else {
992 printf("%s", NPSTR(np));
993 cp += ntohs(ext->len);
994 }
995 return cp;
996 }
997
998 static u_char *
999 isakmp_sub_print(u_char np, struct isakmp_gen *ext, u_char *ep,
1000 u_int32_t phase, u_int32_t doi, u_int32_t proto)
1001 {
1002 u_char *cp;
1003 static int depth = 0;
1004 int i;
1005
1006 cp = (u_char *)ext;
1007
1008 while (np) {
1009 if (ep < (u_char *)ext + ntohs(ext->len)) {
1010 printf(" [|%s]", NPSTR(np));
1011 cp = ep + 1;
1012 break;
1013 }
1014 depth++;
1015 printf("\n");
1016 for (i = 0; i < depth; i++)
1017 printf(" ");
1018 printf("(");
1019 cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto);
1020 printf(")");
1021 depth--;
1022
1023 np = ext->np;
1024 ext = (struct isakmp_gen *)cp;
1025 }
1026 return cp;
1027 }
1028
1029 static char *
1030 numstr(int x)
1031 {
1032 static char buf[20];
1033 snprintf(buf, sizeof(buf), "#%d", x);
1034 return buf;
1035 }
1036
1037 void
1038 isakmp_print(const u_char *bp, u_int length, const u_char *bp2)
1039 {
1040 struct isakmp *base;
1041 u_char *ep;
1042 u_char np;
1043 int i;
1044 int phase;
1045 int major, minor;
1046
1047 base = (struct isakmp *)bp;
1048 ep = (u_char *)snapend;
1049
1050 if ((struct isakmp *)ep < base + 1) {
1051 printf("[|isakmp]");
1052 return;
1053 }
1054
1055 printf("isakmp");
1056 if (vflag) {
1057 major = (base->vers & ISAKMP_VERS_MAJOR)
1058 >> ISAKMP_VERS_MAJOR_SHIFT;
1059 minor = (base->vers & ISAKMP_VERS_MINOR)
1060 >> ISAKMP_VERS_MINOR_SHIFT;
1061 printf(" %d.%d", major, minor);
1062 }
1063
1064 if (vflag) {
1065 printf(" msgid ");
1066 rawprint((caddr_t)&base->msgid, sizeof(base->msgid));
1067 }
1068
1069 if (1 < vflag) {
1070 printf(" cookie ");
1071 rawprint((caddr_t)&base->i_ck, sizeof(base->i_ck));
1072 printf("->");
1073 rawprint((caddr_t)&base->r_ck, sizeof(base->r_ck));
1074 }
1075 printf(":");
1076
1077 phase = (*(u_int32_t *)base->msgid == 0) ? 1 : 2;
1078 if (phase == 1)
1079 printf(" phase %d", phase);
1080 else
1081 printf(" phase %d/others", phase);
1082
1083 i = cookie_find(&base->i_ck);
1084 if (i < 0) {
1085 if (iszero((u_char *)&base->r_ck, sizeof(base->r_ck))) {
1086 /* the first packet */
1087 printf(" I");
1088 if (bp2)
1089 cookie_record(&base->i_ck, bp2);
1090 } else
1091 printf(" ?");
1092 } else {
1093 if (bp2 && cookie_isinitiator(i, bp2))
1094 printf(" I");
1095 else if (bp2 && cookie_isresponder(i, bp2))
1096 printf(" R");
1097 else
1098 printf(" ?");
1099 }
1100
1101 printf(" %s", ETYPESTR(base->etype));
1102 if (base->flags) {
1103 printf("[%s%s]", base->flags & ISAKMP_FLAG_E ? "E" : "",
1104 base->flags & ISAKMP_FLAG_C ? "C" : "");
1105 }
1106 printf(":");
1107
1108 {
1109 struct isakmp_gen *ext;
1110 int nparen;
1111
1112 #define CHECKLEN(p, np) \
1113 if (ep < (u_char *)(p)) { \
1114 printf(" [|%s]", NPSTR(np)); \
1115 goto done; \
1116 }
1117
1118 /* regardless of phase... */
1119 if (base->flags & ISAKMP_FLAG_E) {
1120 /*
1121 * encrypted, nothing we can do right now.
1122 * we hope to decrypt the packet in the future...
1123 */
1124 printf(" [|%s]", NPSTR(base->np));
1125 goto done;
1126 }
1127
1128 nparen = 0;
1129 CHECKLEN(base + 1, base->np)
1130
1131 np = base->np;
1132 ext = (struct isakmp_gen *)(base + 1);
1133 isakmp_sub_print(np, ext, ep, phase, 0, 0);
1134 }
1135
1136 done:
1137 if (vflag) {
1138 if (ntohl(base->len) != length) {
1139 printf(" (len mismatch: isakmp %u/ip %d)",
1140 (u_int32_t)ntohl(base->len), length);
1141 }
1142 }
1143 }