LCOV - code coverage report
Current view: top level - netinet - ip_spd.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 382 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: ip_spd.c,v 1.98 2018/06/25 11:11:41 mpi Exp $ */
       2             : /*
       3             :  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
       4             :  *
       5             :  * Copyright (c) 2000-2001 Angelos D. Keromytis.
       6             :  *
       7             :  * Permission to use, copy, and modify this software with or without fee
       8             :  * is hereby granted, provided that this entire notice is included in
       9             :  * all copies of any software which is or includes a copy or
      10             :  * modification of this software.
      11             :  * You may use this code under the GNU public license if you so wish. Please
      12             :  * contribute changes back to the authors under this freer than GPL license
      13             :  * so that we may further the use of strong encryption without limitations to
      14             :  * all.
      15             :  *
      16             :  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
      17             :  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
      18             :  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
      19             :  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
      20             :  * PURPOSE.
      21             :  */
      22             : 
      23             : #include <sys/param.h>
      24             : #include <sys/systm.h>
      25             : #include <sys/mbuf.h>
      26             : #include <sys/socket.h>
      27             : #include <sys/kernel.h>
      28             : #include <sys/socketvar.h>
      29             : #include <sys/domain.h>
      30             : #include <sys/protosw.h>
      31             : #include <sys/pool.h>
      32             : #include <sys/timeout.h>
      33             : 
      34             : #include <net/route.h>
      35             : #include <net/netisr.h>
      36             : 
      37             : #include <netinet/in.h>
      38             : #include <netinet/ip.h>
      39             : #include <netinet/ip_var.h>
      40             : #include <netinet/in_pcb.h>
      41             : #include <netinet/ip_ipsp.h>
      42             : #include <net/pfkeyv2.h>
      43             : 
      44             : int     ipsp_acquire_sa(struct ipsec_policy *, union sockaddr_union *,
      45             :             union sockaddr_union *, struct sockaddr_encap *, struct mbuf *);
      46             : struct  ipsec_acquire *ipsp_pending_acquire(struct ipsec_policy *,
      47             :             union sockaddr_union *);
      48             : void    ipsp_delete_acquire_timo(void *);
      49             : void    ipsp_delete_acquire(struct ipsec_acquire *);
      50             : 
      51             : struct pool ipsec_policy_pool;
      52             : struct pool ipsec_acquire_pool;
      53             : int ipsec_policy_pool_initialized = 0;
      54             : 
      55             : /* Protected by the NET_LOCK(). */
      56             : int ipsec_acquire_pool_initialized = 0;
      57             : struct radix_node_head **spd_tables;
      58             : unsigned int spd_table_max;
      59             : TAILQ_HEAD(ipsec_acquire_head, ipsec_acquire) ipsec_acquire_head =
      60             :     TAILQ_HEAD_INITIALIZER(ipsec_acquire_head);
      61             : 
      62             : struct radix_node_head *
      63           0 : spd_table_get(unsigned int rtableid)
      64             : {
      65             :         unsigned int rdomain;
      66             : 
      67           0 :         NET_ASSERT_LOCKED();
      68             : 
      69           0 :         if (spd_tables == NULL)
      70           0 :                 return (NULL);
      71             : 
      72           0 :         rdomain = rtable_l2(rtableid);
      73           0 :         if (rdomain > spd_table_max)
      74           0 :                 return (NULL);
      75             : 
      76           0 :         return (spd_tables[rdomain]);
      77           0 : }
      78             : 
      79             : struct radix_node_head *
      80           0 : spd_table_add(unsigned int rtableid)
      81             : {
      82           0 :         struct radix_node_head *rnh = NULL;
      83             :         unsigned int rdomain;
      84             :         void *p;
      85             : 
      86           0 :         NET_ASSERT_LOCKED();
      87             : 
      88           0 :         rdomain = rtable_l2(rtableid);
      89           0 :         if (spd_tables == NULL || rdomain > spd_table_max) {
      90           0 :                 if ((p = mallocarray(rdomain + 1, sizeof(*rnh),
      91           0 :                     M_RTABLE, M_NOWAIT|M_ZERO)) == NULL)
      92           0 :                         return (NULL);
      93             : 
      94           0 :                 if (spd_tables != NULL) {
      95           0 :                         memcpy(p, spd_tables, sizeof(*rnh) * (spd_table_max+1));
      96           0 :                         free(spd_tables, M_RTABLE, 0);
      97           0 :                 }
      98           0 :                 spd_tables = p;
      99           0 :                 spd_table_max = rdomain;
     100           0 :         }
     101             : 
     102           0 :         if (spd_tables[rdomain] == NULL) {
     103           0 :                 if (rn_inithead((void **)&rnh,
     104           0 :                     offsetof(struct sockaddr_encap, sen_type)) == 0)
     105           0 :                         rnh = NULL;
     106           0 :                 spd_tables[rdomain] = rnh;
     107           0 :         }
     108             : 
     109           0 :         return (spd_tables[rdomain]);
     110           0 : }
     111             : 
     112             : int
     113           0 : spd_table_walk(unsigned int rtableid,
     114             :     int (*func)(struct ipsec_policy *, void *, unsigned int), void *arg)
     115             : {
     116             :         struct radix_node_head *rnh;
     117           0 :         int (*walker)(struct radix_node *, void *, u_int) = (void *)func;
     118             :         int error;
     119             : 
     120           0 :         rnh = spd_table_get(rtableid);
     121           0 :         if (rnh == NULL)
     122           0 :                 return (0);
     123             : 
     124             :         /* EGAIN means the tree changed. */
     125           0 :         while ((error = rn_walktree(rnh, walker, arg)) == EAGAIN)
     126           0 :                 continue;
     127             : 
     128           0 :         return (error);
     129           0 : }
     130             : 
     131             : /*
     132             :  * Lookup at the SPD based on the headers contained on the mbuf. The second
     133             :  * argument indicates what protocol family the header at the beginning of
     134             :  * the mbuf is. hlen is the offset of the transport protocol header
     135             :  * in the mbuf.
     136             :  *
     137             :  * Return combinations (of return value and in *error):
     138             :  * - NULL/0 -> no IPsec required on packet
     139             :  * - NULL/-EINVAL -> silently drop the packet
     140             :  * - NULL/errno -> drop packet and return error
     141             :  * or a pointer to a TDB (and 0 in *error).
     142             :  *
     143             :  * In the case of incoming flows, only the first three combinations are
     144             :  * returned.
     145             :  */
     146             : struct tdb *
     147           0 : ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
     148             :     struct tdb *tdbp, struct inpcb *inp, u_int32_t ipsecflowinfo)
     149             : {
     150             :         struct radix_node_head *rnh;
     151             :         struct radix_node *rn;
     152           0 :         union sockaddr_union sdst, ssrc;
     153           0 :         struct sockaddr_encap *ddst, dst;
     154             :         struct ipsec_policy *ipo;
     155             :         struct ipsec_ids *ids = NULL;
     156             :         int signore = 0, dignore = 0;
     157           0 :         u_int rdomain = rtable_l2(m->m_pkthdr.ph_rtableid);
     158             : 
     159           0 :         NET_ASSERT_LOCKED();
     160             : 
     161             :         /*
     162             :          * If there are no flows in place, there's no point
     163             :          * continuing with the SPD lookup.
     164             :          */
     165           0 :         if (!ipsec_in_use && inp == NULL) {
     166           0 :                 *error = 0;
     167           0 :                 return NULL;
     168             :         }
     169             : 
     170             :         /*
     171             :          * If an input packet is destined to a BYPASS socket, just accept it.
     172             :          */
     173           0 :         if ((inp != NULL) && (direction == IPSP_DIRECTION_IN) &&
     174           0 :             (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
     175           0 :             (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS) &&
     176           0 :             (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
     177           0 :                 *error = 0;
     178           0 :                 return NULL;
     179             :         }
     180             : 
     181           0 :         memset(&dst, 0, sizeof(dst));
     182           0 :         memset(&sdst, 0, sizeof(union sockaddr_union));
     183           0 :         memset(&ssrc, 0, sizeof(union sockaddr_union));
     184             :         ddst = (struct sockaddr_encap *)&dst;
     185           0 :         ddst->sen_family = PF_KEY;
     186           0 :         ddst->sen_len = SENT_LEN;
     187             : 
     188           0 :         switch (af) {
     189             :         case AF_INET:
     190           0 :                 if (hlen < sizeof (struct ip) || m->m_pkthdr.len < hlen) {
     191           0 :                         *error = EINVAL;
     192           0 :                         return NULL;
     193             :                 }
     194           0 :                 ddst->sen_direction = direction;
     195           0 :                 ddst->sen_type = SENT_IP4;
     196             : 
     197           0 :                 m_copydata(m, offsetof(struct ip, ip_src),
     198           0 :                     sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_src));
     199           0 :                 m_copydata(m, offsetof(struct ip, ip_dst),
     200           0 :                     sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_dst));
     201           0 :                 m_copydata(m, offsetof(struct ip, ip_p), sizeof(u_int8_t),
     202           0 :                     (caddr_t) &(ddst->sen_proto));
     203             : 
     204           0 :                 sdst.sin.sin_family = ssrc.sin.sin_family = AF_INET;
     205           0 :                 sdst.sin.sin_len = ssrc.sin.sin_len =
     206             :                     sizeof(struct sockaddr_in);
     207           0 :                 ssrc.sin.sin_addr = ddst->sen_ip_src;
     208           0 :                 sdst.sin.sin_addr = ddst->sen_ip_dst;
     209             : 
     210             :                 /*
     211             :                  * If TCP/UDP, extract the port numbers to use in the lookup.
     212             :                  */
     213           0 :                 switch (ddst->sen_proto) {
     214             :                 case IPPROTO_UDP:
     215             :                 case IPPROTO_TCP:
     216             :                         /* Make sure there's enough data in the packet. */
     217           0 :                         if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
     218           0 :                                 *error = EINVAL;
     219           0 :                                 return NULL;
     220             :                         }
     221             : 
     222             :                         /*
     223             :                          * Luckily, the offset of the src/dst ports in
     224             :                          * both the UDP and TCP headers is the same (first
     225             :                          * two 16-bit values in the respective headers),
     226             :                          * so we can just copy them.
     227             :                          */
     228           0 :                         m_copydata(m, hlen, sizeof(u_int16_t),
     229           0 :                             (caddr_t) &(ddst->sen_sport));
     230           0 :                         m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
     231           0 :                             (caddr_t) &(ddst->sen_dport));
     232           0 :                         break;
     233             : 
     234             :                 default:
     235           0 :                         ddst->sen_sport = 0;
     236           0 :                         ddst->sen_dport = 0;
     237           0 :                 }
     238             : 
     239             :                 break;
     240             : 
     241             : #ifdef INET6
     242             :         case AF_INET6:
     243           0 :                 if (hlen < sizeof (struct ip6_hdr) || m->m_pkthdr.len < hlen) {
     244           0 :                         *error = EINVAL;
     245           0 :                         return NULL;
     246             :                 }
     247           0 :                 ddst->sen_type = SENT_IP6;
     248           0 :                 ddst->sen_ip6_direction = direction;
     249             : 
     250           0 :                 m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
     251             :                     sizeof(struct in6_addr),
     252           0 :                     (caddr_t) &(ddst->sen_ip6_src));
     253           0 :                 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
     254             :                     sizeof(struct in6_addr),
     255           0 :                     (caddr_t) &(ddst->sen_ip6_dst));
     256           0 :                 m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
     257             :                     sizeof(u_int8_t),
     258           0 :                     (caddr_t) &(ddst->sen_ip6_proto));
     259             : 
     260           0 :                 sdst.sin6.sin6_family = ssrc.sin6.sin6_family = AF_INET6;
     261           0 :                 sdst.sin6.sin6_len = ssrc.sin6.sin6_len =
     262             :                     sizeof(struct sockaddr_in6);
     263           0 :                 in6_recoverscope(&ssrc.sin6, &ddst->sen_ip6_src);
     264           0 :                 in6_recoverscope(&sdst.sin6, &ddst->sen_ip6_dst);
     265             : 
     266             :                 /*
     267             :                  * If TCP/UDP, extract the port numbers to use in the lookup.
     268             :                  */
     269           0 :                 switch (ddst->sen_ip6_proto) {
     270             :                 case IPPROTO_UDP:
     271             :                 case IPPROTO_TCP:
     272             :                         /* Make sure there's enough data in the packet. */
     273           0 :                         if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
     274           0 :                                 *error = EINVAL;
     275           0 :                                 return NULL;
     276             :                         }
     277             : 
     278             :                         /*
     279             :                          * Luckily, the offset of the src/dst ports in
     280             :                          * both the UDP and TCP headers is the same
     281             :                          * (first two 16-bit values in the respective
     282             :                          * headers), so we can just copy them.
     283             :                          */
     284           0 :                         m_copydata(m, hlen, sizeof(u_int16_t),
     285           0 :                             (caddr_t) &(ddst->sen_ip6_sport));
     286           0 :                         m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
     287           0 :                             (caddr_t) &(ddst->sen_ip6_dport));
     288           0 :                         break;
     289             : 
     290             :                 default:
     291           0 :                         ddst->sen_ip6_sport = 0;
     292           0 :                         ddst->sen_ip6_dport = 0;
     293           0 :                 }
     294             : 
     295             :                 break;
     296             : #endif /* INET6 */
     297             : 
     298             :         default:
     299           0 :                 *error = EAFNOSUPPORT;
     300           0 :                 return NULL;
     301             :         }
     302             : 
     303             :         /* Actual SPD lookup. */
     304           0 :         if ((rnh = spd_table_get(rdomain)) == NULL ||
     305           0 :             (rn = rn_match((caddr_t)&dst, rnh)) == NULL) {
     306             :                 /*
     307             :                  * Return whatever the socket requirements are, there are no
     308             :                  * system-wide policies.
     309             :                  */
     310           0 :                 *error = 0;
     311           0 :                 return ipsp_spd_inp(m, af, hlen, error, direction,
     312             :                     tdbp, inp, NULL);
     313             :         }
     314           0 :         ipo = (struct ipsec_policy *)rn;
     315             : 
     316           0 :         switch (ipo->ipo_type) {
     317             :         case IPSP_PERMIT:
     318           0 :                 *error = 0;
     319           0 :                 return ipsp_spd_inp(m, af, hlen, error, direction, tdbp,
     320             :                     inp, ipo);
     321             : 
     322             :         case IPSP_DENY:
     323           0 :                 *error = EHOSTUNREACH;
     324           0 :                 return NULL;
     325             : 
     326             :         case IPSP_IPSEC_USE:
     327             :         case IPSP_IPSEC_ACQUIRE:
     328             :         case IPSP_IPSEC_REQUIRE:
     329             :         case IPSP_IPSEC_DONTACQ:
     330             :                 /* Nothing more needed here. */
     331             :                 break;
     332             : 
     333             :         default:
     334           0 :                 *error = EINVAL;
     335           0 :                 return NULL;
     336             :         }
     337             : 
     338             :         /* Check for non-specific destination in the policy. */
     339           0 :         switch (ipo->ipo_dst.sa.sa_family) {
     340             :         case AF_INET:
     341           0 :                 if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) ||
     342           0 :                     (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST))
     343           0 :                         dignore = 1;
     344             :                 break;
     345             : 
     346             : #ifdef INET6
     347             :         case AF_INET6:
     348           0 :                 if ((IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) ||
     349           0 :                     (memcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
     350           0 :                     sizeof(in6mask128)) == 0))
     351           0 :                         dignore = 1;
     352             :                 break;
     353             : #endif /* INET6 */
     354             :         }
     355             : 
     356             :         /* Likewise for source. */
     357           0 :         switch (ipo->ipo_src.sa.sa_family) {
     358             :         case AF_INET:
     359           0 :                 if (ipo->ipo_src.sin.sin_addr.s_addr == INADDR_ANY)
     360           0 :                         signore = 1;
     361             :                 break;
     362             : 
     363             : #ifdef INET6
     364             :         case AF_INET6:
     365           0 :                 if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr))
     366           0 :                         signore = 1;
     367             :                 break;
     368             : #endif /* INET6 */
     369             :         }
     370             : 
     371             :         /* Do we have a cached entry ? If so, check if it's still valid. */
     372           0 :         if ((ipo->ipo_tdb) && (ipo->ipo_tdb->tdb_flags & TDBF_INVALID)) {
     373           0 :                 TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
     374             :                     ipo_tdb_next);
     375           0 :                 ipo->ipo_tdb = NULL;
     376           0 :         }
     377             : 
     378             :         /* Outgoing packet policy check. */
     379           0 :         if (direction == IPSP_DIRECTION_OUT) {
     380             :                 /*
     381             :                  * If the packet is destined for the policy-specified
     382             :                  * gateway/endhost, and the socket has the BYPASS
     383             :                  * option set, skip IPsec processing.
     384             :                  */
     385           0 :                 if ((inp != NULL) &&
     386           0 :                     (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
     387           0 :                     (inp->inp_seclevel[SL_ESP_NETWORK] ==
     388           0 :                         IPSEC_LEVEL_BYPASS) &&
     389           0 :                     (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
     390             :                         /* Direct match. */
     391           0 :                         if (dignore ||
     392           0 :                             !memcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len)) {
     393           0 :                                 *error = 0;
     394           0 :                                 return NULL;
     395             :                         }
     396             :                 }
     397             : 
     398           0 :                 if (ipsecflowinfo)
     399           0 :                         ids = ipsp_ids_lookup(ipsecflowinfo);
     400             : 
     401             :                 /* Check that the cached TDB (if present), is appropriate. */
     402           0 :                 if (ipo->ipo_tdb) {
     403           0 :                         if ((ipo->ipo_last_searched <= ipsec_last_added) ||
     404           0 :                             (ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) ||
     405           0 :                             memcmp(dignore ? &sdst : &ipo->ipo_dst,
     406             :                             &ipo->ipo_tdb->tdb_dst,
     407             :                             ipo->ipo_tdb->tdb_dst.sa.sa_len))
     408             :                                 goto nomatchout;
     409             : 
     410           0 :                         if (!ipsp_aux_match(ipo->ipo_tdb,
     411           0 :                             ids ? ids : ipo->ipo_ids,
     412           0 :                             &ipo->ipo_addr, &ipo->ipo_mask))
     413             :                                 goto nomatchout;
     414             : 
     415             :                         /* Cached entry is good. */
     416           0 :                         *error = 0;
     417           0 :                         return ipsp_spd_inp(m, af, hlen, error, direction,
     418             :                             tdbp, inp, ipo);
     419             : 
     420             :   nomatchout:
     421             :                         /* Cached TDB was not good. */
     422           0 :                         TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
     423             :                             ipo_tdb_next);
     424           0 :                         ipo->ipo_tdb = NULL;
     425           0 :                         ipo->ipo_last_searched = 0;
     426           0 :                 }
     427             : 
     428             :                 /*
     429             :                  * If no SA has been added since the last time we did a
     430             :                  * lookup, there's no point searching for one. However, if the
     431             :                  * destination gateway is left unspecified (or is all-1's),
     432             :                  * always lookup since this is a generic-match rule
     433             :                  * (otherwise, we can have situations where SAs to some
     434             :                  * destinations exist but are not used, possibly leading to an
     435             :                  * explosion in the number of acquired SAs).
     436             :                  */
     437           0 :                 if (ipo->ipo_last_searched <= ipsec_last_added)   {
     438             :                         /* "Touch" the entry. */
     439           0 :                         if (dignore == 0)
     440           0 :                                 ipo->ipo_last_searched = time_second;
     441             : 
     442             :                         /* Find an appropriate SA from the existing ones. */
     443           0 :                         ipo->ipo_tdb =
     444           0 :                             gettdbbydst(rdomain,
     445           0 :                                 dignore ? &sdst : &ipo->ipo_dst,
     446           0 :                                 ipo->ipo_sproto,
     447           0 :                                 ids ? ids: ipo->ipo_ids,
     448           0 :                                 &ipo->ipo_addr, &ipo->ipo_mask);
     449           0 :                         if (ipo->ipo_tdb) {
     450           0 :                                 TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
     451             :                                     ipo, ipo_tdb_next);
     452           0 :                                 *error = 0;
     453           0 :                                 return ipsp_spd_inp(m, af, hlen, error,
     454             :                                     direction, tdbp, inp, ipo);
     455             :                         }
     456             :                 }
     457             : 
     458             :                 /* So, we don't have an SA -- just a policy. */
     459           0 :                 switch (ipo->ipo_type) {
     460             :                 case IPSP_IPSEC_REQUIRE:
     461             :                         /* Acquire SA through key management. */
     462           0 :                         if (ipsp_acquire_sa(ipo,
     463           0 :                             dignore ? &sdst : &ipo->ipo_dst,
     464           0 :                             signore ? NULL : &ipo->ipo_src, ddst, m) != 0) {
     465           0 :                                 *error = EACCES;
     466           0 :                                 return NULL;
     467             :                         }
     468             : 
     469             :                         /* FALLTHROUGH */
     470             :                 case IPSP_IPSEC_DONTACQ:
     471           0 :                         *error = -EINVAL; /* Silently drop packet. */
     472           0 :                         return NULL;
     473             : 
     474             :                 case IPSP_IPSEC_ACQUIRE:
     475             :                         /* Acquire SA through key management. */
     476           0 :                         ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst,
     477           0 :                             signore ? NULL : &ipo->ipo_src, ddst, NULL);
     478             : 
     479             :                         /* FALLTHROUGH */
     480             :                 case IPSP_IPSEC_USE:
     481           0 :                         *error = 0;
     482           0 :                         return ipsp_spd_inp(m, af, hlen, error, direction,
     483             :                             tdbp, inp, ipo);
     484             :                 }
     485             :         } else { /* IPSP_DIRECTION_IN */
     486           0 :                 if (tdbp != NULL) {
     487             :                         /* Direct match in the cache. */
     488           0 :                         if (ipo->ipo_tdb == tdbp) {
     489           0 :                                 *error = 0;
     490           0 :                                 return ipsp_spd_inp(m, af, hlen, error,
     491             :                                     direction, tdbp, inp, ipo);
     492             :                         }
     493             : 
     494           0 :                         if (memcmp(dignore ? &ssrc : &ipo->ipo_dst,
     495           0 :                             &tdbp->tdb_src, tdbp->tdb_src.sa.sa_len) ||
     496           0 :                             (ipo->ipo_sproto != tdbp->tdb_sproto))
     497             :                                 goto nomatchin;
     498             : 
     499             :                         /* Match source/dest IDs. */
     500           0 :                         if (ipo->ipo_ids)
     501           0 :                                 if (tdbp->tdb_ids == NULL ||
     502           0 :                                     !ipsp_ids_match(ipo->ipo_ids, tdbp->tdb_ids))
     503             :                                         goto nomatchin;
     504             : 
     505             :                         /* Add it to the cache. */
     506           0 :                         if (ipo->ipo_tdb)
     507           0 :                                 TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
     508             :                                     ipo, ipo_tdb_next);
     509           0 :                         ipo->ipo_tdb = tdbp;
     510           0 :                         TAILQ_INSERT_TAIL(&tdbp->tdb_policy_head, ipo,
     511             :                             ipo_tdb_next);
     512           0 :                         *error = 0;
     513           0 :                         return ipsp_spd_inp(m, af, hlen, error, direction,
     514             :                             tdbp, inp, ipo);
     515             : 
     516             :   nomatchin: /* Nothing needed here, falling through */
     517             :         ;
     518             :                 }
     519             : 
     520             :                 /* Check whether cached entry applies. */
     521           0 :                 if (ipo->ipo_tdb) {
     522             :                         /*
     523             :                          * We only need to check that the correct
     524             :                          * security protocol and security gateway are
     525             :                          * set; IDs will be the same since the cached
     526             :                          * entry is linked on this policy.
     527             :                          */
     528           0 :                         if (ipo->ipo_sproto == ipo->ipo_tdb->tdb_sproto &&
     529           0 :                             !memcmp(&ipo->ipo_tdb->tdb_src,
     530             :                             dignore ? &ssrc : &ipo->ipo_dst,
     531             :                             ipo->ipo_tdb->tdb_src.sa.sa_len))
     532             :                                 goto skipinputsearch;
     533             : 
     534             :                         /* Not applicable, unlink. */
     535           0 :                         TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
     536             :                             ipo_tdb_next);
     537           0 :                         ipo->ipo_last_searched = 0;
     538           0 :                         ipo->ipo_tdb = NULL;
     539           0 :                 }
     540             : 
     541             :                 /* Find whether there exists an appropriate SA. */
     542           0 :                 if (ipo->ipo_last_searched <= ipsec_last_added)   {
     543           0 :                         if (dignore == 0)
     544           0 :                                 ipo->ipo_last_searched = time_second;
     545             : 
     546           0 :                         ipo->ipo_tdb =
     547           0 :                             gettdbbysrc(rdomain,
     548           0 :                                 dignore ? &ssrc : &ipo->ipo_dst,
     549           0 :                                 ipo->ipo_sproto, ipo->ipo_ids,
     550           0 :                                 &ipo->ipo_addr, &ipo->ipo_mask);
     551           0 :                         if (ipo->ipo_tdb)
     552           0 :                                 TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
     553             :                                     ipo, ipo_tdb_next);
     554             :                 }
     555             :   skipinputsearch:
     556             : 
     557           0 :                 switch (ipo->ipo_type) {
     558             :                 case IPSP_IPSEC_REQUIRE:
     559             :                         /* If appropriate SA exists, don't acquire another. */
     560           0 :                         if (ipo->ipo_tdb) {
     561           0 :                                 *error = -EINVAL;
     562           0 :                                 return NULL;
     563             :                         }
     564             : 
     565             :                         /* Acquire SA through key management. */
     566           0 :                         if ((*error = ipsp_acquire_sa(ipo,
     567           0 :                             dignore ? &ssrc : &ipo->ipo_dst,
     568           0 :                             signore ? NULL : &ipo->ipo_src, ddst, m)) != 0)
     569           0 :                                 return NULL;
     570             : 
     571             :                         /* FALLTHROUGH */
     572             :                 case IPSP_IPSEC_DONTACQ:
     573             :                         /* Drop packet. */
     574           0 :                         *error = -EINVAL;
     575           0 :                         return NULL;
     576             : 
     577             :                 case IPSP_IPSEC_ACQUIRE:
     578             :                         /* If appropriate SA exists, don't acquire another. */
     579           0 :                         if (ipo->ipo_tdb) {
     580           0 :                                 *error = 0;
     581           0 :                                 return ipsp_spd_inp(m, af, hlen, error,
     582             :                                     direction, tdbp, inp, ipo);
     583             :                         }
     584             : 
     585             :                         /* Acquire SA through key management. */
     586           0 :                         ipsp_acquire_sa(ipo, dignore ? &ssrc : &ipo->ipo_dst,
     587           0 :                             signore ? NULL : &ipo->ipo_src, ddst, NULL);
     588             : 
     589             :                         /* FALLTHROUGH */
     590             :                 case IPSP_IPSEC_USE:
     591           0 :                         *error = 0;
     592           0 :                         return ipsp_spd_inp(m, af, hlen, error, direction,
     593             :                             tdbp, inp, ipo);
     594             :                 }
     595             :         }
     596             : 
     597             :         /* Shouldn't ever get this far. */
     598           0 :         *error = EINVAL;
     599           0 :         return NULL;
     600           0 : }
     601             : 
     602             : /*
     603             :  * Delete a policy from the SPD.
     604             :  */
     605             : int
     606           0 : ipsec_delete_policy(struct ipsec_policy *ipo)
     607             : {
     608             :         struct ipsec_acquire *ipa;
     609             :         struct radix_node_head *rnh;
     610           0 :         struct radix_node *rn = (struct radix_node *)ipo;
     611             :         int err = 0;
     612             : 
     613           0 :         NET_ASSERT_LOCKED();
     614             : 
     615           0 :         if (--ipo->ipo_ref_count > 0)
     616           0 :                 return 0;
     617             : 
     618             :         /* Delete from SPD. */
     619           0 :         if ((rnh = spd_table_get(ipo->ipo_rdomain)) == NULL ||
     620           0 :             rn_delete(&ipo->ipo_addr, &ipo->ipo_mask, rnh, rn) == NULL)
     621           0 :                 return (ESRCH);
     622             : 
     623           0 :         if (ipo->ipo_tdb != NULL)
     624           0 :                 TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
     625             :                     ipo_tdb_next);
     626             : 
     627           0 :         while ((ipa = TAILQ_FIRST(&ipo->ipo_acquires)) != NULL)
     628           0 :                 ipsp_delete_acquire(ipa);
     629             : 
     630           0 :         TAILQ_REMOVE(&ipsec_policy_head, ipo, ipo_list);
     631             : 
     632           0 :         if (ipo->ipo_ids)
     633           0 :                 ipsp_ids_free(ipo->ipo_ids);
     634             : 
     635           0 :         ipsec_in_use--;
     636             : 
     637           0 :         pool_put(&ipsec_policy_pool, ipo);
     638             : 
     639           0 :         return err;
     640           0 : }
     641             : 
     642             : void
     643           0 : ipsp_delete_acquire_timo(void *v)
     644             : {
     645           0 :         struct ipsec_acquire *ipa = v;
     646             : 
     647           0 :         NET_LOCK();
     648           0 :         ipsp_delete_acquire(ipa);
     649           0 :         NET_UNLOCK();
     650           0 : }
     651             : 
     652             : /*
     653             :  * Delete a pending IPsec acquire record.
     654             :  */
     655             : void
     656           0 : ipsp_delete_acquire(struct ipsec_acquire *ipa)
     657             : {
     658           0 :         NET_ASSERT_LOCKED();
     659             : 
     660           0 :         timeout_del(&ipa->ipa_timeout);
     661           0 :         TAILQ_REMOVE(&ipsec_acquire_head, ipa, ipa_next);
     662           0 :         if (ipa->ipa_policy != NULL)
     663           0 :                 TAILQ_REMOVE(&ipa->ipa_policy->ipo_acquires, ipa,
     664             :                     ipa_ipo_next);
     665           0 :         pool_put(&ipsec_acquire_pool, ipa);
     666           0 : }
     667             : 
     668             : /*
     669             :  * Find out if there's an ACQUIRE pending.
     670             :  * XXX Need a better structure.
     671             :  */
     672             : struct ipsec_acquire *
     673           0 : ipsp_pending_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw)
     674             : {
     675             :         struct ipsec_acquire *ipa;
     676             : 
     677           0 :         NET_ASSERT_LOCKED();
     678             : 
     679           0 :         TAILQ_FOREACH (ipa, &ipo->ipo_acquires, ipa_ipo_next) {
     680           0 :                 if (!memcmp(gw, &ipa->ipa_addr, gw->sa.sa_len))
     681           0 :                         return ipa;
     682             :         }
     683             : 
     684           0 :         return NULL;
     685           0 : }
     686             : 
     687             : /*
     688             :  * Signal key management that we need an SA.
     689             :  * XXX For outgoing policies, we could try to hold on to the mbuf.
     690             :  */
     691             : int
     692           0 : ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
     693             :     union sockaddr_union *laddr, struct sockaddr_encap *ddst, struct mbuf *m)
     694             : {
     695             :         struct ipsec_acquire *ipa;
     696             : 
     697           0 :         NET_ASSERT_LOCKED();
     698             : 
     699             :         /* Check whether request has been made already. */
     700           0 :         if ((ipa = ipsp_pending_acquire(ipo, gw)) != NULL)
     701           0 :                 return 0;
     702             : 
     703             :         /* Add request in cache and proceed. */
     704           0 :         if (ipsec_acquire_pool_initialized == 0) {
     705           0 :                 ipsec_acquire_pool_initialized = 1;
     706           0 :                 pool_init(&ipsec_acquire_pool, sizeof(struct ipsec_acquire),
     707             :                     0, IPL_SOFTNET, 0, "ipsec acquire", NULL);
     708           0 :         }
     709             : 
     710           0 :         ipa = pool_get(&ipsec_acquire_pool, PR_NOWAIT|PR_ZERO);
     711           0 :         if (ipa == NULL)
     712           0 :                 return ENOMEM;
     713             : 
     714           0 :         ipa->ipa_addr = *gw;
     715             : 
     716           0 :         timeout_set_proc(&ipa->ipa_timeout, ipsp_delete_acquire_timo, ipa);
     717             : 
     718           0 :         ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN;
     719           0 :         ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY;
     720             : 
     721             :         /* Just copy the right information. */
     722           0 :         switch (ipo->ipo_addr.sen_type) {
     723             :         case SENT_IP4:
     724           0 :                 ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP4;
     725           0 :                 ipa->ipa_info.sen_direction = ipo->ipo_addr.sen_direction;
     726           0 :                 ipa->ipa_mask.sen_direction = ipo->ipo_mask.sen_direction;
     727             : 
     728           0 :                 if (ipsp_is_unspecified(ipo->ipo_dst)) {
     729           0 :                         ipa->ipa_info.sen_ip_src = ddst->sen_ip_src;
     730           0 :                         ipa->ipa_mask.sen_ip_src.s_addr = INADDR_BROADCAST;
     731             : 
     732           0 :                         ipa->ipa_info.sen_ip_dst = ddst->sen_ip_dst;
     733           0 :                         ipa->ipa_mask.sen_ip_dst.s_addr = INADDR_BROADCAST;
     734           0 :                 } else {
     735           0 :                         ipa->ipa_info.sen_ip_src = ipo->ipo_addr.sen_ip_src;
     736           0 :                         ipa->ipa_mask.sen_ip_src = ipo->ipo_mask.sen_ip_src;
     737             : 
     738           0 :                         ipa->ipa_info.sen_ip_dst = ipo->ipo_addr.sen_ip_dst;
     739           0 :                         ipa->ipa_mask.sen_ip_dst = ipo->ipo_mask.sen_ip_dst;
     740             :                 }
     741             : 
     742           0 :                 ipa->ipa_info.sen_proto = ipo->ipo_addr.sen_proto;
     743           0 :                 ipa->ipa_mask.sen_proto = ipo->ipo_mask.sen_proto;
     744             : 
     745           0 :                 if (ipo->ipo_addr.sen_proto) {
     746           0 :                         ipa->ipa_info.sen_sport = ipo->ipo_addr.sen_sport;
     747           0 :                         ipa->ipa_mask.sen_sport = ipo->ipo_mask.sen_sport;
     748             : 
     749           0 :                         ipa->ipa_info.sen_dport = ipo->ipo_addr.sen_dport;
     750           0 :                         ipa->ipa_mask.sen_dport = ipo->ipo_mask.sen_dport;
     751           0 :                 }
     752             :                 break;
     753             : 
     754             : #ifdef INET6
     755             :         case SENT_IP6:
     756           0 :                 ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP6;
     757           0 :                 ipa->ipa_info.sen_ip6_direction =
     758           0 :                     ipo->ipo_addr.sen_ip6_direction;
     759           0 :                 ipa->ipa_mask.sen_ip6_direction =
     760           0 :                     ipo->ipo_mask.sen_ip6_direction;
     761             : 
     762           0 :                 if (ipsp_is_unspecified(ipo->ipo_dst)) {
     763           0 :                         ipa->ipa_info.sen_ip6_src = ddst->sen_ip6_src;
     764           0 :                         ipa->ipa_mask.sen_ip6_src = in6mask128;
     765             : 
     766           0 :                         ipa->ipa_info.sen_ip6_dst = ddst->sen_ip6_dst;
     767           0 :                         ipa->ipa_mask.sen_ip6_dst = in6mask128;
     768           0 :                 } else {
     769           0 :                         ipa->ipa_info.sen_ip6_src = ipo->ipo_addr.sen_ip6_src;
     770           0 :                         ipa->ipa_mask.sen_ip6_src = ipo->ipo_mask.sen_ip6_src;
     771             : 
     772           0 :                         ipa->ipa_info.sen_ip6_dst = ipo->ipo_addr.sen_ip6_dst;
     773           0 :                         ipa->ipa_mask.sen_ip6_dst = ipo->ipo_mask.sen_ip6_dst;
     774             :                 }
     775             : 
     776           0 :                 ipa->ipa_info.sen_ip6_proto = ipo->ipo_addr.sen_ip6_proto;
     777           0 :                 ipa->ipa_mask.sen_ip6_proto = ipo->ipo_mask.sen_ip6_proto;
     778             : 
     779           0 :                 if (ipo->ipo_mask.sen_ip6_proto) {
     780           0 :                         ipa->ipa_info.sen_ip6_sport =
     781           0 :                             ipo->ipo_addr.sen_ip6_sport;
     782           0 :                         ipa->ipa_mask.sen_ip6_sport =
     783           0 :                             ipo->ipo_mask.sen_ip6_sport;
     784           0 :                         ipa->ipa_info.sen_ip6_dport =
     785           0 :                             ipo->ipo_addr.sen_ip6_dport;
     786           0 :                         ipa->ipa_mask.sen_ip6_dport =
     787           0 :                             ipo->ipo_mask.sen_ip6_dport;
     788           0 :                 }
     789             :                 break;
     790             : #endif /* INET6 */
     791             : 
     792             :         default:
     793           0 :                 pool_put(&ipsec_acquire_pool, ipa);
     794           0 :                 return 0;
     795             :         }
     796             : 
     797             : #ifdef IPSEC
     798           0 :         timeout_add_sec(&ipa->ipa_timeout, ipsec_expire_acquire);
     799             : #endif
     800             : 
     801           0 :         TAILQ_INSERT_TAIL(&ipsec_acquire_head, ipa, ipa_next);
     802           0 :         TAILQ_INSERT_TAIL(&ipo->ipo_acquires, ipa, ipa_ipo_next);
     803           0 :         ipa->ipa_policy = ipo;
     804             : 
     805             :         /* PF_KEYv2 notification message. */
     806           0 :         return pfkeyv2_acquire(ipo, gw, laddr, &ipa->ipa_seq, ddst);
     807           0 : }
     808             : 
     809             : /*
     810             :  * Deal with PCB security requirements.
     811             :  */
     812             : struct tdb *
     813           0 : ipsp_spd_inp(struct mbuf *m, int af, int hlen, int *error, int direction,
     814             :     struct tdb *tdbp, struct inpcb *inp, struct ipsec_policy *ipo)
     815             : {
     816             :         /* Sanity check. */
     817           0 :         if (inp == NULL)
     818             :                 goto justreturn;
     819             : 
     820             :         /* We only support IPSEC_LEVEL_BYPASS or IPSEC_LEVEL_AVAIL */
     821             : 
     822           0 :         if (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS &&
     823           0 :             inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS &&
     824           0 :             inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)
     825             :                 goto justreturn;
     826             : 
     827           0 :         if (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_AVAIL &&
     828           0 :             inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_AVAIL &&
     829           0 :             inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_AVAIL)
     830             :                 goto justreturn;
     831             : 
     832           0 :         *error = -EINVAL;
     833           0 :         return NULL;
     834             : 
     835             :  justreturn:
     836           0 :         if (ipo != NULL)
     837           0 :                 return ipo->ipo_tdb;
     838             :         else
     839           0 :                 return NULL;
     840           0 : }
     841             : 
     842             : /*
     843             :  * Find a pending ACQUIRE record based on its sequence number.
     844             :  * XXX Need to use a better data structure.
     845             :  */
     846             : struct ipsec_acquire *
     847           0 : ipsec_get_acquire(u_int32_t seq)
     848             : {
     849             :         struct ipsec_acquire *ipa;
     850             : 
     851           0 :         NET_ASSERT_LOCKED();
     852             : 
     853           0 :         TAILQ_FOREACH (ipa, &ipsec_acquire_head, ipa_next)
     854           0 :                 if (ipa->ipa_seq == seq)
     855           0 :                         return ipa;
     856             : 
     857           0 :         return NULL;
     858           0 : }

Generated by: LCOV version 1.13