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