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