xref: /openbsd-src/usr.sbin/tcpdump/print-ike.c (revision 3a50f0a93a2072911d0ba6ababa815fb04bf9a71)
1 /*	$OpenBSD: print-ike.c,v 1.41 2022/12/28 21:30:19 jmc Exp $	*/
2 
3 /*
4  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
5  *	The Regents of the University of California.  All rights reserved.
6  * Copyright (c) 2001 H�kan Olsson.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that: (1) source code distributions
10  * retain the above copyright notice and this paragraph in its entirety, (2)
11  * distributions including binary code include the above copyright notice and
12  * this paragraph in its entirety in the documentation or other materials
13  * provided with the distribution, and (3) all advertising materials mentioning
14  * features or use of this software display the following acknowledgement:
15  * ``This product includes software developed by the University of California,
16  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17  * the University nor the names of its contributors may be used to endorse
18  * or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23  *
24  * Format and print ike (isakmp) packets.
25  *	By Tero Kivinen <kivinen@ssh.fi>, Tero Mononen <tmo@ssh.fi>,
26  *         Tatu Ylonen <ylo@ssh.fi> and Timo J. Rinne <tri@ssh.fi>
27  *         in co-operation with SSH Communications Security, Espoo, Finland
28  */
29 
30 #include <sys/time.h>
31 #include <sys/socket.h>
32 
33 #include <net/if.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 
37 #include <ctype.h>
38 #include <stdio.h>
39 #include <string.h>
40 
41 #include "interface.h"
42 #include "addrtoname.h"
43 #include "ike.h"
44 
45 struct isakmp_header {
46 	u_int8_t	init_cookie[8];
47 	u_int8_t	resp_cookie[8];
48 	u_int8_t	next_payload;
49 	u_int8_t	version;
50 	u_int8_t	exgtype;
51 	u_int8_t	flags;
52 	u_int8_t	msgid[4];
53 	u_int32_t	length;
54 	u_int8_t	payloads[0];
55 };
56 
57 struct sa_payload {
58 	u_int8_t	next_payload;
59 	u_int8_t	reserved;
60 	u_int16_t	payload_length;
61 	u_int32_t	doi;
62 	u_int8_t	situation[0];
63 };
64 
65 struct proposal_payload {
66 	u_int8_t	next_payload;
67 	u_int8_t	reserved;
68 	u_int16_t	payload_length;
69 	u_int8_t	nprop;
70 	u_int8_t	proto;
71 	u_int8_t	spi_size;
72 	u_int8_t	nspis;
73 	u_int8_t	spi[0];
74 };
75 
76 struct transform_payload {
77 	u_int8_t	next_payload;
78 	u_int8_t	reserved;
79 	u_int16_t	payload_length;
80 	u_int8_t	ntrans;
81 	u_int8_t	transform;
82 	u_int16_t	reserved2;
83 	u_int8_t	attribute[0];
84 };
85 
86 struct ke_payload {
87 	u_int8_t	next_payload;
88 	u_int8_t	reserved;
89 	u_int16_t	payload_length;
90 	u_int8_t	data[0];
91 };
92 
93 struct id_payload {
94 	u_int8_t	next_payload;
95 	u_int8_t	reserved;
96 	u_int16_t	payload_length;
97 	u_int8_t	type;
98 	u_int8_t	id_data[3];
99 	u_int8_t	data[0];
100 };
101 
102 struct notification_payload {
103 	u_int8_t	next_payload;
104 	u_int8_t	reserved;
105 	u_int16_t	payload_length;
106 	u_int32_t	doi;
107 	u_int8_t	protocol_id;
108   	u_int8_t	spi_size;
109   	u_int16_t	type;
110 	u_int8_t	data[0];
111 };
112 
113 struct delete_payload {
114 	u_int8_t	next_payload;
115 	u_int8_t	reserved;
116 	u_int16_t	payload_length;
117 	u_int32_t	doi;
118 	u_int8_t	proto;
119 	u_int8_t	spi_size;
120 	u_int16_t	nspis;
121 	u_int8_t	spi[0];
122 };
123 
124 struct vendor_payload {
125 	u_int8_t	next_payload;
126 	u_int8_t	reserved;
127 	u_int16_t	payload_length;
128 	u_int8_t	vid[0];
129 };
130 
131 struct attribute_payload {
132 	u_int8_t	next_payload;
133 	u_int8_t	reserved;
134 	u_int16_t	payload_length;
135 	u_int8_t	type;
136 	u_int8_t	reserved2;
137 	u_int16_t	id;
138 };
139 
140 static void ike_pl_print(u_int8_t, u_int8_t *, u_int8_t);
141 
142 int ike_tab_level = 0;
143 u_int8_t xform_proto;
144 
145 static const char *ike[] = IKE_PROTO_INITIALIZER;
146 
147 #define SMALL_TABS 4
148 #define SPACES "                                                   "
149 const char *
ike_tab_offset(void)150 ike_tab_offset(void)
151 {
152 	const char *p, *endline;
153 	static const char line[] = SPACES;
154 
155 	endline = line + sizeof line - 1;
156 	p = endline - SMALL_TABS * (ike_tab_level);
157 
158 	return (p > line ? p : line);
159 }
160 
161 static char *
ike_get_cookie(u_int8_t * ic,u_int8_t * rc)162 ike_get_cookie (u_int8_t *ic, u_int8_t *rc)
163 {
164 	static char cookie_jar[35];
165 	int i;
166 
167 	for (i = 0; i < 8; i++)
168 		snprintf(cookie_jar + i*2, sizeof(cookie_jar) - i*2,
169 		    "%02x", *(ic + i));
170 	strlcat(cookie_jar, "->", sizeof(cookie_jar));
171 	for (i = 0; i < 8; i++)
172 		snprintf(cookie_jar + 18 + i*2, sizeof(cookie_jar) - 18 - i*2,
173 		    "%02x", *(rc + i));
174 	return cookie_jar;
175 }
176 
177 /*
178  * Print isakmp requests
179  */
180 void
ike_print(const u_int8_t * cp,u_int length)181 ike_print (const u_int8_t *cp, u_int length)
182 {
183 	struct isakmp_header *ih;
184 	const u_int8_t *ep;
185 	u_int8_t *payload, next_payload;
186 	int encrypted;
187 	static const char *exgtypes[] = IKE_EXCHANGE_TYPES_INITIALIZER;
188 
189 	encrypted = 0;
190 
191 #ifdef TCHECK
192 #undef TCHECK
193 #endif
194 #define TCHECK(var, l) if ((u_int8_t *)&(var) > ep - l) goto trunc
195 
196 	ih = (struct isakmp_header *)cp;
197 
198 	if (length < sizeof (struct isakmp_header))
199 		goto trunc;
200 
201 	/* 'ep' points to the end of available data. */
202 	ep = snapend;
203 
204 	printf("isakmp v%u.%u", ih->version >> 4, ih->version & 0xf);
205 
206 	printf(" exchange ");
207 	if (ih->exgtype < (sizeof exgtypes/sizeof exgtypes[0]))
208 		printf("%s", exgtypes[ih->exgtype]);
209 	else
210 		printf("%d (unknown)", ih->exgtype);
211 
212 	if (ih->flags & FLAGS_ENCRYPTION) {
213 		printf(" encrypted");
214 		encrypted = 1;
215 	}
216 
217 	if (ih->flags & FLAGS_COMMIT) {
218 		printf(" commit");
219 	}
220 
221 	printf("\n\tcookie: %s", ike_get_cookie (ih->init_cookie,
222 						 ih->resp_cookie));
223 
224 	TCHECK(ih->msgid, sizeof(ih->msgid));
225 	printf(" msgid: %02x%02x%02x%02x", ih->msgid[0], ih->msgid[1],
226 	    ih->msgid[2], ih->msgid[3]);
227 
228 	TCHECK(ih->length, sizeof(ih->length));
229 	printf(" len: %d", ntohl(ih->length));
230 
231 	if (ih->version > IKE_VERSION_2) {
232 		printf(" new version");
233 		return;
234 	}
235 
236 	payload = ih->payloads;
237 	next_payload = ih->next_payload;
238 
239 	/* if encrypted, then open special file for encryption keys */
240 	if (encrypted) {
241 		/* decrypt XXX */
242 		return;
243 	}
244 
245 	/* if verbose, print payload data */
246 	if (vflag)
247 		ike_pl_print(next_payload, payload, ISAKMP_DOI);
248 
249 	return;
250 
251 trunc:
252 	printf(" [|isakmp]");
253 }
254 
255 void
ike_pl_sa_print(u_int8_t * buf,int len)256 ike_pl_sa_print (u_int8_t *buf, int len)
257 {
258 	struct sa_payload *sp = (struct sa_payload *)buf;
259 	u_int32_t sit_ipsec, doi;
260 
261 	if (len < sizeof(struct sa_payload)) {
262 		printf(" [|payload]");
263 		return;
264 	}
265 
266 	doi = ntohl(sp->doi);
267 	printf(" DOI: %d", doi);
268 
269 	if (doi == IPSEC_DOI) {
270 		if ((sp->situation + sizeof(u_int32_t)) > (buf + len)) {
271 			printf(" [|payload]");
272 			return;
273 		}
274 		printf("(IPSEC) situation: ");
275 		sit_ipsec = ntohl(*(u_int32_t *)sp->situation);
276 		if (sit_ipsec & IKE_SITUATION_IDENTITY_ONLY)
277 			printf("IDENTITY_ONLY ");
278 		if (sit_ipsec & IKE_SITUATION_SECRECY)
279 			printf("SECRECY ");
280 		if (sit_ipsec & IKE_SITUATION_INTEGRITY)
281 			printf("INTEGRITY ");
282 		if ((sit_ipsec & IKE_SITUATION_MASK) == 0)
283 			printf("0x%x (unknown)", sit_ipsec);
284 		ike_pl_print (PAYLOAD_PROPOSAL, buf +
285 		    sizeof(struct sa_payload) + sizeof(u_int32_t), IPSEC_DOI);
286 	} else
287 		printf(" situation: (unknown)");
288 }
289 
290 int
ike_attribute_print(u_int8_t * buf,u_int8_t doi,int maxlen)291 ike_attribute_print (u_int8_t *buf, u_int8_t doi, int maxlen)
292 {
293 	static char *attrs[] = IKE_ATTR_INITIALIZER;
294 	static char *attr_enc[] = IKE_ATTR_ENCRYPT_INITIALIZER;
295 	static char *attr_hash[] = IKE_ATTR_HASH_INITIALIZER;
296 	static char *attr_auth[] = IKE_ATTR_AUTH_INITIALIZER;
297 	static char *attr_gdesc[] = IKE_ATTR_GROUP_DESC_INITIALIZER;
298 	static char *attr_gtype[] = IKE_ATTR_GROUP_INITIALIZER;
299 	static char *attr_ltype[] = IKE_ATTR_SA_DURATION_INITIALIZER;
300 	static char *ipsec_attrs[] = IPSEC_ATTR_INITIALIZER;
301 	static char *ipsec_attr_auth[] = IPSEC_ATTR_AUTH_INITIALIZER;
302 	static char *ipsec_attr_ltype[] = IPSEC_ATTR_DURATION_INITIALIZER;
303 
304 	u_int8_t af   = buf[0] >> 7;
305 	u_int16_t type = (buf[0] & 0x7f) << 8 | buf[1];
306 	u_int16_t len  = buf[2] << 8 | buf[3], val;
307 
308 	if (doi == ISAKMP_DOI)
309 		printf("\n\t%sattribute %s = ", ike_tab_offset(),
310 		    (type < sizeof attrs / sizeof attrs[0] ?
311 		    attrs[type] : "<unknown>"));
312 	else
313 		printf("\n\t%sattribute %s = ", ike_tab_offset(),
314 		    (type < (sizeof ipsec_attrs / sizeof ipsec_attrs[0]) ?
315 		    ipsec_attrs[type] : "<unknown>"));
316 
317 	if ((af == 1 && maxlen < 4) || (af == 0 && maxlen < (len + 4))) {
318 		printf("\n\t%s[|attr]", ike_tab_offset());
319 		return maxlen;
320 	}
321 
322 	if (af == 0) {
323 		/* AF=0; print the variable length attribute value */
324 		for (val = 0; val < len; val++)
325 			printf("%02x", *(buf + 4 + val));
326 		return len + 4;
327 	}
328 
329 	val = len;	/* For AF=1, this field is the "VALUE" */
330 	len = 4; 	/* and with AF=1, length is always 4 */
331 
332 #define CASE_PRINT(TYPE, var) \
333 	case TYPE : \
334 		if (val < sizeof var / sizeof var [0]) \
335 			printf("%s", var [val]); \
336 		else \
337 			printf("%d (unknown)", val); \
338 		break;
339 
340 	if (doi == ISAKMP_DOI)
341 		switch(type) {
342 			CASE_PRINT(IKE_ATTR_ENCRYPTION_ALGORITHM, attr_enc);
343 			CASE_PRINT(IKE_ATTR_HASH_ALGORITHM, attr_hash);
344 			CASE_PRINT(IKE_ATTR_AUTHENTICATION_METHOD, attr_auth);
345 			CASE_PRINT(IKE_ATTR_GROUP_DESC, attr_gdesc);
346 			CASE_PRINT(IKE_ATTR_GROUP_TYPE, attr_gtype);
347 			CASE_PRINT(IKE_ATTR_LIFE_TYPE, attr_ltype);
348 		default:
349 			printf("%d", val);
350 		}
351 	else
352 		switch(type) {
353 			CASE_PRINT(IPSEC_ATTR_SA_LIFE_TYPE, ipsec_attr_ltype);
354 			CASE_PRINT(IPSEC_ATTR_AUTHENTICATION_ALGORITHM,
355 			    ipsec_attr_auth);
356 			case IPSEC_ATTR_ENCAPSULATION_MODE:
357 				printf("%s", tok2str(ipsec_attr_encap,
358 				    "%d", val));
359 				break;
360 		default:
361 			printf("%d", val);
362 		}
363 
364 #undef CASE_PRINT
365 	return len;
366 }
367 
368 void
ike_pl_transform_print(u_int8_t * buf,int len,u_int8_t doi)369 ike_pl_transform_print (u_int8_t *buf, int len, u_int8_t doi)
370 {
371 	struct transform_payload *tp = (struct transform_payload *)buf;
372 	const char *ah[] = IPSEC_AH_INITIALIZER;
373 	const char *esp[] = IPSEC_ESP_INITIALIZER;
374 	const char *ipcomp[] = IPCOMP_INITIALIZER;
375 	u_int8_t *attr = tp->attribute;
376 
377 	if (len < sizeof(struct transform_payload)) {
378 		printf(" [|payload]");
379 		return;
380 	}
381 
382 	printf("\n\t%stransform: %u ID: ", ike_tab_offset(), tp->ntrans);
383 
384 	switch (doi) {
385 	case ISAKMP_DOI:
386 		if (tp->transform < (sizeof ike / sizeof ike[0]))
387 			printf("%s", ike[tp->transform]);
388 		else
389 			printf("%d(unknown)", tp->transform);
390 		break;
391 
392 	default: /* IPSEC_DOI */
393 		switch (xform_proto) { /* from ike_proposal_print */
394 		case PROTO_IPSEC_AH:
395 			if (tp->transform < (sizeof ah / sizeof ah[0]))
396 				printf("%s", ah[tp->transform]);
397 			else
398 				printf("%d(unknown)", tp->transform);
399 			break;
400 		case PROTO_IPSEC_ESP:
401 			if (tp->transform < (sizeof esp / sizeof esp[0]))
402 				printf("%s", esp[tp->transform]);
403 			else
404 				printf("%d(unknown)", tp->transform);
405 			break;
406 		case PROTO_IPCOMP:
407 			if (tp->transform < (sizeof ipcomp / sizeof ipcomp[0]))
408 				printf("%s", ipcomp[tp->transform]);
409 			else
410 				printf("%d(unknown)", tp->transform);
411 			break;
412 		default:
413 			printf("%d(unknown)", tp->transform);
414 		}
415 		break;
416 	}
417 
418 	ike_tab_level++;
419 	while ((int)(attr - buf) < len) /* Skip last 'NONE' attr */
420 		attr += ike_attribute_print(attr, doi, len - (attr - buf));
421 	ike_tab_level--;
422 }
423 
424 void
ike_pl_proposal_print(u_int8_t * buf,int len,u_int8_t doi)425 ike_pl_proposal_print (u_int8_t *buf, int len, u_int8_t doi)
426 {
427 	struct proposal_payload *pp = (struct proposal_payload *)buf;
428 	int i;
429 
430 	if (len < sizeof(struct proposal_payload)) {
431 		printf(" [|payload]");
432 		return;
433 	}
434 
435 	printf(" proposal: %d proto: %s spisz: %d xforms: %d",
436 	    pp->nprop, (pp->proto < (sizeof ike / sizeof ike[0]) ?
437 	    ike[pp->proto] : "(unknown)"), pp->spi_size, pp->nspis);
438 
439 	xform_proto = pp->proto;
440 
441 	if (pp->spi_size) {
442 		if ((pp->spi + pp->spi_size) > (buf + len)) {
443 			printf(" [|payload]");
444 			return;
445 		}
446 		if (pp->proto == PROTO_IPCOMP)
447 			printf(" CPI: 0x");
448 		else
449 			printf(" SPI: 0x");
450 		for (i = 0; i < pp->spi_size; i++)
451 			printf("%02x", pp->spi[i]);
452 	}
453 
454 	/* Reset to sane value. */
455 	if (pp->proto == PROTO_ISAKMP)
456 		doi = ISAKMP_DOI;
457 	else
458 		doi = IPSEC_DOI;
459 
460 	if (pp->nspis > 0)
461 		ike_pl_print(PAYLOAD_TRANSFORM, pp->spi + pp->spi_size, doi);
462 }
463 
464 void
ike_pl_ke_print(u_int8_t * buf,int len,u_int8_t doi)465 ike_pl_ke_print (u_int8_t *buf, int len, u_int8_t doi)
466 {
467 	if (len < sizeof(struct ke_payload)) {
468 		printf(" [|payload]");
469 		return;
470 	}
471 
472 	if (doi != IPSEC_DOI)
473 		return;
474 
475 	/* XXX ... */
476 }
477 
478 void
ipsec_id_print(u_int8_t * buf,int len,u_int8_t doi)479 ipsec_id_print (u_int8_t *buf, int len, u_int8_t doi)
480 {
481 	struct id_payload *ip = (struct id_payload *)buf;
482 	static const char *idtypes[] = IPSEC_ID_TYPE_INITIALIZER;
483 	char ntop_buf[INET6_ADDRSTRLEN];
484 	struct in_addr in;
485 	u_int8_t *p;
486 
487 	if (len < sizeof (struct id_payload)) {
488 		printf(" [|payload]");
489 		return;
490 	}
491 
492 	if (doi != ISAKMP_DOI)
493 		return;
494 
495 	/* Don't print proto+port unless actually used */
496 	if (ip->id_data[0] | ip->id_data[1] | ip->id_data[2])
497 		printf(" proto: %d port: %d", ip->id_data[0],
498 		    (ip->id_data[1] << 8) + ip->id_data[2]);
499 
500 	printf(" type: %s = ", ip->type < (sizeof idtypes/sizeof idtypes[0]) ?
501 	    idtypes[ip->type] : "<unknown>");
502 
503 	switch (ip->type) {
504 	case IPSEC_ID_IPV4_ADDR:
505 		if ((ip->data + sizeof in) > (buf + len)) {
506 			printf(" [|payload]");
507 			return;
508 		}
509 		memcpy (&in.s_addr, ip->data, sizeof in);
510 		printf("%s", inet_ntoa (in));
511 		break;
512 
513 	case IPSEC_ID_IPV4_ADDR_SUBNET:
514 	case IPSEC_ID_IPV4_ADDR_RANGE:
515 		if ((ip->data + 2 * (sizeof in)) > (buf + len)) {
516 			printf(" [|payload]");
517 			return;
518 		}
519 		memcpy (&in.s_addr, ip->data, sizeof in);
520 		printf("%s%s", inet_ntoa (in),
521 		    ip->type == IPSEC_ID_IPV4_ADDR_SUBNET ? "/" : "-");
522 		memcpy (&in.s_addr, ip->data + sizeof in, sizeof in);
523 		printf("%s", inet_ntoa (in));
524 		break;
525 
526 	case IPSEC_ID_IPV6_ADDR:
527 		if ((ip->data + sizeof ntop_buf) > (buf + len)) {
528 			printf(" [|payload]");
529 			return;
530 		}
531 		printf("%s", inet_ntop (AF_INET6, ip->data, ntop_buf,
532 		    sizeof ntop_buf));
533 		break;
534 
535 	case IPSEC_ID_IPV6_ADDR_SUBNET:
536 	case IPSEC_ID_IPV6_ADDR_RANGE:
537 		if ((ip->data + 2 * sizeof ntop_buf) > (buf + len)) {
538 			printf(" [|payload]");
539 			return;
540 		}
541 		printf("%s%s", inet_ntop (AF_INET6, ip->data, ntop_buf,
542 		    sizeof ntop_buf),
543 		    ip->type == IPSEC_ID_IPV6_ADDR_SUBNET ? "/" : "-");
544 		printf("%s", inet_ntop (AF_INET6, ip->data + sizeof ntop_buf,
545 		    ntop_buf, sizeof ntop_buf));
546 		break;
547 
548 	case IPSEC_ID_FQDN:
549 	case IPSEC_ID_USER_FQDN:
550 		printf("\"");
551 		for (p = ip->data; (int)(p - buf) < len; p++)
552 			printf("%c",(isprint(*p) ? *p : '.'));
553 		printf("\"");
554 		break;
555 
556 	case IPSEC_ID_DER_ASN1_DN:
557 	case IPSEC_ID_DER_ASN1_GN:
558 	case IPSEC_ID_KEY_ID:
559 	default:
560 		printf("\"(not shown)\"");
561 		break;
562 	}
563 }
564 
565 void
ike_pl_delete_print(u_int8_t * buf,int len)566 ike_pl_delete_print (u_int8_t *buf, int len)
567 {
568   	struct delete_payload *dp = (struct delete_payload *)buf;
569 	u_int32_t doi;
570 	u_int16_t s, nspis;
571 	u_int8_t *data;
572 
573 	if (len < sizeof (struct delete_payload)) {
574 		printf(" [|payload]");
575 		return;
576 	}
577 
578 	doi   = ntohl(dp->doi);
579 	nspis = ntohs(dp->nspis);
580 
581 	if (doi != ISAKMP_DOI && doi != IPSEC_DOI) {
582 		printf(" (unknown DOI)");
583 		return;
584 	}
585 
586 	printf(" DOI: %u(%s) proto: %s nspis: %u", doi,
587 	    doi == ISAKMP_DOI ? "ISAKMP" : "IPSEC",
588 	    dp->proto < (sizeof ike / sizeof ike[0]) ? ike[dp->proto] :
589 	    "(unknown)", nspis);
590 
591 	if ((dp->spi + nspis * dp->spi_size) > (buf + len)) {
592 		printf(" [|payload]");
593 		return;
594 	}
595 
596 	for (s = 0; s < nspis; s++) {
597 		data = dp->spi + s * dp->spi_size;
598 		if (dp->spi_size == 16)
599 			printf("\n\t%scookie: %s", ike_tab_offset(),
600 			    ike_get_cookie(&data[0], &data[8]));
601 		else
602 			printf("\n\t%sSPI: 0x%08x", ike_tab_offset(),
603 			    data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3]);
604 	}
605 }
606 
607 void
ike_pl_notification_print(u_int8_t * buf,int len)608 ike_pl_notification_print (u_int8_t *buf, int len)
609 {
610   	static const char *nftypes[] = IKE_NOTIFY_TYPES_INITIALIZER;
611   	struct notification_payload *np = (struct notification_payload *)buf;
612 	u_int32_t *replay, *seq;
613 	u_int32_t doi;
614 	u_int16_t type;
615 	u_int8_t *attr;
616 
617 	if (len < sizeof (struct notification_payload)) {
618 		printf(" [|payload]");
619 		return;
620 	}
621 
622 	doi  = ntohl (np->doi);
623 	type = ntohs (np->type);
624 
625 	if (doi != ISAKMP_DOI && doi != IPSEC_DOI) {
626 		printf(" (unknown DOI)");
627 		return;
628 	}
629 
630 	printf("\n\t%snotification: ", ike_tab_offset());
631 
632 	if (type > 0 && type < (sizeof nftypes / sizeof nftypes[0])) {
633 		printf("%s", nftypes[type]);
634 		return;
635 	}
636 	switch (type) {
637 
638 	case NOTIFY_IPSEC_RESPONDER_LIFETIME:
639 		printf("RESPONDER LIFETIME ");
640 		if (np->spi_size == 16)
641 			printf("(%s)", ike_get_cookie (&np->data[0],
642 			    &np->data[8]));
643 		else
644 			printf("SPI: 0x%08x", np->data[0]<<24 |
645 			    np->data[1]<<16 | np->data[2]<<8 | np->data[3]);
646 		attr = &np->data[np->spi_size];
647 		ike_tab_level++;
648 		while ((int)(attr - buf) < len - 4)  /* Skip last 'NONE' attr */
649 			attr += ike_attribute_print(attr, IPSEC_DOI,
650 			    len - (attr-buf));
651 		ike_tab_level--;
652 		break;
653 
654 	case NOTIFY_IPSEC_REPLAY_STATUS:
655 		replay = (u_int32_t *)&np->data[np->spi_size];
656 		printf("REPLAY STATUS [%sabled] ", *replay ? "en" : "dis");
657 		if (np->spi_size == 16)
658 			printf("(%s)", ike_get_cookie (&np->data[0],
659 			    &np->data[8]));
660 		else
661 			printf("SPI: 0x%08x", np->data[0]<<24 |
662 			    np->data[1]<<16 | np->data[2]<<8 | np->data[3]);
663 		break;
664 
665 	case NOTIFY_IPSEC_INITIAL_CONTACT:
666 		printf("INITIAL CONTACT (%s)", ike_get_cookie (&np->data[0],
667 		    &np->data[8]));
668 		break;
669 
670 	case NOTIFY_STATUS_DPD_R_U_THERE:
671 	case NOTIFY_STATUS_DPD_R_U_THERE_ACK:
672 		printf("STATUS_DPD_R_U_THERE%s ",
673 		    type == NOTIFY_STATUS_DPD_R_U_THERE ? "" : "_ACK");
674 		if (np->spi_size != 16 ||
675 		    len < sizeof(struct notification_payload) +
676 		    sizeof(u_int32_t))
677 			printf("[bad notify]");
678 		else {
679 			seq = (u_int32_t *)&np->data[np->spi_size];
680 			printf("seq %u", ntohl(*seq));
681 		}
682 		break;
683 
684 
685 	default:
686 	  	printf("%d (unknown)", type);
687 		break;
688 	}
689 }
690 
691 void
ike_pl_vendor_print(u_int8_t * buf,int len,u_int8_t doi)692 ike_pl_vendor_print (u_int8_t *buf, int len, u_int8_t doi)
693 {
694 	struct vendor_payload *vp = (struct vendor_payload *)buf;
695 	u_int8_t *p;
696 	int i;
697 
698 	if (len < sizeof(struct vendor_payload)) {
699 		printf(" [|payload]");
700 		return;
701 	}
702 
703 	for (i = 0; i < sizeof vendor_ids / sizeof vendor_ids[0]; i ++)
704 		if (memcmp(vp->vid, vendor_ids[i].vid,
705 		    vendor_ids[i].len) == 0) {
706 			printf (" (supports %s)", vendor_ids[i].name);
707 			return;
708 		}
709 
710 	if (doi != IPSEC_DOI)
711 		return;
712 
713 	printf(" \"");
714 	for (p = vp->vid; (int)(p - buf) < len; p++)
715 		printf("%c", (isprint(*p) ? *p : '.'));
716 	printf("\"");
717 }
718 
719 /* IKE mode-config. */
720 int
ike_cfg_attribute_print(u_int8_t * buf,int attr_type,int maxlen)721 ike_cfg_attribute_print (u_int8_t *buf, int attr_type, int maxlen)
722 {
723 	static char *attrs[] = IKE_CFG_ATTRIBUTE_INITIALIZER;
724 	char ntop_buf[INET6_ADDRSTRLEN];
725 	struct in_addr in;
726 
727 	u_int8_t af = buf[0] >> 7;
728 	u_int16_t type = (buf[0] & 0x7f) << 8 | buf[1];
729 	u_int16_t len = af ? 2 : buf[2] << 8 | buf[3], p;
730 	u_int8_t *val = af ? buf + 2 : buf + 4;
731 
732 	printf("\n\t%sattribute %s = ", ike_tab_offset(),
733 	    type < (sizeof attrs / sizeof attrs[0]) ? attrs[type] :
734 	    "<unknown>");
735 
736 	if ((af == 1 && maxlen < 4) ||
737 	    (af == 0 && maxlen < (len + 4))) {
738 		printf("\n\t%s[|attr]", ike_tab_offset());
739 		return maxlen;
740 	}
741 
742 	/* XXX The 2nd term is for bug compatibility with PGPnet.  */
743 	if (len == 0 || (af && !val[0] && !val[1])) {
744 		printf("<none>");
745 		return 4;
746 	}
747 
748 	/* XXX Generally lengths are not checked well below.  */
749 	switch (type) {
750 	case IKE_CFG_ATTR_INTERNAL_IP4_ADDRESS:
751 	case IKE_CFG_ATTR_INTERNAL_IP4_NETMASK:
752 	case IKE_CFG_ATTR_INTERNAL_IP4_DNS:
753 	case IKE_CFG_ATTR_INTERNAL_IP4_NBNS:
754 	case IKE_CFG_ATTR_INTERNAL_IP4_DHCP:
755 		memcpy (&in.s_addr, val, sizeof in);
756 		printf("%s", inet_ntoa (in));
757 		break;
758 
759 	case IKE_CFG_ATTR_INTERNAL_IP6_ADDRESS:
760 	case IKE_CFG_ATTR_INTERNAL_IP6_NETMASK:
761 	case IKE_CFG_ATTR_INTERNAL_IP6_DNS:
762 	case IKE_CFG_ATTR_INTERNAL_IP6_NBNS:
763 	case IKE_CFG_ATTR_INTERNAL_IP6_DHCP:
764 		printf("%s", inet_ntop (AF_INET6, val, ntop_buf,
765 		    sizeof ntop_buf));
766 		break;
767 
768 	case IKE_CFG_ATTR_INTERNAL_IP4_SUBNET:
769 		memcpy(&in.s_addr, val, sizeof in);
770 		printf("%s/", inet_ntoa (in));
771 		memcpy(&in.s_addr, val + sizeof in, sizeof in);
772 		printf("%s", inet_ntoa (in));
773 		break;
774 
775 	case IKE_CFG_ATTR_INTERNAL_IP6_SUBNET:
776 		printf("%s/%u", inet_ntop (AF_INET6, val, ntop_buf,
777 		    sizeof ntop_buf), val[16]);
778 		break;
779 
780 	case IKE_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY:
781 		printf("%u seconds",
782 		    val[0] << 24 | val[1] << 16 | val[2] << 8 | val[3]);
783 		break;
784 
785 	case IKE_CFG_ATTR_APPLICATION_VERSION:
786 		for (p = 0; p < len; p++)
787 			printf("%c", isprint(val[p]) ? val[p] : '.');
788 		break;
789 
790 	case IKE_CFG_ATTR_SUPPORTED_ATTRIBUTES:
791 		printf("<%d attributes>", len / 2);
792 		ike_tab_level++;
793 		for (p = 0; p < len; p += 2) {
794 			type = (val[p] << 8 | val[p + 1]) & 0x7fff;
795 			printf("\n\t%s%s", ike_tab_offset(),
796 			    type < (sizeof attrs/sizeof attrs[0]) ?
797 			    attrs[type] : "<unknown>");
798 		}
799 		ike_tab_level--;
800 		break;
801 
802 	default:
803 		break;
804 	}
805 	return af ? 4 : len + 4;
806 }
807 
808 void
ike_pl_attribute_print(u_int8_t * buf,int len)809 ike_pl_attribute_print (u_int8_t *buf, int len)
810 {
811 	struct attribute_payload *ap = (struct attribute_payload *)buf;
812 	static const char *pl_attr[] = IKE_CFG_ATTRIBUTE_TYPE_INITIALIZER;
813 	u_int8_t *attr = buf + sizeof(struct attribute_payload);
814 
815 	if (len < sizeof(struct attribute_payload)) {
816 		printf(" [|payload]");
817 		return;
818 	}
819 
820 	printf(" type: %s Id: %d",
821 	    ap->type < (sizeof pl_attr/sizeof pl_attr[0]) ? pl_attr[ap->type] :
822 	    "<unknown>", ap->id);
823 
824 	while ((int)(attr - buf) < len)
825 		attr += ike_cfg_attribute_print(attr, ap->type,
826 		    len - (attr - buf));
827 }
828 
829 void
ike_pl_print(u_int8_t type,u_int8_t * buf,u_int8_t doi)830 ike_pl_print (u_int8_t type, u_int8_t *buf, u_int8_t doi)
831 {
832 	static const char *pltypes[] = IKE_PAYLOAD_TYPES_INITIALIZER;
833 	static const char *plprivtypes[] =
834 	    IKE_PRIVATE_PAYLOAD_TYPES_INITIALIZER;
835 	static const char *plv2types[] = IKEV2_PAYLOAD_TYPES_INITIALIZER;
836 	u_int8_t next_type;
837 	u_int16_t this_len;
838 
839 	if (&buf[4] > snapend) {
840 		goto pltrunc;
841 	}
842 
843 	next_type = buf[0];
844 	this_len = buf[2]<<8 | buf[3];
845 
846 	if (type < PAYLOAD_PRIVATE_MIN && type >= PAYLOAD_IKEV2_SA)
847 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
848 		    plv2types[type - PAYLOAD_IKEV2_SA], this_len);
849 	else if (type < PAYLOAD_PRIVATE_MIN || type >= PAYLOAD_PRIVATE_MAX)
850 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
851 		    (type < (sizeof pltypes/sizeof pltypes[0]) ?
852 			pltypes[type] : "<unknown>"), this_len);
853 	else
854 		printf("\n\t%spayload: %s len: %hu", ike_tab_offset(),
855 		    plprivtypes[type - PAYLOAD_PRIVATE_MIN], this_len);
856 
857 	if ((type < PAYLOAD_RESERVED_MIN &&
858 	    (type < sizeof(min_payload_lengths)/sizeof(min_payload_lengths[0]) &&
859 	    this_len < min_payload_lengths[type])) ||
860 	    this_len == 0)
861 		goto pltrunc;
862 
863 	if ((type > PAYLOAD_PRIVATE_MIN && type < PAYLOAD_PRIVATE_MAX &&
864 	    this_len < min_priv_payload_lengths[type - PAYLOAD_PRIVATE_MIN]) ||
865 	    this_len == 0)
866 		goto pltrunc;
867 
868 	if (buf + this_len > snapend)
869 		goto pltrunc;
870 
871 	ike_tab_level++;
872 	switch (type) {
873 	case PAYLOAD_NONE:
874 		return;
875 
876 	case PAYLOAD_SA:
877 		ike_pl_sa_print(buf, this_len);
878 		break;
879 
880 	case PAYLOAD_PROPOSAL:
881 		ike_pl_proposal_print(buf, this_len, doi);
882 		break;
883 
884 	case PAYLOAD_TRANSFORM:
885 		ike_pl_transform_print(buf, this_len, doi);
886 		break;
887 
888 	case PAYLOAD_KE:
889 		ike_pl_ke_print(buf, this_len, doi);
890 		break;
891 
892 	case PAYLOAD_ID:
893 		/* Should only happen with IPsec DOI */
894 		ipsec_id_print(buf, this_len, doi);
895 		break;
896 
897 	case PAYLOAD_CERT:
898 	case PAYLOAD_CERTREQUEST:
899 	case PAYLOAD_HASH:
900 	case PAYLOAD_SIG:
901 	case PAYLOAD_NONCE:
902 		break;
903 
904 	case PAYLOAD_DELETE:
905 		ike_pl_delete_print(buf, this_len);
906 		break;
907 
908 	case PAYLOAD_NOTIFICATION:
909 	  	ike_pl_notification_print(buf, this_len);
910 		break;
911 
912 	case PAYLOAD_VENDOR:
913 		ike_pl_vendor_print(buf, this_len, doi);
914 		break;
915 
916 	case PAYLOAD_ATTRIBUTE:
917 		ike_pl_attribute_print(buf, this_len);
918 		break;
919 
920 	case PAYLOAD_SAK:
921 	case PAYLOAD_SAT:
922 	case PAYLOAD_KD:
923 	case PAYLOAD_SEQ:
924 	case PAYLOAD_POP:
925 	case PAYLOAD_NAT_D:
926 		break;
927 
928 	case PAYLOAD_NAT_OA:
929 		/* RFC3947 NAT-OA uses a subset of the ID payload */
930 		ipsec_id_print(buf, this_len, doi);
931 		break;
932 
933 	case PAYLOAD_NAT_D_DRAFT:
934 		break;
935 
936 	case PAYLOAD_NAT_OA_DRAFT:
937 		ipsec_id_print(buf, this_len, doi);
938 		break;
939 
940 	default:
941 		break;
942 	}
943 	ike_tab_level--;
944 
945 	if (next_type)  /* Recurse over next payload */
946 		ike_pl_print(next_type, buf + this_len, doi);
947 
948 	return;
949 
950 pltrunc:
951 	if (doi == ISAKMP_DOI)
952 		printf(" [|isakmp]");
953 	else
954 		printf(" [|ipsec]");
955 }
956