1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/stream.h> 30 #include <sys/sunddi.h> 31 #include <sys/ddi.h> 32 #include <sys/strlog.h> 33 34 #include <inet/common.h> 35 #include <inet/mib2.h> 36 #include <inet/ip.h> 37 #include <inet/ip6.h> 38 #include <inet/ipdrop.h> 39 40 #include <net/pfkeyv2.h> 41 #include <inet/ipsec_info.h> 42 #include <inet/sadb.h> 43 #include <inet/ipsec_impl.h> 44 #include <inet/ipsecesp.h> 45 #include <inet/ipsecah.h> 46 #include <sys/kstat.h> 47 48 /* stats */ 49 static kstat_t *ipsec_ksp; 50 ipsec_kstats_t *ipsec_kstats; 51 52 /* The IPsec SADBs for AH and ESP */ 53 sadbp_t ah_sadb, esp_sadb; 54 55 /* Packet dropper for IP IPsec processing failures */ 56 extern ipdropper_t ip_dropper; 57 58 void 59 ipsec_kstat_init(void) 60 { 61 ipsec_ksp = kstat_create("ip", 0, "ipsec_stat", "net", 62 KSTAT_TYPE_NAMED, sizeof (*ipsec_kstats) / sizeof (kstat_named_t), 63 KSTAT_FLAG_PERSISTENT); 64 65 ASSERT(ipsec_ksp != NULL); 66 67 ipsec_kstats = ipsec_ksp->ks_data; 68 69 #define KI(x) kstat_named_init(&ipsec_kstats->x, #x, KSTAT_DATA_UINT64) 70 KI(esp_stat_in_requests); 71 KI(esp_stat_in_discards); 72 KI(esp_stat_lookup_failure); 73 KI(ah_stat_in_requests); 74 KI(ah_stat_in_discards); 75 KI(ah_stat_lookup_failure); 76 KI(sadb_acquire_maxpackets); 77 KI(sadb_acquire_qhiwater); 78 #undef KI 79 80 kstat_install(ipsec_ksp); 81 } 82 83 void 84 ipsec_kstat_destroy(void) 85 { 86 kstat_delete(ipsec_ksp); 87 } 88 89 /* 90 * Returns B_TRUE if the identities in the SA match the identities 91 * in the "latch" structure. 92 */ 93 94 static boolean_t 95 ipsec_match_outbound_ids(ipsec_latch_t *ipl, ipsa_t *sa) 96 { 97 ASSERT(ipl->ipl_ids_latched == B_TRUE); 98 return ipsid_equal(ipl->ipl_local_cid, sa->ipsa_src_cid) && 99 ipsid_equal(ipl->ipl_remote_cid, sa->ipsa_dst_cid); 100 } 101 102 /* 103 * Look up a security association based on the unique ID generated by IP and 104 * transport or tunnel information, such as ports and upper-layer protocol, 105 * and the inner and outer address(es). Used for uniqueness testing and 106 * outbound packets. The outer source address may be ignored. 107 * 108 * I expect an SA hash bucket, and that its per-bucket mutex is held. 109 * The SA ptr I return will have its reference count incremented by one. 110 */ 111 ipsa_t * 112 ipsec_getassocbyconn(isaf_t *bucket, ipsec_out_t *io, uint32_t *src, 113 uint32_t *dst, sa_family_t af, uint8_t protocol) 114 { 115 ipsa_t *retval, *candidate; 116 ipsec_action_t *candact; 117 boolean_t need_unique; 118 boolean_t tunnel_mode = io->ipsec_out_tunnel; 119 uint64_t unique_id; 120 uint32_t old_flags, excludeflags; 121 ipsec_policy_t *pp = io->ipsec_out_policy; 122 ipsec_action_t *actlist = io->ipsec_out_act; 123 ipsec_action_t *act; 124 ipsec_latch_t *ipl = io->ipsec_out_latch; 125 ipsa_ref_t *ipr = NULL; 126 sa_family_t inaf = io->ipsec_out_inaf; 127 uint32_t *insrc = io->ipsec_out_insrc; 128 uint32_t *indst = io->ipsec_out_indst; 129 uint8_t insrcpfx = io->ipsec_out_insrcpfx; 130 uint8_t indstpfx = io->ipsec_out_indstpfx; 131 132 ASSERT(MUTEX_HELD(&bucket->isaf_lock)); 133 134 /* 135 * Caller must set ipsec_out_t structure such that we know 136 * whether this is tunnel mode or transport mode based on 137 * io->ipsec_out_tunnel. If this flag is set, we assume that 138 * there are valid inner src and destination addresses to compare. 139 */ 140 141 /* 142 * Fast path: do we have a latch structure, is it for this bucket, 143 * and does the generation number match? If so, refhold and return. 144 */ 145 146 if (ipl != NULL) { 147 ASSERT((protocol == IPPROTO_AH) || (protocol == IPPROTO_ESP)); 148 ipr = &ipl->ipl_ref[protocol - IPPROTO_ESP]; 149 150 retval = ipr->ipsr_sa; 151 152 /* 153 * NOTE: The isaf_gen check (incremented upon 154 * sadb_unlinkassoc()) protects against retval being a freed 155 * SA. (We're exploiting short-circuit evaluation.) 156 */ 157 if ((bucket == ipr->ipsr_bucket) && 158 (bucket->isaf_gen == ipr->ipsr_gen) && 159 (retval->ipsa_state != IPSA_STATE_DEAD) && 160 !(retval->ipsa_flags & IPSA_F_CINVALID)) { 161 IPSA_REFHOLD(retval); 162 return (retval); 163 } 164 } 165 166 ASSERT((pp != NULL) || (actlist != NULL)); 167 if (actlist == NULL) 168 actlist = pp->ipsp_act; 169 ASSERT(actlist != NULL); 170 171 need_unique = actlist->ipa_want_unique; 172 unique_id = SA_FORM_UNIQUE_ID(io); 173 174 /* 175 * Precompute mask for SA flags comparison: If we need a 176 * unique SA and an SA has already been used, or if the SA has 177 * a unique value which doesn't match, we aren't interested in 178 * the SA.. 179 */ 180 181 excludeflags = IPSA_F_UNIQUE; 182 if (need_unique) 183 excludeflags |= IPSA_F_USED; 184 185 /* 186 * Walk the hash bucket, matching on: 187 * 188 * - unique_id 189 * - destination 190 * - source 191 * - algorithms 192 * - inner dst 193 * - inner src 194 * - <MORE TBD> 195 * 196 * Make sure that wildcard sources are inserted at the end of the hash 197 * bucket. 198 * 199 * DEFINITIONS: A _shared_ SA is one with unique_id == 0 and USED. 200 * An _unused_ SA is one with unique_id == 0 and not USED. 201 * A _unique_ SA is one with unique_id != 0 and USED. 202 * An SA with unique_id != 0 and not USED never happens. 203 */ 204 205 candidate = NULL; 206 207 for (retval = bucket->isaf_ipsa; retval != NULL; 208 retval = retval->ipsa_next) { 209 ASSERT((candidate == NULL) || 210 MUTEX_HELD(&candidate->ipsa_lock)); 211 212 /* 213 * Q: Should I lock this SA? 214 * A: For now, yes. I change and use too many fields in here 215 * (e.g. unique_id) that I may be racing with other threads. 216 * Also, the refcnt needs to be bumped up. 217 */ 218 219 mutex_enter(&retval->ipsa_lock); 220 221 /* My apologies for the use of goto instead of continue. */ 222 223 /* Outer destination address */ 224 if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af)) 225 goto next_ipsa; /* Destination mismatch. */ 226 227 /* Outer source address */ 228 if (!IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) && 229 !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) 230 goto next_ipsa; /* Specific source and not matched. */ 231 232 if (tunnel_mode) { 233 /* Check tunnel mode */ 234 if (!(retval->ipsa_flags & IPSA_F_TUNNEL)) 235 goto next_ipsa; /* Not tunnel mode SA */ 236 237 /* Inner destination address */ 238 if (!IPSA_IS_ADDR_UNSPEC(retval->ipsa_innerdst, inaf)) { 239 if (!ip_addr_match((uint8_t *)indst, 240 min(indstpfx, retval->ipsa_innerdstpfx), 241 (in6_addr_t *)retval->ipsa_innerdst)) 242 goto next_ipsa; /* not matched. */ 243 } 244 245 /* Inner source address */ 246 if (!IPSA_IS_ADDR_UNSPEC(retval->ipsa_innersrc, inaf)) { 247 if (!ip_addr_match((uint8_t *)insrc, 248 min(insrcpfx, retval->ipsa_innersrcpfx), 249 (in6_addr_t *)retval->ipsa_innersrc)) 250 goto next_ipsa; /* not matched. */ 251 } 252 } else { 253 /* Check transport mode */ 254 if (retval->ipsa_flags & IPSA_F_TUNNEL) 255 goto next_ipsa; /* Not transport mode SA */ 256 257 /* 258 * TODO - If we ever do RFC 3884's dream of transport- 259 * mode SAs with inner IP address selectors, we need 260 * to put some code here. 261 */ 262 } 263 264 /* 265 * XXX should be able to use cached/latched action 266 * to dodge this loop 267 */ 268 for (act = actlist; act != NULL; act = act->ipa_next) { 269 ipsec_act_t *ap = &act->ipa_act; 270 if (ap->ipa_type != IPSEC_POLICY_APPLY) 271 continue; 272 273 /* 274 * XXX ugly. should be better way to do this test 275 */ 276 if (protocol == IPPROTO_AH) { 277 if (!(ap->ipa_apply.ipp_use_ah)) 278 continue; 279 if (ap->ipa_apply.ipp_auth_alg != 280 retval->ipsa_auth_alg) 281 continue; 282 if (ap->ipa_apply.ipp_ah_minbits > 283 retval->ipsa_authkeybits) 284 continue; 285 } else { 286 if (!(ap->ipa_apply.ipp_use_esp)) 287 continue; 288 289 if ((ap->ipa_apply.ipp_encr_alg != 290 retval->ipsa_encr_alg)) 291 continue; 292 293 if (ap->ipa_apply.ipp_espe_minbits > 294 retval->ipsa_encrkeybits) 295 continue; 296 297 if (ap->ipa_apply.ipp_esp_auth_alg != 0) { 298 if (ap->ipa_apply.ipp_esp_auth_alg != 299 retval->ipsa_auth_alg) 300 continue; 301 if (ap->ipa_apply.ipp_espa_minbits > 302 retval->ipsa_authkeybits) 303 continue; 304 } 305 } 306 307 /* 308 * Check key mgmt proto, cookie 309 */ 310 if ((ap->ipa_apply.ipp_km_proto != 0) && 311 (retval->ipsa_kmp != 0) && 312 (ap->ipa_apply.ipp_km_proto != retval->ipsa_kmp)) 313 continue; 314 315 if ((ap->ipa_apply.ipp_km_cookie != 0) && 316 (retval->ipsa_kmc != 0) && 317 (ap->ipa_apply.ipp_km_cookie != retval->ipsa_kmc)) 318 continue; 319 320 break; 321 } 322 if (act == NULL) 323 goto next_ipsa; /* nothing matched */ 324 325 /* 326 * Do identities match? 327 */ 328 if (ipl && ipl->ipl_ids_latched && 329 !ipsec_match_outbound_ids(ipl, retval)) 330 goto next_ipsa; 331 332 /* 333 * At this point, we know that we have at least a match on: 334 * 335 * - dest 336 * - source (if source is specified, i.e. non-zeroes) 337 * - inner dest (if specified) 338 * - inner source (if specified) 339 * - auth alg (if auth alg is specified, i.e. non-zero) 340 * - encrypt. alg (if encrypt. alg is specified, i.e. non-zero) 341 * and we know that the SA keylengths are appropriate. 342 * 343 * (Keep in mind known-src SAs are hit before zero-src SAs, 344 * thanks to sadb_insertassoc().) 345 * If we need a unique asssociation, optimally we have 346 * ipsa_unique_id == unique_id, otherwise NOT USED 347 * is held in reserve (stored in candidate). 348 * 349 * For those stored in candidate, take best-match (i.e. given 350 * a choice, candidate should have non-zero ipsa_src). 351 */ 352 353 /* 354 * If SA has a unique value which matches, we're all set... 355 * "key management knows best" 356 */ 357 if ((retval->ipsa_flags & IPSA_F_UNIQUE) && 358 ((unique_id & retval->ipsa_unique_mask) == 359 retval->ipsa_unique_id)) 360 break; 361 362 /* 363 * If we need a unique SA and this SA has already been used, 364 * or if the SA has a unique value which doesn't match, 365 * this isn't for us. 366 */ 367 368 if (retval->ipsa_flags & excludeflags) 369 goto next_ipsa; 370 371 372 /* 373 * I found a candidate.. 374 */ 375 if (candidate == NULL) { 376 /* 377 * and didn't already have one.. 378 */ 379 candidate = retval; 380 candact = act; 381 continue; 382 } else { 383 /* 384 * If candidate's source address is zero and 385 * the current match (i.e. retval) address is 386 * not zero, we have a better candidate.. 387 */ 388 if (IPSA_IS_ADDR_UNSPEC(candidate->ipsa_srcaddr, af) && 389 !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) { 390 mutex_exit(&candidate->ipsa_lock); 391 candidate = retval; 392 candact = act; 393 continue; 394 } 395 } 396 next_ipsa: 397 mutex_exit(&retval->ipsa_lock); 398 } 399 ASSERT((retval == NULL) || MUTEX_HELD(&retval->ipsa_lock)); 400 ASSERT((candidate == NULL) || MUTEX_HELD(&candidate->ipsa_lock)); 401 ASSERT((retval == NULL) || (act != NULL)); 402 ASSERT((candidate == NULL) || (candact != NULL)); 403 404 /* Let caller react to a lookup failure when it gets NULL. */ 405 if (retval == NULL && candidate == NULL) 406 return (NULL); 407 408 if (retval == NULL) { 409 ASSERT(MUTEX_HELD(&candidate->ipsa_lock)); 410 retval = candidate; 411 act = candact; 412 } else if (candidate != NULL) { 413 mutex_exit(&candidate->ipsa_lock); 414 } 415 ASSERT(MUTEX_HELD(&retval->ipsa_lock)); 416 ASSERT(act != NULL); 417 418 /* 419 * Even though I hold the mutex, since the reference counter is an 420 * atomic operation, I really have to use the IPSA_REFHOLD macro. 421 */ 422 IPSA_REFHOLD(retval); 423 424 /* 425 * This association is no longer unused. 426 */ 427 old_flags = retval->ipsa_flags; 428 retval->ipsa_flags |= IPSA_F_USED; 429 430 /* 431 * Cache a reference to this SA for the fast path. 432 */ 433 if (ipr != NULL) { 434 ipr->ipsr_bucket = bucket; 435 ipr->ipsr_gen = bucket->isaf_gen; 436 ipr->ipsr_sa = retval; 437 /* I'm now caching, so the cache-invalid flag goes away! */ 438 retval->ipsa_flags &= ~IPSA_F_CINVALID; 439 } 440 /* 441 * Latch various things while we're here.. 442 */ 443 if (ipl != NULL) { 444 if (!ipl->ipl_ids_latched) { 445 ipsec_latch_ids(ipl, 446 retval->ipsa_src_cid, retval->ipsa_dst_cid); 447 } 448 if (!ipl->ipl_out_action_latched) { 449 IPACT_REFHOLD(act); 450 ipl->ipl_out_action = act; 451 ipl->ipl_out_action_latched = B_TRUE; 452 } 453 } 454 455 /* 456 * Set the uniqueness only first time. 457 */ 458 if (need_unique && !(old_flags & IPSA_F_USED)) { 459 if (retval->ipsa_unique_id == 0) { 460 ASSERT((retval->ipsa_flags & IPSA_F_UNIQUE) == 0); 461 /* 462 * From now on, only this src, dst[ports, addr], 463 * proto, should use it. 464 */ 465 retval->ipsa_flags |= IPSA_F_UNIQUE; 466 retval->ipsa_unique_id = unique_id; 467 retval->ipsa_unique_mask = SA_UNIQUE_MASK( 468 io->ipsec_out_src_port, io->ipsec_out_dst_port, 469 protocol, 0); 470 } 471 472 /* 473 * Set the source address and adjust the hash 474 * buckets only if src_addr is zero. 475 */ 476 if (IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) { 477 /* 478 * sadb_unlinkassoc() will decrement the refcnt. Bump 479 * up when we have the lock so that we don't have to 480 * acquire locks when we come back from 481 * sadb_insertassoc(). 482 * 483 * We don't need to bump the bucket's gen since 484 * we aren't moving to a new bucket. 485 */ 486 IPSA_REFHOLD(retval); 487 IPSA_COPY_ADDR(retval->ipsa_srcaddr, src, af); 488 mutex_exit(&retval->ipsa_lock); 489 sadb_unlinkassoc(retval); 490 /* 491 * Since the bucket lock is held, we know 492 * sadb_insertassoc() will succeed. 493 */ 494 #ifdef DEBUG 495 if (sadb_insertassoc(retval, bucket) != 0) { 496 cmn_err(CE_PANIC, 497 "sadb_insertassoc() failed in " 498 "ipsec_getassocbyconn().\n"); 499 } 500 #else /* non-DEBUG */ 501 (void) sadb_insertassoc(retval, bucket); 502 #endif /* DEBUG */ 503 return (retval); 504 } 505 } 506 mutex_exit(&retval->ipsa_lock); 507 508 return (retval); 509 } 510 511 /* 512 * Look up a security association based on the security parameters index (SPI) 513 * and address(es). This is used for inbound packets and general SA lookups 514 * (even in outbound SA tables). The source address may be ignored. Return 515 * NULL if no association is available. If an SA is found, return it, with 516 * its refcnt incremented. The caller must REFRELE after using the SA. 517 * The hash bucket must be locked down before calling. 518 */ 519 ipsa_t * 520 ipsec_getassocbyspi(isaf_t *bucket, uint32_t spi, uint32_t *src, uint32_t *dst, 521 sa_family_t af) 522 { 523 ipsa_t *retval; 524 525 ASSERT(MUTEX_HELD(&bucket->isaf_lock)); 526 527 /* 528 * Walk the hash bucket, matching exactly on SPI, then destination, 529 * then source. 530 * 531 * Per-SA locking doesn't need to happen, because I'm only matching 532 * on addresses. Addresses are only changed during insertion/deletion 533 * from the hash bucket. Since the hash bucket lock is held, we don't 534 * need to worry about addresses changing. 535 */ 536 537 for (retval = bucket->isaf_ipsa; retval != NULL; 538 retval = retval->ipsa_next) { 539 if (retval->ipsa_spi != spi) 540 continue; 541 if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af)) 542 continue; 543 544 /* 545 * Assume that wildcard source addresses are inserted at the 546 * end of the hash bucket. (See sadb_insertassoc().) 547 * The following check for source addresses is a weak form 548 * of access control/source identity verification. If an 549 * SA has a source address, I only match an all-zeroes 550 * source address, or that particular one. If the SA has 551 * an all-zeroes source, then I match regardless. 552 * 553 * There is a weakness here in that a packet with all-zeroes 554 * for an address will match regardless of the source address 555 * stored in the packet. 556 * 557 * Note that port-level packet selectors, if present, 558 * are checked in ipsec_check_ipsecin_unique(). 559 */ 560 if (IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) || 561 IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af) || 562 IPSA_IS_ADDR_UNSPEC(src, af)) 563 break; 564 } 565 566 if (retval != NULL) { 567 /* 568 * Just refhold the return value. The caller will then 569 * make the appropriate calls to set the USED flag. 570 */ 571 IPSA_REFHOLD(retval); 572 } 573 574 return (retval); 575 } 576 577 boolean_t 578 ipsec_outbound_sa(mblk_t *mp, uint_t proto) 579 { 580 mblk_t *data_mp; 581 ipsec_out_t *io; 582 ipaddr_t dst; 583 uint32_t *dst_ptr, *src_ptr; 584 isaf_t *bucket; 585 ipsa_t *assoc; 586 ip6_pkt_t ipp; 587 in6_addr_t dst6; 588 ipsa_t **sa; 589 sadbp_t *sadbp; 590 sadb_t *sp; 591 sa_family_t af; 592 593 data_mp = mp->b_cont; 594 io = (ipsec_out_t *)mp->b_rptr; 595 596 if (proto == IPPROTO_ESP) { 597 sa = &io->ipsec_out_esp_sa; 598 sadbp = &esp_sadb; 599 } else { 600 ASSERT(proto == IPPROTO_AH); 601 sa = &io->ipsec_out_ah_sa; 602 sadbp = &ah_sadb; 603 } 604 605 ASSERT(*sa == NULL); 606 607 if (io->ipsec_out_v4) { 608 ipha_t *ipha = (ipha_t *)data_mp->b_rptr; 609 610 ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION); 611 dst = ip_get_dst(ipha); 612 sp = &sadbp->s_v4; 613 af = AF_INET; 614 615 /* 616 * NOTE:Getting the outbound association is considerably 617 * painful. ipsec_getassocbyconn() will require more 618 * parameters as policy implementations mature. 619 */ 620 bucket = OUTBOUND_BUCKET_V4(sp, dst); 621 src_ptr = (uint32_t *)&ipha->ipha_src; 622 dst_ptr = (uint32_t *)&dst; 623 } else { 624 ip6_t *ip6h = (ip6_t *)data_mp->b_rptr; 625 626 ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION); 627 dst6 = ip_get_dst_v6(ip6h, NULL); 628 af = AF_INET6; 629 630 bzero(&ipp, sizeof (ipp)); 631 sp = &sadbp->s_v6; 632 633 /* Same NOTE: applies here! */ 634 bucket = OUTBOUND_BUCKET_V6(sp, dst6); 635 src_ptr = (uint32_t *)&ip6h->ip6_src; 636 dst_ptr = (uint32_t *)&dst6; 637 } 638 639 mutex_enter(&bucket->isaf_lock); 640 assoc = ipsec_getassocbyconn(bucket, io, src_ptr, dst_ptr, af, proto); 641 mutex_exit(&bucket->isaf_lock); 642 643 if (assoc == NULL) 644 return (B_FALSE); 645 646 if (assoc->ipsa_state == IPSA_STATE_DEAD) { 647 IPSA_REFRELE(assoc); 648 return (B_FALSE); 649 } 650 651 ASSERT(assoc->ipsa_state != IPSA_STATE_LARVAL); 652 653 *sa = assoc; 654 return (B_TRUE); 655 } 656 657 /* 658 * Inbound IPsec SA selection. 659 */ 660 661 ah_t * 662 ipsec_inbound_ah_sa(mblk_t *mp) 663 { 664 mblk_t *ipsec_in; 665 ipha_t *ipha; 666 ipsa_t *assoc; 667 ah_t *ah; 668 isaf_t *hptr; 669 ipsec_in_t *ii; 670 boolean_t isv6; 671 ip6_t *ip6h; 672 int ah_offset; 673 uint32_t *src_ptr, *dst_ptr; 674 int pullup_len; 675 sadb_t *sp; 676 sa_family_t af; 677 678 IP_AH_BUMP_STAT(in_requests); 679 680 ASSERT(mp->b_datap->db_type == M_CTL); 681 682 ipsec_in = mp; 683 ii = (ipsec_in_t *)ipsec_in->b_rptr; 684 mp = mp->b_cont; 685 686 ASSERT(mp->b_datap->db_type == M_DATA); 687 688 isv6 = !ii->ipsec_in_v4; 689 if (isv6) { 690 ip6h = (ip6_t *)mp->b_rptr; 691 ah_offset = ipsec_ah_get_hdr_size_v6(mp, B_TRUE); 692 } else { 693 ipha = (ipha_t *)mp->b_rptr; 694 ASSERT(ipha->ipha_protocol == IPPROTO_AH); 695 ah_offset = ipha->ipha_version_and_hdr_length - 696 (uint8_t)((IP_VERSION << 4)); 697 ah_offset <<= 2; 698 } 699 700 /* 701 * We assume that the IP header is pulled up until 702 * the options. We need to see whether we have the 703 * AH header in the same mblk or not. 704 */ 705 pullup_len = ah_offset + sizeof (ah_t); 706 if (mp->b_rptr + pullup_len > mp->b_wptr) { 707 if (!pullupmsg(mp, pullup_len)) { 708 ipsec_rl_strlog(ip_mod_info.mi_idnum, 0, 0, 709 SL_WARN | SL_ERROR, 710 "ipsec_inbound_ah_sa: Small AH header\n"); 711 IP_AH_BUMP_STAT(in_discards); 712 ip_drop_packet(ipsec_in, B_TRUE, NULL, NULL, 713 &ipdrops_ah_bad_length, &ip_dropper); 714 return (NULL); 715 } 716 if (isv6) 717 ip6h = (ip6_t *)mp->b_rptr; 718 else 719 ipha = (ipha_t *)mp->b_rptr; 720 } 721 722 ah = (ah_t *)(mp->b_rptr + ah_offset); 723 724 if (isv6) { 725 src_ptr = (uint32_t *)&ip6h->ip6_src; 726 dst_ptr = (uint32_t *)&ip6h->ip6_dst; 727 sp = &ah_sadb.s_v6; 728 af = AF_INET6; 729 } else { 730 src_ptr = (uint32_t *)&ipha->ipha_src; 731 dst_ptr = (uint32_t *)&ipha->ipha_dst; 732 sp = &ah_sadb.s_v4; 733 af = AF_INET; 734 } 735 736 hptr = INBOUND_BUCKET(sp, ah->ah_spi); 737 mutex_enter(&hptr->isaf_lock); 738 assoc = ipsec_getassocbyspi(hptr, ah->ah_spi, src_ptr, dst_ptr, af); 739 mutex_exit(&hptr->isaf_lock); 740 741 if (assoc == NULL || assoc->ipsa_state == IPSA_STATE_DEAD) { 742 IP_AH_BUMP_STAT(lookup_failure); 743 IP_AH_BUMP_STAT(in_discards); 744 ipsecah_in_assocfailure(ipsec_in, 0, 745 SL_ERROR | SL_CONSOLE | SL_WARN, 746 "ipsec_inbound_ah_sa: No association found for " 747 "spi 0x%x, dst addr %s\n", 748 ah->ah_spi, dst_ptr, af); 749 if (assoc != NULL) { 750 IPSA_REFRELE(assoc); 751 } 752 return (NULL); 753 } 754 755 if (assoc->ipsa_state == IPSA_STATE_LARVAL) { 756 /* Not fully baked; swap the packet under a rock until then */ 757 sadb_set_lpkt(assoc, ipsec_in); 758 IPSA_REFRELE(assoc); 759 return (NULL); 760 } 761 762 /* 763 * Save a reference to the association so that it can 764 * be retrieved after execution. We free any AH SA reference 765 * already there (innermost SA "wins". The reference to 766 * the SA will also be used later when doing the policy checks. 767 */ 768 if (ii->ipsec_in_ah_sa != NULL) { 769 IPSA_REFRELE(ii->ipsec_in_ah_sa); 770 } 771 ii->ipsec_in_ah_sa = assoc; 772 773 return (ah); 774 } 775 776 esph_t * 777 ipsec_inbound_esp_sa(mblk_t *ipsec_in_mp) 778 { 779 mblk_t *data_mp, *placeholder; 780 uint32_t *src_ptr, *dst_ptr; 781 ipsec_in_t *ii; 782 ipha_t *ipha; 783 ip6_t *ip6h; 784 esph_t *esph; 785 ipsa_t *ipsa; 786 isaf_t *bucket; 787 uint_t preamble; 788 sa_family_t af; 789 boolean_t isv6; 790 sadb_t *sp; 791 792 IP_ESP_BUMP_STAT(in_requests); 793 ASSERT(ipsec_in_mp->b_datap->db_type == M_CTL); 794 795 /* We have IPSEC_IN already! */ 796 ii = (ipsec_in_t *)ipsec_in_mp->b_rptr; 797 data_mp = ipsec_in_mp->b_cont; 798 799 ASSERT(ii->ipsec_in_type == IPSEC_IN); 800 801 isv6 = !ii->ipsec_in_v4; 802 if (isv6) { 803 ip6h = (ip6_t *)data_mp->b_rptr; 804 } else { 805 ipha = (ipha_t *)data_mp->b_rptr; 806 } 807 808 /* 809 * Put all data into one mblk if it's not there already. 810 * XXX This is probably bad long-term. Figure out better ways of doing 811 * this. Much of the inbound path depends on all of the data being 812 * in one mblk. 813 * 814 * XXX Jumbogram issues will have to be dealt with here. 815 * If the plen is 0, we'll have to scan for a HBH header with the 816 * actual packet length. 817 */ 818 if (data_mp->b_datap->db_ref > 1 || 819 (data_mp->b_wptr - data_mp->b_rptr) < 820 (isv6 ? (ntohs(ip6h->ip6_plen) + sizeof (ip6_t)) 821 : ntohs(ipha->ipha_length))) { 822 placeholder = msgpullup(data_mp, -1); 823 if (placeholder == NULL) { 824 IP_ESP_BUMP_STAT(in_discards); 825 /* 826 * TODO: Extract inbound interface from the IPSEC_IN 827 * message's ii->ipsec_in_rill_index. 828 */ 829 ip_drop_packet(ipsec_in_mp, B_TRUE, NULL, NULL, 830 &ipdrops_esp_nomem, &ip_dropper); 831 return (NULL); 832 } else { 833 /* Reset packet with new pulled up mblk. */ 834 freemsg(data_mp); 835 data_mp = placeholder; 836 ipsec_in_mp->b_cont = data_mp; 837 } 838 } 839 840 /* 841 * Find the ESP header, point the address pointers at the appropriate 842 * IPv4/IPv6 places. 843 */ 844 if (isv6) { 845 ip6h = (ip6_t *)data_mp->b_rptr; 846 src_ptr = (uint32_t *)&ip6h->ip6_src; 847 dst_ptr = (uint32_t *)&ip6h->ip6_dst; 848 if (ip6h->ip6_nxt != IPPROTO_ESP) { 849 /* There are options that need to be processed. */ 850 preamble = ip_hdr_length_v6(data_mp, ip6h); 851 } else { 852 preamble = sizeof (ip6_t); 853 } 854 855 sp = &esp_sadb.s_v6; 856 af = AF_INET6; 857 } else { 858 ipha = (ipha_t *)data_mp->b_rptr; 859 src_ptr = (uint32_t *)&ipha->ipha_src; 860 dst_ptr = (uint32_t *)&ipha->ipha_dst; 861 preamble = IPH_HDR_LENGTH(ipha); 862 863 sp = &esp_sadb.s_v4; 864 af = AF_INET; 865 } 866 867 esph = (esph_t *)(data_mp->b_rptr + preamble); 868 869 /* Since hash is common on inbound (SPI value), hash here. */ 870 bucket = INBOUND_BUCKET(sp, esph->esph_spi); 871 mutex_enter(&bucket->isaf_lock); 872 ipsa = ipsec_getassocbyspi(bucket, esph->esph_spi, src_ptr, dst_ptr, 873 af); 874 mutex_exit(&bucket->isaf_lock); 875 876 if (ipsa == NULL || ipsa->ipsa_state == IPSA_STATE_DEAD) { 877 /* This is a loggable error! AUDIT ME! */ 878 IP_ESP_BUMP_STAT(lookup_failure); 879 IP_ESP_BUMP_STAT(in_discards); 880 ipsecesp_in_assocfailure(ipsec_in_mp, 0, 881 SL_ERROR | SL_CONSOLE | SL_WARN, 882 "ipsec_inbound_esp_sa: No association found for " 883 "spi 0x%x, dst addr %s\n", 884 esph->esph_spi, dst_ptr, af); 885 if (ipsa != NULL) { 886 IPSA_REFRELE(ipsa); 887 } 888 return (NULL); 889 } 890 891 if (ipsa->ipsa_state == IPSA_STATE_LARVAL) { 892 /* Not fully baked; swap the packet under a rock until then */ 893 sadb_set_lpkt(ipsa, ipsec_in_mp); 894 IPSA_REFRELE(ipsa); 895 return (NULL); 896 } 897 898 /* 899 * Save a reference to the association so that it can 900 * be retrieved after execution. We free any AH SA reference 901 * already there (innermost SA "wins". The reference to 902 * the SA will also be used later when doing the policy checks. 903 */ 904 if (ii->ipsec_in_esp_sa != NULL) { 905 IPSA_REFRELE(ii->ipsec_in_esp_sa); 906 } 907 ii->ipsec_in_esp_sa = ipsa; 908 909 return (esph); 910 } 911