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/ipsec_info.h> 40 #include <inet/sadb.h> 41 #include <inet/ipsec_impl.h> 42 #include <inet/ipdrop.h> 43 #include <inet/ipsecesp.h> 44 #include <inet/ipsecah.h> 45 #include <sys/kstat.h> 46 47 /* 48 * Returns B_TRUE if the identities in the SA match the identities 49 * in the "latch" structure. 50 */ 51 52 static boolean_t 53 ipsec_match_outbound_ids(ipsec_latch_t *ipl, ipsa_t *sa) 54 { 55 ASSERT(ipl->ipl_ids_latched == B_TRUE); 56 return ipsid_equal(ipl->ipl_local_cid, sa->ipsa_src_cid) && 57 ipsid_equal(ipl->ipl_remote_cid, sa->ipsa_dst_cid); 58 } 59 60 /* cr1 is packet cred; cr2 is SA credential */ 61 boolean_t 62 ipsec_label_match(cred_t *cr1, cred_t *cr2) 63 { 64 ts_label_t *l1, *l2; 65 66 if (!is_system_labeled()) 67 return (B_TRUE); 68 69 /* 70 * Check for NULL creds. Unlabeled SA always matches; 71 * unlabeled user with labeled SA always fails 72 */ 73 if (cr2 == NULL) 74 return (B_TRUE); 75 76 if (cr1 == NULL) 77 return (B_FALSE); 78 79 /* If we reach here, we have two passed-in creds. */ 80 ASSERT(cr2 != NULL && cr1 != NULL); 81 82 /* Check for NULL labels. Two is good, one is bad, zero is good. */ 83 l1 = crgetlabel(cr1); 84 l2 = crgetlabel(cr2); 85 if (l1 == NULL) 86 return (l2 == NULL); 87 88 if (l2 == NULL) 89 return (B_FALSE); 90 91 /* Simple IPsec MLS policy: labels must be equal */ 92 /* In future will need bit in policy saying whether this is the case */ 93 94 /* 95 * label_equal() checks DOI and label contents. We should be 96 * good to go with this check. 97 */ 98 return (label_equal(l1, l2)); 99 } 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, cred_t *cr) 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 * Do labels match? 334 */ 335 if (!ipsec_label_match(cr, retval->ipsa_cred)) 336 goto next_ipsa; 337 338 /* 339 * At this point, we know that we have at least a match on: 340 * 341 * - dest 342 * - source (if source is specified, i.e. non-zeroes) 343 * - inner dest (if specified) 344 * - inner source (if specified) 345 * - auth alg (if auth alg is specified, i.e. non-zero) 346 * - encrypt. alg (if encrypt. alg is specified, i.e. non-zero) 347 * and we know that the SA keylengths are appropriate. 348 * 349 * (Keep in mind known-src SAs are hit before zero-src SAs, 350 * thanks to sadb_insertassoc().) 351 * If we need a unique asssociation, optimally we have 352 * ipsa_unique_id == unique_id, otherwise NOT USED 353 * is held in reserve (stored in candidate). 354 * 355 * For those stored in candidate, take best-match (i.e. given 356 * a choice, candidate should have non-zero ipsa_src). 357 */ 358 359 /* 360 * If SA has a unique value which matches, we're all set... 361 * "key management knows best" 362 */ 363 if ((retval->ipsa_flags & IPSA_F_UNIQUE) && 364 ((unique_id & retval->ipsa_unique_mask) == 365 retval->ipsa_unique_id)) 366 break; 367 368 /* 369 * If we need a unique SA and this SA has already been used, 370 * or if the SA has a unique value which doesn't match, 371 * this isn't for us. 372 */ 373 374 if (retval->ipsa_flags & excludeflags) 375 goto next_ipsa; 376 377 378 /* 379 * I found a candidate.. 380 */ 381 if (candidate == NULL) { 382 /* 383 * and didn't already have one.. 384 */ 385 candidate = retval; 386 candact = act; 387 continue; 388 } else { 389 /* 390 * If candidate's source address is zero and 391 * the current match (i.e. retval) address is 392 * not zero, we have a better candidate.. 393 */ 394 if (IPSA_IS_ADDR_UNSPEC(candidate->ipsa_srcaddr, af) && 395 !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) { 396 mutex_exit(&candidate->ipsa_lock); 397 candidate = retval; 398 candact = act; 399 continue; 400 } 401 } 402 next_ipsa: 403 mutex_exit(&retval->ipsa_lock); 404 } 405 ASSERT((retval == NULL) || MUTEX_HELD(&retval->ipsa_lock)); 406 ASSERT((candidate == NULL) || MUTEX_HELD(&candidate->ipsa_lock)); 407 ASSERT((retval == NULL) || (act != NULL)); 408 ASSERT((candidate == NULL) || (candact != NULL)); 409 410 /* Let caller react to a lookup failure when it gets NULL. */ 411 if (retval == NULL && candidate == NULL) 412 return (NULL); 413 414 if (retval == NULL) { 415 ASSERT(MUTEX_HELD(&candidate->ipsa_lock)); 416 retval = candidate; 417 act = candact; 418 } else if (candidate != NULL) { 419 mutex_exit(&candidate->ipsa_lock); 420 } 421 ASSERT(MUTEX_HELD(&retval->ipsa_lock)); 422 ASSERT(act != NULL); 423 424 /* 425 * Even though I hold the mutex, since the reference counter is an 426 * atomic operation, I really have to use the IPSA_REFHOLD macro. 427 */ 428 IPSA_REFHOLD(retval); 429 430 /* 431 * This association is no longer unused. 432 */ 433 old_flags = retval->ipsa_flags; 434 retval->ipsa_flags |= IPSA_F_USED; 435 436 /* 437 * Cache a reference to this SA for the fast path. 438 */ 439 if (ipr != NULL) { 440 ipr->ipsr_bucket = bucket; 441 ipr->ipsr_gen = bucket->isaf_gen; 442 ipr->ipsr_sa = retval; 443 /* I'm now caching, so the cache-invalid flag goes away! */ 444 retval->ipsa_flags &= ~IPSA_F_CINVALID; 445 } 446 /* 447 * Latch various things while we're here.. 448 */ 449 if (ipl != NULL) { 450 if (!ipl->ipl_ids_latched) { 451 ipsec_latch_ids(ipl, 452 retval->ipsa_src_cid, retval->ipsa_dst_cid); 453 } 454 if (!ipl->ipl_out_action_latched) { 455 IPACT_REFHOLD(act); 456 ipl->ipl_out_action = act; 457 ipl->ipl_out_action_latched = B_TRUE; 458 } 459 } 460 461 /* 462 * Set the uniqueness only first time. 463 */ 464 if (need_unique && !(old_flags & IPSA_F_USED)) { 465 if (retval->ipsa_unique_id == 0) { 466 ASSERT((retval->ipsa_flags & IPSA_F_UNIQUE) == 0); 467 /* 468 * From now on, only this src, dst[ports, addr], 469 * proto, should use it. 470 */ 471 retval->ipsa_flags |= IPSA_F_UNIQUE; 472 retval->ipsa_unique_id = unique_id; 473 retval->ipsa_unique_mask = SA_UNIQUE_MASK( 474 io->ipsec_out_src_port, io->ipsec_out_dst_port, 475 protocol, 0); 476 } 477 478 /* 479 * Set the source address and adjust the hash 480 * buckets only if src_addr is zero. 481 */ 482 if (IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) { 483 /* 484 * sadb_unlinkassoc() will decrement the refcnt. Bump 485 * up when we have the lock so that we don't have to 486 * acquire locks when we come back from 487 * sadb_insertassoc(). 488 * 489 * We don't need to bump the bucket's gen since 490 * we aren't moving to a new bucket. 491 */ 492 IPSA_REFHOLD(retval); 493 IPSA_COPY_ADDR(retval->ipsa_srcaddr, src, af); 494 mutex_exit(&retval->ipsa_lock); 495 sadb_unlinkassoc(retval); 496 /* 497 * Since the bucket lock is held, we know 498 * sadb_insertassoc() will succeed. 499 */ 500 #ifdef DEBUG 501 if (sadb_insertassoc(retval, bucket) != 0) { 502 cmn_err(CE_PANIC, 503 "sadb_insertassoc() failed in " 504 "ipsec_getassocbyconn().\n"); 505 } 506 #else /* non-DEBUG */ 507 (void) sadb_insertassoc(retval, bucket); 508 #endif /* DEBUG */ 509 return (retval); 510 } 511 } 512 mutex_exit(&retval->ipsa_lock); 513 514 return (retval); 515 } 516 517 /* 518 * Look up a security association based on the security parameters index (SPI) 519 * and address(es). This is used for inbound packets and general SA lookups 520 * (even in outbound SA tables). The source address may be ignored. Return 521 * NULL if no association is available. If an SA is found, return it, with 522 * its refcnt incremented. The caller must REFRELE after using the SA. 523 * The hash bucket must be locked down before calling. 524 */ 525 ipsa_t * 526 ipsec_getassocbyspi(isaf_t *bucket, uint32_t spi, uint32_t *src, uint32_t *dst, 527 sa_family_t af) 528 { 529 ipsa_t *retval; 530 531 ASSERT(MUTEX_HELD(&bucket->isaf_lock)); 532 533 /* 534 * Walk the hash bucket, matching exactly on SPI, then destination, 535 * then source. 536 * 537 * Per-SA locking doesn't need to happen, because I'm only matching 538 * on addresses. Addresses are only changed during insertion/deletion 539 * from the hash bucket. Since the hash bucket lock is held, we don't 540 * need to worry about addresses changing. 541 */ 542 543 for (retval = bucket->isaf_ipsa; retval != NULL; 544 retval = retval->ipsa_next) { 545 if (retval->ipsa_spi != spi) 546 continue; 547 if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af)) 548 continue; 549 550 /* 551 * Assume that wildcard source addresses are inserted at the 552 * end of the hash bucket. (See sadb_insertassoc().) 553 * The following check for source addresses is a weak form 554 * of access control/source identity verification. If an 555 * SA has a source address, I only match an all-zeroes 556 * source address, or that particular one. If the SA has 557 * an all-zeroes source, then I match regardless. 558 * 559 * There is a weakness here in that a packet with all-zeroes 560 * for an address will match regardless of the source address 561 * stored in the packet. 562 * 563 * Note that port-level packet selectors, if present, 564 * are checked in ipsec_check_ipsecin_unique(). 565 */ 566 if (IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) || 567 IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af) || 568 IPSA_IS_ADDR_UNSPEC(src, af)) 569 break; 570 } 571 572 if (retval != NULL) { 573 /* 574 * Just refhold the return value. The caller will then 575 * make the appropriate calls to set the USED flag. 576 */ 577 IPSA_REFHOLD(retval); 578 } 579 580 return (retval); 581 } 582 583 boolean_t 584 ipsec_outbound_sa(mblk_t *mp, uint_t proto) 585 { 586 mblk_t *data_mp; 587 ipsec_out_t *io; 588 ipaddr_t dst; 589 uint32_t *dst_ptr, *src_ptr; 590 isaf_t *bucket; 591 ipsa_t *assoc; 592 ip6_pkt_t ipp; 593 in6_addr_t dst6; 594 ipsa_t **sa; 595 sadbp_t *sadbp; 596 sadb_t *sp; 597 sa_family_t af; 598 cred_t *cr; 599 netstack_t *ns; 600 601 data_mp = mp->b_cont; 602 io = (ipsec_out_t *)mp->b_rptr; 603 ns = io->ipsec_out_ns; 604 605 if (proto == IPPROTO_ESP) { 606 ipsecesp_stack_t *espstack; 607 608 espstack = ns->netstack_ipsecesp; 609 sa = &io->ipsec_out_esp_sa; 610 sadbp = &espstack->esp_sadb; 611 } else { 612 ipsecah_stack_t *ahstack; 613 614 ASSERT(proto == IPPROTO_AH); 615 ahstack = ns->netstack_ipsecah; 616 sa = &io->ipsec_out_ah_sa; 617 sadbp = &ahstack->ah_sadb; 618 } 619 620 ASSERT(*sa == NULL); 621 622 if (io->ipsec_out_v4) { 623 ipha_t *ipha = (ipha_t *)data_mp->b_rptr; 624 625 ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION); 626 dst = ip_get_dst(ipha); 627 sp = &sadbp->s_v4; 628 af = AF_INET; 629 630 /* 631 * NOTE:Getting the outbound association is considerably 632 * painful. ipsec_getassocbyconn() will require more 633 * parameters as policy implementations mature. 634 */ 635 bucket = OUTBOUND_BUCKET_V4(sp, dst); 636 src_ptr = (uint32_t *)&ipha->ipha_src; 637 dst_ptr = (uint32_t *)&dst; 638 } else { 639 ip6_t *ip6h = (ip6_t *)data_mp->b_rptr; 640 641 ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION); 642 dst6 = ip_get_dst_v6(ip6h, data_mp, NULL); 643 af = AF_INET6; 644 645 bzero(&ipp, sizeof (ipp)); 646 sp = &sadbp->s_v6; 647 648 /* Same NOTE: applies here! */ 649 bucket = OUTBOUND_BUCKET_V6(sp, dst6); 650 src_ptr = (uint32_t *)&ip6h->ip6_src; 651 dst_ptr = (uint32_t *)&dst6; 652 } 653 654 cr = msg_getcred(data_mp, NULL); 655 656 mutex_enter(&bucket->isaf_lock); 657 assoc = ipsec_getassocbyconn(bucket, io, src_ptr, dst_ptr, af, 658 proto, cr); 659 mutex_exit(&bucket->isaf_lock); 660 661 if (assoc == NULL) 662 return (B_FALSE); 663 664 if (assoc->ipsa_state == IPSA_STATE_DEAD) { 665 IPSA_REFRELE(assoc); 666 return (B_FALSE); 667 } 668 669 ASSERT(assoc->ipsa_state != IPSA_STATE_LARVAL); 670 671 *sa = assoc; 672 return (B_TRUE); 673 } 674 675 /* 676 * Inbound IPsec SA selection. 677 */ 678 679 ah_t * 680 ipsec_inbound_ah_sa(mblk_t *mp, netstack_t *ns) 681 { 682 mblk_t *ipsec_in; 683 ipha_t *ipha; 684 ipsa_t *assoc; 685 ah_t *ah; 686 isaf_t *hptr; 687 ipsec_in_t *ii; 688 boolean_t isv6; 689 ip6_t *ip6h; 690 int ah_offset; 691 uint32_t *src_ptr, *dst_ptr; 692 int pullup_len; 693 sadb_t *sp; 694 sa_family_t af; 695 ipsec_stack_t *ipss = ns->netstack_ipsec; 696 ipsecah_stack_t *ahstack = ns->netstack_ipsecah; 697 698 IP_AH_BUMP_STAT(ipss, in_requests); 699 700 ASSERT(mp->b_datap->db_type == M_CTL); 701 702 ipsec_in = mp; 703 ii = (ipsec_in_t *)ipsec_in->b_rptr; 704 mp = mp->b_cont; 705 706 ASSERT(mp->b_datap->db_type == M_DATA); 707 708 isv6 = !ii->ipsec_in_v4; 709 if (isv6) { 710 ip6h = (ip6_t *)mp->b_rptr; 711 ah_offset = ipsec_ah_get_hdr_size_v6(mp, B_TRUE); 712 } else { 713 ipha = (ipha_t *)mp->b_rptr; 714 ASSERT(ipha->ipha_protocol == IPPROTO_AH); 715 ah_offset = ipha->ipha_version_and_hdr_length - 716 (uint8_t)((IP_VERSION << 4)); 717 ah_offset <<= 2; 718 } 719 720 /* 721 * We assume that the IP header is pulled up until 722 * the options. We need to see whether we have the 723 * AH header in the same mblk or not. 724 */ 725 pullup_len = ah_offset + sizeof (ah_t); 726 if (mp->b_rptr + pullup_len > mp->b_wptr) { 727 if (!pullupmsg(mp, pullup_len)) { 728 ipsec_rl_strlog(ns, ip_mod_info.mi_idnum, 0, 0, 729 SL_WARN | SL_ERROR, 730 "ipsec_inbound_ah_sa: Small AH header\n"); 731 IP_AH_BUMP_STAT(ipss, in_discards); 732 ip_drop_packet(ipsec_in, B_TRUE, NULL, NULL, 733 DROPPER(ipss, ipds_ah_bad_length), 734 &ipss->ipsec_dropper); 735 return (NULL); 736 } 737 if (isv6) 738 ip6h = (ip6_t *)mp->b_rptr; 739 else 740 ipha = (ipha_t *)mp->b_rptr; 741 } 742 743 ah = (ah_t *)(mp->b_rptr + ah_offset); 744 745 if (isv6) { 746 src_ptr = (uint32_t *)&ip6h->ip6_src; 747 dst_ptr = (uint32_t *)&ip6h->ip6_dst; 748 sp = &ahstack->ah_sadb.s_v6; 749 af = AF_INET6; 750 } else { 751 src_ptr = (uint32_t *)&ipha->ipha_src; 752 dst_ptr = (uint32_t *)&ipha->ipha_dst; 753 sp = &ahstack->ah_sadb.s_v4; 754 af = AF_INET; 755 } 756 757 hptr = INBOUND_BUCKET(sp, ah->ah_spi); 758 mutex_enter(&hptr->isaf_lock); 759 assoc = ipsec_getassocbyspi(hptr, ah->ah_spi, src_ptr, dst_ptr, af); 760 mutex_exit(&hptr->isaf_lock); 761 762 if (assoc == NULL || assoc->ipsa_state == IPSA_STATE_DEAD || 763 assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) { 764 IP_AH_BUMP_STAT(ipss, lookup_failure); 765 IP_AH_BUMP_STAT(ipss, in_discards); 766 ipsecah_in_assocfailure(ipsec_in, 0, 767 SL_ERROR | SL_CONSOLE | SL_WARN, 768 "ipsec_inbound_ah_sa: No association found for " 769 "spi 0x%x, dst addr %s\n", 770 ah->ah_spi, dst_ptr, af, ahstack); 771 if (assoc != NULL) { 772 IPSA_REFRELE(assoc); 773 } 774 return (NULL); 775 } 776 777 if (assoc->ipsa_state == IPSA_STATE_LARVAL && 778 sadb_set_lpkt(assoc, ipsec_in, ns)) { 779 /* Not fully baked; swap the packet under a rock until then */ 780 IPSA_REFRELE(assoc); 781 return (NULL); 782 } 783 784 /* 785 * Save a reference to the association so that it can 786 * be retrieved after execution. We free any AH SA reference 787 * already there (innermost SA "wins". The reference to 788 * the SA will also be used later when doing the policy checks. 789 */ 790 791 if (ii->ipsec_in_ah_sa != NULL) { 792 IPSA_REFRELE(ii->ipsec_in_ah_sa); 793 } 794 ii->ipsec_in_ah_sa = assoc; 795 796 return (ah); 797 } 798 799 esph_t * 800 ipsec_inbound_esp_sa(mblk_t *ipsec_in_mp, netstack_t *ns) 801 { 802 mblk_t *data_mp, *placeholder; 803 uint32_t *src_ptr, *dst_ptr; 804 ipsec_in_t *ii; 805 ipha_t *ipha; 806 ip6_t *ip6h; 807 esph_t *esph; 808 ipsa_t *ipsa; 809 isaf_t *bucket; 810 uint_t preamble; 811 sa_family_t af; 812 boolean_t isv6; 813 sadb_t *sp; 814 ipsec_stack_t *ipss = ns->netstack_ipsec; 815 ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; 816 817 IP_ESP_BUMP_STAT(ipss, in_requests); 818 ASSERT(ipsec_in_mp->b_datap->db_type == M_CTL); 819 820 /* We have IPSEC_IN already! */ 821 ii = (ipsec_in_t *)ipsec_in_mp->b_rptr; 822 data_mp = ipsec_in_mp->b_cont; 823 824 ASSERT(ii->ipsec_in_type == IPSEC_IN); 825 826 isv6 = !ii->ipsec_in_v4; 827 if (isv6) { 828 ip6h = (ip6_t *)data_mp->b_rptr; 829 } else { 830 ipha = (ipha_t *)data_mp->b_rptr; 831 } 832 833 /* 834 * Put all data into one mblk if it's not there already. 835 * XXX This is probably bad long-term. Figure out better ways of doing 836 * this. Much of the inbound path depends on all of the data being 837 * in one mblk. 838 * 839 * XXX Jumbogram issues will have to be dealt with here. 840 * If the plen is 0, we'll have to scan for a HBH header with the 841 * actual packet length. 842 */ 843 if (data_mp->b_datap->db_ref > 1 || 844 (data_mp->b_wptr - data_mp->b_rptr) < 845 (isv6 ? (ntohs(ip6h->ip6_plen) + sizeof (ip6_t)) 846 : ntohs(ipha->ipha_length))) { 847 placeholder = msgpullup(data_mp, -1); 848 if (placeholder == NULL) { 849 IP_ESP_BUMP_STAT(ipss, in_discards); 850 /* 851 * TODO: Extract inbound interface from the IPSEC_IN 852 * message's ii->ipsec_in_rill_index. 853 */ 854 ip_drop_packet(ipsec_in_mp, B_TRUE, NULL, NULL, 855 DROPPER(ipss, ipds_esp_nomem), 856 &ipss->ipsec_dropper); 857 return (NULL); 858 } else { 859 /* Reset packet with new pulled up mblk. */ 860 freemsg(data_mp); 861 data_mp = placeholder; 862 ipsec_in_mp->b_cont = data_mp; 863 } 864 } 865 866 /* 867 * Find the ESP header, point the address pointers at the appropriate 868 * IPv4/IPv6 places. 869 */ 870 if (isv6) { 871 ip6h = (ip6_t *)data_mp->b_rptr; 872 src_ptr = (uint32_t *)&ip6h->ip6_src; 873 dst_ptr = (uint32_t *)&ip6h->ip6_dst; 874 if (ip6h->ip6_nxt != IPPROTO_ESP) { 875 /* There are options that need to be processed. */ 876 preamble = ip_hdr_length_v6(data_mp, ip6h); 877 } else { 878 preamble = sizeof (ip6_t); 879 } 880 881 sp = &espstack->esp_sadb.s_v6; 882 af = AF_INET6; 883 } else { 884 ipha = (ipha_t *)data_mp->b_rptr; 885 src_ptr = (uint32_t *)&ipha->ipha_src; 886 dst_ptr = (uint32_t *)&ipha->ipha_dst; 887 preamble = IPH_HDR_LENGTH(ipha); 888 889 sp = &espstack->esp_sadb.s_v4; 890 af = AF_INET; 891 } 892 893 esph = (esph_t *)(data_mp->b_rptr + preamble); 894 895 /* Since hash is common on inbound (SPI value), hash here. */ 896 bucket = INBOUND_BUCKET(sp, esph->esph_spi); 897 mutex_enter(&bucket->isaf_lock); 898 ipsa = ipsec_getassocbyspi(bucket, esph->esph_spi, src_ptr, dst_ptr, 899 af); 900 mutex_exit(&bucket->isaf_lock); 901 902 if (ipsa == NULL || ipsa->ipsa_state == IPSA_STATE_DEAD || 903 ipsa->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) { 904 /* This is a loggable error! AUDIT ME! */ 905 IP_ESP_BUMP_STAT(ipss, lookup_failure); 906 IP_ESP_BUMP_STAT(ipss, in_discards); 907 ipsecesp_in_assocfailure(ipsec_in_mp, 0, 908 SL_ERROR | SL_CONSOLE | SL_WARN, 909 "ipsec_inbound_esp_sa: No association found for " 910 "spi 0x%x, dst addr %s\n", 911 esph->esph_spi, dst_ptr, af, espstack); 912 if (ipsa != NULL) { 913 IPSA_REFRELE(ipsa); 914 } 915 return (NULL); 916 } 917 918 if (ipsa->ipsa_state == IPSA_STATE_LARVAL && 919 sadb_set_lpkt(ipsa, ipsec_in_mp, ns)) { 920 /* Not fully baked; swap the packet under a rock until then */ 921 IPSA_REFRELE(ipsa); 922 return (NULL); 923 } 924 925 /* 926 * Save a reference to the association so that it can 927 * be retrieved after execution. We free any AH SA reference 928 * already there (innermost SA "wins". The reference to 929 * the SA will also be used later when doing the policy checks. 930 */ 931 if (ii->ipsec_in_esp_sa != NULL) { 932 IPSA_REFRELE(ii->ipsec_in_esp_sa); 933 } 934 ii->ipsec_in_esp_sa = ipsa; 935 936 return (esph); 937 } 938