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[] _U_ =
33 "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.51 2005/04/07 00:28:17 mcr 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 u_int, 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 *, u_int,
116 const u_char *, 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
iszero(u_char * p,size_t l)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
cookie_find(cookie_t * in)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
cookie_record(cookie_t * in,const u_char * bp2)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
cookie_sidecheck(int i,const u_char * bp2,int initiator)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 int
rawprint(caddr_t loc,size_t len)325 rawprint(caddr_t loc, size_t len)
326 {
327 static u_char *p;
328 size_t i;
329
330 TCHECK2(*loc, len);
331
332 p = (u_char *)loc;
333 for (i = 0; i < len; i++)
334 printf("%02x", p[i] & 0xff);
335 return 1;
336 trunc:
337 return 0;
338 }
339
340 struct attrmap {
341 const char *type;
342 u_int nvalue;
343 const char *value[30]; /*XXX*/
344 };
345
346 static const u_char *
isakmp_attrmap_print(const u_char * p,const u_char * ep,const struct attrmap * map,size_t nmap)347 isakmp_attrmap_print(const u_char *p, const u_char *ep,
348 const struct attrmap *map, size_t nmap)
349 {
350 u_int16_t *q;
351 int totlen;
352 u_int32_t t, v;
353
354 q = (u_int16_t *)p;
355 if (p[0] & 0x80)
356 totlen = 4;
357 else
358 totlen = 4 + EXTRACT_16BITS(&q[1]);
359 if (ep < p + totlen) {
360 printf("[|attr]");
361 return ep + 1;
362 }
363
364 printf("(");
365 t = EXTRACT_16BITS(&q[0]) & 0x7fff;
366 if (map && t < nmap && map[t].type)
367 printf("type=%s ", map[t].type);
368 else
369 printf("type=#%d ", t);
370 if (p[0] & 0x80) {
371 printf("value=");
372 v = EXTRACT_16BITS(&q[1]);
373 if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
374 printf("%s", map[t].value[v]);
375 else
376 rawprint((caddr_t)&q[1], 2);
377 } else {
378 printf("len=%d value=", EXTRACT_16BITS(&q[1]));
379 rawprint((caddr_t)&p[4], EXTRACT_16BITS(&q[1]));
380 }
381 printf(")");
382 return p + totlen;
383 }
384
385 static const u_char *
isakmp_attr_print(const u_char * p,const u_char * ep)386 isakmp_attr_print(const u_char *p, const u_char *ep)
387 {
388 u_int16_t *q;
389 int totlen;
390 u_int32_t t;
391
392 q = (u_int16_t *)p;
393 if (p[0] & 0x80)
394 totlen = 4;
395 else
396 totlen = 4 + EXTRACT_16BITS(&q[1]);
397 if (ep < p + totlen) {
398 printf("[|attr]");
399 return ep + 1;
400 }
401
402 printf("(");
403 t = EXTRACT_16BITS(&q[0]) & 0x7fff;
404 printf("type=#%d ", t);
405 if (p[0] & 0x80) {
406 printf("value=");
407 t = q[1];
408 rawprint((caddr_t)&q[1], 2);
409 } else {
410 printf("len=%d value=", EXTRACT_16BITS(&q[1]));
411 rawprint((caddr_t)&p[2], EXTRACT_16BITS(&q[1]));
412 }
413 printf(")");
414 return p + totlen;
415 }
416
417 static const u_char *
isakmp_sa_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep,u_int32_t phase,u_int32_t doi0 _U_,u_int32_t proto0,int depth)418 isakmp_sa_print(const struct isakmp_gen *ext,
419 u_int item_len _U_,
420 const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
421 u_int32_t proto0, int depth)
422 {
423 const struct isakmp_pl_sa *p;
424 struct isakmp_pl_sa sa;
425 const u_int32_t *q;
426 u_int32_t doi, sit, ident;
427 const u_char *cp, *np;
428 int t;
429
430 printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
431
432 p = (struct isakmp_pl_sa *)ext;
433 TCHECK(*p);
434 safememcpy(&sa, ext, sizeof(sa));
435 doi = ntohl(sa.doi);
436 sit = ntohl(sa.sit);
437 if (doi != 1) {
438 printf(" doi=%d", doi);
439 printf(" situation=%u", (u_int32_t)ntohl(sa.sit));
440 return (u_char *)(p + 1);
441 }
442
443 printf(" doi=ipsec");
444 q = (u_int32_t *)&sa.sit;
445 printf(" situation=");
446 t = 0;
447 if (sit & 0x01) {
448 printf("identity");
449 t++;
450 }
451 if (sit & 0x02) {
452 printf("%ssecrecy", t ? "+" : "");
453 t++;
454 }
455 if (sit & 0x04)
456 printf("%sintegrity", t ? "+" : "");
457
458 np = (u_char *)ext + sizeof(sa);
459 if (sit != 0x01) {
460 TCHECK2(*(ext + 1), sizeof(ident));
461 safememcpy(&ident, ext + 1, sizeof(ident));
462 printf(" ident=%u", (u_int32_t)ntohl(ident));
463 np += sizeof(ident);
464 }
465
466 ext = (struct isakmp_gen *)np;
467 TCHECK(*ext);
468
469 cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
470 depth);
471
472 return cp;
473 trunc:
474 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
475 return NULL;
476 }
477
478 static const u_char *
isakmp_p_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep,u_int32_t phase,u_int32_t doi0,u_int32_t proto0 _U_,int depth)479 isakmp_p_print(const struct isakmp_gen *ext, u_int item_len _U_,
480 const u_char *ep, u_int32_t phase, u_int32_t doi0,
481 u_int32_t proto0 _U_, int depth)
482 {
483 const struct isakmp_pl_p *p;
484 struct isakmp_pl_p prop;
485 const u_char *cp;
486
487 printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
488
489 p = (struct isakmp_pl_p *)ext;
490 TCHECK(*p);
491 safememcpy(&prop, ext, sizeof(prop));
492 printf(" #%d protoid=%s transform=%d",
493 prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
494 if (prop.spi_size) {
495 printf(" spi=");
496 if (!rawprint((caddr_t)(p + 1), prop.spi_size))
497 goto trunc;
498 }
499
500 ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
501 TCHECK(*ext);
502
503 cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
504 prop.prot_id, depth);
505
506 return cp;
507 trunc:
508 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
509 return NULL;
510 }
511
512 static const char *isakmp_p_map[] = {
513 NULL, "ike",
514 };
515
516 static const char *ah_p_map[] = {
517 NULL, "(reserved)", "md5", "sha", "1des",
518 "sha2-256", "sha2-384", "sha2-512",
519 };
520
521 static const char *esp_p_map[] = {
522 NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
523 "blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
524 };
525
526 static const char *ipcomp_p_map[] = {
527 NULL, "oui", "deflate", "lzs",
528 };
529
530 const struct attrmap ipsec_t_map[] = {
531 { NULL, 0, { NULL } },
532 { "lifetype", 3, { NULL, "sec", "kb", }, },
533 { "life", 0, { NULL } },
534 { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155",
535 "EC2N 2^185", }, },
536 { "enc mode", 3, { NULL, "tunnel", "transport", }, },
537 { "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
538 { "keylen", 0, { NULL } },
539 { "rounds", 0, { NULL } },
540 { "dictsize", 0, { NULL } },
541 { "privalg", 0, { NULL } },
542 };
543
544 const struct attrmap oakley_t_map[] = {
545 { NULL, 0, { NULL } },
546 { "enc", 8, { NULL, "1des", "idea", "blowfish", "rc5",
547 "3des", "cast", "aes", }, },
548 { "hash", 7, { NULL, "md5", "sha1", "tiger",
549 "sha2-256", "sha2-384", "sha2-512", }, },
550 { "auth", 6, { NULL, "preshared", "dss", "rsa sig", "rsa enc",
551 "rsa enc revised", }, },
552 { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155",
553 "EC2N 2^185", }, },
554 { "group type", 4, { NULL, "MODP", "ECP", "EC2N", }, },
555 { "group prime", 0, { NULL } },
556 { "group gen1", 0, { NULL } },
557 { "group gen2", 0, { NULL } },
558 { "group curve A", 0, { NULL } },
559 { "group curve B", 0, { NULL } },
560 { "lifetype", 3, { NULL, "sec", "kb", }, },
561 { "lifeduration", 0, { NULL } },
562 { "prf", 0, { NULL } },
563 { "keylen", 0, { NULL } },
564 { "field", 0, { NULL } },
565 { "order", 0, { NULL } },
566 };
567
568 static const u_char *
isakmp_t_print(const struct isakmp_gen * ext,u_int item_len,const u_char * ep,u_int32_t phase _U_,u_int32_t doi _U_,u_int32_t proto,int depth _U_)569 isakmp_t_print(const struct isakmp_gen *ext, u_int item_len,
570 const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
571 u_int32_t proto, int depth _U_)
572 {
573 const struct isakmp_pl_t *p;
574 struct isakmp_pl_t t;
575 const u_char *cp;
576 const char *idstr;
577 const struct attrmap *map;
578 size_t nmap;
579 const u_char *ep2;
580
581 printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
582
583 p = (struct isakmp_pl_t *)ext;
584 TCHECK(*p);
585 safememcpy(&t, ext, sizeof(t));
586
587 switch (proto) {
588 case 1:
589 idstr = STR_OR_ID(t.t_id, isakmp_p_map);
590 map = oakley_t_map;
591 nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
592 break;
593 case 2:
594 idstr = STR_OR_ID(t.t_id, ah_p_map);
595 map = ipsec_t_map;
596 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
597 break;
598 case 3:
599 idstr = STR_OR_ID(t.t_id, esp_p_map);
600 map = ipsec_t_map;
601 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
602 break;
603 case 4:
604 idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
605 map = ipsec_t_map;
606 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
607 break;
608 default:
609 idstr = NULL;
610 map = NULL;
611 nmap = 0;
612 break;
613 }
614
615 if (idstr)
616 printf(" #%d id=%s ", t.t_no, idstr);
617 else
618 printf(" #%d id=%d ", t.t_no, t.t_id);
619 cp = (u_char *)(p + 1);
620 ep2 = (u_char *)p + item_len;
621 while (cp < ep && cp < ep2) {
622 if (map && nmap) {
623 cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
624 map, nmap);
625 } else
626 cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
627 }
628 if (ep < ep2)
629 printf("...");
630 return cp;
631 trunc:
632 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
633 return NULL;
634 }
635
636 static const u_char *
isakmp_ke_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase _U_,u_int32_t doi _U_,u_int32_t proto _U_,int depth _U_)637 isakmp_ke_print(const struct isakmp_gen *ext, u_int item_len _U_,
638 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
639 u_int32_t proto _U_, int depth _U_)
640 {
641 struct isakmp_gen e;
642
643 printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
644
645 TCHECK(*ext);
646 safememcpy(&e, ext, sizeof(e));
647 printf(" key len=%d", ntohs(e.len) - 4);
648 if (2 < vflag && 4 < ntohs(e.len)) {
649 printf(" ");
650 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
651 goto trunc;
652 }
653 return (u_char *)ext + ntohs(e.len);
654 trunc:
655 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
656 return NULL;
657 }
658
659 static const u_char *
isakmp_id_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase,u_int32_t doi _U_,u_int32_t proto _U_,int depth _U_)660 isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
661 const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
662 u_int32_t proto _U_, int depth _U_)
663 {
664 #define USE_IPSECDOI_IN_PHASE1 1
665 const struct isakmp_pl_id *p;
666 struct isakmp_pl_id id;
667 static const char *idtypestr[] = {
668 "IPv4", "IPv4net", "IPv6", "IPv6net",
669 };
670 static const char *ipsecidtypestr[] = {
671 NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
672 "IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
673 "keyid",
674 };
675 int len;
676 const u_char *data;
677
678 printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
679
680 p = (struct isakmp_pl_id *)ext;
681 TCHECK(*p);
682 safememcpy(&id, ext, sizeof(id));
683 if (sizeof(*p) < item_len) {
684 data = (u_char *)(p + 1);
685 len = item_len - sizeof(*p);
686 } else {
687 data = NULL;
688 len = 0;
689 }
690
691 #if 0 /*debug*/
692 printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
693 #endif
694 switch (phase) {
695 #ifndef USE_IPSECDOI_IN_PHASE1
696 case 1:
697 #endif
698 default:
699 printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr));
700 printf(" doi_data=%u",
701 (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff));
702 break;
703
704 #ifdef USE_IPSECDOI_IN_PHASE1
705 case 1:
706 #endif
707 case 2:
708 {
709 const struct ipsecdoi_id *p;
710 struct ipsecdoi_id id;
711 struct protoent *pe;
712
713 p = (struct ipsecdoi_id *)ext;
714 TCHECK(*p);
715 safememcpy(&id, ext, sizeof(id));
716 printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
717 if (id.proto_id) {
718 #ifndef WIN32
719 // not supported on android
720 //setprotoent(1);
721 #endif /* WIN32 */
722 pe = getprotobynumber(id.proto_id);
723 if (pe)
724 printf(" protoid=%s", pe->p_name);
725 #ifndef WIN32
726 // not supported on android
727 //endprotoent();
728 #endif /* WIN32 */
729 } else {
730 /* it DOES NOT mean IPPROTO_IP! */
731 printf(" protoid=%s", "0");
732 }
733 printf(" port=%d", ntohs(id.port));
734 if (!len)
735 break;
736 if (data == NULL)
737 goto trunc;
738 TCHECK2(*data, len);
739 switch (id.type) {
740 case IPSECDOI_ID_IPV4_ADDR:
741 if (len < 4)
742 printf(" len=%d [bad: < 4]", len);
743 else
744 printf(" len=%d %s", len, ipaddr_string(data));
745 len = 0;
746 break;
747 case IPSECDOI_ID_FQDN:
748 case IPSECDOI_ID_USER_FQDN:
749 {
750 int i;
751 printf(" len=%d ", len);
752 for (i = 0; i < len; i++)
753 safeputchar(data[i]);
754 len = 0;
755 break;
756 }
757 case IPSECDOI_ID_IPV4_ADDR_SUBNET:
758 {
759 const u_char *mask;
760 if (len < 8)
761 printf(" len=%d [bad: < 8]", len);
762 else {
763 mask = data + sizeof(struct in_addr);
764 printf(" len=%d %s/%u.%u.%u.%u", len,
765 ipaddr_string(data),
766 mask[0], mask[1], mask[2], mask[3]);
767 }
768 len = 0;
769 break;
770 }
771 #ifdef INET6
772 case IPSECDOI_ID_IPV6_ADDR:
773 if (len < 16)
774 printf(" len=%d [bad: < 16]", len);
775 else
776 printf(" len=%d %s", len, ip6addr_string(data));
777 len = 0;
778 break;
779 case IPSECDOI_ID_IPV6_ADDR_SUBNET:
780 {
781 const u_int32_t *mask;
782 if (len < 20)
783 printf(" len=%d [bad: < 20]", len);
784 else {
785 mask = (u_int32_t *)(data + sizeof(struct in6_addr));
786 /*XXX*/
787 printf(" len=%d %s/0x%08x%08x%08x%08x", len,
788 ip6addr_string(data),
789 mask[0], mask[1], mask[2], mask[3]);
790 }
791 len = 0;
792 break;
793 }
794 #endif /*INET6*/
795 case IPSECDOI_ID_IPV4_ADDR_RANGE:
796 if (len < 8)
797 printf(" len=%d [bad: < 8]", len);
798 else {
799 printf(" len=%d %s-%s", len,
800 ipaddr_string(data),
801 ipaddr_string(data + sizeof(struct in_addr)));
802 }
803 len = 0;
804 break;
805 #ifdef INET6
806 case IPSECDOI_ID_IPV6_ADDR_RANGE:
807 if (len < 32)
808 printf(" len=%d [bad: < 32]", len);
809 else {
810 printf(" len=%d %s-%s", len,
811 ip6addr_string(data),
812 ip6addr_string(data + sizeof(struct in6_addr)));
813 }
814 len = 0;
815 break;
816 #endif /*INET6*/
817 case IPSECDOI_ID_DER_ASN1_DN:
818 case IPSECDOI_ID_DER_ASN1_GN:
819 case IPSECDOI_ID_KEY_ID:
820 break;
821 }
822 break;
823 }
824 }
825 if (data && len) {
826 printf(" len=%d", len);
827 if (2 < vflag) {
828 printf(" ");
829 if (!rawprint((caddr_t)data, len))
830 goto trunc;
831 }
832 }
833 return (u_char *)ext + item_len;
834 trunc:
835 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
836 return NULL;
837 }
838
839 static const u_char *
isakmp_cert_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase _U_,u_int32_t doi0 _U_,u_int32_t proto0 _U_,int depth _U_)840 isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_,
841 const u_char *ep _U_, u_int32_t phase _U_,
842 u_int32_t doi0 _U_,
843 u_int32_t proto0 _U_, int depth _U_)
844 {
845 const struct isakmp_pl_cert *p;
846 struct isakmp_pl_cert cert;
847 static const char *certstr[] = {
848 "none", "pkcs7", "pgp", "dns",
849 "x509sign", "x509ke", "kerberos", "crl",
850 "arl", "spki", "x509attr",
851 };
852
853 printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
854
855 p = (struct isakmp_pl_cert *)ext;
856 TCHECK(*p);
857 safememcpy(&cert, ext, sizeof(cert));
858 printf(" len=%d", item_len - 4);
859 printf(" type=%s", STR_OR_ID((cert.encode), certstr));
860 if (2 < vflag && 4 < item_len) {
861 printf(" ");
862 if (!rawprint((caddr_t)(ext + 1), item_len - 4))
863 goto trunc;
864 }
865 return (u_char *)ext + item_len;
866 trunc:
867 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
868 return NULL;
869 }
870
871 static const u_char *
isakmp_cr_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase _U_,u_int32_t doi0 _U_,u_int32_t proto0 _U_,int depth _U_)872 isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_,
873 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
874 u_int32_t proto0 _U_, int depth _U_)
875 {
876 const struct isakmp_pl_cert *p;
877 struct isakmp_pl_cert cert;
878 static const char *certstr[] = {
879 "none", "pkcs7", "pgp", "dns",
880 "x509sign", "x509ke", "kerberos", "crl",
881 "arl", "spki", "x509attr",
882 };
883
884 printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
885
886 p = (struct isakmp_pl_cert *)ext;
887 TCHECK(*p);
888 safememcpy(&cert, ext, sizeof(cert));
889 printf(" len=%d", item_len - 4);
890 printf(" type=%s", STR_OR_ID((cert.encode), certstr));
891 if (2 < vflag && 4 < item_len) {
892 printf(" ");
893 if (!rawprint((caddr_t)(ext + 1), item_len - 4))
894 goto trunc;
895 }
896 return (u_char *)ext + item_len;
897 trunc:
898 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
899 return NULL;
900 }
901
902 static const u_char *
isakmp_hash_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase _U_,u_int32_t doi _U_,u_int32_t proto _U_,int depth _U_)903 isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_,
904 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
905 u_int32_t proto _U_, int depth _U_)
906 {
907 struct isakmp_gen e;
908
909 printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
910
911 TCHECK(*ext);
912 safememcpy(&e, ext, sizeof(e));
913 printf(" len=%d", ntohs(e.len) - 4);
914 if (2 < vflag && 4 < ntohs(e.len)) {
915 printf(" ");
916 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
917 goto trunc;
918 }
919 return (u_char *)ext + ntohs(e.len);
920 trunc:
921 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
922 return NULL;
923 }
924
925 static const u_char *
isakmp_sig_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase _U_,u_int32_t doi _U_,u_int32_t proto _U_,int depth _U_)926 isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_,
927 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
928 u_int32_t proto _U_, int depth _U_)
929 {
930 struct isakmp_gen e;
931
932 printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
933
934 TCHECK(*ext);
935 safememcpy(&e, ext, sizeof(e));
936 printf(" len=%d", ntohs(e.len) - 4);
937 if (2 < vflag && 4 < ntohs(e.len)) {
938 printf(" ");
939 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
940 goto trunc;
941 }
942 return (u_char *)ext + ntohs(e.len);
943 trunc:
944 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
945 return NULL;
946 }
947
948 static const u_char *
isakmp_nonce_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase _U_,u_int32_t doi _U_,u_int32_t proto _U_,int depth _U_)949 isakmp_nonce_print(const struct isakmp_gen *ext,
950 u_int item_len _U_,
951 const u_char *ep _U_,
952 u_int32_t phase _U_, u_int32_t doi _U_,
953 u_int32_t proto _U_, int depth _U_)
954 {
955 struct isakmp_gen e;
956
957 printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
958
959 TCHECK(*ext);
960 safememcpy(&e, ext, sizeof(e));
961 printf(" n len=%d", ntohs(e.len) - 4);
962 if (2 < vflag && 4 < ntohs(e.len)) {
963 printf(" ");
964 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
965 goto trunc;
966 }
967 return (u_char *)ext + ntohs(e.len);
968 trunc:
969 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
970 return NULL;
971 }
972
973 static const u_char *
isakmp_n_print(const struct isakmp_gen * ext,u_int item_len,const u_char * ep,u_int32_t phase,u_int32_t doi0 _U_,u_int32_t proto0 _U_,int depth)974 isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
975 const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
976 u_int32_t proto0 _U_, int depth)
977 {
978 struct isakmp_pl_n *p, n;
979 const u_char *cp;
980 u_char *ep2;
981 u_int32_t doi;
982 u_int32_t proto;
983 static const char *notify_error_str[] = {
984 NULL, "INVALID-PAYLOAD-TYPE",
985 "DOI-NOT-SUPPORTED", "SITUATION-NOT-SUPPORTED",
986 "INVALID-COOKIE", "INVALID-MAJOR-VERSION",
987 "INVALID-MINOR-VERSION", "INVALID-EXCHANGE-TYPE",
988 "INVALID-FLAGS", "INVALID-MESSAGE-ID",
989 "INVALID-PROTOCOL-ID", "INVALID-SPI",
990 "INVALID-TRANSFORM-ID", "ATTRIBUTES-NOT-SUPPORTED",
991 "NO-PROPOSAL-CHOSEN", "BAD-PROPOSAL-SYNTAX",
992 "PAYLOAD-MALFORMED", "INVALID-KEY-INFORMATION",
993 "INVALID-ID-INFORMATION", "INVALID-CERT-ENCODING",
994 "INVALID-CERTIFICATE", "CERT-TYPE-UNSUPPORTED",
995 "INVALID-CERT-AUTHORITY", "INVALID-HASH-INFORMATION",
996 "AUTHENTICATION-FAILED", "INVALID-SIGNATURE",
997 "ADDRESS-NOTIFICATION", "NOTIFY-SA-LIFETIME",
998 "CERTIFICATE-UNAVAILABLE", "UNSUPPORTED-EXCHANGE-TYPE",
999 "UNEQUAL-PAYLOAD-LENGTHS",
1000 };
1001 static const char *ipsec_notify_error_str[] = {
1002 "RESERVED",
1003 };
1004 static const char *notify_status_str[] = {
1005 "CONNECTED",
1006 };
1007 static const char *ipsec_notify_status_str[] = {
1008 "RESPONDER-LIFETIME", "REPLAY-STATUS",
1009 "INITIAL-CONTACT",
1010 };
1011 /* NOTE: these macro must be called with x in proper range */
1012
1013 /* 0 - 8191 */
1014 #define NOTIFY_ERROR_STR(x) \
1015 STR_OR_ID((x), notify_error_str)
1016
1017 /* 8192 - 16383 */
1018 #define IPSEC_NOTIFY_ERROR_STR(x) \
1019 STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1020
1021 /* 16384 - 24575 */
1022 #define NOTIFY_STATUS_STR(x) \
1023 STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1024
1025 /* 24576 - 32767 */
1026 #define IPSEC_NOTIFY_STATUS_STR(x) \
1027 STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1028
1029 printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
1030
1031 p = (struct isakmp_pl_n *)ext;
1032 TCHECK(*p);
1033 safememcpy(&n, ext, sizeof(n));
1034 doi = ntohl(n.doi);
1035 proto = n.prot_id;
1036 if (doi != 1) {
1037 printf(" doi=%d", doi);
1038 printf(" proto=%d", proto);
1039 if (ntohs(n.type) < 8192)
1040 printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1041 else if (ntohs(n.type) < 16384)
1042 printf(" type=%s", numstr(ntohs(n.type)));
1043 else if (ntohs(n.type) < 24576)
1044 printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1045 else
1046 printf(" type=%s", numstr(ntohs(n.type)));
1047 if (n.spi_size) {
1048 printf(" spi=");
1049 if (!rawprint((caddr_t)(p + 1), n.spi_size))
1050 goto trunc;
1051 }
1052 return (u_char *)(p + 1) + n.spi_size;
1053 }
1054
1055 printf(" doi=ipsec");
1056 printf(" proto=%s", PROTOIDSTR(proto));
1057 if (ntohs(n.type) < 8192)
1058 printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
1059 else if (ntohs(n.type) < 16384)
1060 printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type)));
1061 else if (ntohs(n.type) < 24576)
1062 printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
1063 else if (ntohs(n.type) < 32768)
1064 printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type)));
1065 else
1066 printf(" type=%s", numstr(ntohs(n.type)));
1067 if (n.spi_size) {
1068 printf(" spi=");
1069 if (!rawprint((caddr_t)(p + 1), n.spi_size))
1070 goto trunc;
1071 }
1072
1073 cp = (u_char *)(p + 1) + n.spi_size;
1074 ep2 = (u_char *)p + item_len;
1075
1076 if (cp < ep) {
1077 printf(" orig=(");
1078 switch (ntohs(n.type)) {
1079 case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
1080 {
1081 const struct attrmap *map = oakley_t_map;
1082 size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1083 while (cp < ep && cp < ep2) {
1084 cp = isakmp_attrmap_print(cp,
1085 (ep < ep2) ? ep : ep2, map, nmap);
1086 }
1087 break;
1088 }
1089 case IPSECDOI_NTYPE_REPLAY_STATUS:
1090 printf("replay detection %sabled",
1091 (*(u_int32_t *)cp) ? "en" : "dis");
1092 break;
1093 case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
1094 if (isakmp_sub_print(ISAKMP_NPTYPE_SA,
1095 (struct isakmp_gen *)cp, ep, phase, doi, proto,
1096 depth) == NULL)
1097 return NULL;
1098 break;
1099 default:
1100 /* NULL is dummy */
1101 isakmp_print(gndo, cp,
1102 item_len - sizeof(*p) - n.spi_size,
1103 NULL);
1104 }
1105 printf(")");
1106 }
1107 return (u_char *)ext + item_len;
1108 trunc:
1109 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
1110 return NULL;
1111 }
1112
1113 static const u_char *
isakmp_d_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase _U_,u_int32_t doi0 _U_,u_int32_t proto0 _U_,int depth _U_)1114 isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_,
1115 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
1116 u_int32_t proto0 _U_, int depth _U_)
1117 {
1118 const struct isakmp_pl_d *p;
1119 struct isakmp_pl_d d;
1120 const u_int8_t *q;
1121 u_int32_t doi;
1122 u_int32_t proto;
1123 int i;
1124
1125 printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
1126
1127 p = (struct isakmp_pl_d *)ext;
1128 TCHECK(*p);
1129 safememcpy(&d, ext, sizeof(d));
1130 doi = ntohl(d.doi);
1131 proto = d.prot_id;
1132 if (doi != 1) {
1133 printf(" doi=%u", doi);
1134 printf(" proto=%u", proto);
1135 } else {
1136 printf(" doi=ipsec");
1137 printf(" proto=%s", PROTOIDSTR(proto));
1138 }
1139 printf(" spilen=%u", d.spi_size);
1140 printf(" nspi=%u", ntohs(d.num_spi));
1141 printf(" spi=");
1142 q = (u_int8_t *)(p + 1);
1143 for (i = 0; i < ntohs(d.num_spi); i++) {
1144 if (i != 0)
1145 printf(",");
1146 if (!rawprint((caddr_t)q, d.spi_size))
1147 goto trunc;
1148 q += d.spi_size;
1149 }
1150 return q;
1151 trunc:
1152 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
1153 return NULL;
1154 }
1155
1156 static const u_char *
isakmp_vid_print(const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,u_int32_t phase _U_,u_int32_t doi _U_,u_int32_t proto _U_,int depth _U_)1157 isakmp_vid_print(const struct isakmp_gen *ext,
1158 u_int item_len _U_, const u_char *ep _U_,
1159 u_int32_t phase _U_, u_int32_t doi _U_,
1160 u_int32_t proto _U_, int depth _U_)
1161 {
1162 struct isakmp_gen e;
1163
1164 printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1165
1166 TCHECK(*ext);
1167 safememcpy(&e, ext, sizeof(e));
1168 printf(" len=%d", ntohs(e.len) - 4);
1169 if (2 < vflag && 4 < ntohs(e.len)) {
1170 printf(" ");
1171 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
1172 goto trunc;
1173 }
1174 return (u_char *)ext + ntohs(e.len);
1175 trunc:
1176 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
1177 return NULL;
1178 }
1179
1180 static const u_char *
isakmp_sub0_print(u_char np,const struct isakmp_gen * ext,const u_char * ep,u_int32_t phase,u_int32_t doi,u_int32_t proto,int depth)1181 isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1182 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1183 {
1184 const u_char *cp;
1185 struct isakmp_gen e;
1186 u_int item_len;
1187
1188 cp = (u_char *)ext;
1189 TCHECK(*ext);
1190 safememcpy(&e, ext, sizeof(e));
1191
1192 /*
1193 * Since we can't have a payload length of less than 4 bytes,
1194 * we need to bail out here if the generic header is nonsensical
1195 * or truncated, otherwise we could loop forever processing
1196 * zero-length items or otherwise misdissect the packet.
1197 */
1198 item_len = ntohs(e.len);
1199 if (item_len <= 4)
1200 return NULL;
1201
1202 if (NPFUNC(np)) {
1203 /*
1204 * XXX - what if item_len is too short, or too long,
1205 * for this payload type?
1206 */
1207 cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth);
1208 } else {
1209 printf("%s", NPSTR(np));
1210 cp += item_len;
1211 }
1212
1213 return cp;
1214 trunc:
1215 printf(" [|isakmp]");
1216 return NULL;
1217 }
1218
1219 static const u_char *
isakmp_sub_print(u_char np,const struct isakmp_gen * ext,const u_char * ep,u_int32_t phase,u_int32_t doi,u_int32_t proto,int depth)1220 isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
1221 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
1222 {
1223 const u_char *cp;
1224 int i;
1225 struct isakmp_gen e;
1226
1227 cp = (const u_char *)ext;
1228
1229 while (np) {
1230 TCHECK(*ext);
1231
1232 safememcpy(&e, ext, sizeof(e));
1233
1234 TCHECK2(*ext, ntohs(e.len));
1235
1236 depth++;
1237 printf("\n");
1238 for (i = 0; i < depth; i++)
1239 printf(" ");
1240 printf("(");
1241 cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth);
1242 printf(")");
1243 depth--;
1244
1245 if (cp == NULL) {
1246 /* Zero-length subitem */
1247 return NULL;
1248 }
1249
1250 np = e.np;
1251 ext = (struct isakmp_gen *)cp;
1252 }
1253 return cp;
1254 trunc:
1255 printf(" [|%s]", NPSTR(np));
1256 return NULL;
1257 }
1258
1259 static char *
numstr(int x)1260 numstr(int x)
1261 {
1262 static char buf[20];
1263 snprintf(buf, sizeof(buf), "#%d", x);
1264 return buf;
1265 }
1266
1267 /*
1268 * some compiler tries to optimize memcpy(), using the alignment constraint
1269 * on the argument pointer type. by using this function, we try to avoid the
1270 * optimization.
1271 */
1272 static void
safememcpy(void * p,const void * q,size_t l)1273 safememcpy(void *p, const void *q, size_t l)
1274 {
1275 memcpy(p, q, l);
1276 }
1277
1278 void
isakmp_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2)1279 isakmp_print(netdissect_options *ndo,
1280 const u_char *bp, u_int length,
1281 const u_char *bp2)
1282 {
1283 const struct isakmp *p;
1284 struct isakmp base;
1285 const u_char *ep;
1286 u_char np;
1287 int i;
1288 int phase;
1289 int major, minor;
1290
1291 p = (const struct isakmp *)bp;
1292 ep = ndo->ndo_snapend;
1293
1294 if ((struct isakmp *)ep < p + 1) {
1295 printf("[|isakmp]");
1296 return;
1297 }
1298
1299 safememcpy(&base, p, sizeof(base));
1300
1301 printf("isakmp");
1302 if (vflag) {
1303 major = (base.vers & ISAKMP_VERS_MAJOR)
1304 >> ISAKMP_VERS_MAJOR_SHIFT;
1305 minor = (base.vers & ISAKMP_VERS_MINOR)
1306 >> ISAKMP_VERS_MINOR_SHIFT;
1307 printf(" %d.%d", major, minor);
1308 }
1309
1310 if (vflag) {
1311 printf(" msgid ");
1312 rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
1313 }
1314
1315 if (1 < vflag) {
1316 printf(" cookie ");
1317 rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
1318 printf("->");
1319 rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
1320 }
1321 printf(":");
1322
1323 phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
1324 if (phase == 1)
1325 printf(" phase %d", phase);
1326 else
1327 printf(" phase %d/others", phase);
1328
1329 i = cookie_find(&base.i_ck);
1330 if (i < 0) {
1331 if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
1332 /* the first packet */
1333 printf(" I");
1334 if (bp2)
1335 cookie_record(&base.i_ck, bp2);
1336 } else
1337 printf(" ?");
1338 } else {
1339 if (bp2 && cookie_isinitiator(i, bp2))
1340 printf(" I");
1341 else if (bp2 && cookie_isresponder(i, bp2))
1342 printf(" R");
1343 else
1344 printf(" ?");
1345 }
1346
1347 printf(" %s", ETYPESTR(base.etype));
1348 if (base.flags) {
1349 printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
1350 base.flags & ISAKMP_FLAG_C ? "C" : "");
1351 }
1352
1353 if (vflag) {
1354 const struct isakmp_gen *ext;
1355 int nparen;
1356
1357 #define CHECKLEN(p, np) \
1358 if (ep < (u_char *)(p)) { \
1359 printf(" [|%s]", NPSTR(np)); \
1360 goto done; \
1361 }
1362
1363 printf(":");
1364
1365 /* regardless of phase... */
1366 if (base.flags & ISAKMP_FLAG_E) {
1367 /*
1368 * encrypted, nothing we can do right now.
1369 * we hope to decrypt the packet in the future...
1370 */
1371 printf(" [encrypted %s]", NPSTR(base.np));
1372 goto done;
1373 }
1374
1375 nparen = 0;
1376 CHECKLEN(p + 1, base.np)
1377
1378 np = base.np;
1379 ext = (struct isakmp_gen *)(p + 1);
1380 isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
1381 }
1382
1383 done:
1384 if (vflag) {
1385 if (ntohl(base.len) != length) {
1386 printf(" (len mismatch: isakmp %u/ip %u)",
1387 (u_int32_t)ntohl(base.len), length);
1388 }
1389 }
1390 }
1391
1392 void
isakmp_rfc3948_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2)1393 isakmp_rfc3948_print(netdissect_options *ndo,
1394 const u_char *bp, u_int length,
1395 const u_char *bp2)
1396 {
1397 const u_char *ep;
1398 ep = ndo->ndo_snapend;
1399
1400 if(length == 1 && bp[0]==0xff) {
1401 ND_PRINT((ndo, "isakmp-nat-keep-alive"));
1402 return;
1403 }
1404
1405 if(length < 4) {
1406 goto trunc;
1407 }
1408
1409 /*
1410 * see if this is an IKE packet
1411 */
1412 if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) {
1413 ND_PRINT((ndo, "NONESP-encap: "));
1414 isakmp_print(ndo, bp+4, length-4, bp2);
1415 return;
1416 }
1417
1418 /* must be an ESP packet */
1419 {
1420 int nh, enh, padlen;
1421 int advance;
1422
1423 ND_PRINT((ndo, "UDP-encap: "));
1424
1425 advance = esp_print(ndo, bp, length, bp2, &enh, &padlen);
1426 if(advance <= 0)
1427 return;
1428
1429 bp += advance;
1430 length -= advance + padlen;
1431 nh = enh & 0xff;
1432
1433 ip_print_inner(ndo, bp, length, nh, bp2);
1434 return;
1435 }
1436
1437 trunc:
1438 printf("[|isakmp]");
1439 return;
1440 }
1441
1442 /*
1443 * Local Variables:
1444 * c-style: whitesmith
1445 * c-basic-offset: 8
1446 * End:
1447 */
1448