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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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