Mercurial > illumos > illumos-gate
changeset 3192:e4e2ffd4e00f
6478675 inconsistent ESP padding verification in OpenSolaris
Contributed by Jean-Paul Degabriele <jeanpaul.degabriele@gmail.com>.
6481387 Freed queue_t gets passed to ipsec_log_policy_failure() during OPL ttcp runs...
6494630 qs21 may be validating cert chains incorrectly.
6495455 assertion failure when using IPsec global policy with IPv6 tunnels
6496323 AH-only on tunnels doesn't work.
6497625 More debugging and output cleanliness in in.iked's cert-chain processing.
author | danmcd |
---|---|
date | Wed, 29 Nov 2006 16:09:14 -0800 |
parents | 6941d6cb4c23 |
children | 18a2947957c4 |
files | usr/src/uts/common/inet/ip/ipsecah.c usr/src/uts/common/inet/ip/ipsecesp.c usr/src/uts/common/inet/ip/spd.c usr/src/uts/common/inet/ipsec_impl.h usr/src/uts/common/inet/tcp/tcp.c |
diffstat | 5 files changed, 163 insertions(+), 151 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/ipsecah.c Tue Nov 28 16:45:29 2006 -0800 +++ b/usr/src/uts/common/inet/ip/ipsecah.c Wed Nov 29 16:09:14 2006 -0800 @@ -35,6 +35,7 @@ #include <sys/ddi.h> #include <sys/sunddi.h> #include <sys/kmem.h> +#include <sys/sysmacros.h> #include <sys/cmn_err.h> #include <sys/vtrace.h> #include <sys/debug.h> @@ -3726,14 +3727,14 @@ ipha_t *ipha; uint_t ah_offset = 0; mblk_t *mp; - int align_len; + int align_len, newpos; ah_t *ah; - ipha_t *nipha; uint32_t length; + uint32_t *dest32; + uint8_t *dest; ipsec_in_t *ii; boolean_t isv4; ip6_t *ip6h; - ip6_t *nip6h; uint_t icv_len; ipsa_t *assoc; kstat_named_t *counter; @@ -3774,6 +3775,7 @@ } ah = (ah_t *)(mp->b_rptr + ah_offset); + newpos = sizeof (ah_t) + align_len; /* * We get here only when authentication passed. @@ -3812,22 +3814,18 @@ /* * We need to remove the AH header from the original - * datagram. Easy way to do this is to use phdr_mp - * to hold the IP header and the orginal mp to hold - * the rest of it. So, we copy the IP header on to - * phdr_mp, and set the b_rptr in mp past AH header. + * datagram. Best way to do this is to move the pre-AH headers + * forward in the (relatively simple) IPv4 case. In IPv6, it's + * a bit more complicated because of IPv6's next-header chaining, + * but it's doable. */ if (isv4) { - bcopy(mp->b_rptr, phdr_mp->b_rptr, ah_offset); - phdr_mp->b_wptr = phdr_mp->b_rptr + ah_offset; - nipha = (ipha_t *)phdr_mp->b_rptr; /* * Assign the right protocol, adjust the length as we * are removing the AH header and adjust the checksum to * account for the protocol and length. */ - nipha->ipha_protocol = ah->ah_nexthdr; - length = ntohs(nipha->ipha_length); + length = ntohs(ipha->ipha_length); if (!ah_age_bytes(assoc, length, B_TRUE)) { /* The ipsa has hit hard expiration, LOG and AUDIT. */ ipsec_assocfailure(info.mi_idnum, 0, 0, @@ -3839,16 +3837,12 @@ counter = &ipdrops_ah_bytes_expire; goto ah_in_discard; } - length -= (sizeof (ah_t) + align_len); - - nipha->ipha_length = htons((uint16_t)length); - nipha->ipha_hdr_checksum = 0; - nipha->ipha_hdr_checksum = (uint16_t)ip_csum_hdr(nipha); - /* - * Skip IP,AH and the authentication data in the - * original datagram. - */ - mp->b_rptr += (ah_offset + sizeof (ah_t) + align_len); + ipha->ipha_protocol = ah->ah_nexthdr; + length -= newpos; + + ipha->ipha_length = htons((uint16_t)length); + ipha->ipha_hdr_checksum = 0; + ipha->ipha_hdr_checksum = (uint16_t)ip_csum_hdr(ipha); } else { uchar_t *whereptr; int hdrlen; @@ -3857,13 +3851,11 @@ ip6_dest_t *dsthdr; ip6_rthdr0_t *rthdr; - nip6h = (ip6_t *)phdr_mp->b_rptr; - /* * Make phdr_mp hold until the AH header and make * mp hold everything past AH header. */ - length = ntohs(nip6h->ip6_plen); + length = ntohs(ip6h->ip6_plen); if (!ah_age_bytes(assoc, length + sizeof (ip6_t), B_TRUE)) { /* The ipsa has hit hard expiration, LOG and AUDIT. */ ipsec_assocfailure(info.mi_idnum, 0, 0, @@ -3875,9 +3867,6 @@ counter = &ipdrops_ah_bytes_expire; goto ah_in_discard; } - bcopy(ip6h, nip6h, ah_offset); - phdr_mp->b_wptr = phdr_mp->b_rptr + ah_offset; - mp->b_rptr += (ah_offset + sizeof (ah_t) + align_len); /* * Update the next header field of the header preceding @@ -3885,8 +3874,8 @@ * IPv6 header and proceed with the extension headers * until we find what we're looking for. */ - nexthdr = &nip6h->ip6_nxt; - whereptr = (uchar_t *)nip6h; + nexthdr = &ip6h->ip6_nxt; + whereptr = (uchar_t *)ip6h; hdrlen = sizeof (ip6_t); while (*nexthdr != IPPROTO_AH) { @@ -3913,16 +3902,29 @@ } } *nexthdr = ah->ah_nexthdr; - - length -= (sizeof (ah_t) + align_len); - nip6h->ip6_plen = htons((uint16_t)length); + length -= newpos; + ip6h->ip6_plen = htons((uint16_t)length); } + /* Now that we've fixed the IP header, move it forward. */ + mp->b_rptr += newpos; + if (IS_P2ALIGNED(mp->b_rptr, sizeof (uint32_t))) { + dest32 = (uint32_t *)(mp->b_rptr + ah_offset); + while (--dest32 >= (uint32_t *)mp->b_rptr) + *dest32 = *(dest32 - (newpos >> 2)); + } else { + dest = mp->b_rptr + ah_offset; + while (--dest >= mp->b_rptr) + *dest = *(dest - newpos); + } + freeb(phdr_mp); + ipsec_in->b_cont = mp; + if (is_system_labeled()) { /* * inherit the label by setting it in the new ip header */ - mblk_setcred(phdr_mp, DB_CRED(mp)); + mblk_setcred(mp, DB_CRED(mp)); } return (IPSEC_STATUS_SUCCESS);
--- a/usr/src/uts/common/inet/ip/ipsecesp.c Tue Nov 28 16:45:29 2006 -0800 +++ b/usr/src/uts/common/inet/ip/ipsecesp.c Wed Nov 29 16:09:14 2006 -0800 @@ -763,7 +763,7 @@ /* - * Strip ESP header and fix IP header + * Strip ESP header, check padding, and fix IP header. * Returns B_TRUE on success, B_FALSE if an error occured. */ static boolean_t @@ -776,6 +776,7 @@ mblk_t *scratch; uint8_t nexthdr, padlen; uint8_t lastpad; + uint8_t *lastbyte; /* * Strip ESP data and fix IP header. @@ -807,9 +808,9 @@ * lastpad is the last byte of the padding, which can be used for * a quick check to see if the padding is correct. */ - nexthdr = *(scratch->b_wptr - 1); - padlen = *(scratch->b_wptr - 2); - lastpad = *(scratch->b_wptr - 3); + lastbyte = scratch->b_wptr - 1; + nexthdr = *lastbyte--; + padlen = *lastbyte--; if (isv4) { /* Fix part of the IP header. */ @@ -822,7 +823,7 @@ sizeof (esph_t) - ivlen) { ESP_BUMP_STAT(bad_decrypt); ipsec_rl_strlog(info.mi_idnum, 0, 0, SL_ERROR | SL_WARN, - "Possibly corrupt ESP packet."); + "Corrupt ESP packet (padlen too big).\n"); esp1dbg(("padlen (%d) is greater than:\n", padlen)); esp1dbg(("pkt len(%d) - ip hdr - esp hdr - ivlen(%d) " "= %d.\n", ntohs(ipha->ipha_length), ivlen, @@ -867,7 +868,7 @@ ivlen) { ESP_BUMP_STAT(bad_decrypt); ipsec_rl_strlog(info.mi_idnum, 0, 0, SL_ERROR | SL_WARN, - "Possibly corrupt ESP packet."); + "Corrupt ESP packet (v6 padlen too big).\n"); esp1dbg(("padlen (%d) is greater than:\n", padlen)); esp1dbg(("pkt len(%u) - ip hdr - esp hdr - ivlen(%d)" " = %u.\n", (unsigned)(ntohs(ip6h->ip6_plen) @@ -888,41 +889,57 @@ 2 - sizeof (esph_t) - ivlen); } - if (ipsecesp_padding_check > 0 && - padlen != lastpad && padlen != 0) { - ipsec_rl_strlog(info.mi_idnum, 0, 0, SL_ERROR | SL_WARN, - "Possibly corrupt ESP packet."); - esp1dbg(("lastpad (%d) not equal to padlen (%d):\n", - lastpad, padlen)); - ESP_BUMP_STAT(bad_padding); - *counter = &ipdrops_esp_bad_padding; - return (B_FALSE); - } - - if (ipsecesp_padding_check > 1) { - uint8_t *last = (uint8_t *)(scratch->b_wptr - 3); - uint8_t lastval = *last; + if (ipsecesp_padding_check > 0 && padlen > 0) { + /* + * Weak padding check: compare last-byte to length, they + * should be equal. + */ + lastpad = *lastbyte--; + + if (padlen != lastpad) { + ipsec_rl_strlog(info.mi_idnum, 0, 0, SL_ERROR | SL_WARN, + "Corrupt ESP packet (lastpad != padlen).\n"); + esp1dbg(("lastpad (%d) not equal to padlen (%d):\n", + lastpad, padlen)); + ESP_BUMP_STAT(bad_padding); + *counter = &ipdrops_esp_bad_padding; + return (B_FALSE); + } /* - * this assert may have to become an if - * and a pullup if we start accepting - * multi-dblk mblks. Any packet here will - * have been pulled up in esp_inbound. + * Strong padding check: Check all pad bytes to see that + * they're ascending. Go backwards using a descending counter + * to verify. padlen == 1 is checked by previous block, so + * only bother if we've more than 1 byte of padding. + * Consequently, start the check one byte before the location + * of "lastpad". */ - ASSERT(MBLKL(scratch) >= lastval + 3); - - while (lastval != 0) { - if (lastval != *last) { - ipsec_rl_strlog(info.mi_idnum, 0, 0, - SL_ERROR | SL_WARN, - "Possibly corrupt ESP packet."); - esp1dbg(("padding not in correct" - " format:\n")); - ESP_BUMP_STAT(bad_padding); - *counter = &ipdrops_esp_bad_padding; - return (B_FALSE); + if (ipsecesp_padding_check > 1) { + /* + * This assert may have to become an if and a pullup + * if we start accepting multi-dblk mblks. For now, + * though, any packet here will have been pulled up in + * esp_inbound. + */ + ASSERT(MBLKL(scratch) >= lastpad + 3); + + /* + * Use "--lastpad" because we already checked the very + * last pad byte previously. + */ + while (--lastpad != 0) { + if (lastpad != *lastbyte) { + ipsec_rl_strlog(info.mi_idnum, 0, 0, + SL_ERROR | SL_WARN, "Corrupt ESP " + "packet (bad padding).\n"); + esp1dbg(("padding not in correct" + " format:\n")); + ESP_BUMP_STAT(bad_padding); + *counter = &ipdrops_esp_bad_padding; + return (B_FALSE); + } + lastbyte--; } - lastval--; last--; } } @@ -2051,7 +2068,7 @@ uintptr_t esplen = sizeof (esph_t); uint8_t protocol; ipsa_t *assoc; - uint_t iv_len = 0, mac_len = 0; + uint_t iv_len, mac_len = 0; uchar_t *icv_buf; udpha_t *udpha; boolean_t is_natt = B_FALSE; @@ -2148,26 +2165,25 @@ esplen += UDPH_SIZE; } - if (assoc->ipsa_encr_alg != SADB_EALG_NULL) - iv_len = assoc->ipsa_iv_len; - /* * Set up ESP header and encryption padding for ENCR PI request. */ - /* - * Determine the padding length. Pad to 4-bytes. - * - * Include the two additional bytes (hence the - 2) for the padding - * length and the next header. Take this into account when - * calculating the actual length of the padding. - */ - + /* Determine the padding length. Pad to 4-bytes for no-encryption. */ if (assoc->ipsa_encr_alg != SADB_EALG_NULL) { - padlen = ((unsigned)(iv_len - datalen - 2)) % iv_len; + iv_len = assoc->ipsa_iv_len; + + /* + * Include the two additional bytes (hence the - 2) for the + * padding length and the next header. Take this into account + * when calculating the actual length of the padding. + */ + ASSERT(ISP2(iv_len)); + padlen = ((unsigned)(iv_len - datalen - 2)) & (iv_len - 1); } else { - padlen = ((unsigned)(sizeof (uint32_t) - datalen - 2)) % - sizeof (uint32_t); + iv_len = 0; + padlen = ((unsigned)(sizeof (uint32_t) - datalen - 2)) & + (sizeof (uint32_t) - 1); } /* Allocate ESP header and IV. */
--- a/usr/src/uts/common/inet/ip/spd.c Tue Nov 28 16:45:29 2006 -0800 +++ b/usr/src/uts/common/inet/ip/spd.c Wed Nov 29 16:09:14 2006 -0800 @@ -63,6 +63,9 @@ #include <inet/ipsec_info.h> #include <inet/sadb.h> #include <inet/ipsec_impl.h> + +#include <inet/ip_impl.h> /* For IP_MOD_ID */ + #include <inet/ipsecah.h> #include <inet/ipsecesp.h> #include <inet/ipdrop.h> @@ -77,8 +80,8 @@ ipsec_selector_t *); static mblk_t *ipsec_apply_global_policy(mblk_t *, conn_t *, ipsec_selector_t *); -static mblk_t *ipsec_check_ipsecin_policy(queue_t *, mblk_t *, - ipsec_policy_t *, ipha_t *, ip6_t *, uint64_t); +static mblk_t *ipsec_check_ipsecin_policy(mblk_t *, ipsec_policy_t *, + ipha_t *, ip6_t *, uint64_t); static void ipsec_in_release_refs(ipsec_in_t *); static void ipsec_out_release_refs(ipsec_out_t *); static void ipsec_action_reclaim(void *); @@ -952,14 +955,13 @@ * */ void -ipsec_log_policy_failure(queue_t *q, int type, char *func_name, ipha_t *ipha, - ip6_t *ip6h, boolean_t secure) +ipsec_log_policy_failure(int type, char *func_name, ipha_t *ipha, ip6_t *ip6h, + boolean_t secure) { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; char *s; char *d; - short mid = 0; ASSERT((ipha == NULL && ip6h != NULL) || (ip6h == NULL && ipha != NULL)); @@ -976,13 +978,9 @@ /* Always bump the policy failure counter. */ ipsec_policy_failure_count[type]++; - if (q != NULL) { - mid = q->q_qinfo->qi_minfo->mi_idnum; - } - ipsec_rl_strlog(mid, 0, 0, SL_ERROR|SL_WARN|SL_CONSOLE, - ipsec_policy_failure_msgs[type], - func_name, - (secure ? "secure" : "not secure"), s, d); + ipsec_rl_strlog(IP_MOD_ID, 0, 0, SL_ERROR|SL_WARN|SL_CONSOLE, + ipsec_policy_failure_msgs[type], func_name, + (secure ? "secure" : "not secure"), s, d); } /* @@ -1446,13 +1444,12 @@ } -/* ARGSUSED */ /* * Consumes a reference to ipsp. */ static mblk_t * -ipsec_check_loopback_policy(queue_t *q, mblk_t *first_mp, - boolean_t mctl_present, ipsec_policy_t *ipsp) +ipsec_check_loopback_policy(mblk_t *first_mp, boolean_t mctl_present, + ipsec_policy_t *ipsp) { mblk_t *ipsec_mp; ipsec_in_t *ii; @@ -1468,7 +1465,8 @@ /* * We should do an actual policy check here. Revisit this - * when we revisit the IPsec API. + * when we revisit the IPsec API. (And pass a conn_t in when we + * get there.) */ return (first_mp); @@ -1798,14 +1796,13 @@ * Consumes a reference to ipsp. */ static mblk_t * -ipsec_check_ipsecin_policy(queue_t *q, mblk_t *first_mp, ipsec_policy_t *ipsp, +ipsec_check_ipsecin_policy(mblk_t *first_mp, ipsec_policy_t *ipsp, ipha_t *ipha, ip6_t *ip6h, uint64_t pkt_unique) { ipsec_in_t *ii; ipsec_action_t *ap; const char *reason = "no policy actions found"; mblk_t *data_mp, *ipsec_mp; - short mid = 0; kstat_named_t *counter = &ipdrops_spd_got_secure; data_mp = first_mp->b_cont; @@ -1819,7 +1816,7 @@ ii = (ipsec_in_t *)ipsec_mp->b_rptr; if (ii->ipsec_in_loopback) - return (ipsec_check_loopback_policy(q, first_mp, B_TRUE, ipsp)); + return (ipsec_check_loopback_policy(first_mp, B_TRUE, ipsp)); ASSERT(ii->ipsec_in_type == IPSEC_IN); ASSERT(ii->ipsec_in_secure); @@ -1855,10 +1852,7 @@ } } drop: - if (q != NULL) { - mid = q->q_qinfo->qi_minfo->mi_idnum; - } - ipsec_rl_strlog(mid, 0, 0, SL_ERROR|SL_WARN|SL_CONSOLE, + ipsec_rl_strlog(IP_MOD_ID, 0, 0, SL_ERROR|SL_WARN|SL_CONSOLE, "ipsec inbound policy mismatch: %s, packet dropped\n", reason); IPPOL_REFRELE(ipsp); @@ -2068,7 +2062,6 @@ { ipsec_policy_t *p; ipsec_selector_t sel; - queue_t *q = NULL; mblk_t *data_mp, *ipsec_mp; boolean_t policy_present; kstat_named_t *counter; @@ -2096,9 +2089,6 @@ return (first_mp); } - if (connp != NULL) - q = CONNP_TO_WQ(connp); - if (ipsec_mp != NULL) { ASSERT(ipsec_mp->b_datap->db_type == M_CTL); ii = (ipsec_in_t *)(ipsec_mp->b_rptr); @@ -2126,7 +2116,7 @@ * Technically not a policy mismatch, but it is * an internal failure. */ - ipsec_log_policy_failure(q, IPSEC_POLICY_MISMATCH, + ipsec_log_policy_failure(IPSEC_POLICY_MISMATCH, "ipsec_init_inbound_sel", ipha, ip6h, B_FALSE); counter = &ipdrops_spd_nomem; goto fail; @@ -2158,14 +2148,15 @@ return (first_mp); } else { counter = &ipdrops_spd_got_secure; - ipsec_log_policy_failure(q, IPSEC_POLICY_NOT_NEEDED, + ipsec_log_policy_failure(IPSEC_POLICY_NOT_NEEDED, "ipsec_check_global_policy", ipha, ip6h, B_TRUE); goto fail; } } - if ((ii != NULL) && (ii->ipsec_in_secure)) - return (ipsec_check_ipsecin_policy(q, ipsec_mp, p, ipha, ip6h, - pkt_unique)); + if ((ii != NULL) && (ii->ipsec_in_secure)) { + return (ipsec_check_ipsecin_policy(ipsec_mp, p, ipha, ip6h, + pkt_unique)); + } if (p->ipsp_act->ipa_allow_clear) { BUMP_MIB(&ip_mib, ipsecInSucceeded); IPPOL_REFRELE(p); @@ -2177,7 +2168,7 @@ * global policy check because the packet was cleartext, and it * should not have been. */ - ipsec_log_policy_failure(q, IPSEC_POLICY_MISMATCH, + ipsec_log_policy_failure(IPSEC_POLICY_MISMATCH, "ipsec_check_global_policy", ipha, ip6h, B_FALSE); counter = &ipdrops_spd_got_clear; @@ -2400,8 +2391,6 @@ { ipsec_in_t *ii; boolean_t ret; - queue_t *q; - short mid = 0; mblk_t *mp = mctl_present ? first_mp->b_cont : first_mp; mblk_t *ipsec_mp = mctl_present ? first_mp : NULL; ipsec_latch_t *ipl; @@ -2433,7 +2422,6 @@ return (first_mp); } else { ipsec_log_policy_failure( - CONNP_TO_WQ(connp), IPSEC_POLICY_MISMATCH, "ipsec_check_inbound_policy", ipha, ip6h, B_FALSE); @@ -2507,11 +2495,7 @@ BUMP_MIB(&ip_mib, ipsecInSucceeded); return (first_mp); } - q = CONNP_TO_WQ(connp); - if (q != NULL) { - mid = q->q_qinfo->qi_minfo->mi_idnum; - } - ipsec_rl_strlog(mid, 0, 0, SL_ERROR|SL_WARN|SL_CONSOLE, + ipsec_rl_strlog(IP_MOD_ID, 0, 0, SL_ERROR|SL_WARN|SL_CONSOLE, "ipsec inbound policy mismatch: %s, packet dropped\n", reason); ip_drop_packet(first_mp, B_TRUE, NULL, NULL, counter, @@ -2525,8 +2509,8 @@ unique_id = conn_to_unique(connp, mp, ipha, ip6h); IPPOL_REFHOLD(ipl->ipl_in_policy); - first_mp = ipsec_check_ipsecin_policy(CONNP_TO_WQ(connp), first_mp, - ipl->ipl_in_policy, ipha, ip6h, unique_id); + first_mp = ipsec_check_ipsecin_policy(first_mp, ipl->ipl_in_policy, + ipha, ip6h, unique_id); /* * NOTE: ipsecIn{Failed,Succeeeded} bumped by * ipsec_check_ipsecin_policy(). @@ -4010,18 +3994,12 @@ uint8_t proto) { mblk_t *ipsec_mp; - queue_t *q; - short mid = 0; ASSERT((pol != NULL) || (connp != NULL)); ipsec_mp = ipsec_alloc_ipsec_out(); if (ipsec_mp == NULL) { - q = CONNP_TO_WQ(connp); - if (q != NULL) { - mid = q->q_qinfo->qi_minfo->mi_idnum; - } - ipsec_rl_strlog(mid, 0, 0, SL_ERROR|SL_NOTE, + ipsec_rl_strlog(IP_MOD_ID, 0, 0, SL_ERROR|SL_NOTE, "ipsec_attach_ipsec_out: Allocation failure\n"); BUMP_MIB(&ip_mib, ipOutDiscards); ip_drop_packet(mp, B_FALSE, NULL, NULL, &ipdrops_spd_nomem, @@ -5444,8 +5422,8 @@ */ IPPOL_REFHOLD(pol); - if (ipsec_check_ipsecin_policy(NULL, ipsec_mp, pol, - inner_ipv4, inner_ipv6, pkt_unique) != NULL) { + if (ipsec_check_ipsecin_policy(ipsec_mp, pol, inner_ipv4, + inner_ipv6, pkt_unique) != NULL) { if (data_tail == NULL) { /* First one */ data_chain = data_tail = ipsec_mp->b_cont; @@ -5504,14 +5482,22 @@ ipsec_policy_t *pol; uint16_t tmpport; selret_t rc; - boolean_t retval, port_policy_present, is_icmp; + boolean_t retval, port_policy_present, is_icmp, global_present; in6_addr_t tmpaddr; - uint8_t flags; + uint8_t flags, *holder, *outer_hdr; sel.ips_is_icmp_inv_acq = 0; - ASSERT(outer_ipv4 != NULL && outer_ipv6 == NULL || - outer_ipv4 == NULL && outer_ipv6 != NULL); + if (outer_ipv4 != NULL) { + ASSERT(outer_ipv6 == NULL); + outer_hdr = (uint8_t *)outer_ipv4; + global_present = ipsec_inbound_v4_policy_present; + } else { + outer_hdr = (uint8_t *)outer_ipv6; + global_present = ipsec_inbound_v6_policy_present; + } + ASSERT(outer_hdr != NULL); + ASSERT(inner_ipv4 != NULL && inner_ipv6 == NULL || inner_ipv4 == NULL && inner_ipv6 != NULL); ASSERT(message == *data_mp || message->b_cont == *data_mp); @@ -5709,9 +5695,7 @@ */ /* If no per-tunnel security, check global policy now. */ - if (ipsec_mp != NULL && - (((outer_ipv4 != NULL) && !ipsec_inbound_v4_policy_present) || - ((outer_ipv6 != NULL) && !ipsec_inbound_v6_policy_present))) { + if (ipsec_mp != NULL && !global_present) { if (((ipsec_in_t *)(ipsec_mp->b_rptr))-> ipsec_in_icmp_loopback) { /* @@ -5728,12 +5712,24 @@ return (B_FALSE); } + /* + * The following assertion is valid because only the tun module alters + * the mblk chain - stripping the outer header by advancing mp->b_rptr. + */ + ASSERT(is_icmp || + ((*data_mp)->b_datap->db_base <= outer_hdr && + outer_hdr < (*data_mp)->b_rptr)); + holder = (*data_mp)->b_rptr; + (*data_mp)->b_rptr = outer_hdr; + /* NOTE: Frees message if it returns NULL. */ if (ipsec_check_global_policy(message, NULL, outer_ipv4, outer_ipv6, (ipsec_mp != NULL)) == NULL) { return (B_FALSE); } + (*data_mp)->b_rptr = holder; + if (ipsec_mp != NULL) freeb(ipsec_mp);
--- a/usr/src/uts/common/inet/ipsec_impl.h Tue Nov 28 16:45:29 2006 -0800 +++ b/usr/src/uts/common/inet/ipsec_impl.h Wed Nov 29 16:09:14 2006 -0800 @@ -651,8 +651,7 @@ boolean_t); extern boolean_t ipsec_in_to_out(mblk_t *, ipha_t *, ip6_t *); -extern void ipsec_log_policy_failure(queue_t *, int, char *, ipha_t *, - ip6_t *, boolean_t); +extern void ipsec_log_policy_failure(int, char *, ipha_t *, ip6_t *, boolean_t); extern boolean_t ipsec_inbound_accept_clear(mblk_t *, ipha_t *, ip6_t *); extern int ipsec_conn_cache_policy(conn_t *, boolean_t); extern mblk_t *ipsec_alloc_ipsec_out(void);
--- a/usr/src/uts/common/inet/tcp/tcp.c Tue Nov 28 16:45:29 2006 -0800 +++ b/usr/src/uts/common/inet/tcp/tcp.c Wed Nov 29 16:09:14 2006 -0800 @@ -12082,7 +12082,7 @@ if (act == NULL || act->ipa_act.ipa_type == IPSEC_ACT_BYPASS || act->ipa_act.ipa_type == IPSEC_ACT_CLEAR) return (B_TRUE); - ipsec_log_policy_failure(tcp->tcp_wq, IPSEC_POLICY_MISMATCH, + ipsec_log_policy_failure(IPSEC_POLICY_MISMATCH, "tcp_check_policy", ipha, ip6h, secure); ip_drop_packet(first_mp, B_TRUE, NULL, NULL, &ipdrops_tcp_clear, &tcp_dropper); @@ -12093,9 +12093,8 @@ * We have a secure packet. */ if (act == NULL) { - ipsec_log_policy_failure(tcp->tcp_wq, - IPSEC_POLICY_NOT_NEEDED, "tcp_check_policy", ipha, ip6h, - secure); + ipsec_log_policy_failure(IPSEC_POLICY_NOT_NEEDED, + "tcp_check_policy", ipha, ip6h, secure); ip_drop_packet(first_mp, B_TRUE, NULL, NULL, &ipdrops_tcp_secure, &tcp_dropper); return (B_FALSE);