xref: /freebsd/contrib/tcpdump/print-isakmp.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
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.26 2000/12/12 09:20:26 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, sit, ident;
426 	u_char *cp, *np;
427 	int t;
428 
429 	printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
430 
431 	p = (struct isakmp_pl_sa *)ext;
432 	safememcpy(&sa, ext, sizeof(sa));
433 	doi = ntohl(sa.doi);
434 	sit = ntohl(sa.sit);
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 (sit & 0x01) {
446 		printf("identity");
447 		t++;
448 	}
449 	if (sit & 0x02) {
450 		printf("%ssecrecy", t ? "+" : "");
451 		t++;
452 	}
453 	if (sit & 0x04)
454 		printf("%sintegrity", t ? "+" : "");
455 
456 	np = (u_char *)ext + sizeof(sa);
457 	if (sit != 0x01) {
458 		safememcpy(&ident, ext + 1, sizeof(ident));
459 		printf(" ident=%u", (u_int32_t)ntohl(ident));
460 		np += sizeof(ident);
461 	}
462 
463 	ext = (struct isakmp_gen *)np;
464 
465 	cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0);
466 
467 	return cp;
468 }
469 
470 static u_char *
471 isakmp_p_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
472 	u_int32_t doi0, u_int32_t proto0)
473 {
474 	struct isakmp_pl_p *p, prop;
475 	u_char *cp;
476 
477 	printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
478 
479 	p = (struct isakmp_pl_p *)ext;
480 	safememcpy(&prop, ext, sizeof(prop));
481 	printf(" #%d protoid=%s transform=%d",
482 		prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
483 	if (prop.spi_size) {
484 		printf(" spi=");
485 		rawprint((caddr_t)(p + 1), prop.spi_size);
486 	}
487 
488 	ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
489 
490 	cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
491 		prop.prot_id);
492 
493 	return cp;
494 }
495 
496 static char *isakmp_p_map[] = {
497 	NULL, "ike",
498 };
499 
500 static char *ah_p_map[] = {
501 	NULL, "(reserved)", "md5", "sha", "1des",
502 	"sha2-256", "sha2-384", "sha2-512",
503 };
504 
505 static char *esp_p_map[] = {
506 	NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
507 	"blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
508 };
509 
510 static char *ipcomp_p_map[] = {
511 	NULL, "oui", "deflate", "lzs",
512 };
513 
514 struct attrmap ipsec_t_map[] = {
515 	{ NULL,	0, },
516 	{ "lifetype", 3, { NULL, "sec", "kb", }, },
517 	{ "life", 0, },
518 	{ "group desc", 5,	{ NULL, "modp768", "modp1024", "EC2N 2^155",
519 				  "EC2N 2^185", }, },
520 	{ "enc mode", 3, { NULL, "tunnel", "transport", }, },
521 	{ "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
522 	{ "keylen", 0, },
523 	{ "rounds", 0, },
524 	{ "dictsize", 0, },
525 	{ "privalg", 0, },
526 };
527 
528 struct attrmap oakley_t_map[] = {
529 	{ NULL,	0 },
530 	{ "enc", 8,	{ NULL, "1des", "idea", "blowfish", "rc5",
531 		 	  "3des", "cast", "aes", }, },
532 	{ "hash", 7,	{ NULL, "md5", "sha1", "tiger",
533 			  "sha2-256", "sha2-384", "sha2-512", }, },
534 	{ "auth", 6,	{ NULL, "preshared", "dss", "rsa sig", "rsa enc",
535 			  "rsa enc revised", }, },
536 	{ "group desc", 5,	{ NULL, "modp768", "modp1024", "EC2N 2^155",
537 				  "EC2N 2^185", }, },
538 	{ "group type", 4,	{ NULL, "MODP", "ECP", "EC2N", }, },
539 	{ "group prime", 0, },
540 	{ "group gen1", 0, },
541 	{ "group gen2", 0, },
542 	{ "group curve A", 0, },
543 	{ "group curve B", 0, },
544 	{ "lifetype", 3,	{ NULL, "sec", "kb", }, },
545 	{ "lifeduration", 0, },
546 	{ "prf", 0, },
547 	{ "keylen", 0, },
548 	{ "field", 0, },
549 	{ "order", 0, },
550 };
551 
552 static u_char *
553 isakmp_t_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
554 	u_int32_t doi, u_int32_t proto)
555 {
556 	struct isakmp_pl_t *p, t;
557 	u_char *cp;
558 	char *idstr;
559 	struct attrmap *map;
560 	size_t nmap;
561 	u_char *ep2;
562 
563 	printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
564 
565 	p = (struct isakmp_pl_t *)ext;
566 	safememcpy(&t, ext, sizeof(t));
567 
568 	switch (proto) {
569 	case 1:
570 		idstr = STR_OR_ID(t.t_id, isakmp_p_map);
571 		map = oakley_t_map;
572 		nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
573 		break;
574 	case 2:
575 		idstr = STR_OR_ID(t.t_id, ah_p_map);
576 		map = ipsec_t_map;
577 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
578 		break;
579 	case 3:
580 		idstr = STR_OR_ID(t.t_id, esp_p_map);
581 		map = ipsec_t_map;
582 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
583 		break;
584 	case 4:
585 		idstr = STR_OR_ID(t.t_id, ipcomp_p_map);
586 		map = ipsec_t_map;
587 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
588 		break;
589 	default:
590 		idstr = NULL;
591 		map = NULL;
592 		nmap = 0;
593 		break;
594 	}
595 
596 	if (idstr)
597 		printf(" #%d id=%s ", t.t_no, idstr);
598 	else
599 		printf(" #%d id=%d ", t.t_no, t.t_id);
600 	cp = (u_char *)(p + 1);
601 	ep2 = (u_char *)p + ntohs(t.h.len);
602 	while (cp < ep && cp < ep2) {
603 		if (map && nmap) {
604 			cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
605 				map, nmap);
606 		} else
607 			cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
608 	}
609 	if (ep < ep2)
610 		printf("...");
611 	return cp;
612 }
613 
614 static u_char *
615 isakmp_ke_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
616 	u_int32_t doi, u_int32_t proto)
617 {
618 	struct isakmp_gen e;
619 
620 	printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
621 
622 	safememcpy(&e, ext, sizeof(e));
623 	printf(" key len=%d", ntohs(e.len) - 4);
624 	if (2 < vflag && 4 < ntohs(e.len)) {
625 		printf(" ");
626 		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
627 	}
628 	return (u_char *)ext + ntohs(e.len);
629 }
630 
631 static u_char *
632 isakmp_id_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
633 	u_int32_t doi, u_int32_t proto)
634 {
635 #define USE_IPSECDOI_IN_PHASE1	1
636 	struct isakmp_pl_id *p, id;
637 	static char *idtypestr[] = {
638 		"IPv4", "IPv4net", "IPv6", "IPv6net",
639 	};
640 	static char *ipsecidtypestr[] = {
641 		NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
642 		"IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
643 		"keyid",
644 	};
645 	int len;
646 	u_char *data;
647 
648 	printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
649 
650 	p = (struct isakmp_pl_id *)ext;
651 	safememcpy(&id, ext, sizeof(id));
652 	if (sizeof(*p) < id.h.len)
653 		data = (u_char *)(p + 1);
654 	else
655 		data = NULL;
656 	len = ntohs(id.h.len) - sizeof(*p);
657 
658 #if 0 /*debug*/
659 	printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
660 #endif
661 	switch (phase) {
662 #ifndef USE_IPSECDOI_IN_PHASE1
663 	case 1:
664 #endif
665 	default:
666 		printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr));
667 		printf(" doi_data=%u",
668 			(u_int32_t)(ntohl(id.d.doi_data) & 0xffffff));
669 		break;
670 
671 #ifdef USE_IPSECDOI_IN_PHASE1
672 	case 1:
673 #endif
674 	case 2:
675 	    {
676 		struct ipsecdoi_id *p, id;
677 		struct protoent *pe;
678 
679 		p = (struct ipsecdoi_id *)ext;
680 		safememcpy(&id, ext, sizeof(id));
681 		printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
682 		if (id.proto_id) {
683 			setprotoent(1);
684 			pe = getprotobynumber(id.proto_id);
685 			if (pe)
686 				printf(" protoid=%s", pe->p_name);
687 			endprotoent();
688 		} else {
689 			/* it DOES NOT mean IPPROTO_IP! */
690 			printf(" protoid=%s", "0");
691 		}
692 		printf(" port=%d", ntohs(id.port));
693 		if (!len)
694 			break;
695 		switch (id.type) {
696 		case IPSECDOI_ID_IPV4_ADDR:
697 			printf(" len=%d %s", len, ipaddr_string(data));
698 			len = 0;
699 			break;
700 		case IPSECDOI_ID_FQDN:
701 		case IPSECDOI_ID_USER_FQDN:
702 		    {
703 			int i;
704 			printf(" len=%d ", len);
705 			for (i = 0; i < len; i++) {
706 				if (isprint(data[i]))
707 					printf("%c", data[i]);
708 				else
709 					printf("\\%03o", data[i]);
710 			}
711 			len = 0;
712 			break;
713 		    }
714 		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
715 		    {
716 			u_char *mask;
717 			mask = data + sizeof(struct in_addr);
718 			printf(" len=%d %s/%u.%u.%u.%u", len,
719 				ipaddr_string(data),
720 				mask[0], mask[1], mask[2], mask[3]);
721 			len = 0;
722 			break;
723 		    }
724 #ifdef INET6
725 		case IPSECDOI_ID_IPV6_ADDR:
726 			printf(" len=%d %s", len, ip6addr_string(data));
727 			len = 0;
728 			break;
729 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
730 		    {
731 			u_int32_t *mask;
732 			mask = (u_int32_t *)(data + sizeof(struct in6_addr));
733 			/*XXX*/
734 			printf(" len=%d %s/0x%08x%08x%08x%08x", len,
735 				ip6addr_string(data),
736 				mask[0], mask[1], mask[2], mask[3]);
737 			len = 0;
738 			break;
739 		    }
740 #endif /*INET6*/
741 		case IPSECDOI_ID_IPV4_ADDR_RANGE:
742 			printf(" len=%d %s-%s", len, ipaddr_string(data),
743 				ipaddr_string(data + sizeof(struct in_addr)));
744 			len = 0;
745 			break;
746 #ifdef INET6
747 		case IPSECDOI_ID_IPV6_ADDR_RANGE:
748 			printf(" len=%d %s-%s", len, ip6addr_string(data),
749 				ip6addr_string(data + sizeof(struct in6_addr)));
750 			len = 0;
751 			break;
752 #endif /*INET6*/
753 		case IPSECDOI_ID_DER_ASN1_DN:
754 		case IPSECDOI_ID_DER_ASN1_GN:
755 		case IPSECDOI_ID_KEY_ID:
756 			break;
757 		}
758 		break;
759 	    }
760 	}
761 	if (data && len) {
762 		len -= sizeof(*p);
763 		printf(" len=%d", len);
764 		if (2 < vflag) {
765 			printf(" ");
766 			rawprint((caddr_t)data, len);
767 		}
768 	}
769 	return (u_char *)ext + ntohs(id.h.len);
770 }
771 
772 static u_char *
773 isakmp_cert_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
774 	u_int32_t doi0, u_int32_t proto0)
775 {
776 	struct isakmp_pl_cert *p, cert;
777 	static char *certstr[] = {
778 		"none",	"pkcs7", "pgp", "dns",
779 		"x509sign", "x509ke", "kerberos", "crl",
780 		"arl", "spki", "x509attr",
781 	};
782 
783 	printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
784 
785 	p = (struct isakmp_pl_cert *)ext;
786 	safememcpy(&cert, ext, sizeof(cert));
787 	printf(" len=%d", ntohs(cert.h.len) - 4);
788 	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
789 	if (2 < vflag && 4 < ntohs(cert.h.len)) {
790 		printf(" ");
791 		rawprint((caddr_t)(ext + 1), ntohs(cert.h.len) - 4);
792 	}
793 	return (u_char *)ext + ntohs(cert.h.len);
794 }
795 
796 static u_char *
797 isakmp_cr_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
798 	u_int32_t doi0, u_int32_t proto0)
799 {
800 	struct isakmp_pl_cert *p, cert;
801 	static char *certstr[] = {
802 		"none",	"pkcs7", "pgp", "dns",
803 		"x509sign", "x509ke", "kerberos", "crl",
804 		"arl", "spki", "x509attr",
805 	};
806 
807 	printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
808 
809 	p = (struct isakmp_pl_cert *)ext;
810 	safememcpy(&cert, ext, sizeof(cert));
811 	printf(" len=%d", ntohs(cert.h.len) - 4);
812 	printf(" type=%s", STR_OR_ID((cert.encode), certstr));
813 	if (2 < vflag && 4 < ntohs(cert.h.len)) {
814 		printf(" ");
815 		rawprint((caddr_t)(ext + 1), ntohs(cert.h.len) - 4);
816 	}
817 	return (u_char *)ext + ntohs(cert.h.len);
818 }
819 
820 static u_char *
821 isakmp_hash_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
822 	u_int32_t doi, u_int32_t proto)
823 {
824 	struct isakmp_gen e;
825 
826 	printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
827 
828 	safememcpy(&e, ext, sizeof(e));
829 	printf(" len=%d", ntohs(e.len) - 4);
830 	if (2 < vflag && 4 < ntohs(e.len)) {
831 		printf(" ");
832 		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
833 	}
834 	return (u_char *)ext + ntohs(e.len);
835 }
836 
837 static u_char *
838 isakmp_sig_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
839 	u_int32_t doi, u_int32_t proto)
840 {
841 	struct isakmp_gen e;
842 
843 	printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
844 
845 	safememcpy(&e, ext, sizeof(e));
846 	printf(" len=%d", ntohs(e.len) - 4);
847 	if (2 < vflag && 4 < ntohs(e.len)) {
848 		printf(" ");
849 		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
850 	}
851 	return (u_char *)ext + ntohs(e.len);
852 }
853 
854 static u_char *
855 isakmp_nonce_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
856 	u_int32_t doi, u_int32_t proto)
857 {
858 	struct isakmp_gen e;
859 
860 	printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
861 
862 	safememcpy(&e, ext, sizeof(e));
863 	printf(" n len=%d", ntohs(e.len) - 4);
864 	if (2 < vflag && 4 < ntohs(e.len)) {
865 		printf(" ");
866 		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
867 	}
868 	return (u_char *)ext + ntohs(e.len);
869 }
870 
871 static u_char *
872 isakmp_n_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
873 	u_int32_t doi0, u_int32_t proto0)
874 {
875 	struct isakmp_pl_n *p, n;
876 	u_char *cp;
877 	u_char *ep2;
878 	u_int32_t doi;
879 	u_int32_t proto;
880 	static char *notifystr[] = {
881 		NULL,				"INVALID-PAYLOAD-TYPE",
882 		"DOI-NOT-SUPPORTED",		"SITUATION-NOT-SUPPORTED",
883 		"INVALID-COOKIE",		"INVALID-MAJOR-VERSION",
884 		"INVALID-MINOR-VERSION",	"INVALID-EXCHANGE-TYPE",
885 		"INVALID-FLAGS",		"INVALID-MESSAGE-ID",
886 		"INVALID-PROTOCOL-ID",		"INVALID-SPI",
887 		"INVALID-TRANSFORM-ID",		"ATTRIBUTES-NOT-SUPPORTED",
888 		"NO-PROPOSAL-CHOSEN",		"BAD-PROPOSAL-SYNTAX",
889 		"PAYLOAD-MALFORMED",		"INVALID-KEY-INFORMATION",
890 		"INVALID-ID-INFORMATION",	"INVALID-CERT-ENCODING",
891 		"INVALID-CERTIFICATE",		"CERT-TYPE-UNSUPPORTED",
892 		"INVALID-CERT-AUTHORITY",	"INVALID-HASH-INFORMATION",
893 		"AUTHENTICATION-FAILED",	"INVALID-SIGNATURE",
894 		"ADDRESS-NOTIFICATION",		"NOTIFY-SA-LIFETIME",
895 		"CERTIFICATE-UNAVAILABLE",	"UNSUPPORTED-EXCHANGE-TYPE",
896 		"UNEQUAL-PAYLOAD-LENGTHS",
897 	};
898 	static char *ipsecnotifystr[] = {
899 		"RESPONDER-LIFETIME",		"REPLAY-STATUS",
900 		"INITIAL-CONTACT",
901 	};
902 /* NOTE: these macro must be called with x in proper range */
903 #define NOTIFYSTR(x) \
904 	(((x) == 16384) ? "CONNECTED" : STR_OR_ID((x), notifystr))
905 #define IPSECNOTIFYSTR(x) \
906 	(((x) == 8192) ? "RESERVED" : STR_OR_ID(((x) - 24576), ipsecnotifystr))
907 
908 	printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
909 
910 	p = (struct isakmp_pl_n *)ext;
911 	safememcpy(&n, ext, sizeof(n));
912 	doi = ntohl(n.doi);
913 	proto = n.prot_id;
914 	if (doi != 1) {
915 		printf(" doi=%d", doi);
916 		printf(" proto=%d", proto);
917 		printf(" type=%s", NOTIFYSTR(ntohs(n.type)));
918 		if (n.spi_size) {
919 			printf(" spi=");
920 			rawprint((caddr_t)(p + 1), n.spi_size);
921 		}
922 		return (u_char *)(p + 1) + n.spi_size;
923 	}
924 
925 	printf(" doi=ipsec");
926 	printf(" proto=%s", PROTOIDSTR(proto));
927 	if (ntohs(n.type) < 8192)
928 		printf(" type=%s", NOTIFYSTR(ntohs(n.type)));
929 	else if (ntohs(n.type) < 16384)
930 		printf(" type=%s", IPSECNOTIFYSTR(ntohs(n.type)));
931 	else if (ntohs(n.type) < 24576)
932 		printf(" type=%s", NOTIFYSTR(ntohs(n.type)));
933 	else if (ntohs(n.type) < 40960)
934 		printf(" type=%s", IPSECNOTIFYSTR(ntohs(n.type)));
935 	else
936 		printf(" type=%s", NOTIFYSTR(ntohs(n.type)));
937 	if (n.spi_size) {
938 		printf(" spi=");
939 		rawprint((caddr_t)(p + 1), n.spi_size);
940 	}
941 
942 	cp = (u_char *)(p + 1) + n.spi_size;
943 	ep2 = (u_char *)p + ntohs(n.h.len);
944 
945 	if (cp < ep) {
946 		printf(" orig=(");
947 		switch (ntohs(n.type)) {
948 		case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
949 		    {
950 			struct attrmap *map = oakley_t_map;
951 			size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
952 			while (cp < ep && cp < ep2) {
953 				cp = isakmp_attrmap_print(cp,
954 					(ep < ep2) ? ep : ep2, map, nmap);
955 			}
956 			break;
957 		    }
958 		case IPSECDOI_NTYPE_REPLAY_STATUS:
959 			printf("replay detection %sabled",
960 				(*(u_int32_t *)cp) ? "en" : "dis");
961 			break;
962 		case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
963 			isakmp_sub_print(ISAKMP_NPTYPE_SA,
964 				(struct isakmp_gen *)cp, ep, phase, doi, proto);
965 			break;
966 		default:
967 			/* NULL is dummy */
968 			isakmp_print(cp,
969 				ntohs(n.h.len) - sizeof(*p) - n.spi_size,
970 				NULL);
971 		}
972 		printf(")");
973 	}
974 	return (u_char *)ext + ntohs(n.h.len);
975 }
976 
977 static u_char *
978 isakmp_d_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
979 	u_int32_t doi0, u_int32_t proto0)
980 {
981 	struct isakmp_pl_d *p, d;
982 	u_int8_t *q;
983 	u_int32_t doi;
984 	u_int32_t proto;
985 	int i;
986 
987 	printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
988 
989 	p = (struct isakmp_pl_d *)ext;
990 	safememcpy(&d, ext, sizeof(d));
991 	doi = ntohl(d.doi);
992 	proto = d.prot_id;
993 	if (doi != 1) {
994 		printf(" doi=%u", doi);
995 		printf(" proto=%u", proto);
996 	} else {
997 		printf(" doi=ipsec");
998 		printf(" proto=%s", PROTOIDSTR(proto));
999 	}
1000 	printf(" spilen=%u", d.spi_size);
1001 	printf(" nspi=%u", ntohs(d.num_spi));
1002 	printf(" spi=");
1003 	q = (u_int8_t *)(p + 1);
1004 	for (i = 0; i < ntohs(d.num_spi); i++) {
1005 		if (i != 0)
1006 			printf(",");
1007 		rawprint((caddr_t)q, d.spi_size);
1008 		q += d.spi_size;
1009 	}
1010 	return q;
1011 }
1012 
1013 static u_char *
1014 isakmp_vid_print(struct isakmp_gen *ext, u_char *ep, u_int32_t phase,
1015 	u_int32_t doi, u_int32_t proto)
1016 {
1017 	struct isakmp_gen e;
1018 
1019 	printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1020 
1021 	safememcpy(&e, ext, sizeof(e));
1022 	printf(" len=%d", ntohs(e.len) - 4);
1023 	if (2 < vflag && 4 < ntohs(e.len)) {
1024 		printf(" ");
1025 		rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4);
1026 	}
1027 	return (u_char *)ext + ntohs(e.len);
1028 }
1029 
1030 static u_char *
1031 isakmp_sub0_print(u_char np, struct isakmp_gen *ext, u_char *ep,
1032 	u_int32_t phase, u_int32_t doi, u_int32_t proto)
1033 {
1034 	u_char *cp;
1035 	struct isakmp_gen e;
1036 
1037 	cp = (u_char *)ext;
1038 	safememcpy(&e, ext, sizeof(e));
1039 
1040 	if (NPFUNC(np))
1041 		cp = (*NPFUNC(np))(ext, ep, phase, doi, proto);
1042 	else {
1043 		printf("%s", NPSTR(np));
1044 		cp += ntohs(e.len);
1045 	}
1046 	return cp;
1047 }
1048 
1049 static u_char *
1050 isakmp_sub_print(u_char np, struct isakmp_gen *ext, u_char *ep,
1051 	u_int32_t phase, u_int32_t doi, u_int32_t proto)
1052 {
1053 	u_char *cp;
1054 	static int depth = 0;
1055 	int i;
1056 	struct isakmp_gen e;
1057 
1058 	cp = (u_char *)ext;
1059 
1060 	while (np) {
1061 		safememcpy(&e, ext, sizeof(e));
1062 
1063 		if (ep < (u_char *)ext + ntohs(e.len)) {
1064 			printf(" [|%s]", NPSTR(np));
1065 			cp = ep + 1;
1066 			break;
1067 		}
1068 		depth++;
1069 		printf("\n");
1070 		for (i = 0; i < depth; i++)
1071 			printf("    ");
1072 		printf("(");
1073 		cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto);
1074 		printf(")");
1075 		depth--;
1076 
1077 		np = e.np;
1078 		ext = (struct isakmp_gen *)cp;
1079 	}
1080 	return cp;
1081 }
1082 
1083 static char *
1084 numstr(int x)
1085 {
1086 	static char buf[20];
1087 	snprintf(buf, sizeof(buf), "#%d", x);
1088 	return buf;
1089 }
1090 
1091 /*
1092  * some compiler tries to optimize memcpy(), using the alignment constraint
1093  * on the argument pointer type.  by using this function, we try to avoid the
1094  * optimization.
1095  */
1096 static void
1097 safememcpy(void *p, void *q, size_t l)
1098 {
1099 	memcpy(p, q, l);
1100 }
1101 
1102 void
1103 isakmp_print(const u_char *bp, u_int length, const u_char *bp2)
1104 {
1105 	struct isakmp *p, base;
1106 	u_char *ep;
1107 	u_char np;
1108 	int i;
1109 	int phase;
1110 	int major, minor;
1111 
1112 	p = (struct isakmp *)bp;
1113 	ep = (u_char *)snapend;
1114 
1115 	if ((struct isakmp *)ep < p + 1) {
1116 		printf("[|isakmp]");
1117 		return;
1118 	}
1119 
1120 	safememcpy(&base, p, sizeof(base));
1121 
1122 	printf("isakmp");
1123 	if (vflag) {
1124 		major = (base.vers & ISAKMP_VERS_MAJOR)
1125 				>> ISAKMP_VERS_MAJOR_SHIFT;
1126 		minor = (base.vers & ISAKMP_VERS_MINOR)
1127 				>> ISAKMP_VERS_MINOR_SHIFT;
1128 		printf(" %d.%d", major, minor);
1129 	}
1130 
1131 	if (vflag) {
1132 		printf(" msgid ");
1133 		rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
1134 	}
1135 
1136 	if (1 < vflag) {
1137 		printf(" cookie ");
1138 		rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
1139 		printf("->");
1140 		rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
1141 	}
1142 	printf(":");
1143 
1144 	phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
1145 	if (phase == 1)
1146 		printf(" phase %d", phase);
1147 	else
1148 		printf(" phase %d/others", phase);
1149 
1150 	i = cookie_find(&base.i_ck);
1151 	if (i < 0) {
1152 		if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
1153 			/* the first packet */
1154 			printf(" I");
1155 			if (bp2)
1156 				cookie_record(&base.i_ck, bp2);
1157 		} else
1158 			printf(" ?");
1159 	} else {
1160 		if (bp2 && cookie_isinitiator(i, bp2))
1161 			printf(" I");
1162 		else if (bp2 && cookie_isresponder(i, bp2))
1163 			printf(" R");
1164 		else
1165 			printf(" ?");
1166 	}
1167 
1168 	printf(" %s", ETYPESTR(base.etype));
1169 	if (base.flags) {
1170 		printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
1171 			base.flags & ISAKMP_FLAG_C ? "C" : "");
1172 	}
1173 	printf(":");
1174 
1175     {
1176 	struct isakmp_gen *ext;
1177 	int nparen;
1178 
1179 #define CHECKLEN(p, np) \
1180 	if (ep < (u_char *)(p)) {				\
1181 		printf(" [|%s]", NPSTR(np));			\
1182 		goto done;					\
1183 	}
1184 
1185 	/* regardless of phase... */
1186 	if (base.flags & ISAKMP_FLAG_E) {
1187 		/*
1188 		 * encrypted, nothing we can do right now.
1189 		 * we hope to decrypt the packet in the future...
1190 		 */
1191 		printf(" [|%s]", NPSTR(base.np));
1192 		goto done;
1193 	}
1194 
1195 	nparen = 0;
1196 	CHECKLEN(p + 1, base.np)
1197 
1198 	np = base.np;
1199 	ext = (struct isakmp_gen *)(p + 1);
1200 	isakmp_sub_print(np, ext, ep, phase, 0, 0);
1201     }
1202 
1203 done:
1204 	if (vflag) {
1205 		if (ntohl(base.len) != length) {
1206 			printf(" (len mismatch: isakmp %u/ip %d)",
1207 				(u_int32_t)ntohl(base.len), length);
1208 		}
1209 	}
1210 }
1211