print-isakmp.c revision 146773
1292928Sdim/* 2292928Sdim * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3292928Sdim * All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6353358Sdim * modification, are permitted provided that the following conditions 7292928Sdim * are met: 8292928Sdim * 1. Redistributions of source code must retain the above copyright 9292928Sdim * notice, this list of conditions and the following disclaimer. 10292928Sdim * 2. Redistributions in binary form must reproduce the above copyright 11292928Sdim * notice, this list of conditions and the following disclaimer in the 12292928Sdim * documentation and/or other materials provided with the distribution. 13292928Sdim * 3. Neither the name of the project nor the names of its contributors 14292928Sdim * may be used to endorse or promote products derived from this software 15292928Sdim * without specific prior written permission. 16292928Sdim * 17292928Sdim * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18292928Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19292928Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20292928Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21292928Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22292928Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23292928Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24292928Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25292928Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26292928Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27292928Sdim * SUCH DAMAGE. 28292928Sdim * 29292928Sdim */ 30292928Sdim 31292928Sdim#ifndef lint 32292928Sdimstatic const char rcsid[] _U_ = 33292928Sdim "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.51 2005/04/07 00:28:17 mcr Exp $ (LBL)"; 34292928Sdim#endif 35292928Sdim 36292928Sdim#ifdef HAVE_CONFIG_H 37292928Sdim#include "config.h" 38292928Sdim#endif 39292928Sdim 40292928Sdim#include <tcpdump-stdinc.h> 41292928Sdim 42292928Sdim#include <string.h> 43292928Sdim 44292928Sdim#include <stdio.h> 45292928Sdim 46292928Sdim#include "isakmp.h" 47292928Sdim#include "ipsec_doi.h" 48292928Sdim#include "oakley.h" 49292928Sdim#include "interface.h" 50292928Sdim#include "addrtoname.h" 51292928Sdim#include "extract.h" /* must come after interface.h */ 52292928Sdim 53292928Sdim#include "ip.h" 54292928Sdim#ifdef INET6 55292928Sdim#include "ip6.h" 56292928Sdim#endif 57292928Sdim 58292928Sdim#ifndef HAVE_SOCKADDR_STORAGE 59292928Sdim#define sockaddr_storage sockaddr 60292928Sdim#endif 61292928Sdim 62292928Sdimstatic const u_char *isakmp_sa_print(const struct isakmp_gen *, 63292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 64292928Sdimstatic const u_char *isakmp_p_print(const struct isakmp_gen *, 65292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 66292928Sdimstatic const u_char *isakmp_t_print(const struct isakmp_gen *, 67292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 68292928Sdimstatic const u_char *isakmp_ke_print(const struct isakmp_gen *, 69292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 70292928Sdimstatic const u_char *isakmp_id_print(const struct isakmp_gen *, 71292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 72292928Sdimstatic const u_char *isakmp_cert_print(const struct isakmp_gen *, 73292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 74292928Sdimstatic const u_char *isakmp_cr_print(const struct isakmp_gen *, 75292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 76292928Sdimstatic const u_char *isakmp_sig_print(const struct isakmp_gen *, 77292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 78292928Sdimstatic const u_char *isakmp_hash_print(const struct isakmp_gen *, 79292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 80292928Sdimstatic const u_char *isakmp_nonce_print(const struct isakmp_gen *, 81292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 82292928Sdimstatic const u_char *isakmp_n_print(const struct isakmp_gen *, 83292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 84292928Sdimstatic const u_char *isakmp_d_print(const struct isakmp_gen *, 85292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 86292928Sdimstatic const u_char *isakmp_vid_print(const struct isakmp_gen *, 87292928Sdim u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 88292928Sdimstatic const u_char *isakmp_sub0_print(u_char, const struct isakmp_gen *, 89292928Sdim const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 90292928Sdimstatic const u_char *isakmp_sub_print(u_char, const struct isakmp_gen *, 91292928Sdim const u_char *, u_int32_t, u_int32_t, u_int32_t, int); 92292928Sdimstatic char *numstr(int); 93292928Sdimstatic void safememcpy(void *, const void *, size_t); 94292928Sdim 95292928Sdim#define MAXINITIATORS 20 96292928Sdimint ninitiator = 0; 97292928Sdimstruct { 98292928Sdim cookie_t initiator; 99292928Sdim struct sockaddr_storage iaddr; 100292928Sdim struct sockaddr_storage raddr; 101292928Sdim} cookiecache[MAXINITIATORS]; 102292928Sdim 103292928Sdim/* protocol id */ 104292928Sdimstatic const char *protoidstr[] = { 105292928Sdim NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp", 106292928Sdim}; 107292928Sdim 108292928Sdim/* isakmp->np */ 109292928Sdimstatic const char *npstr[] = { 110292928Sdim "none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash", 111292928Sdim "sig", "nonce", "n", "d", "vid" 112292928Sdim}; 113292928Sdim 114292928Sdim/* isakmp->np */ 115292928Sdimstatic const u_char *(*npfunc[])(const struct isakmp_gen *, u_int, 116292928Sdim const u_char *, u_int32_t, u_int32_t, u_int32_t, int) = { 117292928Sdim NULL, 118292928Sdim isakmp_sa_print, 119292928Sdim isakmp_p_print, 120309124Sdim isakmp_t_print, 121292928Sdim isakmp_ke_print, 122292928Sdim isakmp_id_print, 123292928Sdim isakmp_cert_print, 124292928Sdim isakmp_cr_print, 125292928Sdim isakmp_hash_print, 126292928Sdim isakmp_sig_print, 127327952Sdim isakmp_nonce_print, 128327952Sdim isakmp_n_print, 129327952Sdim isakmp_d_print, 130327952Sdim isakmp_vid_print, 131292928Sdim}; 132292928Sdim 133309124Sdim/* isakmp->etype */ 134309124Sdimstatic const char *etypestr[] = { 135309124Sdim "none", "base", "ident", "auth", "agg", "inf", NULL, NULL, 136309124Sdim NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 137309124Sdim NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 138309124Sdim NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 139309124Sdim "oakley-quick", "oakley-newgroup", 140309124Sdim}; 141309124Sdim 142309124Sdim#define STR_OR_ID(x, tab) \ 143309124Sdim (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) 144309124Sdim#define PROTOIDSTR(x) STR_OR_ID(x, protoidstr) 145309124Sdim#define NPSTR(x) STR_OR_ID(x, npstr) 146309124Sdim#define ETYPESTR(x) STR_OR_ID(x, etypestr) 147309124Sdim 148309124Sdim#define NPFUNC(x) \ 149309124Sdim (((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \ 150309124Sdim ? npfunc[(x)] : NULL) 151309124Sdim 152309124Sdimstatic int 153309124Sdimiszero(u_char *p, size_t l) 154309124Sdim{ 155309124Sdim while (l--) { 156309124Sdim if (*p++) 157309124Sdim return 0; 158309124Sdim } 159309124Sdim return 1; 160309124Sdim} 161309124Sdim 162309124Sdim/* find cookie from initiator cache */ 163309124Sdimstatic int 164309124Sdimcookie_find(cookie_t *in) 165309124Sdim{ 166309124Sdim int i; 167309124Sdim 168309124Sdim for (i = 0; i < MAXINITIATORS; i++) { 169309124Sdim if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0) 170309124Sdim return i; 171309124Sdim } 172321369Sdim 173321369Sdim return -1; 174321369Sdim} 175321369Sdim 176321369Sdim/* record initiator */ 177321369Sdimstatic void 178292928Sdimcookie_record(cookie_t *in, const u_char *bp2) 179292928Sdim{ 180292928Sdim int i; 181292928Sdim struct ip *ip; 182 struct sockaddr_in *sin; 183#ifdef INET6 184 struct ip6_hdr *ip6; 185 struct sockaddr_in6 *sin6; 186#endif 187 188 i = cookie_find(in); 189 if (0 <= i) { 190 ninitiator = (i + 1) % MAXINITIATORS; 191 return; 192 } 193 194 ip = (struct ip *)bp2; 195 switch (IP_V(ip)) { 196 case 4: 197 memset(&cookiecache[ninitiator].iaddr, 0, 198 sizeof(cookiecache[ninitiator].iaddr)); 199 memset(&cookiecache[ninitiator].raddr, 0, 200 sizeof(cookiecache[ninitiator].raddr)); 201 202 sin = (struct sockaddr_in *)&cookiecache[ninitiator].iaddr; 203#ifdef HAVE_SOCKADDR_SA_LEN 204 sin->sin_len = sizeof(struct sockaddr_in); 205#endif 206 sin->sin_family = AF_INET; 207 memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src)); 208 sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr; 209#ifdef HAVE_SOCKADDR_SA_LEN 210 sin->sin_len = sizeof(struct sockaddr_in); 211#endif 212 sin->sin_family = AF_INET; 213 memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)); 214 break; 215#ifdef INET6 216 case 6: 217 memset(&cookiecache[ninitiator].iaddr, 0, 218 sizeof(cookiecache[ninitiator].iaddr)); 219 memset(&cookiecache[ninitiator].raddr, 0, 220 sizeof(cookiecache[ninitiator].raddr)); 221 222 ip6 = (struct ip6_hdr *)bp2; 223 sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].iaddr; 224#ifdef HAVE_SOCKADDR_SA_LEN 225 sin6->sin6_len = sizeof(struct sockaddr_in6); 226#endif 227 sin6->sin6_family = AF_INET6; 228 memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src)); 229 sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr; 230#ifdef HAVE_SOCKADDR_SA_LEN 231 sin6->sin6_len = sizeof(struct sockaddr_in6); 232#endif 233 sin6->sin6_family = AF_INET6; 234 memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); 235 break; 236#endif 237 default: 238 return; 239 } 240 memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in)); 241 ninitiator = (ninitiator + 1) % MAXINITIATORS; 242} 243 244#define cookie_isinitiator(x, y) cookie_sidecheck((x), (y), 1) 245#define cookie_isresponder(x, y) cookie_sidecheck((x), (y), 0) 246static int 247cookie_sidecheck(int i, const u_char *bp2, int initiator) 248{ 249 struct sockaddr_storage ss; 250 struct sockaddr *sa; 251 struct ip *ip; 252 struct sockaddr_in *sin; 253#ifdef INET6 254 struct ip6_hdr *ip6; 255 struct sockaddr_in6 *sin6; 256#endif 257 int salen; 258 259 memset(&ss, 0, sizeof(ss)); 260 ip = (struct ip *)bp2; 261 switch (IP_V(ip)) { 262 case 4: 263 sin = (struct sockaddr_in *)&ss; 264#ifdef HAVE_SOCKADDR_SA_LEN 265 sin->sin_len = sizeof(struct sockaddr_in); 266#endif 267 sin->sin_family = AF_INET; 268 memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src)); 269 break; 270#ifdef INET6 271 case 6: 272 ip6 = (struct ip6_hdr *)bp2; 273 sin6 = (struct sockaddr_in6 *)&ss; 274#ifdef HAVE_SOCKADDR_SA_LEN 275 sin6->sin6_len = sizeof(struct sockaddr_in6); 276#endif 277 sin6->sin6_family = AF_INET6; 278 memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src)); 279 break; 280#endif 281 default: 282 return 0; 283 } 284 285 sa = (struct sockaddr *)&ss; 286 if (initiator) { 287 if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].iaddr)->sa_family) 288 return 0; 289#ifdef HAVE_SOCKADDR_SA_LEN 290 salen = sa->sa_len; 291#else 292#ifdef INET6 293 if (sa->sa_family == AF_INET6) 294 salen = sizeof(struct sockaddr_in6); 295 else 296 salen = sizeof(struct sockaddr); 297#else 298 salen = sizeof(struct sockaddr); 299#endif 300#endif 301 if (memcmp(&ss, &cookiecache[i].iaddr, salen) == 0) 302 return 1; 303 } else { 304 if (sa->sa_family != ((struct sockaddr *)&cookiecache[i].raddr)->sa_family) 305 return 0; 306#ifdef HAVE_SOCKADDR_SA_LEN 307 salen = sa->sa_len; 308#else 309#ifdef INET6 310 if (sa->sa_family == AF_INET6) 311 salen = sizeof(struct sockaddr_in6); 312 else 313 salen = sizeof(struct sockaddr); 314#else 315 salen = sizeof(struct sockaddr); 316#endif 317#endif 318 if (memcmp(&ss, &cookiecache[i].raddr, salen) == 0) 319 return 1; 320 } 321 return 0; 322} 323 324static int 325rawprint(caddr_t loc, size_t len) 326{ 327 static u_char *p; 328 size_t i; 329 330 TCHECK2(*loc, len); 331 332 p = (u_char *)loc; 333 for (i = 0; i < len; i++) 334 printf("%02x", p[i] & 0xff); 335 return 1; 336trunc: 337 return 0; 338} 339 340struct attrmap { 341 const char *type; 342 u_int nvalue; 343 const char *value[30]; /*XXX*/ 344}; 345 346static const u_char * 347isakmp_attrmap_print(const u_char *p, const u_char *ep, 348 const struct attrmap *map, size_t nmap) 349{ 350 u_int16_t *q; 351 int totlen; 352 u_int32_t t, v; 353 354 q = (u_int16_t *)p; 355 if (p[0] & 0x80) 356 totlen = 4; 357 else 358 totlen = 4 + EXTRACT_16BITS(&q[1]); 359 if (ep < p + totlen) { 360 printf("[|attr]"); 361 return ep + 1; 362 } 363 364 printf("("); 365 t = EXTRACT_16BITS(&q[0]) & 0x7fff; 366 if (map && t < nmap && map[t].type) 367 printf("type=%s ", map[t].type); 368 else 369 printf("type=#%d ", t); 370 if (p[0] & 0x80) { 371 printf("value="); 372 v = EXTRACT_16BITS(&q[1]); 373 if (map && t < nmap && v < map[t].nvalue && map[t].value[v]) 374 printf("%s", map[t].value[v]); 375 else 376 rawprint((caddr_t)&q[1], 2); 377 } else { 378 printf("len=%d value=", EXTRACT_16BITS(&q[1])); 379 rawprint((caddr_t)&p[4], EXTRACT_16BITS(&q[1])); 380 } 381 printf(")"); 382 return p + totlen; 383} 384 385static const u_char * 386isakmp_attr_print(const u_char *p, const u_char *ep) 387{ 388 u_int16_t *q; 389 int totlen; 390 u_int32_t t; 391 392 q = (u_int16_t *)p; 393 if (p[0] & 0x80) 394 totlen = 4; 395 else 396 totlen = 4 + EXTRACT_16BITS(&q[1]); 397 if (ep < p + totlen) { 398 printf("[|attr]"); 399 return ep + 1; 400 } 401 402 printf("("); 403 t = EXTRACT_16BITS(&q[0]) & 0x7fff; 404 printf("type=#%d ", t); 405 if (p[0] & 0x80) { 406 printf("value="); 407 t = q[1]; 408 rawprint((caddr_t)&q[1], 2); 409 } else { 410 printf("len=%d value=", EXTRACT_16BITS(&q[1])); 411 rawprint((caddr_t)&p[2], EXTRACT_16BITS(&q[1])); 412 } 413 printf(")"); 414 return p + totlen; 415} 416 417static const u_char * 418isakmp_sa_print(const struct isakmp_gen *ext, 419 u_int item_len _U_, 420 const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_, 421 u_int32_t proto0, int depth) 422{ 423 const struct isakmp_pl_sa *p; 424 struct isakmp_pl_sa sa; 425 const u_int32_t *q; 426 u_int32_t doi, sit, ident; 427 const u_char *cp, *np; 428 int t; 429 430 printf("%s:", NPSTR(ISAKMP_NPTYPE_SA)); 431 432 p = (struct isakmp_pl_sa *)ext; 433 TCHECK(*p); 434 safememcpy(&sa, ext, sizeof(sa)); 435 doi = ntohl(sa.doi); 436 sit = ntohl(sa.sit); 437 if (doi != 1) { 438 printf(" doi=%d", doi); 439 printf(" situation=%u", (u_int32_t)ntohl(sa.sit)); 440 return (u_char *)(p + 1); 441 } 442 443 printf(" doi=ipsec"); 444 q = (u_int32_t *)&sa.sit; 445 printf(" situation="); 446 t = 0; 447 if (sit & 0x01) { 448 printf("identity"); 449 t++; 450 } 451 if (sit & 0x02) { 452 printf("%ssecrecy", t ? "+" : ""); 453 t++; 454 } 455 if (sit & 0x04) 456 printf("%sintegrity", t ? "+" : ""); 457 458 np = (u_char *)ext + sizeof(sa); 459 if (sit != 0x01) { 460 TCHECK2(*(ext + 1), sizeof(ident)); 461 safememcpy(&ident, ext + 1, sizeof(ident)); 462 printf(" ident=%u", (u_int32_t)ntohl(ident)); 463 np += sizeof(ident); 464 } 465 466 ext = (struct isakmp_gen *)np; 467 TCHECK(*ext); 468 469 cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0, 470 depth); 471 472 return cp; 473trunc: 474 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA)); 475 return NULL; 476} 477 478static const u_char * 479isakmp_p_print(const struct isakmp_gen *ext, u_int item_len _U_, 480 const u_char *ep, u_int32_t phase, u_int32_t doi0, 481 u_int32_t proto0 _U_, int depth) 482{ 483 const struct isakmp_pl_p *p; 484 struct isakmp_pl_p prop; 485 const u_char *cp; 486 487 printf("%s:", NPSTR(ISAKMP_NPTYPE_P)); 488 489 p = (struct isakmp_pl_p *)ext; 490 TCHECK(*p); 491 safememcpy(&prop, ext, sizeof(prop)); 492 printf(" #%d protoid=%s transform=%d", 493 prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t); 494 if (prop.spi_size) { 495 printf(" spi="); 496 if (!rawprint((caddr_t)(p + 1), prop.spi_size)) 497 goto trunc; 498 } 499 500 ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size); 501 TCHECK(*ext); 502 503 cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0, 504 prop.prot_id, depth); 505 506 return cp; 507trunc: 508 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_P)); 509 return NULL; 510} 511 512static const char *isakmp_p_map[] = { 513 NULL, "ike", 514}; 515 516static const char *ah_p_map[] = { 517 NULL, "(reserved)", "md5", "sha", "1des", 518 "sha2-256", "sha2-384", "sha2-512", 519}; 520 521static const char *esp_p_map[] = { 522 NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast", 523 "blowfish", "3idea", "1des-iv32", "rc4", "null", "aes" 524}; 525 526static const char *ipcomp_p_map[] = { 527 NULL, "oui", "deflate", "lzs", 528}; 529 530const struct attrmap ipsec_t_map[] = { 531 { NULL, 0, { NULL } }, 532 { "lifetype", 3, { NULL, "sec", "kb", }, }, 533 { "life", 0, { NULL } }, 534 { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155", 535 "EC2N 2^185", }, }, 536 { "enc mode", 3, { NULL, "tunnel", "transport", }, }, 537 { "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, }, 538 { "keylen", 0, { NULL } }, 539 { "rounds", 0, { NULL } }, 540 { "dictsize", 0, { NULL } }, 541 { "privalg", 0, { NULL } }, 542}; 543 544const struct attrmap oakley_t_map[] = { 545 { NULL, 0, { NULL } }, 546 { "enc", 8, { NULL, "1des", "idea", "blowfish", "rc5", 547 "3des", "cast", "aes", }, }, 548 { "hash", 7, { NULL, "md5", "sha1", "tiger", 549 "sha2-256", "sha2-384", "sha2-512", }, }, 550 { "auth", 6, { NULL, "preshared", "dss", "rsa sig", "rsa enc", 551 "rsa enc revised", }, }, 552 { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155", 553 "EC2N 2^185", }, }, 554 { "group type", 4, { NULL, "MODP", "ECP", "EC2N", }, }, 555 { "group prime", 0, { NULL } }, 556 { "group gen1", 0, { NULL } }, 557 { "group gen2", 0, { NULL } }, 558 { "group curve A", 0, { NULL } }, 559 { "group curve B", 0, { NULL } }, 560 { "lifetype", 3, { NULL, "sec", "kb", }, }, 561 { "lifeduration", 0, { NULL } }, 562 { "prf", 0, { NULL } }, 563 { "keylen", 0, { NULL } }, 564 { "field", 0, { NULL } }, 565 { "order", 0, { NULL } }, 566}; 567 568static const u_char * 569isakmp_t_print(const struct isakmp_gen *ext, u_int item_len, 570 const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_, 571 u_int32_t proto, int depth _U_) 572{ 573 const struct isakmp_pl_t *p; 574 struct isakmp_pl_t t; 575 const u_char *cp; 576 const char *idstr; 577 const struct attrmap *map; 578 size_t nmap; 579 const u_char *ep2; 580 581 printf("%s:", NPSTR(ISAKMP_NPTYPE_T)); 582 583 p = (struct isakmp_pl_t *)ext; 584 TCHECK(*p); 585 safememcpy(&t, ext, sizeof(t)); 586 587 switch (proto) { 588 case 1: 589 idstr = STR_OR_ID(t.t_id, isakmp_p_map); 590 map = oakley_t_map; 591 nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]); 592 break; 593 case 2: 594 idstr = STR_OR_ID(t.t_id, ah_p_map); 595 map = ipsec_t_map; 596 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]); 597 break; 598 case 3: 599 idstr = STR_OR_ID(t.t_id, esp_p_map); 600 map = ipsec_t_map; 601 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]); 602 break; 603 case 4: 604 idstr = STR_OR_ID(t.t_id, ipcomp_p_map); 605 map = ipsec_t_map; 606 nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]); 607 break; 608 default: 609 idstr = NULL; 610 map = NULL; 611 nmap = 0; 612 break; 613 } 614 615 if (idstr) 616 printf(" #%d id=%s ", t.t_no, idstr); 617 else 618 printf(" #%d id=%d ", t.t_no, t.t_id); 619 cp = (u_char *)(p + 1); 620 ep2 = (u_char *)p + item_len; 621 while (cp < ep && cp < ep2) { 622 if (map && nmap) { 623 cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2, 624 map, nmap); 625 } else 626 cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2); 627 } 628 if (ep < ep2) 629 printf("..."); 630 return cp; 631trunc: 632 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_T)); 633 return NULL; 634} 635 636static const u_char * 637isakmp_ke_print(const struct isakmp_gen *ext, u_int item_len _U_, 638 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_, 639 u_int32_t proto _U_, int depth _U_) 640{ 641 struct isakmp_gen e; 642 643 printf("%s:", NPSTR(ISAKMP_NPTYPE_KE)); 644 645 TCHECK(*ext); 646 safememcpy(&e, ext, sizeof(e)); 647 printf(" key len=%d", ntohs(e.len) - 4); 648 if (2 < vflag && 4 < ntohs(e.len)) { 649 printf(" "); 650 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4)) 651 goto trunc; 652 } 653 return (u_char *)ext + ntohs(e.len); 654trunc: 655 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE)); 656 return NULL; 657} 658 659static const u_char * 660isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_, 661 const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_, 662 u_int32_t proto _U_, int depth _U_) 663{ 664#define USE_IPSECDOI_IN_PHASE1 1 665 const struct isakmp_pl_id *p; 666 struct isakmp_pl_id id; 667 static const char *idtypestr[] = { 668 "IPv4", "IPv4net", "IPv6", "IPv6net", 669 }; 670 static const char *ipsecidtypestr[] = { 671 NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6", 672 "IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN", 673 "keyid", 674 }; 675 int len; 676 const u_char *data; 677 678 printf("%s:", NPSTR(ISAKMP_NPTYPE_ID)); 679 680 p = (struct isakmp_pl_id *)ext; 681 TCHECK(*p); 682 safememcpy(&id, ext, sizeof(id)); 683 if (sizeof(*p) < item_len) { 684 data = (u_char *)(p + 1); 685 len = item_len - sizeof(*p); 686 } else { 687 data = NULL; 688 len = 0; 689 } 690 691#if 0 /*debug*/ 692 printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto); 693#endif 694 switch (phase) { 695#ifndef USE_IPSECDOI_IN_PHASE1 696 case 1: 697#endif 698 default: 699 printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr)); 700 printf(" doi_data=%u", 701 (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff)); 702 break; 703 704#ifdef USE_IPSECDOI_IN_PHASE1 705 case 1: 706#endif 707 case 2: 708 { 709 const struct ipsecdoi_id *p; 710 struct ipsecdoi_id id; 711 struct protoent *pe; 712 713 p = (struct ipsecdoi_id *)ext; 714 TCHECK(*p); 715 safememcpy(&id, ext, sizeof(id)); 716 printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr)); 717 if (id.proto_id) { 718#ifndef WIN32 719 setprotoent(1); 720#endif /* WIN32 */ 721 pe = getprotobynumber(id.proto_id); 722 if (pe) 723 printf(" protoid=%s", pe->p_name); 724#ifndef WIN32 725 endprotoent(); 726#endif /* WIN32 */ 727 } else { 728 /* it DOES NOT mean IPPROTO_IP! */ 729 printf(" protoid=%s", "0"); 730 } 731 printf(" port=%d", ntohs(id.port)); 732 if (!len) 733 break; 734 if (data == NULL) 735 goto trunc; 736 TCHECK2(*data, len); 737 switch (id.type) { 738 case IPSECDOI_ID_IPV4_ADDR: 739 if (len < 4) 740 printf(" len=%d [bad: < 4]", len); 741 else 742 printf(" len=%d %s", len, ipaddr_string(data)); 743 len = 0; 744 break; 745 case IPSECDOI_ID_FQDN: 746 case IPSECDOI_ID_USER_FQDN: 747 { 748 int i; 749 printf(" len=%d ", len); 750 for (i = 0; i < len; i++) 751 safeputchar(data[i]); 752 len = 0; 753 break; 754 } 755 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 756 { 757 const u_char *mask; 758 if (len < 8) 759 printf(" len=%d [bad: < 8]", len); 760 else { 761 mask = data + sizeof(struct in_addr); 762 printf(" len=%d %s/%u.%u.%u.%u", len, 763 ipaddr_string(data), 764 mask[0], mask[1], mask[2], mask[3]); 765 } 766 len = 0; 767 break; 768 } 769#ifdef INET6 770 case IPSECDOI_ID_IPV6_ADDR: 771 if (len < 16) 772 printf(" len=%d [bad: < 16]", len); 773 else 774 printf(" len=%d %s", len, ip6addr_string(data)); 775 len = 0; 776 break; 777 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 778 { 779 const u_int32_t *mask; 780 if (len < 20) 781 printf(" len=%d [bad: < 20]", len); 782 else { 783 mask = (u_int32_t *)(data + sizeof(struct in6_addr)); 784 /*XXX*/ 785 printf(" len=%d %s/0x%08x%08x%08x%08x", len, 786 ip6addr_string(data), 787 mask[0], mask[1], mask[2], mask[3]); 788 } 789 len = 0; 790 break; 791 } 792#endif /*INET6*/ 793 case IPSECDOI_ID_IPV4_ADDR_RANGE: 794 if (len < 8) 795 printf(" len=%d [bad: < 8]", len); 796 else { 797 printf(" len=%d %s-%s", len, 798 ipaddr_string(data), 799 ipaddr_string(data + sizeof(struct in_addr))); 800 } 801 len = 0; 802 break; 803#ifdef INET6 804 case IPSECDOI_ID_IPV6_ADDR_RANGE: 805 if (len < 32) 806 printf(" len=%d [bad: < 32]", len); 807 else { 808 printf(" len=%d %s-%s", len, 809 ip6addr_string(data), 810 ip6addr_string(data + sizeof(struct in6_addr))); 811 } 812 len = 0; 813 break; 814#endif /*INET6*/ 815 case IPSECDOI_ID_DER_ASN1_DN: 816 case IPSECDOI_ID_DER_ASN1_GN: 817 case IPSECDOI_ID_KEY_ID: 818 break; 819 } 820 break; 821 } 822 } 823 if (data && len) { 824 printf(" len=%d", len); 825 if (2 < vflag) { 826 printf(" "); 827 if (!rawprint((caddr_t)data, len)) 828 goto trunc; 829 } 830 } 831 return (u_char *)ext + item_len; 832trunc: 833 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID)); 834 return NULL; 835} 836 837static const u_char * 838isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_, 839 const u_char *ep _U_, u_int32_t phase _U_, 840 u_int32_t doi0 _U_, 841 u_int32_t proto0 _U_, int depth _U_) 842{ 843 const struct isakmp_pl_cert *p; 844 struct isakmp_pl_cert cert; 845 static const char *certstr[] = { 846 "none", "pkcs7", "pgp", "dns", 847 "x509sign", "x509ke", "kerberos", "crl", 848 "arl", "spki", "x509attr", 849 }; 850 851 printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT)); 852 853 p = (struct isakmp_pl_cert *)ext; 854 TCHECK(*p); 855 safememcpy(&cert, ext, sizeof(cert)); 856 printf(" len=%d", item_len - 4); 857 printf(" type=%s", STR_OR_ID((cert.encode), certstr)); 858 if (2 < vflag && 4 < item_len) { 859 printf(" "); 860 if (!rawprint((caddr_t)(ext + 1), item_len - 4)) 861 goto trunc; 862 } 863 return (u_char *)ext + item_len; 864trunc: 865 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT)); 866 return NULL; 867} 868 869static const u_char * 870isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_, 871 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_, 872 u_int32_t proto0 _U_, int depth _U_) 873{ 874 const struct isakmp_pl_cert *p; 875 struct isakmp_pl_cert cert; 876 static const char *certstr[] = { 877 "none", "pkcs7", "pgp", "dns", 878 "x509sign", "x509ke", "kerberos", "crl", 879 "arl", "spki", "x509attr", 880 }; 881 882 printf("%s:", NPSTR(ISAKMP_NPTYPE_CR)); 883 884 p = (struct isakmp_pl_cert *)ext; 885 TCHECK(*p); 886 safememcpy(&cert, ext, sizeof(cert)); 887 printf(" len=%d", item_len - 4); 888 printf(" type=%s", STR_OR_ID((cert.encode), certstr)); 889 if (2 < vflag && 4 < item_len) { 890 printf(" "); 891 if (!rawprint((caddr_t)(ext + 1), item_len - 4)) 892 goto trunc; 893 } 894 return (u_char *)ext + item_len; 895trunc: 896 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR)); 897 return NULL; 898} 899 900static const u_char * 901isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_, 902 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_, 903 u_int32_t proto _U_, int depth _U_) 904{ 905 struct isakmp_gen e; 906 907 printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH)); 908 909 TCHECK(*ext); 910 safememcpy(&e, ext, sizeof(e)); 911 printf(" len=%d", ntohs(e.len) - 4); 912 if (2 < vflag && 4 < ntohs(e.len)) { 913 printf(" "); 914 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4)) 915 goto trunc; 916 } 917 return (u_char *)ext + ntohs(e.len); 918trunc: 919 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH)); 920 return NULL; 921} 922 923static const u_char * 924isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_, 925 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_, 926 u_int32_t proto _U_, int depth _U_) 927{ 928 struct isakmp_gen e; 929 930 printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG)); 931 932 TCHECK(*ext); 933 safememcpy(&e, ext, sizeof(e)); 934 printf(" len=%d", ntohs(e.len) - 4); 935 if (2 < vflag && 4 < ntohs(e.len)) { 936 printf(" "); 937 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4)) 938 goto trunc; 939 } 940 return (u_char *)ext + ntohs(e.len); 941trunc: 942 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG)); 943 return NULL; 944} 945 946static const u_char * 947isakmp_nonce_print(const struct isakmp_gen *ext, 948 u_int item_len _U_, 949 const u_char *ep _U_, 950 u_int32_t phase _U_, u_int32_t doi _U_, 951 u_int32_t proto _U_, int depth _U_) 952{ 953 struct isakmp_gen e; 954 955 printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE)); 956 957 TCHECK(*ext); 958 safememcpy(&e, ext, sizeof(e)); 959 printf(" n len=%d", ntohs(e.len) - 4); 960 if (2 < vflag && 4 < ntohs(e.len)) { 961 printf(" "); 962 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4)) 963 goto trunc; 964 } 965 return (u_char *)ext + ntohs(e.len); 966trunc: 967 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE)); 968 return NULL; 969} 970 971static const u_char * 972isakmp_n_print(const struct isakmp_gen *ext, u_int item_len, 973 const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_, 974 u_int32_t proto0 _U_, int depth) 975{ 976 struct isakmp_pl_n *p, n; 977 const u_char *cp; 978 u_char *ep2; 979 u_int32_t doi; 980 u_int32_t proto; 981 static const char *notify_error_str[] = { 982 NULL, "INVALID-PAYLOAD-TYPE", 983 "DOI-NOT-SUPPORTED", "SITUATION-NOT-SUPPORTED", 984 "INVALID-COOKIE", "INVALID-MAJOR-VERSION", 985 "INVALID-MINOR-VERSION", "INVALID-EXCHANGE-TYPE", 986 "INVALID-FLAGS", "INVALID-MESSAGE-ID", 987 "INVALID-PROTOCOL-ID", "INVALID-SPI", 988 "INVALID-TRANSFORM-ID", "ATTRIBUTES-NOT-SUPPORTED", 989 "NO-PROPOSAL-CHOSEN", "BAD-PROPOSAL-SYNTAX", 990 "PAYLOAD-MALFORMED", "INVALID-KEY-INFORMATION", 991 "INVALID-ID-INFORMATION", "INVALID-CERT-ENCODING", 992 "INVALID-CERTIFICATE", "CERT-TYPE-UNSUPPORTED", 993 "INVALID-CERT-AUTHORITY", "INVALID-HASH-INFORMATION", 994 "AUTHENTICATION-FAILED", "INVALID-SIGNATURE", 995 "ADDRESS-NOTIFICATION", "NOTIFY-SA-LIFETIME", 996 "CERTIFICATE-UNAVAILABLE", "UNSUPPORTED-EXCHANGE-TYPE", 997 "UNEQUAL-PAYLOAD-LENGTHS", 998 }; 999 static const char *ipsec_notify_error_str[] = { 1000 "RESERVED", 1001 }; 1002 static const char *notify_status_str[] = { 1003 "CONNECTED", 1004 }; 1005 static const char *ipsec_notify_status_str[] = { 1006 "RESPONDER-LIFETIME", "REPLAY-STATUS", 1007 "INITIAL-CONTACT", 1008 }; 1009/* NOTE: these macro must be called with x in proper range */ 1010 1011/* 0 - 8191 */ 1012#define NOTIFY_ERROR_STR(x) \ 1013 STR_OR_ID((x), notify_error_str) 1014 1015/* 8192 - 16383 */ 1016#define IPSEC_NOTIFY_ERROR_STR(x) \ 1017 STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str) 1018 1019/* 16384 - 24575 */ 1020#define NOTIFY_STATUS_STR(x) \ 1021 STR_OR_ID((u_int)((x) - 16384), notify_status_str) 1022 1023/* 24576 - 32767 */ 1024#define IPSEC_NOTIFY_STATUS_STR(x) \ 1025 STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str) 1026 1027 printf("%s:", NPSTR(ISAKMP_NPTYPE_N)); 1028 1029 p = (struct isakmp_pl_n *)ext; 1030 TCHECK(*p); 1031 safememcpy(&n, ext, sizeof(n)); 1032 doi = ntohl(n.doi); 1033 proto = n.prot_id; 1034 if (doi != 1) { 1035 printf(" doi=%d", doi); 1036 printf(" proto=%d", proto); 1037 if (ntohs(n.type) < 8192) 1038 printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type))); 1039 else if (ntohs(n.type) < 16384) 1040 printf(" type=%s", numstr(ntohs(n.type))); 1041 else if (ntohs(n.type) < 24576) 1042 printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type))); 1043 else 1044 printf(" type=%s", numstr(ntohs(n.type))); 1045 if (n.spi_size) { 1046 printf(" spi="); 1047 if (!rawprint((caddr_t)(p + 1), n.spi_size)) 1048 goto trunc; 1049 } 1050 return (u_char *)(p + 1) + n.spi_size; 1051 } 1052 1053 printf(" doi=ipsec"); 1054 printf(" proto=%s", PROTOIDSTR(proto)); 1055 if (ntohs(n.type) < 8192) 1056 printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type))); 1057 else if (ntohs(n.type) < 16384) 1058 printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type))); 1059 else if (ntohs(n.type) < 24576) 1060 printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type))); 1061 else if (ntohs(n.type) < 32768) 1062 printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type))); 1063 else 1064 printf(" type=%s", numstr(ntohs(n.type))); 1065 if (n.spi_size) { 1066 printf(" spi="); 1067 if (!rawprint((caddr_t)(p + 1), n.spi_size)) 1068 goto trunc; 1069 } 1070 1071 cp = (u_char *)(p + 1) + n.spi_size; 1072 ep2 = (u_char *)p + item_len; 1073 1074 if (cp < ep) { 1075 printf(" orig=("); 1076 switch (ntohs(n.type)) { 1077 case IPSECDOI_NTYPE_RESPONDER_LIFETIME: 1078 { 1079 const struct attrmap *map = oakley_t_map; 1080 size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]); 1081 while (cp < ep && cp < ep2) { 1082 cp = isakmp_attrmap_print(cp, 1083 (ep < ep2) ? ep : ep2, map, nmap); 1084 } 1085 break; 1086 } 1087 case IPSECDOI_NTYPE_REPLAY_STATUS: 1088 printf("replay detection %sabled", 1089 (*(u_int32_t *)cp) ? "en" : "dis"); 1090 break; 1091 case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN: 1092 if (isakmp_sub_print(ISAKMP_NPTYPE_SA, 1093 (struct isakmp_gen *)cp, ep, phase, doi, proto, 1094 depth) == NULL) 1095 return NULL; 1096 break; 1097 default: 1098 /* NULL is dummy */ 1099 isakmp_print(gndo, cp, 1100 item_len - sizeof(*p) - n.spi_size, 1101 NULL); 1102 } 1103 printf(")"); 1104 } 1105 return (u_char *)ext + item_len; 1106trunc: 1107 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N)); 1108 return NULL; 1109} 1110 1111static const u_char * 1112isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_, 1113 const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_, 1114 u_int32_t proto0 _U_, int depth _U_) 1115{ 1116 const struct isakmp_pl_d *p; 1117 struct isakmp_pl_d d; 1118 const u_int8_t *q; 1119 u_int32_t doi; 1120 u_int32_t proto; 1121 int i; 1122 1123 printf("%s:", NPSTR(ISAKMP_NPTYPE_D)); 1124 1125 p = (struct isakmp_pl_d *)ext; 1126 TCHECK(*p); 1127 safememcpy(&d, ext, sizeof(d)); 1128 doi = ntohl(d.doi); 1129 proto = d.prot_id; 1130 if (doi != 1) { 1131 printf(" doi=%u", doi); 1132 printf(" proto=%u", proto); 1133 } else { 1134 printf(" doi=ipsec"); 1135 printf(" proto=%s", PROTOIDSTR(proto)); 1136 } 1137 printf(" spilen=%u", d.spi_size); 1138 printf(" nspi=%u", ntohs(d.num_spi)); 1139 printf(" spi="); 1140 q = (u_int8_t *)(p + 1); 1141 for (i = 0; i < ntohs(d.num_spi); i++) { 1142 if (i != 0) 1143 printf(","); 1144 if (!rawprint((caddr_t)q, d.spi_size)) 1145 goto trunc; 1146 q += d.spi_size; 1147 } 1148 return q; 1149trunc: 1150 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D)); 1151 return NULL; 1152} 1153 1154static const u_char * 1155isakmp_vid_print(const struct isakmp_gen *ext, 1156 u_int item_len _U_, const u_char *ep _U_, 1157 u_int32_t phase _U_, u_int32_t doi _U_, 1158 u_int32_t proto _U_, int depth _U_) 1159{ 1160 struct isakmp_gen e; 1161 1162 printf("%s:", NPSTR(ISAKMP_NPTYPE_VID)); 1163 1164 TCHECK(*ext); 1165 safememcpy(&e, ext, sizeof(e)); 1166 printf(" len=%d", ntohs(e.len) - 4); 1167 if (2 < vflag && 4 < ntohs(e.len)) { 1168 printf(" "); 1169 if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4)) 1170 goto trunc; 1171 } 1172 return (u_char *)ext + ntohs(e.len); 1173trunc: 1174 printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID)); 1175 return NULL; 1176} 1177 1178static const u_char * 1179isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep, 1180 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth) 1181{ 1182 const u_char *cp; 1183 struct isakmp_gen e; 1184 u_int item_len; 1185 1186 cp = (u_char *)ext; 1187 TCHECK(*ext); 1188 safememcpy(&e, ext, sizeof(e)); 1189 1190 /* 1191 * Since we can't have a payload length of less than 4 bytes, 1192 * we need to bail out here if the generic header is nonsensical 1193 * or truncated, otherwise we could loop forever processing 1194 * zero-length items or otherwise misdissect the packet. 1195 */ 1196 item_len = ntohs(e.len); 1197 if (item_len <= 4) 1198 return NULL; 1199 1200 if (NPFUNC(np)) { 1201 /* 1202 * XXX - what if item_len is too short, or too long, 1203 * for this payload type? 1204 */ 1205 cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth); 1206 } else { 1207 printf("%s", NPSTR(np)); 1208 cp += item_len; 1209 } 1210 1211 return cp; 1212trunc: 1213 printf(" [|isakmp]"); 1214 return NULL; 1215} 1216 1217static const u_char * 1218isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep, 1219 u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth) 1220{ 1221 const u_char *cp; 1222 int i; 1223 struct isakmp_gen e; 1224 1225 cp = (const u_char *)ext; 1226 1227 while (np) { 1228 TCHECK(*ext); 1229 1230 safememcpy(&e, ext, sizeof(e)); 1231 1232 TCHECK2(*ext, ntohs(e.len)); 1233 1234 depth++; 1235 printf("\n"); 1236 for (i = 0; i < depth; i++) 1237 printf(" "); 1238 printf("("); 1239 cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth); 1240 printf(")"); 1241 depth--; 1242 1243 if (cp == NULL) { 1244 /* Zero-length subitem */ 1245 return NULL; 1246 } 1247 1248 np = e.np; 1249 ext = (struct isakmp_gen *)cp; 1250 } 1251 return cp; 1252trunc: 1253 printf(" [|%s]", NPSTR(np)); 1254 return NULL; 1255} 1256 1257static char * 1258numstr(int x) 1259{ 1260 static char buf[20]; 1261 snprintf(buf, sizeof(buf), "#%d", x); 1262 return buf; 1263} 1264 1265/* 1266 * some compiler tries to optimize memcpy(), using the alignment constraint 1267 * on the argument pointer type. by using this function, we try to avoid the 1268 * optimization. 1269 */ 1270static void 1271safememcpy(void *p, const void *q, size_t l) 1272{ 1273 memcpy(p, q, l); 1274} 1275 1276void 1277isakmp_print(netdissect_options *ndo, 1278 const u_char *bp, u_int length, 1279 const u_char *bp2) 1280{ 1281 const struct isakmp *p; 1282 struct isakmp base; 1283 const u_char *ep; 1284 u_char np; 1285 int i; 1286 int phase; 1287 int major, minor; 1288 1289 p = (const struct isakmp *)bp; 1290 ep = ndo->ndo_snapend; 1291 1292 if ((struct isakmp *)ep < p + 1) { 1293 printf("[|isakmp]"); 1294 return; 1295 } 1296 1297 safememcpy(&base, p, sizeof(base)); 1298 1299 printf("isakmp"); 1300 if (vflag) { 1301 major = (base.vers & ISAKMP_VERS_MAJOR) 1302 >> ISAKMP_VERS_MAJOR_SHIFT; 1303 minor = (base.vers & ISAKMP_VERS_MINOR) 1304 >> ISAKMP_VERS_MINOR_SHIFT; 1305 printf(" %d.%d", major, minor); 1306 } 1307 1308 if (vflag) { 1309 printf(" msgid "); 1310 rawprint((caddr_t)&base.msgid, sizeof(base.msgid)); 1311 } 1312 1313 if (1 < vflag) { 1314 printf(" cookie "); 1315 rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck)); 1316 printf("->"); 1317 rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck)); 1318 } 1319 printf(":"); 1320 1321 phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2; 1322 if (phase == 1) 1323 printf(" phase %d", phase); 1324 else 1325 printf(" phase %d/others", phase); 1326 1327 i = cookie_find(&base.i_ck); 1328 if (i < 0) { 1329 if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) { 1330 /* the first packet */ 1331 printf(" I"); 1332 if (bp2) 1333 cookie_record(&base.i_ck, bp2); 1334 } else 1335 printf(" ?"); 1336 } else { 1337 if (bp2 && cookie_isinitiator(i, bp2)) 1338 printf(" I"); 1339 else if (bp2 && cookie_isresponder(i, bp2)) 1340 printf(" R"); 1341 else 1342 printf(" ?"); 1343 } 1344 1345 printf(" %s", ETYPESTR(base.etype)); 1346 if (base.flags) { 1347 printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "", 1348 base.flags & ISAKMP_FLAG_C ? "C" : ""); 1349 } 1350 1351 if (vflag) { 1352 const struct isakmp_gen *ext; 1353 int nparen; 1354 1355#define CHECKLEN(p, np) \ 1356 if (ep < (u_char *)(p)) { \ 1357 printf(" [|%s]", NPSTR(np)); \ 1358 goto done; \ 1359 } 1360 1361 printf(":"); 1362 1363 /* regardless of phase... */ 1364 if (base.flags & ISAKMP_FLAG_E) { 1365 /* 1366 * encrypted, nothing we can do right now. 1367 * we hope to decrypt the packet in the future... 1368 */ 1369 printf(" [encrypted %s]", NPSTR(base.np)); 1370 goto done; 1371 } 1372 1373 nparen = 0; 1374 CHECKLEN(p + 1, base.np) 1375 1376 np = base.np; 1377 ext = (struct isakmp_gen *)(p + 1); 1378 isakmp_sub_print(np, ext, ep, phase, 0, 0, 0); 1379 } 1380 1381done: 1382 if (vflag) { 1383 if (ntohl(base.len) != length) { 1384 printf(" (len mismatch: isakmp %u/ip %u)", 1385 (u_int32_t)ntohl(base.len), length); 1386 } 1387 } 1388} 1389 1390void 1391isakmp_rfc3948_print(netdissect_options *ndo, 1392 const u_char *bp, u_int length, 1393 const u_char *bp2) 1394{ 1395 const u_char *ep; 1396 ep = ndo->ndo_snapend; 1397 1398 if(length == 1 && bp[0]==0xff) { 1399 ND_PRINT((ndo, "isakmp-nat-keep-alive")); 1400 return; 1401 } 1402 1403 if(length < 4) { 1404 goto trunc; 1405 } 1406 1407 /* 1408 * see if this is an IKE packet 1409 */ 1410 if(bp[0]==0 && bp[1]==0 && bp[2]==0 && bp[3]==0) { 1411 ND_PRINT((ndo, "NONESP-encap: ")); 1412 isakmp_print(ndo, bp+4, length-4, bp2); 1413 return; 1414 } 1415 1416 /* must be an ESP packet */ 1417 { 1418 int nh, enh, padlen; 1419 int advance; 1420 1421 ND_PRINT((ndo, "UDP-encap: ")); 1422 1423 advance = esp_print(ndo, bp, length, bp2, &enh, &padlen); 1424 if(advance <= 0) 1425 return; 1426 1427 bp += advance; 1428 length -= advance + padlen; 1429 nh = enh & 0xff; 1430 1431 ip_print_inner(ndo, bp, length, nh, bp2); 1432 return; 1433 } 1434 1435trunc: 1436 printf("[|isakmp]"); 1437 return; 1438} 1439 1440/* 1441 * Local Variables: 1442 * c-style: whitesmith 1443 * c-basic-offset: 8 1444 * End: 1445 */ 1446 1447 1448 1449 1450