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