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