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