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