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