Print this page
C. Fraire's code review fixes
8529 Extended and regular SADB_ACQUIREs should share address extension code
Portions contributed by: Bayard Bell <buffer.g.overflow@gmail.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/ip/sadb.c
          +++ new/usr/src/uts/common/inet/ip/sadb.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
       25 + * Copyright (c) 2017 Joyent, Inc.
  25   26   */
  26   27  
  27   28  #include <sys/types.h>
  28   29  #include <sys/stream.h>
  29   30  #include <sys/stropts.h>
  30   31  #include <sys/strsubr.h>
  31   32  #include <sys/errno.h>
  32   33  #include <sys/ddi.h>
  33   34  #include <sys/debug.h>
  34   35  #include <sys/cmn_err.h>
↓ open down ↓ 32 lines elided ↑ open up ↑
  67   68  #include <inet/ipclassifier.h>
  68   69  #include <inet/sctp_ip.h>
  69   70  #include <sys/tsol/tnet.h>
  70   71  
  71   72  /*
  72   73   * This source file contains Security Association Database (SADB) common
  73   74   * routines.  They are linked in with the AH module.  Since AH has no chance
  74   75   * of falling under export control, it was safe to link it in there.
  75   76   */
  76   77  
  77      -static mblk_t *sadb_extended_acquire(ipsec_selector_t *, ipsec_policy_t *,
  78      -    ipsec_action_t *, boolean_t, uint32_t, uint32_t, sadb_sens_t *,
       78 +static uint8_t *sadb_action_to_ecomb(uint8_t *, uint8_t *, ipsec_action_t *,
  79   79      netstack_t *);
  80   80  static ipsa_t *sadb_torch_assoc(isaf_t *, ipsa_t *);
  81   81  static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t,
  82   82                              netstack_t *);
  83   83  static void sadb_destroy(sadb_t *, netstack_t *);
  84   84  static mblk_t *sadb_sa2msg(ipsa_t *, sadb_msg_t *);
  85   85  static ts_label_t *sadb_label_from_sens(sadb_sens_t *, uint64_t *);
  86      -static sadb_sens_t *sadb_make_sens_ext(ts_label_t *tsl, int *len);
  87   86  
  88   87  static time_t sadb_add_time(time_t, uint64_t);
  89   88  static void lifetime_fuzz(ipsa_t *);
  90   89  static void age_pair_peer_list(templist_t *, sadb_t *, boolean_t);
  91   90  static int get_ipsa_pair(ipsa_query_t *, ipsap_t *, int *);
  92   91  static void init_ipsa_pair(ipsap_t *);
  93   92  static void destroy_ipsa_pair(ipsap_t *);
  94   93  static int update_pairing(ipsap_t *, ipsa_query_t *, keysock_in_t *, int *);
  95   94  static void ipsa_set_replay(ipsa_t *ipsa, uint32_t offset);
  96   95  
↓ open down ↓ 4740 lines elided ↑ open up ↑
4837 4836                      (unique_id == walker->ipsacq_unique_id) &&
4838 4837                      (ipsec_label_match(tsl, walker->ipsacq_tsl)))
4839 4838                          break;                  /* everything matched */
4840 4839                  mutex_exit(&walker->ipsacq_lock);
4841 4840          }
4842 4841  
4843 4842          return (walker);
4844 4843  }
4845 4844  
4846 4845  /*
     4846 + * Generate an SADB_ACQUIRE base message mblk, including KEYSOCK_OUT metadata.
     4847 + * In other words, this will return, upon success, a two-mblk chain.
     4848 + */
     4849 +static inline mblk_t *
     4850 +sadb_acquire_msg_base(minor_t serial, uint8_t satype, uint32_t seq, pid_t pid)
     4851 +{
     4852 +        mblk_t *mp;
     4853 +        sadb_msg_t *samsg;
     4854 +
     4855 +        mp = sadb_keysock_out(serial);
     4856 +        if (mp == NULL)
     4857 +                return (NULL);
     4858 +        mp->b_cont = allocb(sizeof (sadb_msg_t), BPRI_HI);
     4859 +        if (mp->b_cont == NULL) {
     4860 +                freeb(mp);
     4861 +                return (NULL);
     4862 +        }
     4863 +
     4864 +        samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
     4865 +        mp->b_cont->b_wptr += sizeof (*samsg);
     4866 +        samsg->sadb_msg_version = PF_KEY_V2;
     4867 +        samsg->sadb_msg_type = SADB_ACQUIRE;
     4868 +        samsg->sadb_msg_errno = 0;
     4869 +        samsg->sadb_msg_reserved = 0;
     4870 +        samsg->sadb_msg_satype = satype;
     4871 +        samsg->sadb_msg_seq = seq;
     4872 +        samsg->sadb_msg_pid = pid;
     4873 +
     4874 +        return (mp);
     4875 +}
     4876 +
     4877 +/*
     4878 + * Generate address and TX/MLS sensitivity label PF_KEY extensions that are
     4879 + * common to both regular and extended ACQUIREs.
     4880 + */
     4881 +static mblk_t *
     4882 +sadb_acquire_msg_common(ipsec_selector_t *sel, ipsec_policy_t *pp,
     4883 +    ipsec_action_t *ap, boolean_t tunnel_mode, ts_label_t *tsl,
     4884 +    sadb_sens_t *sens)
     4885 +{
     4886 +        size_t len;
     4887 +        mblk_t *mp;
     4888 +        uint8_t *start, *cur, *end;
     4889 +        uint32_t *saddrptr, *daddrptr;
     4890 +        sa_family_t af;
     4891 +        ipsec_action_t *oldap;
     4892 +        ipsec_selkey_t *ipsl;
     4893 +        uint8_t proto, pfxlen;
     4894 +        uint16_t lport, rport;
     4895 +        int senslen = 0;
     4896 +
     4897 +        /*
     4898 +         * Get action pointer set if it isn't already.
     4899 +         */
     4900 +        oldap = ap;
     4901 +        if (pp != NULL) {
     4902 +                ap = pp->ipsp_act;
     4903 +                if (ap == NULL)
     4904 +                        ap = oldap;
     4905 +        }
     4906 +
     4907 +        /*
     4908 +         * Biggest-case scenario:
     4909 +         * 4x (sadb_address_t + struct sockaddr_in6)
     4910 +         *      (src, dst, isrc, idst)
     4911 +         *      (COMING SOON, 6x, because of triggering-packet contents.)
     4912 +         * sadb_x_kmc_t
     4913 +         * sadb_sens_t
     4914 +         * And wiggle room for label bitvectors.  Luckily there are
     4915 +         * programmatic ways to find it.
     4916 +         */
     4917 +        len = 4 * (sizeof (sadb_address_t) + sizeof (struct sockaddr_in6));
     4918 +
     4919 +        /* Figure out full and proper length of sensitivity labels. */
     4920 +        if (sens != NULL) {
     4921 +                ASSERT(tsl == NULL);
     4922 +                senslen = SADB_64TO8(sens->sadb_sens_len);
     4923 +        } else if (tsl != NULL) {
     4924 +                senslen = sadb_sens_len_from_label(tsl);
     4925 +        }
     4926 +#ifdef DEBUG
     4927 +        else {
     4928 +                ASSERT(senslen == 0);
     4929 +        }
     4930 +#endif /* DEBUG */
     4931 +        len += senslen;
     4932 +
     4933 +        mp = allocb(len, BPRI_HI);
     4934 +        if (mp == NULL)
     4935 +                return (NULL);
     4936 +
     4937 +        start = mp->b_rptr;
     4938 +        end = start + len;
     4939 +        cur = start;
     4940 +
     4941 +        /*
     4942 +         * Address extensions first, from most-recently-defined to least.
     4943 +         * (This should immediately trigger surprise or verify robustness on
     4944 +         * older apps, like in.iked.)
     4945 +         */
     4946 +        if (tunnel_mode) {
     4947 +                /*
     4948 +                 * Form inner address extensions based NOT on the inner
     4949 +                 * selectors (i.e. the packet data), but on the policy's
     4950 +                 * selector key (i.e. the policy's selector information).
     4951 +                 *
     4952 +                 * NOTE:  The position of IPv4 and IPv6 addresses is the
     4953 +                 * same in ipsec_selkey_t (unless the compiler does very
     4954 +                 * strange things with unions, consult your local C language
     4955 +                 * lawyer for details).
     4956 +                 */
     4957 +                ASSERT(pp != NULL);
     4958 +
     4959 +                ipsl = &(pp->ipsp_sel->ipsl_key);
     4960 +                if (ipsl->ipsl_valid & IPSL_IPV4) {
     4961 +                        af = AF_INET;
     4962 +                        ASSERT(sel->ips_protocol == IPPROTO_ENCAP);
     4963 +                        ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6));
     4964 +                } else {
     4965 +                        af = AF_INET6;
     4966 +                        ASSERT(sel->ips_protocol == IPPROTO_IPV6);
     4967 +                        ASSERT(ipsl->ipsl_valid & IPSL_IPV6);
     4968 +                }
     4969 +
     4970 +                if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) {
     4971 +                        saddrptr = (uint32_t *)(&ipsl->ipsl_local);
     4972 +                        pfxlen = ipsl->ipsl_local_pfxlen;
     4973 +                } else {
     4974 +                        saddrptr = (uint32_t *)(&ipv6_all_zeros);
     4975 +                        pfxlen = 0;
     4976 +                }
     4977 +                /* XXX What about ICMP type/code? */
     4978 +                lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ?
     4979 +                    ipsl->ipsl_lport : 0;
     4980 +                proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ?
     4981 +                    ipsl->ipsl_proto : 0;
     4982 +
     4983 +                cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
     4984 +                    af, saddrptr, lport, proto, pfxlen);
     4985 +                if (cur == NULL) {
     4986 +                        freeb(mp);
     4987 +                        return (NULL);
     4988 +                }
     4989 +
     4990 +                if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) {
     4991 +                        daddrptr = (uint32_t *)(&ipsl->ipsl_remote);
     4992 +                        pfxlen = ipsl->ipsl_remote_pfxlen;
     4993 +                } else {
     4994 +                        daddrptr = (uint32_t *)(&ipv6_all_zeros);
     4995 +                        pfxlen = 0;
     4996 +                }
     4997 +                /* XXX What about ICMP type/code? */
     4998 +                rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ?
     4999 +                    ipsl->ipsl_rport : 0;
     5000 +
     5001 +                cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
     5002 +                    af, daddrptr, rport, proto, pfxlen);
     5003 +                if (cur == NULL) {
     5004 +                        freeb(mp);
     5005 +                        return (NULL);
     5006 +                }
     5007 +                /*
     5008 +                 * TODO  - if we go to 3884's dream of transport mode IP-in-IP
     5009 +                 * _with_ inner-packet address selectors, we'll need to further
     5010 +                 * distinguish tunnel mode here.  For now, having inner
     5011 +                 * addresses and/or ports is sufficient.
     5012 +                 *
     5013 +                 * Meanwhile, whack proto/ports to reflect IP-in-IP for the
     5014 +                 * outer addresses.
     5015 +                 */
     5016 +                proto = sel->ips_protocol;      /* Either _ENCAP or _IPV6 */
     5017 +                lport = rport = 0;
     5018 +        } else if ((ap != NULL) && (!ap->ipa_want_unique)) {
     5019 +                /*
     5020 +                 * For cases when the policy calls out specific ports (or not).
     5021 +                 */
     5022 +                proto = 0;
     5023 +                lport = 0;
     5024 +                rport = 0;
     5025 +                if (pp != NULL) {
     5026 +                        ipsl = &(pp->ipsp_sel->ipsl_key);
     5027 +                        if (ipsl->ipsl_valid & IPSL_PROTOCOL)
     5028 +                                proto = ipsl->ipsl_proto;
     5029 +                        if (ipsl->ipsl_valid & IPSL_REMOTE_PORT)
     5030 +                                rport = ipsl->ipsl_rport;
     5031 +                        if (ipsl->ipsl_valid & IPSL_LOCAL_PORT)
     5032 +                                lport = ipsl->ipsl_lport;
     5033 +                }
     5034 +        } else {
     5035 +                /*
     5036 +                 * For require-unique-SA policies.
     5037 +                 */
     5038 +                proto = sel->ips_protocol;
     5039 +                lport = sel->ips_local_port;
     5040 +                rport = sel->ips_remote_port;
     5041 +        }
     5042 +
     5043 +        /*
     5044 +         * Regular addresses.  These are outer-packet ones for tunnel mode.
     5045 +         * Or for transport mode, the regulard address & port information.
     5046 +         */
     5047 +        af = sel->ips_isv4 ? AF_INET : AF_INET6;
     5048 +
     5049 +        /*
     5050 +         * NOTE:  The position of IPv4 and IPv6 addresses is the same in
     5051 +         * ipsec_selector_t.
     5052 +         */
     5053 +        cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
     5054 +            (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0);
     5055 +        if (cur == NULL) {
     5056 +                freeb(mp);
     5057 +                return (NULL);
     5058 +        }
     5059 +
     5060 +        cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
     5061 +            (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0);
     5062 +        if (cur == NULL) {
     5063 +                freeb(mp);
     5064 +                return (NULL);
     5065 +        }
     5066 +
     5067 +        /*
     5068 +         * If present, generate a sensitivity label.
     5069 +         */
     5070 +        if (cur + senslen > end) {
     5071 +                freeb(mp);
     5072 +                return (NULL);
     5073 +        }
     5074 +        if (sens != NULL) {
     5075 +                /* Explicit sadb_sens_t, usually from inverse-ACQUIRE. */
     5076 +                bcopy(sens, cur, senslen);
     5077 +        } else if (tsl != NULL) {
     5078 +                /* Generate sadb_sens_t from ACQUIRE source. */
     5079 +                sadb_sens_from_label((sadb_sens_t *)cur, SADB_EXT_SENSITIVITY,
     5080 +                    tsl, senslen);
     5081 +        }
     5082 +#ifdef DEBUG
     5083 +        else {
     5084 +                ASSERT(senslen == 0);
     5085 +        }
     5086 +#endif /* DEBUG */
     5087 +        cur += senslen;
     5088 +        mp->b_wptr = cur;
     5089 +
     5090 +        return (mp);
     5091 +}
     5092 +
     5093 +/*
     5094 + * Generate a regular ACQUIRE's proposal extension and KMC information..
     5095 + */
     5096 +static mblk_t *
     5097 +sadb_acquire_prop(ipsec_action_t *ap, netstack_t *ns, boolean_t do_esp)
     5098 +{
     5099 +        ipsec_stack_t *ipss = ns->netstack_ipsec;
     5100 +        ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
     5101 +        ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
     5102 +        mblk_t *mp = NULL;
     5103 +        sadb_prop_t *prop;
     5104 +        sadb_comb_t *comb;
     5105 +        ipsec_action_t *walker;
     5106 +        int ncombs, allocsize, ealgid, aalgid, aminbits, amaxbits, eminbits,
     5107 +            emaxbits, replay;
     5108 +        uint64_t softbytes, hardbytes, softaddtime, hardaddtime, softusetime,
     5109 +            hardusetime;
     5110 +        uint32_t kmc = 0, kmp = 0;
     5111 +
     5112 +        /*
     5113 +         * Since it's an rwlock read, AND writing to the IPsec algorithms is
     5114 +         * rare, just acquire it once up top, and drop it upon return.
     5115 +         */
     5116 +        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
     5117 +        if (do_esp) {
     5118 +                uint64_t num_aalgs, num_ealgs;
     5119 +
     5120 +                if (espstack->esp_kstats == NULL)
     5121 +                        goto bail;
     5122 +
     5123 +                num_aalgs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
     5124 +                num_ealgs = ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
     5125 +                if (num_ealgs == 0)
     5126 +                        goto bail;      /* IPsec not loaded yet, apparently. */
     5127 +                num_aalgs++;    /* No-auth or self-auth-crypto ESP. */
     5128 +
     5129 +                /* Use netstack's maximum loaded algorithms... */
     5130 +                ncombs = num_ealgs * num_aalgs;
     5131 +                replay =  espstack->ipsecesp_replay_size;
     5132 +        } else {
     5133 +                if (ahstack->ah_kstats == NULL)
     5134 +                        goto bail;
     5135 +
     5136 +                ncombs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
     5137 +
     5138 +                if (ncombs == 0)
     5139 +                        goto bail;      /* IPsec not loaded yet, apparently. */
     5140 +                replay =  ahstack->ipsecah_replay_size;
     5141 +        }
     5142 +
     5143 +        allocsize = sizeof (*prop) + ncombs * sizeof (*comb) +
     5144 +            sizeof (sadb_x_kmc_t);
     5145 +        mp = allocb(allocsize, BPRI_HI);
     5146 +        if (mp == NULL)
     5147 +                goto bail;
     5148 +        prop = (sadb_prop_t *)mp->b_rptr;
     5149 +        mp->b_wptr += sizeof (*prop);
     5150 +        comb = (sadb_comb_t *)mp->b_wptr;
     5151 +        /* Decrement allocsize, if it goes to or below 0, stop. */
     5152 +        allocsize -= sizeof (*prop);
     5153 +        prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
     5154 +        prop->sadb_prop_len = SADB_8TO64(sizeof (*prop));
     5155 +        *(uint32_t *)(&prop->sadb_prop_replay) = 0;     /* Quick zero-out! */
     5156 +        prop->sadb_prop_replay = replay;
     5157 +
     5158 +        /*
     5159 +         * Based upon algorithm properties, and what-not, prioritize a
     5160 +         * proposal, based on the ordering of the ESP algorithms in the
     5161 +         * alternatives in the policy rule or socket that was placed
     5162 +         * in the acquire record.
     5163 +         *
     5164 +         * For each action in policy list
     5165 +         *   Add combination.
     5166 +         *   I should not hit it, but if I've hit limit, return.
     5167 +         */
     5168 +
     5169 +        for (walker = ap; walker != NULL; walker = walker->ipa_next) {
     5170 +                ipsec_alginfo_t *ealg, *aalg;
     5171 +                ipsec_prot_t *prot;
     5172 +
     5173 +                if (walker->ipa_act.ipa_type != IPSEC_POLICY_APPLY)
     5174 +                        continue;
     5175 +
     5176 +                prot = &walker->ipa_act.ipa_apply;
     5177 +                if (walker->ipa_act.ipa_apply.ipp_km_proto != 0)
     5178 +                        kmp = walker->ipa_act.ipa_apply.ipp_km_proto;
     5179 +                if (walker->ipa_act.ipa_apply.ipp_km_cookie != 0)
     5180 +                        kmc = walker->ipa_act.ipa_apply.ipp_km_cookie;
     5181 +                if (walker->ipa_act.ipa_apply.ipp_replay_depth) {
     5182 +                        prop->sadb_prop_replay =
     5183 +                            walker->ipa_act.ipa_apply.ipp_replay_depth;
     5184 +                }
     5185 +
     5186 +                if (do_esp) {
     5187 +                        if (!prot->ipp_use_esp)
     5188 +                                continue;
     5189 +
     5190 +                        if (prot->ipp_esp_auth_alg != 0) {
     5191 +                                aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
     5192 +                                    [prot->ipp_esp_auth_alg];
     5193 +                                if (aalg == NULL || !ALG_VALID(aalg))
     5194 +                                        continue;
     5195 +                        } else
     5196 +                                aalg = NULL;
     5197 +
     5198 +                        ASSERT(prot->ipp_encr_alg > 0);
     5199 +                        ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
     5200 +                            [prot->ipp_encr_alg];
     5201 +                        if (ealg == NULL || !ALG_VALID(ealg))
     5202 +                                continue;
     5203 +
     5204 +                        /*
     5205 +                         * These may want to come from policy rule..
     5206 +                         */
     5207 +                        softbytes = espstack->ipsecesp_default_soft_bytes;
     5208 +                        hardbytes = espstack->ipsecesp_default_hard_bytes;
     5209 +                        softaddtime = espstack->ipsecesp_default_soft_addtime;
     5210 +                        hardaddtime = espstack->ipsecesp_default_hard_addtime;
     5211 +                        softusetime = espstack->ipsecesp_default_soft_usetime;
     5212 +                        hardusetime = espstack->ipsecesp_default_hard_usetime;
     5213 +                } else {
     5214 +                        if (!prot->ipp_use_ah)
     5215 +                                continue;
     5216 +                        ealg = NULL;
     5217 +                        aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
     5218 +                            [prot->ipp_auth_alg];
     5219 +                        if (aalg == NULL || !ALG_VALID(aalg))
     5220 +                                continue;
     5221 +
     5222 +                        /*
     5223 +                         * These may want to come from policy rule..
     5224 +                         */
     5225 +                        softbytes = ahstack->ipsecah_default_soft_bytes;
     5226 +                        hardbytes = ahstack->ipsecah_default_hard_bytes;
     5227 +                        softaddtime = ahstack->ipsecah_default_soft_addtime;
     5228 +                        hardaddtime = ahstack->ipsecah_default_hard_addtime;
     5229 +                        softusetime = ahstack->ipsecah_default_soft_usetime;
     5230 +                        hardusetime = ahstack->ipsecah_default_hard_usetime;
     5231 +                }
     5232 +
     5233 +                if (ealg == NULL) {
     5234 +                        ealgid = eminbits = emaxbits = 0;
     5235 +                } else {
     5236 +                        ealgid = ealg->alg_id;
     5237 +                        eminbits =
     5238 +                            MAX(prot->ipp_espe_minbits, ealg->alg_ef_minbits);
     5239 +                        emaxbits =
     5240 +                            MIN(prot->ipp_espe_maxbits, ealg->alg_ef_maxbits);
     5241 +                }
     5242 +
     5243 +                if (aalg == NULL) {
     5244 +                        aalgid = aminbits = amaxbits = 0;
     5245 +                } else {
     5246 +                        aalgid = aalg->alg_id;
     5247 +                        aminbits = MAX(prot->ipp_espa_minbits,
     5248 +                            aalg->alg_ef_minbits);
     5249 +                        amaxbits = MIN(prot->ipp_espa_maxbits,
     5250 +                            aalg->alg_ef_maxbits);
     5251 +                }
     5252 +
     5253 +                comb->sadb_comb_flags = 0;
     5254 +                comb->sadb_comb_reserved = 0;
     5255 +                comb->sadb_comb_encrypt = ealgid;
     5256 +                comb->sadb_comb_encrypt_minbits = eminbits;
     5257 +                comb->sadb_comb_encrypt_maxbits = emaxbits;
     5258 +                comb->sadb_comb_auth = aalgid;
     5259 +                comb->sadb_comb_auth_minbits = aminbits;
     5260 +                comb->sadb_comb_auth_maxbits = amaxbits;
     5261 +                comb->sadb_comb_soft_allocations = 0;
     5262 +                comb->sadb_comb_hard_allocations = 0;
     5263 +                comb->sadb_comb_soft_bytes = softbytes;
     5264 +                comb->sadb_comb_hard_bytes = hardbytes;
     5265 +                comb->sadb_comb_soft_addtime = softaddtime;
     5266 +                comb->sadb_comb_hard_addtime = hardaddtime;
     5267 +                comb->sadb_comb_soft_usetime = softusetime;
     5268 +                comb->sadb_comb_hard_usetime = hardusetime;
     5269 +
     5270 +                prop->sadb_prop_len += SADB_8TO64(sizeof (*comb));
     5271 +                mp->b_wptr += sizeof (*comb);
     5272 +                allocsize -= sizeof (*comb);
     5273 +                /* Should never dip BELOW sizeof (KM cookie extension). */
     5274 +                ASSERT3S(allocsize, >=, sizeof (sadb_x_kmc_t));
     5275 +                if (allocsize <= sizeof (sadb_x_kmc_t))
     5276 +                        break;  /* out of space.. */
     5277 +                comb++;
     5278 +        }
     5279 +
     5280 +        /* Don't include KMC extension if there's no room. */
     5281 +        if (((kmp != 0) || (kmc != 0)) && allocsize >= sizeof (sadb_x_kmc_t)) {
     5282 +                if (sadb_make_kmc_ext(mp->b_wptr,
     5283 +                    mp->b_wptr + sizeof (sadb_x_kmc_t), kmp, kmc) == NULL) {
     5284 +                        freeb(mp);
     5285 +                        mp = NULL;
     5286 +                        goto bail;
     5287 +                }
     5288 +                mp->b_wptr += sizeof (sadb_x_kmc_t);
     5289 +                prop->sadb_prop_len += SADB_8TO64(sizeof (sadb_x_kmc_t));
     5290 +        }
     5291 +
     5292 +bail:
     5293 +        rw_exit(&ipss->ipsec_alg_lock);
     5294 +        return (mp);
     5295 +}
     5296 +
     5297 +/*
     5298 + * Generate an extended ACQUIRE's extended-proposal extension.
     5299 + */
     5300 +/* ARGSUSED */
     5301 +static mblk_t *
     5302 +sadb_acquire_extended_prop(ipsec_action_t *ap, netstack_t *ns)
     5303 +{
     5304 +        sadb_prop_t *eprop;
     5305 +        uint8_t *cur, *end;
     5306 +        mblk_t *mp;
     5307 +        int allocsize, numecombs = 0, numalgdescs = 0;
     5308 +        uint32_t kmc = 0, kmp = 0, replay = 0;
     5309 +        ipsec_action_t *walker;
     5310 +
     5311 +        allocsize = sizeof (*eprop);
     5312 +
     5313 +        /*
     5314 +         * Going to walk through the action list twice.  Once for allocation
     5315 +         * measurement, and once for actual construction.
     5316 +         */
     5317 +        for (walker = ap; walker != NULL; walker = walker->ipa_next) {
     5318 +                ipsec_prot_t *ipp;
     5319 +
     5320 +                /*
     5321 +                 * Skip non-IPsec policies
     5322 +                 */
     5323 +                if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY)
     5324 +                        continue;
     5325 +
     5326 +                ipp = &walker->ipa_act.ipa_apply;
     5327 +
     5328 +                if (walker->ipa_act.ipa_apply.ipp_km_proto)
     5329 +                        kmp = ipp->ipp_km_proto;
     5330 +                if (walker->ipa_act.ipa_apply.ipp_km_cookie)
     5331 +                        kmc = ipp->ipp_km_cookie;
     5332 +                if (walker->ipa_act.ipa_apply.ipp_replay_depth)
     5333 +                        replay = ipp->ipp_replay_depth;
     5334 +
     5335 +                if (ipp->ipp_use_ah)
     5336 +                        numalgdescs++;
     5337 +                if (ipp->ipp_use_esp) {
     5338 +                        numalgdescs++;
     5339 +                        if (ipp->ipp_use_espa)
     5340 +                                numalgdescs++;
     5341 +                }
     5342 +
     5343 +                numecombs++;
     5344 +        }
     5345 +        ASSERT(numecombs > 0);
     5346 +
     5347 +        allocsize += numecombs * sizeof (sadb_x_ecomb_t) +
     5348 +            numalgdescs * sizeof (sadb_x_algdesc_t) + sizeof (sadb_x_kmc_t);
     5349 +        mp = allocb(allocsize, BPRI_HI);
     5350 +        if (mp == NULL)
     5351 +                return (NULL);
     5352 +        eprop = (sadb_prop_t *)mp->b_rptr;
     5353 +        end = mp->b_rptr + allocsize;
     5354 +        cur = mp->b_rptr + sizeof (*eprop);
     5355 +
     5356 +        eprop->sadb_prop_exttype = SADB_X_EXT_EPROP;
     5357 +        eprop->sadb_x_prop_ereserved = 0;
     5358 +        eprop->sadb_x_prop_numecombs = 0;
     5359 +        *(uint32_t *)(&eprop->sadb_prop_replay) = 0;    /* Quick zero-out! */
     5360 +        /* Pick ESP's replay default if need be. */
     5361 +        eprop->sadb_prop_replay = (replay == 0) ?
     5362 +            ns->netstack_ipsecesp->ipsecesp_replay_size : replay;
     5363 +
     5364 +        /* This time, walk through and actually allocate. */
     5365 +        for (walker = ap; walker != NULL; walker = walker->ipa_next) {
     5366 +                /*
     5367 +                 * Skip non-IPsec policies
     5368 +                 */
     5369 +                if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY)
     5370 +                        continue;
     5371 +                cur = sadb_action_to_ecomb(cur, end, walker, ns);
     5372 +                if (cur == NULL) {
     5373 +                        /* NOTE: inverse-ACQUIRE should note this as ENOMEM. */
     5374 +                        freeb(mp);
     5375 +                        return (NULL);
     5376 +                }
     5377 +                eprop->sadb_x_prop_numecombs++;
     5378 +        }
     5379 +
     5380 +        ASSERT(end - cur >= sizeof (sadb_x_kmc_t));
     5381 +        if ((kmp != 0) || (kmc != 0)) {
     5382 +                cur = sadb_make_kmc_ext(cur, end, kmp, kmc);
     5383 +                if (cur == NULL) {
     5384 +                        freeb(mp);
     5385 +                        return (NULL);
     5386 +                }
     5387 +        }
     5388 +        mp->b_wptr = cur;
     5389 +        eprop->sadb_prop_len = SADB_8TO64(cur - mp->b_rptr);
     5390 +
     5391 +        return (mp);
     5392 +}
     5393 +
     5394 +/*
4847 5395   * For this mblk, insert a new acquire record.  Assume bucket contains addrs
4848 5396   * of all of the same length.  Give up (and drop) if memory
4849 5397   * cannot be allocated for a new one; otherwise, invoke callback to
4850 5398   * send the acquire up..
4851 5399   *
4852 5400   * In cases where we need both AH and ESP, add the SA to the ESP ACQUIRE
4853 5401   * list.  The ah_add_sa_finish() routines can look at the packet's attached
4854 5402   * attributes and handle this case specially.
4855 5403   */
4856 5404  void
4857 5405  sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah,
4858 5406      boolean_t need_esp)
4859 5407  {
4860      -        mblk_t  *asyncmp;
     5408 +        mblk_t  *asyncmp, *regular, *extended, *common, *prop, *eprop;
4861 5409          sadbp_t *spp;
4862 5410          sadb_t *sp;
4863 5411          ipsacq_t *newbie;
4864 5412          iacqf_t *bucket;
4865      -        mblk_t *extended;
4866 5413          ipha_t *ipha = (ipha_t *)datamp->b_rptr;
4867 5414          ip6_t *ip6h = (ip6_t *)datamp->b_rptr;
4868 5415          uint32_t *src, *dst, *isrc, *idst;
4869 5416          ipsec_policy_t *pp = ixa->ixa_ipsec_policy;
4870 5417          ipsec_action_t *ap = ixa->ixa_ipsec_action;
4871 5418          sa_family_t af;
4872 5419          int hashoffset;
4873 5420          uint32_t seq;
4874 5421          uint64_t unique_id = 0;
4875      -        ipsec_selector_t sel;
4876 5422          boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL) != 0;
4877      -        ts_label_t      *tsl = NULL;
     5423 +        ts_label_t      *tsl;
4878 5424          netstack_t      *ns = ixa->ixa_ipst->ips_netstack;
4879 5425          ipsec_stack_t   *ipss = ns->netstack_ipsec;
4880      -        sadb_sens_t     *sens = NULL;
4881      -        int             sens_len;
     5426 +        ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
     5427 +        ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
     5428 +        ipsec_selector_t sel;
     5429 +        queue_t *q;
4882 5430  
4883 5431          ASSERT((pp != NULL) || (ap != NULL));
4884 5432  
4885      -        ASSERT(need_ah != NULL || need_esp != NULL);
     5433 +        ASSERT(need_ah || need_esp);
4886 5434  
4887 5435          /* Assign sadb pointers */
4888      -        if (need_esp) { /* ESP for AH+ESP */
4889      -                ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
4890      -
     5436 +        if (need_esp) {
     5437 +                /*
     5438 +                 * ESP happens first if we need both AH and ESP.
     5439 +                 */
4891 5440                  spp = &espstack->esp_sadb;
4892 5441          } else {
4893      -                ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
4894      -
4895 5442                  spp = &ahstack->ah_sadb;
4896 5443          }
4897 5444          sp = (ixa->ixa_flags & IXAF_IS_IPV4) ? &spp->s_v4 : &spp->s_v6;
4898 5445  
4899 5446          if (is_system_labeled())
4900 5447                  tsl = ixa->ixa_tsl;
     5448 +        else
     5449 +                tsl = NULL;
4901 5450  
4902 5451          if (ap == NULL)
4903 5452                  ap = pp->ipsp_act;
4904      -
4905 5453          ASSERT(ap != NULL);
4906 5454  
4907 5455          if (ap->ipa_act.ipa_apply.ipp_use_unique || tunnel_mode)
4908 5456                  unique_id = SA_FORM_UNIQUE_ID(ixa);
4909 5457  
4910 5458          /*
4911 5459           * Set up an ACQUIRE record.
4912 5460           *
4913 5461           * Immediately, make sure the ACQUIRE sequence number doesn't slip
4914 5462           * below the lowest point allowed in the kernel.  (In other words,
↓ open down ↓ 109 lines elided ↑ open up ↑
5024 5572                  /* Statistics for allocation failure */
5025 5573                  if (ixa->ixa_flags & IXAF_IS_IPV4) {
5026 5574                          BUMP_MIB(&ixa->ixa_ipst->ips_ip_mib,
5027 5575                              ipIfStatsOutDiscards);
5028 5576                  } else {
5029 5577                          BUMP_MIB(&ixa->ixa_ipst->ips_ip6_mib,
5030 5578                              ipIfStatsOutDiscards);
5031 5579                  }
5032 5580                  ip_drop_output("No memory for asyncmp", datamp, NULL);
5033 5581                  freemsg(datamp);
     5582 +                /*
     5583 +                 * The acquire record will be freed quickly if it's new
     5584 +                 * (ipsacq_expire == 0), and will proceed as if no packet
     5585 +                 * showed up if not.
     5586 +                 */
     5587 +                mutex_exit(&newbie->ipsacq_lock);
     5588 +                return;
5034 5589          } else if (newbie->ipsacq_numpackets == 0) {
5035 5590                  /* First one. */
5036 5591                  newbie->ipsacq_mp = asyncmp;
5037 5592                  newbie->ipsacq_numpackets = 1;
5038 5593                  newbie->ipsacq_expire = gethrestime_sec();
5039 5594                  /*
5040 5595                   * Extended ACQUIRE with both AH+ESP will use ESP's timeout
5041 5596                   * value.
5042 5597                   */
5043 5598                  newbie->ipsacq_expire += *spp->s_acquire_timeout;
↓ open down ↓ 12 lines elided ↑ open up ↑
5056 5611                          newbie->ipsacq_innerdstpfx = ixa->ixa_ipsec_indstpfx;
5057 5612                          IPSA_COPY_ADDR(newbie->ipsacq_innersrc,
5058 5613                              ixa->ixa_ipsec_insrc, ixa->ixa_ipsec_inaf);
5059 5614                          IPSA_COPY_ADDR(newbie->ipsacq_innerdst,
5060 5615                              ixa->ixa_ipsec_indst, ixa->ixa_ipsec_inaf);
5061 5616                  } else {
5062 5617                          newbie->ipsacq_proto = ixa->ixa_ipsec_proto;
5063 5618                  }
5064 5619                  newbie->ipsacq_unique_id = unique_id;
5065 5620  
5066      -                if (ixa->ixa_tsl != NULL) {
5067      -                        label_hold(ixa->ixa_tsl);
5068      -                        newbie->ipsacq_tsl = ixa->ixa_tsl;
     5621 +                if (tsl != NULL) {
     5622 +                        label_hold(tsl);
     5623 +                        newbie->ipsacq_tsl = tsl;
5069 5624                  }
5070 5625          } else {
5071 5626                  /* Scan to the end of the list & insert. */
5072 5627                  mblk_t *lastone = newbie->ipsacq_mp;
5073 5628  
5074 5629                  while (lastone->b_next != NULL)
5075 5630                          lastone = lastone->b_next;
5076 5631                  lastone->b_next = asyncmp;
5077 5632                  if (newbie->ipsacq_numpackets++ == ipsacq_maxpackets) {
5078 5633                          newbie->ipsacq_numpackets = ipsacq_maxpackets;
↓ open down ↓ 24 lines elided ↑ open up ↑
5103 5658          /*
5104 5659           * If the acquire record has more than one queued packet, we've
5105 5660           * already sent an ACQUIRE, and don't need to repeat ourself.
5106 5661           */
5107 5662          if (newbie->ipsacq_seq != seq || newbie->ipsacq_numpackets > 1) {
5108 5663                  /* I have an acquire outstanding already! */
5109 5664                  mutex_exit(&newbie->ipsacq_lock);
5110 5665                  return;
5111 5666          }
5112 5667  
5113      -        if (!keysock_extended_reg(ns))
5114      -                goto punt_extended;
     5668 +        if (need_esp) {
     5669 +                ESP_BUMP_STAT(espstack, acquire_requests);
     5670 +                q = espstack->esp_pfkey_q;
     5671 +        } else {
     5672 +                /*
     5673 +                 * Two cases get us here:
     5674 +                 * 1.) AH-only policy.
     5675 +                 *
     5676 +                 * 2.) A continuation of an AH+ESP policy, and this is the
     5677 +                 * post-ESP, AH-needs-to-send-a-regular-ACQUIRE case.
     5678 +                 * (i.e. called from esp_do_outbound_ah().)
     5679 +                 */
     5680 +                AH_BUMP_STAT(ahstack, acquire_requests);
     5681 +                q = ahstack->ah_pfkey_q;
     5682 +        }
     5683 +
5115 5684          /*
5116      -         * Construct an extended ACQUIRE.  There are logging
5117      -         * opportunities here in failure cases.
     5685 +         * Get selectors and other policy-expression bits needed for an
     5686 +         * ACQUIRE.
5118 5687           */
5119 5688          bzero(&sel, sizeof (sel));
5120 5689          sel.ips_isv4 = (ixa->ixa_flags & IXAF_IS_IPV4) != 0;
5121 5690          if (tunnel_mode) {
5122 5691                  sel.ips_protocol = (ixa->ixa_ipsec_inaf == AF_INET) ?
5123 5692                      IPPROTO_ENCAP : IPPROTO_IPV6;
5124 5693          } else {
5125 5694                  sel.ips_protocol = ixa->ixa_ipsec_proto;
5126 5695                  sel.ips_local_port = ixa->ixa_ipsec_src_port;
5127 5696                  sel.ips_remote_port = ixa->ixa_ipsec_dst_port;
↓ open down ↓ 2 lines elided ↑ open up ↑
5130 5699          sel.ips_icmp_code = ixa->ixa_ipsec_icmp_code;
5131 5700          sel.ips_is_icmp_inv_acq = 0;
5132 5701          if (af == AF_INET) {
5133 5702                  sel.ips_local_addr_v4 = ipha->ipha_src;
5134 5703                  sel.ips_remote_addr_v4 = ipha->ipha_dst;
5135 5704          } else {
5136 5705                  sel.ips_local_addr_v6 = ip6h->ip6_src;
5137 5706                  sel.ips_remote_addr_v6 = ip6h->ip6_dst;
5138 5707          }
5139 5708  
5140      -        extended = sadb_keysock_out(0);
5141      -        if (extended == NULL)
5142      -                goto punt_extended;
5143 5709  
5144      -        if (ixa->ixa_tsl != NULL) {
5145      -                /*
5146      -                 * XXX MLS correct condition here?
5147      -                 * XXX MLS other credential attributes in acquire?
5148      -                 * XXX malloc failure?  don't fall back to original?
5149      -                 */
5150      -                sens = sadb_make_sens_ext(ixa->ixa_tsl, &sens_len);
     5710 +        /*
     5711 +         * 1. Generate addresses, kmc, and sensitivity.  These are "common"
     5712 +         * and should be an mblk pointed to by common. TBD -- eventually it
     5713 +         * will include triggering packet contents as more address extensions.
     5714 +         *
     5715 +         * 2. Generate ACQUIRE & KEYSOCK_OUT and single-protocol proposal.
     5716 +         * These are "regular" and "prop".  String regular->b_cont->b_cont =
     5717 +         * common, common->b_cont = prop.
     5718 +         *
     5719 +         * 3. If extended register got turned on, generate EXT_ACQUIRE &
     5720 +         * KEYSOCK_OUT and multi-protocol eprop. These are "extended" and
     5721 +         * "eprop".  String extended->b_cont->b_cont = dupb(common) and
     5722 +         * extended->b_cont->b_cont->b_cont = prop.
     5723 +         *
     5724 +         * 4. Deliver:  putnext(q, regular) and if there, putnext(q, extended).
     5725 +         */
5151 5726  
5152      -                if (sens == NULL) {
5153      -                        freeb(extended);
5154      -                        goto punt_extended;
5155      -                }
5156      -        }
     5727 +        regular = extended = prop = eprop = NULL;
5157 5728  
5158      -        extended->b_cont = sadb_extended_acquire(&sel, pp, ap, tunnel_mode,
5159      -            seq, 0, sens, ns);
     5729 +        common = sadb_acquire_msg_common(&sel, pp, ap, tunnel_mode, tsl, NULL);
     5730 +        if (common == NULL)
     5731 +                goto bail;
5160 5732  
5161      -        if (sens != NULL)
5162      -                kmem_free(sens, sens_len);
     5733 +        regular = sadb_acquire_msg_base(0, (need_esp ?
     5734 +            SADB_SATYPE_ESP : SADB_SATYPE_AH), newbie->ipsacq_seq, 0);
     5735 +        if (regular == NULL)
     5736 +                goto bail;
5163 5737  
5164      -        if (extended->b_cont == NULL) {
5165      -                freeb(extended);
5166      -                goto punt_extended;
5167      -        }
     5738 +        /*
     5739 +         * Pardon the boolean cleverness. At least one of need_* must be true.
     5740 +         * If they are equal, it's an AH & ESP policy and ESP needs to go
     5741 +         * first.  If they aren't, just check the contents of need_esp.
     5742 +         */
     5743 +        prop = sadb_acquire_prop(ap, ns, need_esp);
     5744 +        if (prop == NULL)
     5745 +                goto bail;
5168 5746  
     5747 +        /* Link the parts together. */
     5748 +        regular->b_cont->b_cont = common;
     5749 +        common->b_cont = prop;
5169 5750          /*
5170      -         * Send an ACQUIRE message (and possible an extended ACQUIRE) based on
5171      -         * this new record.  The send-acquire callback assumes that acqrec is
5172      -         * already locked.
     5751 +         * Prop is now linked, so don't freemsg() it if the extended
     5752 +         * construction goes off the rails.
5173 5753           */
5174      -        (*spp->s_acqfn)(newbie, extended, ns);
     5754 +        prop = NULL;
     5755 +
     5756 +        ((sadb_msg_t *)(regular->b_cont->b_rptr))->sadb_msg_len =
     5757 +            SADB_8TO64(msgsize(regular->b_cont));
     5758 +
     5759 +        /*
     5760 +         * If we need an extended ACQUIRE, build it here.
     5761 +         */
     5762 +        if (keysock_extended_reg(ns)) {
     5763 +                /* NOTE: "common" still points to what we need. */
     5764 +                extended = sadb_acquire_msg_base(0, 0, newbie->ipsacq_seq, 0);
     5765 +                if (extended == NULL) {
     5766 +                        common = NULL;
     5767 +                        goto bail;
     5768 +                }
     5769 +
     5770 +                extended->b_cont->b_cont = dupb(common);
     5771 +                common = NULL;
     5772 +                if (extended->b_cont->b_cont == NULL)
     5773 +                        goto bail;
     5774 +
     5775 +                eprop = sadb_acquire_extended_prop(ap, ns);
     5776 +                if (eprop == NULL)
     5777 +                        goto bail;
     5778 +                extended->b_cont->b_cont->b_cont = eprop;
     5779 +
     5780 +                ((sadb_msg_t *)(extended->b_cont->b_rptr))->sadb_msg_len =
     5781 +                    SADB_8TO64(msgsize(extended->b_cont));
     5782 +        }
     5783 +
     5784 +        /* So we don't hold a lock across putnext()... */
     5785 +        mutex_exit(&newbie->ipsacq_lock);
     5786 +
     5787 +        if (extended != NULL)
     5788 +                putnext(q, extended);
     5789 +        ASSERT(regular != NULL);
     5790 +        putnext(q, regular);
5175 5791          return;
5176 5792  
5177      -punt_extended:
5178      -        (*spp->s_acqfn)(newbie, NULL, ns);
     5793 +bail:
     5794 +        /* Make this acquire record go away quickly... */
     5795 +        newbie->ipsacq_expire = 0;
     5796 +        /* Exploit freemsg(NULL) being legal for fun & profit. */
     5797 +        freemsg(common);
     5798 +        freemsg(prop);
     5799 +        freemsg(extended);
     5800 +        freemsg(regular);
     5801 +        mutex_exit(&newbie->ipsacq_lock);
5179 5802  }
5180 5803  
5181 5804  /*
5182 5805   * Unlink and free an acquire record.
5183 5806   */
5184 5807  void
5185 5808  sadb_destroy_acquire(ipsacq_t *acqrec, netstack_t *ns)
5186 5809  {
5187 5810          mblk_t          *mp;
5188 5811          ipsec_stack_t   *ipss = ns->netstack_ipsec;
↓ open down ↓ 233 lines elided ↑ open up ↑
5422 6045          sens->sadb_sens_sens_level = LCLASS(sl);
5423 6046          sens->sadb_sens_integ_level = 0; /* TBD */
5424 6047          sens->sadb_sens_sens_len = _C_LEN >> 1;
5425 6048          sens->sadb_sens_integ_len = 0; /* TBD */
5426 6049          sens->sadb_x_sens_flags = 0;
5427 6050  
5428 6051          bitmap = (uint8_t *)(sens + 1);
5429 6052          bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4);
5430 6053  }
5431 6054  
5432      -static sadb_sens_t *
5433      -sadb_make_sens_ext(ts_label_t *tsl, int *len)
5434      -{
5435      -        /* XXX allocation failure? */
5436      -        int sens_len = sadb_sens_len_from_label(tsl);
5437      -
5438      -        sadb_sens_t *sens = kmem_alloc(sens_len, KM_SLEEP);
5439      -
5440      -        sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY, tsl, sens_len);
5441      -
5442      -        *len = sens_len;
5443      -
5444      -        return (sens);
5445      -}
5446      -
5447 6055  /*
5448 6056   * Okay, how do we report errors/invalid labels from this?
5449 6057   * With a special designated "not a label" cred_t ?
5450 6058   */
5451 6059  /* ARGSUSED */
5452 6060  ts_label_t *
5453 6061  sadb_label_from_sens(sadb_sens_t *sens, uint64_t *bitmap)
5454 6062  {
5455 6063          int bitmap_len = SADB_64TO8(sens->sadb_sens_sens_len);
5456 6064          bslabel_t sl;
↓ open down ↓ 16 lines elided ↑ open up ↑
5473 6081                  return (NULL);
5474 6082  
5475 6083          if (sens->sadb_x_sens_flags & SADB_X_SENS_UNLABELED)
5476 6084                  tsl->tsl_flags |= TSLF_UNLABELED;
5477 6085          return (tsl);
5478 6086  }
5479 6087  
5480 6088  /* End XXX label-library-leakage */
5481 6089  
5482 6090  /*
5483      - * Construct an extended ACQUIRE message based on a selector and the resulting
5484      - * IPsec action.
5485      - *
5486      - * NOTE: This is used by both inverse ACQUIRE and actual ACQUIRE
5487      - * generation. As a consequence, expect this function to evolve
5488      - * rapidly.
5489      - */
5490      -static mblk_t *
5491      -sadb_extended_acquire(ipsec_selector_t *sel, ipsec_policy_t *pol,
5492      -    ipsec_action_t *act, boolean_t tunnel_mode, uint32_t seq, uint32_t pid,
5493      -    sadb_sens_t *sens, netstack_t *ns)
5494      -{
5495      -        mblk_t *mp;
5496      -        sadb_msg_t *samsg;
5497      -        uint8_t *start, *cur, *end;
5498      -        uint32_t *saddrptr, *daddrptr;
5499      -        sa_family_t af;
5500      -        sadb_prop_t *eprop;
5501      -        ipsec_action_t *ap, *an;
5502      -        ipsec_selkey_t *ipsl;
5503      -        uint8_t proto, pfxlen;
5504      -        uint16_t lport, rport;
5505      -        uint32_t kmp, kmc;
5506      -
5507      -        /*
5508      -         * Find the action we want sooner rather than later..
5509      -         */
5510      -        an = NULL;
5511      -        if (pol == NULL) {
5512      -                ap = act;
5513      -        } else {
5514      -                ap = pol->ipsp_act;
5515      -
5516      -                if (ap != NULL)
5517      -                        an = ap->ipa_next;
5518      -        }
5519      -
5520      -        /*
5521      -         * Just take a swag for the allocation for now.  We can always
5522      -         * alter it later.
5523      -         */
5524      -#define SADB_EXTENDED_ACQUIRE_SIZE      4096
5525      -        mp = allocb(SADB_EXTENDED_ACQUIRE_SIZE, BPRI_HI);
5526      -        if (mp == NULL)
5527      -                return (NULL);
5528      -
5529      -        start = mp->b_rptr;
5530      -        end = start + SADB_EXTENDED_ACQUIRE_SIZE;
5531      -
5532      -        cur = start;
5533      -
5534      -        samsg = (sadb_msg_t *)cur;
5535      -        cur += sizeof (*samsg);
5536      -
5537      -        samsg->sadb_msg_version = PF_KEY_V2;
5538      -        samsg->sadb_msg_type = SADB_ACQUIRE;
5539      -        samsg->sadb_msg_errno = 0;
5540      -        samsg->sadb_msg_reserved = 0;
5541      -        samsg->sadb_msg_satype = 0;
5542      -        samsg->sadb_msg_seq = seq;
5543      -        samsg->sadb_msg_pid = pid;
5544      -
5545      -        if (tunnel_mode) {
5546      -                /*
5547      -                 * Form inner address extensions based NOT on the inner
5548      -                 * selectors (i.e. the packet data), but on the policy's
5549      -                 * selector key (i.e. the policy's selector information).
5550      -                 *
5551      -                 * NOTE:  The position of IPv4 and IPv6 addresses is the
5552      -                 * same in ipsec_selkey_t (unless the compiler does very
5553      -                 * strange things with unions, consult your local C language
5554      -                 * lawyer for details).
5555      -                 */
5556      -                ASSERT(pol != NULL);
5557      -
5558      -                ipsl = &(pol->ipsp_sel->ipsl_key);
5559      -                if (ipsl->ipsl_valid & IPSL_IPV4) {
5560      -                        af = AF_INET;
5561      -                        ASSERT(sel->ips_protocol == IPPROTO_ENCAP);
5562      -                        ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6));
5563      -                } else {
5564      -                        af = AF_INET6;
5565      -                        ASSERT(sel->ips_protocol == IPPROTO_IPV6);
5566      -                        ASSERT(ipsl->ipsl_valid & IPSL_IPV6);
5567      -                }
5568      -
5569      -                if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) {
5570      -                        saddrptr = (uint32_t *)(&ipsl->ipsl_local);
5571      -                        pfxlen = ipsl->ipsl_local_pfxlen;
5572      -                } else {
5573      -                        saddrptr = (uint32_t *)(&ipv6_all_zeros);
5574      -                        pfxlen = 0;
5575      -                }
5576      -                /* XXX What about ICMP type/code? */
5577      -                lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ?
5578      -                    ipsl->ipsl_lport : 0;
5579      -                proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ?
5580      -                    ipsl->ipsl_proto : 0;
5581      -
5582      -                cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
5583      -                    af, saddrptr, lport, proto, pfxlen);
5584      -                if (cur == NULL) {
5585      -                        freeb(mp);
5586      -                        return (NULL);
5587      -                }
5588      -
5589      -                if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) {
5590      -                        daddrptr = (uint32_t *)(&ipsl->ipsl_remote);
5591      -                        pfxlen = ipsl->ipsl_remote_pfxlen;
5592      -                } else {
5593      -                        daddrptr = (uint32_t *)(&ipv6_all_zeros);
5594      -                        pfxlen = 0;
5595      -                }
5596      -                /* XXX What about ICMP type/code? */
5597      -                rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ?
5598      -                    ipsl->ipsl_rport : 0;
5599      -
5600      -                cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5601      -                    af, daddrptr, rport, proto, pfxlen);
5602      -                if (cur == NULL) {
5603      -                        freeb(mp);
5604      -                        return (NULL);
5605      -                }
5606      -                /*
5607      -                 * TODO  - if we go to 3408's dream of transport mode IP-in-IP
5608      -                 * _with_ inner-packet address selectors, we'll need to further
5609      -                 * distinguish tunnel mode here.  For now, having inner
5610      -                 * addresses and/or ports is sufficient.
5611      -                 *
5612      -                 * Meanwhile, whack proto/ports to reflect IP-in-IP for the
5613      -                 * outer addresses.
5614      -                 */
5615      -                proto = sel->ips_protocol;      /* Either _ENCAP or _IPV6 */
5616      -                lport = rport = 0;
5617      -        } else if ((ap != NULL) && (!ap->ipa_want_unique)) {
5618      -                proto = 0;
5619      -                lport = 0;
5620      -                rport = 0;
5621      -                if (pol != NULL) {
5622      -                        ipsl = &(pol->ipsp_sel->ipsl_key);
5623      -                        if (ipsl->ipsl_valid & IPSL_PROTOCOL)
5624      -                                proto = ipsl->ipsl_proto;
5625      -                        if (ipsl->ipsl_valid & IPSL_REMOTE_PORT)
5626      -                                rport = ipsl->ipsl_rport;
5627      -                        if (ipsl->ipsl_valid & IPSL_LOCAL_PORT)
5628      -                                lport = ipsl->ipsl_lport;
5629      -                }
5630      -        } else {
5631      -                proto = sel->ips_protocol;
5632      -                lport = sel->ips_local_port;
5633      -                rport = sel->ips_remote_port;
5634      -        }
5635      -
5636      -        af = sel->ips_isv4 ? AF_INET : AF_INET6;
5637      -
5638      -        /*
5639      -         * NOTE:  The position of IPv4 and IPv6 addresses is the same in
5640      -         * ipsec_selector_t.
5641      -         */
5642      -        cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
5643      -            (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0);
5644      -
5645      -        if (cur == NULL) {
5646      -                freeb(mp);
5647      -                return (NULL);
5648      -        }
5649      -
5650      -        cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
5651      -            (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0);
5652      -
5653      -        if (cur == NULL) {
5654      -                freeb(mp);
5655      -                return (NULL);
5656      -        }
5657      -
5658      -        if (sens != NULL) {
5659      -                uint8_t *sensext = cur;
5660      -                int senslen = SADB_64TO8(sens->sadb_sens_len);
5661      -
5662      -                cur += senslen;
5663      -                if (cur > end) {
5664      -                        freeb(mp);
5665      -                        return (NULL);
5666      -                }
5667      -                bcopy(sens, sensext, senslen);
5668      -        }
5669      -
5670      -        /*
5671      -         * This section will change a lot as policy evolves.
5672      -         * For now, it'll be relatively simple.
5673      -         */
5674      -        eprop = (sadb_prop_t *)cur;
5675      -        cur += sizeof (*eprop);
5676      -        if (cur > end) {
5677      -                /* no space left */
5678      -                freeb(mp);
5679      -                return (NULL);
5680      -        }
5681      -
5682      -        eprop->sadb_prop_exttype = SADB_X_EXT_EPROP;
5683      -        eprop->sadb_x_prop_ereserved = 0;
5684      -        eprop->sadb_x_prop_numecombs = 0;
5685      -        eprop->sadb_prop_replay = 32;   /* default */
5686      -
5687      -        kmc = kmp = 0;
5688      -
5689      -        for (; ap != NULL; ap = an) {
5690      -                an = (pol != NULL) ? ap->ipa_next : NULL;
5691      -
5692      -                /*
5693      -                 * Skip non-IPsec policies
5694      -                 */
5695      -                if (ap->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5696      -                        continue;
5697      -
5698      -                if (ap->ipa_act.ipa_apply.ipp_km_proto)
5699      -                        kmp = ap->ipa_act.ipa_apply.ipp_km_proto;
5700      -                if (ap->ipa_act.ipa_apply.ipp_km_cookie)
5701      -                        kmc = ap->ipa_act.ipa_apply.ipp_km_cookie;
5702      -                if (ap->ipa_act.ipa_apply.ipp_replay_depth) {
5703      -                        eprop->sadb_prop_replay =
5704      -                            ap->ipa_act.ipa_apply.ipp_replay_depth;
5705      -                }
5706      -
5707      -                cur = sadb_action_to_ecomb(cur, end, ap, ns);
5708      -                if (cur == NULL) { /* no space */
5709      -                        freeb(mp);
5710      -                        return (NULL);
5711      -                }
5712      -                eprop->sadb_x_prop_numecombs++;
5713      -        }
5714      -
5715      -        if (eprop->sadb_x_prop_numecombs == 0) {
5716      -                /*
5717      -                 * This will happen if we fail to find a policy
5718      -                 * allowing for IPsec processing.
5719      -                 * Construct an error message.
5720      -                 */
5721      -                samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
5722      -                samsg->sadb_msg_errno = ENOENT;
5723      -                samsg->sadb_x_msg_diagnostic = 0;
5724      -                return (mp);
5725      -        }
5726      -
5727      -        if ((kmp != 0) || (kmc != 0)) {
5728      -                cur = sadb_make_kmc_ext(cur, end, kmp, kmc);
5729      -                if (cur == NULL) {
5730      -                        freeb(mp);
5731      -                        return (NULL);
5732      -                }
5733      -        }
5734      -
5735      -        eprop->sadb_prop_len = SADB_8TO64(cur - (uint8_t *)eprop);
5736      -        samsg->sadb_msg_len = SADB_8TO64(cur - start);
5737      -        mp->b_wptr = cur;
5738      -
5739      -        return (mp);
5740      -}
5741      -
5742      -/*
5743      - * Generic setup of an RFC 2367 ACQUIRE message.  Caller sets satype.
5744      - *
5745      - * NOTE: This function acquires alg_lock as a side-effect if-and-only-if we
5746      - * succeed (i.e. return non-NULL).  Caller MUST release it.  This is to
5747      - * maximize code consolidation while preventing algorithm changes from messing
5748      - * with the callers finishing touches on the ACQUIRE itself.
5749      - */
5750      -mblk_t *
5751      -sadb_setup_acquire(ipsacq_t *acqrec, uint8_t satype, ipsec_stack_t *ipss)
5752      -{
5753      -        uint_t allocsize;
5754      -        mblk_t *pfkeymp, *msgmp;
5755      -        sa_family_t af;
5756      -        uint8_t *cur, *end;
5757      -        sadb_msg_t *samsg;
5758      -        uint16_t sport_typecode;
5759      -        uint16_t dport_typecode;
5760      -        uint8_t check_proto;
5761      -        boolean_t tunnel_mode = (acqrec->ipsacq_inneraddrfam != 0);
5762      -
5763      -        ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5764      -
5765      -        pfkeymp = sadb_keysock_out(0);
5766      -        if (pfkeymp == NULL)
5767      -                return (NULL);
5768      -
5769      -        /*
5770      -         * First, allocate a basic ACQUIRE message
5771      -         */
5772      -        allocsize = sizeof (sadb_msg_t) + sizeof (sadb_address_t) +
5773      -            sizeof (sadb_address_t) + sizeof (sadb_prop_t);
5774      -
5775      -        /* Make sure there's enough to cover both AF_INET and AF_INET6. */
5776      -        allocsize += 2 * sizeof (struct sockaddr_in6);
5777      -
5778      -        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5779      -        /* NOTE:  The lock is now held through to this function's return. */
5780      -        allocsize += ipss->ipsec_nalgs[IPSEC_ALG_AUTH] *
5781      -            ipss->ipsec_nalgs[IPSEC_ALG_ENCR] * sizeof (sadb_comb_t);
5782      -
5783      -        if (tunnel_mode) {
5784      -                /* Tunnel mode! */
5785      -                allocsize += 2 * sizeof (sadb_address_t);
5786      -                /* Enough to cover both AF_INET and AF_INET6. */
5787      -                allocsize += 2 * sizeof (struct sockaddr_in6);
5788      -        }
5789      -
5790      -        msgmp = allocb(allocsize, BPRI_HI);
5791      -        if (msgmp == NULL) {
5792      -                freeb(pfkeymp);
5793      -                rw_exit(&ipss->ipsec_alg_lock);
5794      -                return (NULL);
5795      -        }
5796      -
5797      -        pfkeymp->b_cont = msgmp;
5798      -        cur = msgmp->b_rptr;
5799      -        end = cur + allocsize;
5800      -        samsg = (sadb_msg_t *)cur;
5801      -        cur += sizeof (sadb_msg_t);
5802      -
5803      -        af = acqrec->ipsacq_addrfam;
5804      -        switch (af) {
5805      -        case AF_INET:
5806      -                check_proto = IPPROTO_ICMP;
5807      -                break;
5808      -        case AF_INET6:
5809      -                check_proto = IPPROTO_ICMPV6;
5810      -                break;
5811      -        default:
5812      -                /* This should never happen unless we have kernel bugs. */
5813      -                cmn_err(CE_WARN,
5814      -                    "sadb_setup_acquire:  corrupt ACQUIRE record.\n");
5815      -                ASSERT(0);
5816      -                rw_exit(&ipss->ipsec_alg_lock);
5817      -                return (NULL);
5818      -        }
5819      -
5820      -        samsg->sadb_msg_version = PF_KEY_V2;
5821      -        samsg->sadb_msg_type = SADB_ACQUIRE;
5822      -        samsg->sadb_msg_satype = satype;
5823      -        samsg->sadb_msg_errno = 0;
5824      -        samsg->sadb_msg_pid = 0;
5825      -        samsg->sadb_msg_reserved = 0;
5826      -        samsg->sadb_msg_seq = acqrec->ipsacq_seq;
5827      -
5828      -        ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5829      -
5830      -        if ((acqrec->ipsacq_proto == check_proto) || tunnel_mode) {
5831      -                sport_typecode = dport_typecode = 0;
5832      -        } else {
5833      -                sport_typecode = acqrec->ipsacq_srcport;
5834      -                dport_typecode = acqrec->ipsacq_dstport;
5835      -        }
5836      -
5837      -        cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
5838      -            acqrec->ipsacq_srcaddr, sport_typecode, acqrec->ipsacq_proto, 0);
5839      -
5840      -        cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
5841      -            acqrec->ipsacq_dstaddr, dport_typecode, acqrec->ipsacq_proto, 0);
5842      -
5843      -        if (tunnel_mode) {
5844      -                sport_typecode = acqrec->ipsacq_srcport;
5845      -                dport_typecode = acqrec->ipsacq_dstport;
5846      -                cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
5847      -                    acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innersrc,
5848      -                    sport_typecode, acqrec->ipsacq_inner_proto,
5849      -                    acqrec->ipsacq_innersrcpfx);
5850      -                cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5851      -                    acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innerdst,
5852      -                    dport_typecode, acqrec->ipsacq_inner_proto,
5853      -                    acqrec->ipsacq_innerdstpfx);
5854      -        }
5855      -
5856      -        /* XXX Insert identity information here. */
5857      -
5858      -        /* XXXMLS Insert sensitivity information here. */
5859      -
5860      -        if (cur != NULL)
5861      -                samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr);
5862      -        else
5863      -                rw_exit(&ipss->ipsec_alg_lock);
5864      -
5865      -        return (pfkeymp);
5866      -}
5867      -
5868      -/*
5869 6091   * Given an SADB_GETSPI message, find an appropriately ranged SA and
5870 6092   * allocate an SA.  If there are message improprieties, return (ipsa_t *)-1.
5871 6093   * If there was a memory allocation error, return NULL.  (Assume NULL !=
5872 6094   * (ipsa_t *)-1).
5873 6095   *
5874 6096   * master_spi is passed in host order.
5875 6097   */
5876 6098  ipsa_t *
5877 6099  sadb_getspi(keysock_in_t *ksi, uint32_t master_spi, int *diagnostic,
5878 6100      netstack_t *ns, uint_t sa_type)
↓ open down ↓ 970 lines elided ↑ open up ↑
6849 7071          if (pp == NULL) {
6850 7072                  pp = ipsec_find_policy(IPSEC_TYPE_OUTBOUND, NULL, &sel, ns);
6851 7073                  if (pp == NULL) {
6852 7074                          /* There's no global policy. */
6853 7075                          err = ENOENT;
6854 7076                          diagnostic = 0;
6855 7077                          goto bail;
6856 7078                  }
6857 7079          }
6858 7080  
6859      -        /*
6860      -         * Now that we have a policy entry/widget, construct an ACQUIRE
6861      -         * message based on that, fix fields where appropriate,
6862      -         * and return the message.
6863      -         */
6864      -        retmp = sadb_extended_acquire(&sel, pp, NULL,
6865      -            (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)),
6866      -            samsg->sadb_msg_seq, samsg->sadb_msg_pid, sens, ns);
     7081 +        ASSERT(pp != NULL);
     7082 +        retmp = sadb_acquire_msg_base(0, 0, samsg->sadb_msg_seq,
     7083 +            samsg->sadb_msg_pid);
     7084 +        if (retmp != NULL) {
     7085 +                /* Remove KEYSOCK_OUT, because caller constructs it instead. */
     7086 +                mblk_t *kso = retmp;
     7087 +
     7088 +                retmp = retmp->b_cont;
     7089 +                freeb(kso);
     7090 +                /* Append addresses... */
     7091 +                retmp->b_cont = sadb_acquire_msg_common(&sel, pp, NULL,
     7092 +                    (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)), NULL,
     7093 +                    sens);
     7094 +                if (retmp->b_cont == NULL) {
     7095 +                        freemsg(retmp);
     7096 +                        retmp = NULL;
     7097 +                }
     7098 +                /* And the policy result. */
     7099 +                retmp->b_cont->b_cont =
     7100 +                    sadb_acquire_extended_prop(pp->ipsp_act, ns);
     7101 +                if (retmp->b_cont->b_cont == NULL) {
     7102 +                        freemsg(retmp);
     7103 +                        retmp = NULL;
     7104 +                }
     7105 +                ((sadb_msg_t *)retmp->b_rptr)->sadb_msg_len =
     7106 +                    SADB_8TO64(msgsize(retmp));
     7107 +        }
     7108 +
6867 7109          if (pp != NULL) {
6868 7110                  IPPOL_REFRELE(pp);
6869 7111          }
6870 7112          ASSERT(err == 0 && diagnostic == 0);
6871 7113          if (retmp == NULL)
6872 7114                  err = ENOMEM;
6873 7115  bail:
6874 7116          if (itp != NULL) {
6875 7117                  ITP_REFRELE(itp, ns);
6876 7118          }
↓ open down ↓ 972 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX