1*a9643ea8Slogwang /* $FreeBSD$ */ 2*a9643ea8Slogwang /* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */ 3*a9643ea8Slogwang 4*a9643ea8Slogwang /*- 5*a9643ea8Slogwang * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6*a9643ea8Slogwang * All rights reserved. 7*a9643ea8Slogwang * 8*a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 9*a9643ea8Slogwang * modification, are permitted provided that the following conditions 10*a9643ea8Slogwang * are met: 11*a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright 12*a9643ea8Slogwang * notice, this list of conditions and the following disclaimer. 13*a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright 14*a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the 15*a9643ea8Slogwang * documentation and/or other materials provided with the distribution. 16*a9643ea8Slogwang * 3. Neither the name of the project nor the names of its contributors 17*a9643ea8Slogwang * may be used to endorse or promote products derived from this software 18*a9643ea8Slogwang * without specific prior written permission. 19*a9643ea8Slogwang * 20*a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21*a9643ea8Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*a9643ea8Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*a9643ea8Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24*a9643ea8Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*a9643ea8Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*a9643ea8Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*a9643ea8Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*a9643ea8Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*a9643ea8Slogwang * SUCH DAMAGE. 31*a9643ea8Slogwang */ 32*a9643ea8Slogwang 33*a9643ea8Slogwang /* 34*a9643ea8Slogwang * IPsec controller part. 35*a9643ea8Slogwang */ 36*a9643ea8Slogwang 37*a9643ea8Slogwang #include "opt_inet.h" 38*a9643ea8Slogwang #include "opt_inet6.h" 39*a9643ea8Slogwang #include "opt_ipsec.h" 40*a9643ea8Slogwang 41*a9643ea8Slogwang #include <sys/param.h> 42*a9643ea8Slogwang #include <sys/systm.h> 43*a9643ea8Slogwang #include <sys/malloc.h> 44*a9643ea8Slogwang #include <sys/mbuf.h> 45*a9643ea8Slogwang #include <sys/domain.h> 46*a9643ea8Slogwang #include <sys/priv.h> 47*a9643ea8Slogwang #include <sys/protosw.h> 48*a9643ea8Slogwang #include <sys/socket.h> 49*a9643ea8Slogwang #include <sys/socketvar.h> 50*a9643ea8Slogwang #include <sys/errno.h> 51*a9643ea8Slogwang #include <sys/hhook.h> 52*a9643ea8Slogwang #include <sys/time.h> 53*a9643ea8Slogwang #include <sys/kernel.h> 54*a9643ea8Slogwang #include <sys/syslog.h> 55*a9643ea8Slogwang #include <sys/sysctl.h> 56*a9643ea8Slogwang #include <sys/proc.h> 57*a9643ea8Slogwang 58*a9643ea8Slogwang #include <net/if.h> 59*a9643ea8Slogwang #include <net/if_enc.h> 60*a9643ea8Slogwang #include <net/if_var.h> 61*a9643ea8Slogwang #include <net/vnet.h> 62*a9643ea8Slogwang 63*a9643ea8Slogwang #include <netinet/in.h> 64*a9643ea8Slogwang #include <netinet/in_systm.h> 65*a9643ea8Slogwang #include <netinet/ip.h> 66*a9643ea8Slogwang #include <netinet/ip_var.h> 67*a9643ea8Slogwang #include <netinet/in_var.h> 68*a9643ea8Slogwang #include <netinet/udp.h> 69*a9643ea8Slogwang #include <netinet/udp_var.h> 70*a9643ea8Slogwang #include <netinet/tcp.h> 71*a9643ea8Slogwang #include <netinet/udp.h> 72*a9643ea8Slogwang 73*a9643ea8Slogwang #include <netinet/ip6.h> 74*a9643ea8Slogwang #ifdef INET6 75*a9643ea8Slogwang #include <netinet6/ip6_var.h> 76*a9643ea8Slogwang #endif 77*a9643ea8Slogwang #include <netinet/in_pcb.h> 78*a9643ea8Slogwang #ifdef INET6 79*a9643ea8Slogwang #include <netinet/icmp6.h> 80*a9643ea8Slogwang #endif 81*a9643ea8Slogwang 82*a9643ea8Slogwang #include <sys/types.h> 83*a9643ea8Slogwang #include <netipsec/ipsec.h> 84*a9643ea8Slogwang #ifdef INET6 85*a9643ea8Slogwang #include <netipsec/ipsec6.h> 86*a9643ea8Slogwang #endif 87*a9643ea8Slogwang #include <netipsec/ah_var.h> 88*a9643ea8Slogwang #include <netipsec/esp_var.h> 89*a9643ea8Slogwang #include <netipsec/ipcomp.h> /*XXX*/ 90*a9643ea8Slogwang #include <netipsec/ipcomp_var.h> 91*a9643ea8Slogwang 92*a9643ea8Slogwang #include <netipsec/key.h> 93*a9643ea8Slogwang #include <netipsec/keydb.h> 94*a9643ea8Slogwang #include <netipsec/key_debug.h> 95*a9643ea8Slogwang 96*a9643ea8Slogwang #include <netipsec/xform.h> 97*a9643ea8Slogwang 98*a9643ea8Slogwang #include <machine/in_cksum.h> 99*a9643ea8Slogwang 100*a9643ea8Slogwang #include <opencrypto/cryptodev.h> 101*a9643ea8Slogwang 102*a9643ea8Slogwang #ifdef IPSEC_DEBUG 103*a9643ea8Slogwang VNET_DEFINE(int, ipsec_debug) = 1; 104*a9643ea8Slogwang #else 105*a9643ea8Slogwang VNET_DEFINE(int, ipsec_debug) = 0; 106*a9643ea8Slogwang #endif 107*a9643ea8Slogwang 108*a9643ea8Slogwang /* NB: name changed so netstat doesn't use it. */ 109*a9643ea8Slogwang VNET_PCPUSTAT_DEFINE(struct ipsecstat, ipsec4stat); 110*a9643ea8Slogwang VNET_PCPUSTAT_SYSINIT(ipsec4stat); 111*a9643ea8Slogwang 112*a9643ea8Slogwang #ifdef VIMAGE 113*a9643ea8Slogwang VNET_PCPUSTAT_SYSUNINIT(ipsec4stat); 114*a9643ea8Slogwang #endif /* VIMAGE */ 115*a9643ea8Slogwang 116*a9643ea8Slogwang VNET_DEFINE(int, ip4_ah_offsetmask) = 0; /* maybe IP_DF? */ 117*a9643ea8Slogwang /* DF bit on encap. 0: clear 1: set 2: copy */ 118*a9643ea8Slogwang VNET_DEFINE(int, ip4_ipsec_dfbit) = 0; 119*a9643ea8Slogwang VNET_DEFINE(int, ip4_esp_trans_deflev) = IPSEC_LEVEL_USE; 120*a9643ea8Slogwang VNET_DEFINE(int, ip4_esp_net_deflev) = IPSEC_LEVEL_USE; 121*a9643ea8Slogwang VNET_DEFINE(int, ip4_ah_trans_deflev) = IPSEC_LEVEL_USE; 122*a9643ea8Slogwang VNET_DEFINE(int, ip4_ah_net_deflev) = IPSEC_LEVEL_USE; 123*a9643ea8Slogwang /* ECN ignore(-1)/forbidden(0)/allowed(1) */ 124*a9643ea8Slogwang VNET_DEFINE(int, ip4_ipsec_ecn) = 0; 125*a9643ea8Slogwang VNET_DEFINE(int, ip4_esp_randpad) = -1; 126*a9643ea8Slogwang 127*a9643ea8Slogwang static VNET_DEFINE(struct secpolicy, def_policy); 128*a9643ea8Slogwang #define V_def_policy VNET(def_policy) 129*a9643ea8Slogwang /* 130*a9643ea8Slogwang * Crypto support requirements: 131*a9643ea8Slogwang * 132*a9643ea8Slogwang * 1 require hardware support 133*a9643ea8Slogwang * -1 require software support 134*a9643ea8Slogwang * 0 take anything 135*a9643ea8Slogwang */ 136*a9643ea8Slogwang VNET_DEFINE(int, crypto_support) = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE; 137*a9643ea8Slogwang 138*a9643ea8Slogwang FEATURE(ipsec, "Internet Protocol Security (IPsec)"); 139*a9643ea8Slogwang #ifdef IPSEC_NAT_T 140*a9643ea8Slogwang FEATURE(ipsec_natt, "UDP Encapsulation of IPsec ESP Packets ('NAT-T')"); 141*a9643ea8Slogwang #endif 142*a9643ea8Slogwang 143*a9643ea8Slogwang SYSCTL_DECL(_net_inet_ipsec); 144*a9643ea8Slogwang 145*a9643ea8Slogwang /* net.inet.ipsec */ 146*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy, 147*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(def_policy).policy, 0, 148*a9643ea8Slogwang "IPsec default policy."); 149*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, 150*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_esp_trans_deflev), 0, 151*a9643ea8Slogwang "Default ESP transport mode level"); 152*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, 153*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_esp_net_deflev), 0, 154*a9643ea8Slogwang "Default ESP tunnel mode level."); 155*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, 156*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ah_trans_deflev), 0, 157*a9643ea8Slogwang "AH transfer mode default level."); 158*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, 159*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ah_net_deflev), 0, 160*a9643ea8Slogwang "AH tunnel mode default level."); 161*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, ah_cleartos, 162*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ah_cleartos), 0, 163*a9643ea8Slogwang "If set clear type-of-service field when doing AH computation."); 164*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, ah_offsetmask, 165*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ah_offsetmask), 0, 166*a9643ea8Slogwang "If not set clear offset field mask when doing AH computation."); 167*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, dfbit, 168*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ipsec_dfbit), 0, 169*a9643ea8Slogwang "Do not fragment bit on encap."); 170*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, ecn, 171*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ipsec_ecn), 0, 172*a9643ea8Slogwang "Explicit Congestion Notification handling."); 173*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG, debug, 174*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_debug), 0, 175*a9643ea8Slogwang "Enable IPsec debugging output when set."); 176*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, crypto_support, 177*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(crypto_support), 0, 178*a9643ea8Slogwang "Crypto driver selection."); 179*a9643ea8Slogwang SYSCTL_VNET_PCPUSTAT(_net_inet_ipsec, OID_AUTO, ipsecstats, struct ipsecstat, 180*a9643ea8Slogwang ipsec4stat, "IPsec IPv4 statistics."); 181*a9643ea8Slogwang 182*a9643ea8Slogwang #ifdef REGRESSION 183*a9643ea8Slogwang /* 184*a9643ea8Slogwang * When set to 1, IPsec will send packets with the same sequence number. 185*a9643ea8Slogwang * This allows to verify if the other side has proper replay attacks detection. 186*a9643ea8Slogwang */ 187*a9643ea8Slogwang VNET_DEFINE(int, ipsec_replay) = 0; 188*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_replay, 189*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_replay), 0, 190*a9643ea8Slogwang "Emulate replay attack"); 191*a9643ea8Slogwang /* 192*a9643ea8Slogwang * When set 1, IPsec will send packets with corrupted HMAC. 193*a9643ea8Slogwang * This allows to verify if the other side properly detects modified packets. 194*a9643ea8Slogwang */ 195*a9643ea8Slogwang VNET_DEFINE(int, ipsec_integrity) = 0; 196*a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_integrity, 197*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_integrity), 0, 198*a9643ea8Slogwang "Emulate man-in-the-middle attack"); 199*a9643ea8Slogwang #endif 200*a9643ea8Slogwang 201*a9643ea8Slogwang #ifdef INET6 202*a9643ea8Slogwang VNET_PCPUSTAT_DEFINE(struct ipsecstat, ipsec6stat); 203*a9643ea8Slogwang VNET_PCPUSTAT_SYSINIT(ipsec6stat); 204*a9643ea8Slogwang 205*a9643ea8Slogwang #ifdef VIMAGE 206*a9643ea8Slogwang VNET_PCPUSTAT_SYSUNINIT(ipsec6stat); 207*a9643ea8Slogwang #endif /* VIMAGE */ 208*a9643ea8Slogwang 209*a9643ea8Slogwang VNET_DEFINE(int, ip6_esp_trans_deflev) = IPSEC_LEVEL_USE; 210*a9643ea8Slogwang VNET_DEFINE(int, ip6_esp_net_deflev) = IPSEC_LEVEL_USE; 211*a9643ea8Slogwang VNET_DEFINE(int, ip6_ah_trans_deflev) = IPSEC_LEVEL_USE; 212*a9643ea8Slogwang VNET_DEFINE(int, ip6_ah_net_deflev) = IPSEC_LEVEL_USE; 213*a9643ea8Slogwang VNET_DEFINE(int, ip6_ipsec_ecn) = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ 214*a9643ea8Slogwang 215*a9643ea8Slogwang SYSCTL_DECL(_net_inet6_ipsec6); 216*a9643ea8Slogwang 217*a9643ea8Slogwang /* net.inet6.ipsec6 */ 218*a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy, 219*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(def_policy).policy, 0, 220*a9643ea8Slogwang "IPsec default policy."); 221*a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, 222*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_esp_trans_deflev), 0, 223*a9643ea8Slogwang "Default ESP transport mode level."); 224*a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, 225*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_esp_net_deflev), 0, 226*a9643ea8Slogwang "Default ESP tunnel mode level."); 227*a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, 228*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ah_trans_deflev), 0, 229*a9643ea8Slogwang "AH transfer mode default level."); 230*a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, 231*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ah_net_deflev), 0, 232*a9643ea8Slogwang "AH tunnel mode default level."); 233*a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, ecn, 234*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ipsec_ecn), 0, 235*a9643ea8Slogwang "Explicit Congestion Notification handling."); 236*a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG, debug, 237*a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_debug), 0, 238*a9643ea8Slogwang "Enable IPsec debugging output when set."); 239*a9643ea8Slogwang SYSCTL_VNET_PCPUSTAT(_net_inet6_ipsec6, IPSECCTL_STATS, ipsecstats, 240*a9643ea8Slogwang struct ipsecstat, ipsec6stat, "IPsec IPv6 statistics."); 241*a9643ea8Slogwang #endif /* INET6 */ 242*a9643ea8Slogwang 243*a9643ea8Slogwang static int ipsec_in_reject(struct secpolicy *, const struct mbuf *); 244*a9643ea8Slogwang static int ipsec_setspidx_inpcb(const struct mbuf *, struct inpcb *); 245*a9643ea8Slogwang static int ipsec_setspidx(const struct mbuf *, struct secpolicyindex *, int); 246*a9643ea8Slogwang static void ipsec4_get_ulp(const struct mbuf *m, struct secpolicyindex *, int); 247*a9643ea8Slogwang static int ipsec4_setspidx_ipaddr(const struct mbuf *, struct secpolicyindex *); 248*a9643ea8Slogwang #ifdef INET6 249*a9643ea8Slogwang static void ipsec6_get_ulp(const struct mbuf *m, struct secpolicyindex *, int); 250*a9643ea8Slogwang static int ipsec6_setspidx_ipaddr(const struct mbuf *, struct secpolicyindex *); 251*a9643ea8Slogwang #endif 252*a9643ea8Slogwang static void ipsec_delpcbpolicy(struct inpcbpolicy *); 253*a9643ea8Slogwang static struct secpolicy *ipsec_deepcopy_policy(struct secpolicy *src); 254*a9643ea8Slogwang static void vshiftl(unsigned char *, int, int); 255*a9643ea8Slogwang 256*a9643ea8Slogwang MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy"); 257*a9643ea8Slogwang 258*a9643ea8Slogwang /* 259*a9643ea8Slogwang * Return a held reference to the default SP. 260*a9643ea8Slogwang */ 261*a9643ea8Slogwang static struct secpolicy * 262*a9643ea8Slogwang key_allocsp_default(const char* where, int tag) 263*a9643ea8Slogwang { 264*a9643ea8Slogwang struct secpolicy *sp; 265*a9643ea8Slogwang 266*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 267*a9643ea8Slogwang printf("DP key_allocsp_default from %s:%u\n", where, tag)); 268*a9643ea8Slogwang 269*a9643ea8Slogwang sp = &V_def_policy; 270*a9643ea8Slogwang if (sp->policy != IPSEC_POLICY_DISCARD && 271*a9643ea8Slogwang sp->policy != IPSEC_POLICY_NONE) { 272*a9643ea8Slogwang ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", 273*a9643ea8Slogwang sp->policy, IPSEC_POLICY_NONE)); 274*a9643ea8Slogwang sp->policy = IPSEC_POLICY_NONE; 275*a9643ea8Slogwang } 276*a9643ea8Slogwang key_addref(sp); 277*a9643ea8Slogwang 278*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 279*a9643ea8Slogwang printf("DP key_allocsp_default returns SP:%p (%u)\n", 280*a9643ea8Slogwang sp, sp->refcnt)); 281*a9643ea8Slogwang return (sp); 282*a9643ea8Slogwang } 283*a9643ea8Slogwang #define KEY_ALLOCSP_DEFAULT() \ 284*a9643ea8Slogwang key_allocsp_default(__FILE__, __LINE__) 285*a9643ea8Slogwang 286*a9643ea8Slogwang /* 287*a9643ea8Slogwang * For OUTBOUND packet having a socket. Searching SPD for packet, 288*a9643ea8Slogwang * and return a pointer to SP. 289*a9643ea8Slogwang * OUT: NULL: no apropreate SP found, the following value is set to error. 290*a9643ea8Slogwang * 0 : bypass 291*a9643ea8Slogwang * EACCES : discard packet. 292*a9643ea8Slogwang * ENOENT : ipsec_acquire() in progress, maybe. 293*a9643ea8Slogwang * others : error occurred. 294*a9643ea8Slogwang * others: a pointer to SP 295*a9643ea8Slogwang * 296*a9643ea8Slogwang * NOTE: IPv6 mapped adddress concern is implemented here. 297*a9643ea8Slogwang */ 298*a9643ea8Slogwang struct secpolicy * 299*a9643ea8Slogwang ipsec_getpolicy(struct tdb_ident *tdbi, u_int dir) 300*a9643ea8Slogwang { 301*a9643ea8Slogwang struct secpolicy *sp; 302*a9643ea8Slogwang 303*a9643ea8Slogwang IPSEC_ASSERT(tdbi != NULL, ("null tdbi")); 304*a9643ea8Slogwang IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, 305*a9643ea8Slogwang ("invalid direction %u", dir)); 306*a9643ea8Slogwang 307*a9643ea8Slogwang sp = KEY_ALLOCSP2(tdbi->spi, &tdbi->dst, tdbi->proto, dir); 308*a9643ea8Slogwang if (sp == NULL) /*XXX????*/ 309*a9643ea8Slogwang sp = KEY_ALLOCSP_DEFAULT(); 310*a9643ea8Slogwang IPSEC_ASSERT(sp != NULL, ("null SP")); 311*a9643ea8Slogwang return (sp); 312*a9643ea8Slogwang } 313*a9643ea8Slogwang 314*a9643ea8Slogwang /* 315*a9643ea8Slogwang * For OUTBOUND packet having a socket. Searching SPD for packet, 316*a9643ea8Slogwang * and return a pointer to SP. 317*a9643ea8Slogwang * OUT: NULL: no apropreate SP found, the following value is set to error. 318*a9643ea8Slogwang * 0 : bypass 319*a9643ea8Slogwang * EACCES : discard packet. 320*a9643ea8Slogwang * ENOENT : ipsec_acquire() in progress, maybe. 321*a9643ea8Slogwang * others : error occurred. 322*a9643ea8Slogwang * others: a pointer to SP 323*a9643ea8Slogwang * 324*a9643ea8Slogwang * NOTE: IPv6 mapped adddress concern is implemented here. 325*a9643ea8Slogwang */ 326*a9643ea8Slogwang static struct secpolicy * 327*a9643ea8Slogwang ipsec_getpolicybysock(const struct mbuf *m, u_int dir, struct inpcb *inp, 328*a9643ea8Slogwang int *error) 329*a9643ea8Slogwang { 330*a9643ea8Slogwang struct inpcbpolicy *pcbsp; 331*a9643ea8Slogwang struct secpolicy *currsp = NULL; /* Policy on socket. */ 332*a9643ea8Slogwang struct secpolicy *sp; 333*a9643ea8Slogwang 334*a9643ea8Slogwang IPSEC_ASSERT(m != NULL, ("null mbuf")); 335*a9643ea8Slogwang IPSEC_ASSERT(inp != NULL, ("null inpcb")); 336*a9643ea8Slogwang IPSEC_ASSERT(error != NULL, ("null error")); 337*a9643ea8Slogwang IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, 338*a9643ea8Slogwang ("invalid direction %u", dir)); 339*a9643ea8Slogwang 340*a9643ea8Slogwang if (!key_havesp(dir)) { 341*a9643ea8Slogwang /* No SP found, use system default. */ 342*a9643ea8Slogwang sp = KEY_ALLOCSP_DEFAULT(); 343*a9643ea8Slogwang return (sp); 344*a9643ea8Slogwang } 345*a9643ea8Slogwang 346*a9643ea8Slogwang /* Set spidx in pcb. */ 347*a9643ea8Slogwang *error = ipsec_setspidx_inpcb(m, inp); 348*a9643ea8Slogwang if (*error) 349*a9643ea8Slogwang return (NULL); 350*a9643ea8Slogwang 351*a9643ea8Slogwang pcbsp = inp->inp_sp; 352*a9643ea8Slogwang IPSEC_ASSERT(pcbsp != NULL, ("null pcbsp")); 353*a9643ea8Slogwang switch (dir) { 354*a9643ea8Slogwang case IPSEC_DIR_INBOUND: 355*a9643ea8Slogwang currsp = pcbsp->sp_in; 356*a9643ea8Slogwang break; 357*a9643ea8Slogwang case IPSEC_DIR_OUTBOUND: 358*a9643ea8Slogwang currsp = pcbsp->sp_out; 359*a9643ea8Slogwang break; 360*a9643ea8Slogwang } 361*a9643ea8Slogwang IPSEC_ASSERT(currsp != NULL, ("null currsp")); 362*a9643ea8Slogwang 363*a9643ea8Slogwang if (pcbsp->priv) { /* When privilieged socket. */ 364*a9643ea8Slogwang switch (currsp->policy) { 365*a9643ea8Slogwang case IPSEC_POLICY_BYPASS: 366*a9643ea8Slogwang case IPSEC_POLICY_IPSEC: 367*a9643ea8Slogwang key_addref(currsp); 368*a9643ea8Slogwang sp = currsp; 369*a9643ea8Slogwang break; 370*a9643ea8Slogwang 371*a9643ea8Slogwang case IPSEC_POLICY_ENTRUST: 372*a9643ea8Slogwang /* Look for a policy in SPD. */ 373*a9643ea8Slogwang sp = KEY_ALLOCSP(&currsp->spidx, dir); 374*a9643ea8Slogwang if (sp == NULL) /* No SP found. */ 375*a9643ea8Slogwang sp = KEY_ALLOCSP_DEFAULT(); 376*a9643ea8Slogwang break; 377*a9643ea8Slogwang 378*a9643ea8Slogwang default: 379*a9643ea8Slogwang ipseclog((LOG_ERR, "%s: Invalid policy for PCB %d\n", 380*a9643ea8Slogwang __func__, currsp->policy)); 381*a9643ea8Slogwang *error = EINVAL; 382*a9643ea8Slogwang return (NULL); 383*a9643ea8Slogwang } 384*a9643ea8Slogwang } else { /* Unpriv, SPD has policy. */ 385*a9643ea8Slogwang sp = KEY_ALLOCSP(&currsp->spidx, dir); 386*a9643ea8Slogwang if (sp == NULL) { /* No SP found. */ 387*a9643ea8Slogwang switch (currsp->policy) { 388*a9643ea8Slogwang case IPSEC_POLICY_BYPASS: 389*a9643ea8Slogwang ipseclog((LOG_ERR, "%s: Illegal policy for " 390*a9643ea8Slogwang "non-priviliged defined %d\n", 391*a9643ea8Slogwang __func__, currsp->policy)); 392*a9643ea8Slogwang *error = EINVAL; 393*a9643ea8Slogwang return (NULL); 394*a9643ea8Slogwang 395*a9643ea8Slogwang case IPSEC_POLICY_ENTRUST: 396*a9643ea8Slogwang sp = KEY_ALLOCSP_DEFAULT(); 397*a9643ea8Slogwang break; 398*a9643ea8Slogwang 399*a9643ea8Slogwang case IPSEC_POLICY_IPSEC: 400*a9643ea8Slogwang key_addref(currsp); 401*a9643ea8Slogwang sp = currsp; 402*a9643ea8Slogwang break; 403*a9643ea8Slogwang 404*a9643ea8Slogwang default: 405*a9643ea8Slogwang ipseclog((LOG_ERR, "%s: Invalid policy for " 406*a9643ea8Slogwang "PCB %d\n", __func__, currsp->policy)); 407*a9643ea8Slogwang *error = EINVAL; 408*a9643ea8Slogwang return (NULL); 409*a9643ea8Slogwang } 410*a9643ea8Slogwang } 411*a9643ea8Slogwang } 412*a9643ea8Slogwang IPSEC_ASSERT(sp != NULL, 413*a9643ea8Slogwang ("null SP (priv %u policy %u", pcbsp->priv, currsp->policy)); 414*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 415*a9643ea8Slogwang printf("DP %s (priv %u policy %u) allocate SP:%p (refcnt %u)\n", 416*a9643ea8Slogwang __func__, pcbsp->priv, currsp->policy, sp, sp->refcnt)); 417*a9643ea8Slogwang return (sp); 418*a9643ea8Slogwang } 419*a9643ea8Slogwang 420*a9643ea8Slogwang /* 421*a9643ea8Slogwang * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet, 422*a9643ea8Slogwang * and return a pointer to SP. 423*a9643ea8Slogwang * OUT: positive: a pointer to the entry for security policy leaf matched. 424*a9643ea8Slogwang * NULL: no apropreate SP found, the following value is set to error. 425*a9643ea8Slogwang * 0 : bypass 426*a9643ea8Slogwang * EACCES : discard packet. 427*a9643ea8Slogwang * ENOENT : ipsec_acquire() in progress, maybe. 428*a9643ea8Slogwang * others : error occurred. 429*a9643ea8Slogwang */ 430*a9643ea8Slogwang struct secpolicy * 431*a9643ea8Slogwang ipsec_getpolicybyaddr(const struct mbuf *m, u_int dir, int *error) 432*a9643ea8Slogwang { 433*a9643ea8Slogwang struct secpolicyindex spidx; 434*a9643ea8Slogwang struct secpolicy *sp; 435*a9643ea8Slogwang 436*a9643ea8Slogwang IPSEC_ASSERT(m != NULL, ("null mbuf")); 437*a9643ea8Slogwang IPSEC_ASSERT(error != NULL, ("null error")); 438*a9643ea8Slogwang IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, 439*a9643ea8Slogwang ("invalid direction %u", dir)); 440*a9643ea8Slogwang 441*a9643ea8Slogwang sp = NULL; 442*a9643ea8Slogwang *error = 0; 443*a9643ea8Slogwang if (key_havesp(dir)) { 444*a9643ea8Slogwang /* Make an index to look for a policy. */ 445*a9643ea8Slogwang *error = ipsec_setspidx(m, &spidx, 0); 446*a9643ea8Slogwang if (*error != 0) { 447*a9643ea8Slogwang DPRINTF(("%s: setpidx failed, dir %u\n", 448*a9643ea8Slogwang __func__, dir)); 449*a9643ea8Slogwang return (NULL); 450*a9643ea8Slogwang } 451*a9643ea8Slogwang spidx.dir = dir; 452*a9643ea8Slogwang sp = KEY_ALLOCSP(&spidx, dir); 453*a9643ea8Slogwang } 454*a9643ea8Slogwang if (sp == NULL) /* No SP found, use system default. */ 455*a9643ea8Slogwang sp = KEY_ALLOCSP_DEFAULT(); 456*a9643ea8Slogwang IPSEC_ASSERT(sp != NULL, ("null SP")); 457*a9643ea8Slogwang return (sp); 458*a9643ea8Slogwang } 459*a9643ea8Slogwang 460*a9643ea8Slogwang struct secpolicy * 461*a9643ea8Slogwang ipsec4_checkpolicy(const struct mbuf *m, u_int dir, int *error, 462*a9643ea8Slogwang struct inpcb *inp) 463*a9643ea8Slogwang { 464*a9643ea8Slogwang struct secpolicy *sp; 465*a9643ea8Slogwang 466*a9643ea8Slogwang *error = 0; 467*a9643ea8Slogwang if (inp == NULL) 468*a9643ea8Slogwang sp = ipsec_getpolicybyaddr(m, dir, error); 469*a9643ea8Slogwang else 470*a9643ea8Slogwang sp = ipsec_getpolicybysock(m, dir, inp, error); 471*a9643ea8Slogwang if (sp == NULL) { 472*a9643ea8Slogwang IPSEC_ASSERT(*error != 0, ("getpolicy failed w/o error")); 473*a9643ea8Slogwang IPSECSTAT_INC(ips_out_inval); 474*a9643ea8Slogwang return (NULL); 475*a9643ea8Slogwang } 476*a9643ea8Slogwang IPSEC_ASSERT(*error == 0, ("sp w/ error set to %u", *error)); 477*a9643ea8Slogwang switch (sp->policy) { 478*a9643ea8Slogwang case IPSEC_POLICY_ENTRUST: 479*a9643ea8Slogwang default: 480*a9643ea8Slogwang printf("%s: invalid policy %u\n", __func__, sp->policy); 481*a9643ea8Slogwang /* FALLTHROUGH */ 482*a9643ea8Slogwang case IPSEC_POLICY_DISCARD: 483*a9643ea8Slogwang IPSECSTAT_INC(ips_out_polvio); 484*a9643ea8Slogwang *error = -EINVAL; /* Packet is discarded by caller. */ 485*a9643ea8Slogwang break; 486*a9643ea8Slogwang case IPSEC_POLICY_BYPASS: 487*a9643ea8Slogwang case IPSEC_POLICY_NONE: 488*a9643ea8Slogwang KEY_FREESP(&sp); 489*a9643ea8Slogwang sp = NULL; /* NB: force NULL result. */ 490*a9643ea8Slogwang break; 491*a9643ea8Slogwang case IPSEC_POLICY_IPSEC: 492*a9643ea8Slogwang if (sp->req == NULL) /* Acquire a SA. */ 493*a9643ea8Slogwang *error = key_spdacquire(sp); 494*a9643ea8Slogwang break; 495*a9643ea8Slogwang } 496*a9643ea8Slogwang if (*error != 0) { 497*a9643ea8Slogwang KEY_FREESP(&sp); 498*a9643ea8Slogwang sp = NULL; 499*a9643ea8Slogwang } 500*a9643ea8Slogwang return (sp); 501*a9643ea8Slogwang } 502*a9643ea8Slogwang 503*a9643ea8Slogwang static int 504*a9643ea8Slogwang ipsec_setspidx_inpcb(const struct mbuf *m, struct inpcb *inp) 505*a9643ea8Slogwang { 506*a9643ea8Slogwang int error; 507*a9643ea8Slogwang 508*a9643ea8Slogwang IPSEC_ASSERT(inp != NULL, ("null inp")); 509*a9643ea8Slogwang IPSEC_ASSERT(inp->inp_sp != NULL, ("null inp_sp")); 510*a9643ea8Slogwang IPSEC_ASSERT(inp->inp_sp->sp_out != NULL && inp->inp_sp->sp_in != NULL, 511*a9643ea8Slogwang ("null sp_in || sp_out")); 512*a9643ea8Slogwang 513*a9643ea8Slogwang error = ipsec_setspidx(m, &inp->inp_sp->sp_in->spidx, 1); 514*a9643ea8Slogwang if (error == 0) { 515*a9643ea8Slogwang inp->inp_sp->sp_in->spidx.dir = IPSEC_DIR_INBOUND; 516*a9643ea8Slogwang inp->inp_sp->sp_out->spidx = inp->inp_sp->sp_in->spidx; 517*a9643ea8Slogwang inp->inp_sp->sp_out->spidx.dir = IPSEC_DIR_OUTBOUND; 518*a9643ea8Slogwang } else { 519*a9643ea8Slogwang bzero(&inp->inp_sp->sp_in->spidx, 520*a9643ea8Slogwang sizeof (inp->inp_sp->sp_in->spidx)); 521*a9643ea8Slogwang bzero(&inp->inp_sp->sp_out->spidx, 522*a9643ea8Slogwang sizeof (inp->inp_sp->sp_in->spidx)); 523*a9643ea8Slogwang } 524*a9643ea8Slogwang return (error); 525*a9643ea8Slogwang } 526*a9643ea8Slogwang 527*a9643ea8Slogwang /* 528*a9643ea8Slogwang * Configure security policy index (src/dst/proto/sport/dport) 529*a9643ea8Slogwang * by looking at the content of mbuf. 530*a9643ea8Slogwang * The caller is responsible for error recovery (like clearing up spidx). 531*a9643ea8Slogwang */ 532*a9643ea8Slogwang static int 533*a9643ea8Slogwang ipsec_setspidx(const struct mbuf *m, struct secpolicyindex *spidx, 534*a9643ea8Slogwang int needport) 535*a9643ea8Slogwang { 536*a9643ea8Slogwang struct ip ipbuf; 537*a9643ea8Slogwang const struct ip *ip = NULL; 538*a9643ea8Slogwang const struct mbuf *n; 539*a9643ea8Slogwang u_int v; 540*a9643ea8Slogwang int len; 541*a9643ea8Slogwang int error; 542*a9643ea8Slogwang 543*a9643ea8Slogwang IPSEC_ASSERT(m != NULL, ("null mbuf")); 544*a9643ea8Slogwang 545*a9643ea8Slogwang /* 546*a9643ea8Slogwang * Validate m->m_pkthdr.len. We see incorrect length if we 547*a9643ea8Slogwang * mistakenly call this function with inconsistent mbuf chain 548*a9643ea8Slogwang * (like 4.4BSD tcp/udp processing). XXX Should we panic here? 549*a9643ea8Slogwang */ 550*a9643ea8Slogwang len = 0; 551*a9643ea8Slogwang for (n = m; n; n = n->m_next) 552*a9643ea8Slogwang len += n->m_len; 553*a9643ea8Slogwang if (m->m_pkthdr.len != len) { 554*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 555*a9643ea8Slogwang printf("%s: pkthdr len(%d) mismatch (%d), ignored.\n", 556*a9643ea8Slogwang __func__, len, m->m_pkthdr.len)); 557*a9643ea8Slogwang return (EINVAL); 558*a9643ea8Slogwang } 559*a9643ea8Slogwang 560*a9643ea8Slogwang if (m->m_pkthdr.len < sizeof(struct ip)) { 561*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 562*a9643ea8Slogwang printf("%s: pkthdr len(%d) too small (v4), ignored.\n", 563*a9643ea8Slogwang __func__, m->m_pkthdr.len)); 564*a9643ea8Slogwang return (EINVAL); 565*a9643ea8Slogwang } 566*a9643ea8Slogwang 567*a9643ea8Slogwang if (m->m_len >= sizeof(*ip)) 568*a9643ea8Slogwang ip = mtod(m, const struct ip *); 569*a9643ea8Slogwang else { 570*a9643ea8Slogwang m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf); 571*a9643ea8Slogwang ip = &ipbuf; 572*a9643ea8Slogwang } 573*a9643ea8Slogwang v = ip->ip_v; 574*a9643ea8Slogwang switch (v) { 575*a9643ea8Slogwang case 4: 576*a9643ea8Slogwang error = ipsec4_setspidx_ipaddr(m, spidx); 577*a9643ea8Slogwang if (error) 578*a9643ea8Slogwang return (error); 579*a9643ea8Slogwang ipsec4_get_ulp(m, spidx, needport); 580*a9643ea8Slogwang return (0); 581*a9643ea8Slogwang #ifdef INET6 582*a9643ea8Slogwang case 6: 583*a9643ea8Slogwang if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) { 584*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 585*a9643ea8Slogwang printf("%s: pkthdr len(%d) too small (v6), " 586*a9643ea8Slogwang "ignored\n", __func__, m->m_pkthdr.len)); 587*a9643ea8Slogwang return (EINVAL); 588*a9643ea8Slogwang } 589*a9643ea8Slogwang error = ipsec6_setspidx_ipaddr(m, spidx); 590*a9643ea8Slogwang if (error) 591*a9643ea8Slogwang return (error); 592*a9643ea8Slogwang ipsec6_get_ulp(m, spidx, needport); 593*a9643ea8Slogwang return (0); 594*a9643ea8Slogwang #endif 595*a9643ea8Slogwang default: 596*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 597*a9643ea8Slogwang printf("%s: " "unknown IP version %u, ignored.\n", 598*a9643ea8Slogwang __func__, v)); 599*a9643ea8Slogwang return (EINVAL); 600*a9643ea8Slogwang } 601*a9643ea8Slogwang } 602*a9643ea8Slogwang 603*a9643ea8Slogwang static void 604*a9643ea8Slogwang ipsec4_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx, 605*a9643ea8Slogwang int needport) 606*a9643ea8Slogwang { 607*a9643ea8Slogwang u_int8_t nxt; 608*a9643ea8Slogwang int off; 609*a9643ea8Slogwang 610*a9643ea8Slogwang /* Sanity check. */ 611*a9643ea8Slogwang IPSEC_ASSERT(m != NULL, ("null mbuf")); 612*a9643ea8Slogwang IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip),("packet too short")); 613*a9643ea8Slogwang 614*a9643ea8Slogwang if (m->m_len >= sizeof (struct ip)) { 615*a9643ea8Slogwang const struct ip *ip = mtod(m, const struct ip *); 616*a9643ea8Slogwang if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) 617*a9643ea8Slogwang goto done; 618*a9643ea8Slogwang off = ip->ip_hl << 2; 619*a9643ea8Slogwang nxt = ip->ip_p; 620*a9643ea8Slogwang } else { 621*a9643ea8Slogwang struct ip ih; 622*a9643ea8Slogwang 623*a9643ea8Slogwang m_copydata(m, 0, sizeof (struct ip), (caddr_t) &ih); 624*a9643ea8Slogwang if (ih.ip_off & htons(IP_MF | IP_OFFMASK)) 625*a9643ea8Slogwang goto done; 626*a9643ea8Slogwang off = ih.ip_hl << 2; 627*a9643ea8Slogwang nxt = ih.ip_p; 628*a9643ea8Slogwang } 629*a9643ea8Slogwang 630*a9643ea8Slogwang while (off < m->m_pkthdr.len) { 631*a9643ea8Slogwang struct ip6_ext ip6e; 632*a9643ea8Slogwang struct tcphdr th; 633*a9643ea8Slogwang struct udphdr uh; 634*a9643ea8Slogwang 635*a9643ea8Slogwang switch (nxt) { 636*a9643ea8Slogwang case IPPROTO_TCP: 637*a9643ea8Slogwang spidx->ul_proto = nxt; 638*a9643ea8Slogwang if (!needport) 639*a9643ea8Slogwang goto done_proto; 640*a9643ea8Slogwang if (off + sizeof(struct tcphdr) > m->m_pkthdr.len) 641*a9643ea8Slogwang goto done; 642*a9643ea8Slogwang m_copydata(m, off, sizeof (th), (caddr_t) &th); 643*a9643ea8Slogwang spidx->src.sin.sin_port = th.th_sport; 644*a9643ea8Slogwang spidx->dst.sin.sin_port = th.th_dport; 645*a9643ea8Slogwang return; 646*a9643ea8Slogwang case IPPROTO_UDP: 647*a9643ea8Slogwang spidx->ul_proto = nxt; 648*a9643ea8Slogwang if (!needport) 649*a9643ea8Slogwang goto done_proto; 650*a9643ea8Slogwang if (off + sizeof(struct udphdr) > m->m_pkthdr.len) 651*a9643ea8Slogwang goto done; 652*a9643ea8Slogwang m_copydata(m, off, sizeof (uh), (caddr_t) &uh); 653*a9643ea8Slogwang spidx->src.sin.sin_port = uh.uh_sport; 654*a9643ea8Slogwang spidx->dst.sin.sin_port = uh.uh_dport; 655*a9643ea8Slogwang return; 656*a9643ea8Slogwang case IPPROTO_AH: 657*a9643ea8Slogwang if (off + sizeof(ip6e) > m->m_pkthdr.len) 658*a9643ea8Slogwang goto done; 659*a9643ea8Slogwang /* XXX Sigh, this works but is totally bogus. */ 660*a9643ea8Slogwang m_copydata(m, off, sizeof(ip6e), (caddr_t) &ip6e); 661*a9643ea8Slogwang off += (ip6e.ip6e_len + 2) << 2; 662*a9643ea8Slogwang nxt = ip6e.ip6e_nxt; 663*a9643ea8Slogwang break; 664*a9643ea8Slogwang case IPPROTO_ICMP: 665*a9643ea8Slogwang default: 666*a9643ea8Slogwang /* XXX Intermediate headers??? */ 667*a9643ea8Slogwang spidx->ul_proto = nxt; 668*a9643ea8Slogwang goto done_proto; 669*a9643ea8Slogwang } 670*a9643ea8Slogwang } 671*a9643ea8Slogwang done: 672*a9643ea8Slogwang spidx->ul_proto = IPSEC_ULPROTO_ANY; 673*a9643ea8Slogwang done_proto: 674*a9643ea8Slogwang spidx->src.sin.sin_port = IPSEC_PORT_ANY; 675*a9643ea8Slogwang spidx->dst.sin.sin_port = IPSEC_PORT_ANY; 676*a9643ea8Slogwang } 677*a9643ea8Slogwang 678*a9643ea8Slogwang /* Assumes that m is sane. */ 679*a9643ea8Slogwang static int 680*a9643ea8Slogwang ipsec4_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx) 681*a9643ea8Slogwang { 682*a9643ea8Slogwang static const struct sockaddr_in template = { 683*a9643ea8Slogwang sizeof (struct sockaddr_in), 684*a9643ea8Slogwang AF_INET, 685*a9643ea8Slogwang 0, { 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } 686*a9643ea8Slogwang }; 687*a9643ea8Slogwang 688*a9643ea8Slogwang spidx->src.sin = template; 689*a9643ea8Slogwang spidx->dst.sin = template; 690*a9643ea8Slogwang 691*a9643ea8Slogwang if (m->m_len < sizeof (struct ip)) { 692*a9643ea8Slogwang m_copydata(m, offsetof(struct ip, ip_src), 693*a9643ea8Slogwang sizeof (struct in_addr), 694*a9643ea8Slogwang (caddr_t) &spidx->src.sin.sin_addr); 695*a9643ea8Slogwang m_copydata(m, offsetof(struct ip, ip_dst), 696*a9643ea8Slogwang sizeof (struct in_addr), 697*a9643ea8Slogwang (caddr_t) &spidx->dst.sin.sin_addr); 698*a9643ea8Slogwang } else { 699*a9643ea8Slogwang const struct ip *ip = mtod(m, const struct ip *); 700*a9643ea8Slogwang spidx->src.sin.sin_addr = ip->ip_src; 701*a9643ea8Slogwang spidx->dst.sin.sin_addr = ip->ip_dst; 702*a9643ea8Slogwang } 703*a9643ea8Slogwang 704*a9643ea8Slogwang spidx->prefs = sizeof(struct in_addr) << 3; 705*a9643ea8Slogwang spidx->prefd = sizeof(struct in_addr) << 3; 706*a9643ea8Slogwang 707*a9643ea8Slogwang return (0); 708*a9643ea8Slogwang } 709*a9643ea8Slogwang 710*a9643ea8Slogwang #ifdef INET6 711*a9643ea8Slogwang static void 712*a9643ea8Slogwang ipsec6_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx, 713*a9643ea8Slogwang int needport) 714*a9643ea8Slogwang { 715*a9643ea8Slogwang int off, nxt; 716*a9643ea8Slogwang struct tcphdr th; 717*a9643ea8Slogwang struct udphdr uh; 718*a9643ea8Slogwang struct icmp6_hdr ih; 719*a9643ea8Slogwang 720*a9643ea8Slogwang /* Sanity check. */ 721*a9643ea8Slogwang if (m == NULL) 722*a9643ea8Slogwang panic("%s: NULL pointer was passed.\n", __func__); 723*a9643ea8Slogwang 724*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 725*a9643ea8Slogwang printf("%s:\n", __func__); kdebug_mbuf(m)); 726*a9643ea8Slogwang 727*a9643ea8Slogwang /* Set default. */ 728*a9643ea8Slogwang spidx->ul_proto = IPSEC_ULPROTO_ANY; 729*a9643ea8Slogwang ((struct sockaddr_in6 *)&spidx->src)->sin6_port = IPSEC_PORT_ANY; 730*a9643ea8Slogwang ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = IPSEC_PORT_ANY; 731*a9643ea8Slogwang 732*a9643ea8Slogwang nxt = -1; 733*a9643ea8Slogwang off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); 734*a9643ea8Slogwang if (off < 0 || m->m_pkthdr.len < off) 735*a9643ea8Slogwang return; 736*a9643ea8Slogwang 737*a9643ea8Slogwang switch (nxt) { 738*a9643ea8Slogwang case IPPROTO_TCP: 739*a9643ea8Slogwang spidx->ul_proto = nxt; 740*a9643ea8Slogwang if (!needport) 741*a9643ea8Slogwang break; 742*a9643ea8Slogwang if (off + sizeof(struct tcphdr) > m->m_pkthdr.len) 743*a9643ea8Slogwang break; 744*a9643ea8Slogwang m_copydata(m, off, sizeof(th), (caddr_t)&th); 745*a9643ea8Slogwang ((struct sockaddr_in6 *)&spidx->src)->sin6_port = th.th_sport; 746*a9643ea8Slogwang ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = th.th_dport; 747*a9643ea8Slogwang break; 748*a9643ea8Slogwang case IPPROTO_UDP: 749*a9643ea8Slogwang spidx->ul_proto = nxt; 750*a9643ea8Slogwang if (!needport) 751*a9643ea8Slogwang break; 752*a9643ea8Slogwang if (off + sizeof(struct udphdr) > m->m_pkthdr.len) 753*a9643ea8Slogwang break; 754*a9643ea8Slogwang m_copydata(m, off, sizeof(uh), (caddr_t)&uh); 755*a9643ea8Slogwang ((struct sockaddr_in6 *)&spidx->src)->sin6_port = uh.uh_sport; 756*a9643ea8Slogwang ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport; 757*a9643ea8Slogwang break; 758*a9643ea8Slogwang case IPPROTO_ICMPV6: 759*a9643ea8Slogwang spidx->ul_proto = nxt; 760*a9643ea8Slogwang if (off + sizeof(struct icmp6_hdr) > m->m_pkthdr.len) 761*a9643ea8Slogwang break; 762*a9643ea8Slogwang m_copydata(m, off, sizeof(ih), (caddr_t)&ih); 763*a9643ea8Slogwang ((struct sockaddr_in6 *)&spidx->src)->sin6_port = 764*a9643ea8Slogwang htons((uint16_t)ih.icmp6_type); 765*a9643ea8Slogwang ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = 766*a9643ea8Slogwang htons((uint16_t)ih.icmp6_code); 767*a9643ea8Slogwang break; 768*a9643ea8Slogwang default: 769*a9643ea8Slogwang /* XXX Intermediate headers??? */ 770*a9643ea8Slogwang spidx->ul_proto = nxt; 771*a9643ea8Slogwang break; 772*a9643ea8Slogwang } 773*a9643ea8Slogwang } 774*a9643ea8Slogwang 775*a9643ea8Slogwang /* Assumes that m is sane. */ 776*a9643ea8Slogwang static int 777*a9643ea8Slogwang ipsec6_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx) 778*a9643ea8Slogwang { 779*a9643ea8Slogwang struct ip6_hdr ip6buf; 780*a9643ea8Slogwang const struct ip6_hdr *ip6 = NULL; 781*a9643ea8Slogwang struct sockaddr_in6 *sin6; 782*a9643ea8Slogwang 783*a9643ea8Slogwang if (m->m_len >= sizeof(*ip6)) 784*a9643ea8Slogwang ip6 = mtod(m, const struct ip6_hdr *); 785*a9643ea8Slogwang else { 786*a9643ea8Slogwang m_copydata(m, 0, sizeof(ip6buf), (caddr_t)&ip6buf); 787*a9643ea8Slogwang ip6 = &ip6buf; 788*a9643ea8Slogwang } 789*a9643ea8Slogwang 790*a9643ea8Slogwang sin6 = (struct sockaddr_in6 *)&spidx->src; 791*a9643ea8Slogwang bzero(sin6, sizeof(*sin6)); 792*a9643ea8Slogwang sin6->sin6_family = AF_INET6; 793*a9643ea8Slogwang sin6->sin6_len = sizeof(struct sockaddr_in6); 794*a9643ea8Slogwang bcopy(&ip6->ip6_src, &sin6->sin6_addr, sizeof(ip6->ip6_src)); 795*a9643ea8Slogwang if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { 796*a9643ea8Slogwang sin6->sin6_addr.s6_addr16[1] = 0; 797*a9643ea8Slogwang sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); 798*a9643ea8Slogwang } 799*a9643ea8Slogwang spidx->prefs = sizeof(struct in6_addr) << 3; 800*a9643ea8Slogwang 801*a9643ea8Slogwang sin6 = (struct sockaddr_in6 *)&spidx->dst; 802*a9643ea8Slogwang bzero(sin6, sizeof(*sin6)); 803*a9643ea8Slogwang sin6->sin6_family = AF_INET6; 804*a9643ea8Slogwang sin6->sin6_len = sizeof(struct sockaddr_in6); 805*a9643ea8Slogwang bcopy(&ip6->ip6_dst, &sin6->sin6_addr, sizeof(ip6->ip6_dst)); 806*a9643ea8Slogwang if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 807*a9643ea8Slogwang sin6->sin6_addr.s6_addr16[1] = 0; 808*a9643ea8Slogwang sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); 809*a9643ea8Slogwang } 810*a9643ea8Slogwang spidx->prefd = sizeof(struct in6_addr) << 3; 811*a9643ea8Slogwang 812*a9643ea8Slogwang return (0); 813*a9643ea8Slogwang } 814*a9643ea8Slogwang #endif 815*a9643ea8Slogwang 816*a9643ea8Slogwang int 817*a9643ea8Slogwang ipsec_run_hhooks(struct ipsec_ctx_data *ctx, int type) 818*a9643ea8Slogwang { 819*a9643ea8Slogwang int idx; 820*a9643ea8Slogwang 821*a9643ea8Slogwang switch (ctx->af) { 822*a9643ea8Slogwang #ifdef INET 823*a9643ea8Slogwang case AF_INET: 824*a9643ea8Slogwang idx = HHOOK_IPSEC_INET; 825*a9643ea8Slogwang break; 826*a9643ea8Slogwang #endif 827*a9643ea8Slogwang #ifdef INET6 828*a9643ea8Slogwang case AF_INET6: 829*a9643ea8Slogwang idx = HHOOK_IPSEC_INET6; 830*a9643ea8Slogwang break; 831*a9643ea8Slogwang #endif 832*a9643ea8Slogwang default: 833*a9643ea8Slogwang return (EPFNOSUPPORT); 834*a9643ea8Slogwang } 835*a9643ea8Slogwang if (type == HHOOK_TYPE_IPSEC_IN) 836*a9643ea8Slogwang HHOOKS_RUN_IF(V_ipsec_hhh_in[idx], ctx, NULL); 837*a9643ea8Slogwang else 838*a9643ea8Slogwang HHOOKS_RUN_IF(V_ipsec_hhh_out[idx], ctx, NULL); 839*a9643ea8Slogwang if (*ctx->mp == NULL) 840*a9643ea8Slogwang return (EACCES); 841*a9643ea8Slogwang return (0); 842*a9643ea8Slogwang } 843*a9643ea8Slogwang 844*a9643ea8Slogwang static void 845*a9643ea8Slogwang ipsec_delpcbpolicy(struct inpcbpolicy *p) 846*a9643ea8Slogwang { 847*a9643ea8Slogwang 848*a9643ea8Slogwang free(p, M_IPSEC_INPCB); 849*a9643ea8Slogwang } 850*a9643ea8Slogwang 851*a9643ea8Slogwang /* Initialize policy in PCB. */ 852*a9643ea8Slogwang int 853*a9643ea8Slogwang ipsec_init_policy(struct socket *so, struct inpcbpolicy **pcb_sp) 854*a9643ea8Slogwang { 855*a9643ea8Slogwang struct inpcbpolicy *new; 856*a9643ea8Slogwang 857*a9643ea8Slogwang /* Sanity check. */ 858*a9643ea8Slogwang if (so == NULL || pcb_sp == NULL) 859*a9643ea8Slogwang panic("%s: NULL pointer was passed.\n", __func__); 860*a9643ea8Slogwang 861*a9643ea8Slogwang new = (struct inpcbpolicy *) malloc(sizeof(struct inpcbpolicy), 862*a9643ea8Slogwang M_IPSEC_INPCB, M_NOWAIT|M_ZERO); 863*a9643ea8Slogwang if (new == NULL) { 864*a9643ea8Slogwang ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 865*a9643ea8Slogwang return (ENOBUFS); 866*a9643ea8Slogwang } 867*a9643ea8Slogwang 868*a9643ea8Slogwang new->priv = IPSEC_IS_PRIVILEGED_SO(so); 869*a9643ea8Slogwang 870*a9643ea8Slogwang if ((new->sp_in = KEY_NEWSP()) == NULL) { 871*a9643ea8Slogwang ipsec_delpcbpolicy(new); 872*a9643ea8Slogwang return (ENOBUFS); 873*a9643ea8Slogwang } 874*a9643ea8Slogwang new->sp_in->policy = IPSEC_POLICY_ENTRUST; 875*a9643ea8Slogwang if ((new->sp_out = KEY_NEWSP()) == NULL) { 876*a9643ea8Slogwang KEY_FREESP(&new->sp_in); 877*a9643ea8Slogwang ipsec_delpcbpolicy(new); 878*a9643ea8Slogwang return (ENOBUFS); 879*a9643ea8Slogwang } 880*a9643ea8Slogwang new->sp_out->policy = IPSEC_POLICY_ENTRUST; 881*a9643ea8Slogwang *pcb_sp = new; 882*a9643ea8Slogwang 883*a9643ea8Slogwang return (0); 884*a9643ea8Slogwang } 885*a9643ea8Slogwang 886*a9643ea8Slogwang /* Copy old IPsec policy into new. */ 887*a9643ea8Slogwang int 888*a9643ea8Slogwang ipsec_copy_policy(struct inpcbpolicy *old, struct inpcbpolicy *new) 889*a9643ea8Slogwang { 890*a9643ea8Slogwang struct secpolicy *sp; 891*a9643ea8Slogwang 892*a9643ea8Slogwang sp = ipsec_deepcopy_policy(old->sp_in); 893*a9643ea8Slogwang if (sp) { 894*a9643ea8Slogwang KEY_FREESP(&new->sp_in); 895*a9643ea8Slogwang new->sp_in = sp; 896*a9643ea8Slogwang } else 897*a9643ea8Slogwang return (ENOBUFS); 898*a9643ea8Slogwang 899*a9643ea8Slogwang sp = ipsec_deepcopy_policy(old->sp_out); 900*a9643ea8Slogwang if (sp) { 901*a9643ea8Slogwang KEY_FREESP(&new->sp_out); 902*a9643ea8Slogwang new->sp_out = sp; 903*a9643ea8Slogwang } else 904*a9643ea8Slogwang return (ENOBUFS); 905*a9643ea8Slogwang 906*a9643ea8Slogwang new->priv = old->priv; 907*a9643ea8Slogwang 908*a9643ea8Slogwang return (0); 909*a9643ea8Slogwang } 910*a9643ea8Slogwang 911*a9643ea8Slogwang struct ipsecrequest * 912*a9643ea8Slogwang ipsec_newisr(void) 913*a9643ea8Slogwang { 914*a9643ea8Slogwang struct ipsecrequest *p; 915*a9643ea8Slogwang 916*a9643ea8Slogwang p = malloc(sizeof(struct ipsecrequest), M_IPSEC_SR, M_NOWAIT|M_ZERO); 917*a9643ea8Slogwang if (p != NULL) 918*a9643ea8Slogwang IPSECREQUEST_LOCK_INIT(p); 919*a9643ea8Slogwang return (p); 920*a9643ea8Slogwang } 921*a9643ea8Slogwang 922*a9643ea8Slogwang void 923*a9643ea8Slogwang ipsec_delisr(struct ipsecrequest *p) 924*a9643ea8Slogwang { 925*a9643ea8Slogwang 926*a9643ea8Slogwang IPSECREQUEST_LOCK_DESTROY(p); 927*a9643ea8Slogwang free(p, M_IPSEC_SR); 928*a9643ea8Slogwang } 929*a9643ea8Slogwang 930*a9643ea8Slogwang /* Deep-copy a policy in PCB. */ 931*a9643ea8Slogwang static struct secpolicy * 932*a9643ea8Slogwang ipsec_deepcopy_policy(struct secpolicy *src) 933*a9643ea8Slogwang { 934*a9643ea8Slogwang struct ipsecrequest *newchain = NULL; 935*a9643ea8Slogwang struct ipsecrequest *p; 936*a9643ea8Slogwang struct ipsecrequest **q; 937*a9643ea8Slogwang struct ipsecrequest *r; 938*a9643ea8Slogwang struct secpolicy *dst; 939*a9643ea8Slogwang 940*a9643ea8Slogwang if (src == NULL) 941*a9643ea8Slogwang return (NULL); 942*a9643ea8Slogwang dst = KEY_NEWSP(); 943*a9643ea8Slogwang if (dst == NULL) 944*a9643ea8Slogwang return (NULL); 945*a9643ea8Slogwang 946*a9643ea8Slogwang /* 947*a9643ea8Slogwang * Deep-copy IPsec request chain. This is required since struct 948*a9643ea8Slogwang * ipsecrequest is not reference counted. 949*a9643ea8Slogwang */ 950*a9643ea8Slogwang q = &newchain; 951*a9643ea8Slogwang for (p = src->req; p; p = p->next) { 952*a9643ea8Slogwang *q = ipsec_newisr(); 953*a9643ea8Slogwang if (*q == NULL) 954*a9643ea8Slogwang goto fail; 955*a9643ea8Slogwang (*q)->saidx.proto = p->saidx.proto; 956*a9643ea8Slogwang (*q)->saidx.mode = p->saidx.mode; 957*a9643ea8Slogwang (*q)->level = p->level; 958*a9643ea8Slogwang (*q)->saidx.reqid = p->saidx.reqid; 959*a9643ea8Slogwang 960*a9643ea8Slogwang bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src)); 961*a9643ea8Slogwang bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst)); 962*a9643ea8Slogwang 963*a9643ea8Slogwang (*q)->sp = dst; 964*a9643ea8Slogwang 965*a9643ea8Slogwang q = &((*q)->next); 966*a9643ea8Slogwang } 967*a9643ea8Slogwang 968*a9643ea8Slogwang dst->req = newchain; 969*a9643ea8Slogwang dst->policy = src->policy; 970*a9643ea8Slogwang /* Do not touch the refcnt fields. */ 971*a9643ea8Slogwang 972*a9643ea8Slogwang return (dst); 973*a9643ea8Slogwang 974*a9643ea8Slogwang fail: 975*a9643ea8Slogwang for (p = newchain; p; p = r) { 976*a9643ea8Slogwang r = p->next; 977*a9643ea8Slogwang ipsec_delisr(p); 978*a9643ea8Slogwang p = NULL; 979*a9643ea8Slogwang } 980*a9643ea8Slogwang KEY_FREESP(&dst); 981*a9643ea8Slogwang return (NULL); 982*a9643ea8Slogwang } 983*a9643ea8Slogwang 984*a9643ea8Slogwang /* Set policy and IPsec request if present. */ 985*a9643ea8Slogwang static int 986*a9643ea8Slogwang ipsec_set_policy_internal(struct secpolicy **pcb_sp, int optname, 987*a9643ea8Slogwang caddr_t request, size_t len, struct ucred *cred) 988*a9643ea8Slogwang { 989*a9643ea8Slogwang struct sadb_x_policy *xpl; 990*a9643ea8Slogwang struct secpolicy *newsp = NULL; 991*a9643ea8Slogwang int error; 992*a9643ea8Slogwang 993*a9643ea8Slogwang /* Sanity check. */ 994*a9643ea8Slogwang if (pcb_sp == NULL || *pcb_sp == NULL || request == NULL) 995*a9643ea8Slogwang return (EINVAL); 996*a9643ea8Slogwang if (len < sizeof(*xpl)) 997*a9643ea8Slogwang return (EINVAL); 998*a9643ea8Slogwang xpl = (struct sadb_x_policy *)request; 999*a9643ea8Slogwang 1000*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 1001*a9643ea8Slogwang printf("%s: passed policy\n", __func__); 1002*a9643ea8Slogwang kdebug_sadb_x_policy((struct sadb_ext *)xpl)); 1003*a9643ea8Slogwang 1004*a9643ea8Slogwang /* Check policy type. */ 1005*a9643ea8Slogwang /* ipsec_set_policy_internal() accepts IPSEC, ENTRUST and BYPASS. */ 1006*a9643ea8Slogwang if (xpl->sadb_x_policy_type == IPSEC_POLICY_DISCARD 1007*a9643ea8Slogwang || xpl->sadb_x_policy_type == IPSEC_POLICY_NONE) 1008*a9643ea8Slogwang return (EINVAL); 1009*a9643ea8Slogwang 1010*a9643ea8Slogwang /* Check privileged socket. */ 1011*a9643ea8Slogwang if (cred != NULL && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS) { 1012*a9643ea8Slogwang error = priv_check_cred(cred, PRIV_NETINET_IPSEC, 0); 1013*a9643ea8Slogwang if (error) 1014*a9643ea8Slogwang return (EACCES); 1015*a9643ea8Slogwang } 1016*a9643ea8Slogwang 1017*a9643ea8Slogwang /* Allocating new SP entry. */ 1018*a9643ea8Slogwang if ((newsp = key_msg2sp(xpl, len, &error)) == NULL) 1019*a9643ea8Slogwang return (error); 1020*a9643ea8Slogwang 1021*a9643ea8Slogwang /* Clear old SP and set new SP. */ 1022*a9643ea8Slogwang KEY_FREESP(pcb_sp); 1023*a9643ea8Slogwang *pcb_sp = newsp; 1024*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 1025*a9643ea8Slogwang printf("%s: new policy\n", __func__); 1026*a9643ea8Slogwang kdebug_secpolicy(newsp)); 1027*a9643ea8Slogwang 1028*a9643ea8Slogwang return (0); 1029*a9643ea8Slogwang } 1030*a9643ea8Slogwang 1031*a9643ea8Slogwang int 1032*a9643ea8Slogwang ipsec_set_policy(struct inpcb *inp, int optname, caddr_t request, 1033*a9643ea8Slogwang size_t len, struct ucred *cred) 1034*a9643ea8Slogwang { 1035*a9643ea8Slogwang struct sadb_x_policy *xpl; 1036*a9643ea8Slogwang struct secpolicy **pcb_sp; 1037*a9643ea8Slogwang 1038*a9643ea8Slogwang /* Sanity check. */ 1039*a9643ea8Slogwang if (inp == NULL || request == NULL) 1040*a9643ea8Slogwang return (EINVAL); 1041*a9643ea8Slogwang if (len < sizeof(*xpl)) 1042*a9643ea8Slogwang return (EINVAL); 1043*a9643ea8Slogwang xpl = (struct sadb_x_policy *)request; 1044*a9643ea8Slogwang 1045*a9643ea8Slogwang /* Select direction. */ 1046*a9643ea8Slogwang switch (xpl->sadb_x_policy_dir) { 1047*a9643ea8Slogwang case IPSEC_DIR_INBOUND: 1048*a9643ea8Slogwang pcb_sp = &inp->inp_sp->sp_in; 1049*a9643ea8Slogwang break; 1050*a9643ea8Slogwang case IPSEC_DIR_OUTBOUND: 1051*a9643ea8Slogwang pcb_sp = &inp->inp_sp->sp_out; 1052*a9643ea8Slogwang break; 1053*a9643ea8Slogwang default: 1054*a9643ea8Slogwang ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__, 1055*a9643ea8Slogwang xpl->sadb_x_policy_dir)); 1056*a9643ea8Slogwang return (EINVAL); 1057*a9643ea8Slogwang } 1058*a9643ea8Slogwang 1059*a9643ea8Slogwang return (ipsec_set_policy_internal(pcb_sp, optname, request, len, cred)); 1060*a9643ea8Slogwang } 1061*a9643ea8Slogwang 1062*a9643ea8Slogwang int 1063*a9643ea8Slogwang ipsec_get_policy(struct inpcb *inp, caddr_t request, size_t len, 1064*a9643ea8Slogwang struct mbuf **mp) 1065*a9643ea8Slogwang { 1066*a9643ea8Slogwang struct sadb_x_policy *xpl; 1067*a9643ea8Slogwang struct secpolicy *pcb_sp; 1068*a9643ea8Slogwang 1069*a9643ea8Slogwang /* Sanity check. */ 1070*a9643ea8Slogwang if (inp == NULL || request == NULL || mp == NULL) 1071*a9643ea8Slogwang return (EINVAL); 1072*a9643ea8Slogwang IPSEC_ASSERT(inp->inp_sp != NULL, ("null inp_sp")); 1073*a9643ea8Slogwang if (len < sizeof(*xpl)) 1074*a9643ea8Slogwang return (EINVAL); 1075*a9643ea8Slogwang xpl = (struct sadb_x_policy *)request; 1076*a9643ea8Slogwang 1077*a9643ea8Slogwang /* Select direction. */ 1078*a9643ea8Slogwang switch (xpl->sadb_x_policy_dir) { 1079*a9643ea8Slogwang case IPSEC_DIR_INBOUND: 1080*a9643ea8Slogwang pcb_sp = inp->inp_sp->sp_in; 1081*a9643ea8Slogwang break; 1082*a9643ea8Slogwang case IPSEC_DIR_OUTBOUND: 1083*a9643ea8Slogwang pcb_sp = inp->inp_sp->sp_out; 1084*a9643ea8Slogwang break; 1085*a9643ea8Slogwang default: 1086*a9643ea8Slogwang ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__, 1087*a9643ea8Slogwang xpl->sadb_x_policy_dir)); 1088*a9643ea8Slogwang return (EINVAL); 1089*a9643ea8Slogwang } 1090*a9643ea8Slogwang 1091*a9643ea8Slogwang /* Sanity check. Should be an IPSEC_ASSERT. */ 1092*a9643ea8Slogwang if (pcb_sp == NULL) 1093*a9643ea8Slogwang return (EINVAL); 1094*a9643ea8Slogwang 1095*a9643ea8Slogwang *mp = key_sp2msg(pcb_sp); 1096*a9643ea8Slogwang if (!*mp) { 1097*a9643ea8Slogwang ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 1098*a9643ea8Slogwang return (ENOBUFS); 1099*a9643ea8Slogwang } 1100*a9643ea8Slogwang 1101*a9643ea8Slogwang (*mp)->m_type = MT_DATA; 1102*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 1103*a9643ea8Slogwang printf("%s:\n", __func__); kdebug_mbuf(*mp)); 1104*a9643ea8Slogwang 1105*a9643ea8Slogwang return (0); 1106*a9643ea8Slogwang } 1107*a9643ea8Slogwang 1108*a9643ea8Slogwang /* Delete policy in PCB. */ 1109*a9643ea8Slogwang int 1110*a9643ea8Slogwang ipsec_delete_pcbpolicy(struct inpcb *inp) 1111*a9643ea8Slogwang { 1112*a9643ea8Slogwang IPSEC_ASSERT(inp != NULL, ("null inp")); 1113*a9643ea8Slogwang 1114*a9643ea8Slogwang if (inp->inp_sp == NULL) 1115*a9643ea8Slogwang return (0); 1116*a9643ea8Slogwang 1117*a9643ea8Slogwang if (inp->inp_sp->sp_in != NULL) 1118*a9643ea8Slogwang KEY_FREESP(&inp->inp_sp->sp_in); 1119*a9643ea8Slogwang 1120*a9643ea8Slogwang if (inp->inp_sp->sp_out != NULL) 1121*a9643ea8Slogwang KEY_FREESP(&inp->inp_sp->sp_out); 1122*a9643ea8Slogwang 1123*a9643ea8Slogwang ipsec_delpcbpolicy(inp->inp_sp); 1124*a9643ea8Slogwang inp->inp_sp = NULL; 1125*a9643ea8Slogwang 1126*a9643ea8Slogwang return (0); 1127*a9643ea8Slogwang } 1128*a9643ea8Slogwang 1129*a9643ea8Slogwang /* 1130*a9643ea8Slogwang * Return current level. 1131*a9643ea8Slogwang * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned. 1132*a9643ea8Slogwang */ 1133*a9643ea8Slogwang u_int 1134*a9643ea8Slogwang ipsec_get_reqlevel(struct ipsecrequest *isr) 1135*a9643ea8Slogwang { 1136*a9643ea8Slogwang u_int level = 0; 1137*a9643ea8Slogwang u_int esp_trans_deflev, esp_net_deflev; 1138*a9643ea8Slogwang u_int ah_trans_deflev, ah_net_deflev; 1139*a9643ea8Slogwang 1140*a9643ea8Slogwang IPSEC_ASSERT(isr != NULL && isr->sp != NULL, ("null argument")); 1141*a9643ea8Slogwang IPSEC_ASSERT(isr->sp->spidx.src.sa.sa_family == isr->sp->spidx.dst.sa.sa_family, 1142*a9643ea8Slogwang ("af family mismatch, src %u, dst %u", 1143*a9643ea8Slogwang isr->sp->spidx.src.sa.sa_family, 1144*a9643ea8Slogwang isr->sp->spidx.dst.sa.sa_family)); 1145*a9643ea8Slogwang 1146*a9643ea8Slogwang /* XXX Note that we have ipseclog() expanded here - code sync issue. */ 1147*a9643ea8Slogwang #define IPSEC_CHECK_DEFAULT(lev) \ 1148*a9643ea8Slogwang (((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE \ 1149*a9643ea8Slogwang && (lev) != IPSEC_LEVEL_UNIQUE) \ 1150*a9643ea8Slogwang ? (V_ipsec_debug \ 1151*a9643ea8Slogwang ? log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\ 1152*a9643ea8Slogwang (lev), IPSEC_LEVEL_REQUIRE) \ 1153*a9643ea8Slogwang : 0), \ 1154*a9643ea8Slogwang (lev) = IPSEC_LEVEL_REQUIRE, \ 1155*a9643ea8Slogwang (lev) \ 1156*a9643ea8Slogwang : (lev)) 1157*a9643ea8Slogwang 1158*a9643ea8Slogwang /* Set default level. */ 1159*a9643ea8Slogwang switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) { 1160*a9643ea8Slogwang #ifdef INET 1161*a9643ea8Slogwang case AF_INET: 1162*a9643ea8Slogwang esp_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip4_esp_trans_deflev); 1163*a9643ea8Slogwang esp_net_deflev = IPSEC_CHECK_DEFAULT(V_ip4_esp_net_deflev); 1164*a9643ea8Slogwang ah_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip4_ah_trans_deflev); 1165*a9643ea8Slogwang ah_net_deflev = IPSEC_CHECK_DEFAULT(V_ip4_ah_net_deflev); 1166*a9643ea8Slogwang break; 1167*a9643ea8Slogwang #endif 1168*a9643ea8Slogwang #ifdef INET6 1169*a9643ea8Slogwang case AF_INET6: 1170*a9643ea8Slogwang esp_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip6_esp_trans_deflev); 1171*a9643ea8Slogwang esp_net_deflev = IPSEC_CHECK_DEFAULT(V_ip6_esp_net_deflev); 1172*a9643ea8Slogwang ah_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip6_ah_trans_deflev); 1173*a9643ea8Slogwang ah_net_deflev = IPSEC_CHECK_DEFAULT(V_ip6_ah_net_deflev); 1174*a9643ea8Slogwang break; 1175*a9643ea8Slogwang #endif /* INET6 */ 1176*a9643ea8Slogwang default: 1177*a9643ea8Slogwang panic("%s: unknown af %u", 1178*a9643ea8Slogwang __func__, isr->sp->spidx.src.sa.sa_family); 1179*a9643ea8Slogwang } 1180*a9643ea8Slogwang 1181*a9643ea8Slogwang #undef IPSEC_CHECK_DEFAULT 1182*a9643ea8Slogwang 1183*a9643ea8Slogwang /* Set level. */ 1184*a9643ea8Slogwang switch (isr->level) { 1185*a9643ea8Slogwang case IPSEC_LEVEL_DEFAULT: 1186*a9643ea8Slogwang switch (isr->saidx.proto) { 1187*a9643ea8Slogwang case IPPROTO_ESP: 1188*a9643ea8Slogwang if (isr->saidx.mode == IPSEC_MODE_TUNNEL) 1189*a9643ea8Slogwang level = esp_net_deflev; 1190*a9643ea8Slogwang else 1191*a9643ea8Slogwang level = esp_trans_deflev; 1192*a9643ea8Slogwang break; 1193*a9643ea8Slogwang case IPPROTO_AH: 1194*a9643ea8Slogwang if (isr->saidx.mode == IPSEC_MODE_TUNNEL) 1195*a9643ea8Slogwang level = ah_net_deflev; 1196*a9643ea8Slogwang else 1197*a9643ea8Slogwang level = ah_trans_deflev; 1198*a9643ea8Slogwang break; 1199*a9643ea8Slogwang case IPPROTO_IPCOMP: 1200*a9643ea8Slogwang /* 1201*a9643ea8Slogwang * We don't really care, as IPcomp document says that 1202*a9643ea8Slogwang * we shouldn't compress small packets. 1203*a9643ea8Slogwang */ 1204*a9643ea8Slogwang level = IPSEC_LEVEL_USE; 1205*a9643ea8Slogwang break; 1206*a9643ea8Slogwang default: 1207*a9643ea8Slogwang panic("%s: Illegal protocol defined %u\n", __func__, 1208*a9643ea8Slogwang isr->saidx.proto); 1209*a9643ea8Slogwang } 1210*a9643ea8Slogwang break; 1211*a9643ea8Slogwang 1212*a9643ea8Slogwang case IPSEC_LEVEL_USE: 1213*a9643ea8Slogwang case IPSEC_LEVEL_REQUIRE: 1214*a9643ea8Slogwang level = isr->level; 1215*a9643ea8Slogwang break; 1216*a9643ea8Slogwang case IPSEC_LEVEL_UNIQUE: 1217*a9643ea8Slogwang level = IPSEC_LEVEL_REQUIRE; 1218*a9643ea8Slogwang break; 1219*a9643ea8Slogwang 1220*a9643ea8Slogwang default: 1221*a9643ea8Slogwang panic("%s: Illegal IPsec level %u\n", __func__, isr->level); 1222*a9643ea8Slogwang } 1223*a9643ea8Slogwang 1224*a9643ea8Slogwang return (level); 1225*a9643ea8Slogwang } 1226*a9643ea8Slogwang 1227*a9643ea8Slogwang /* 1228*a9643ea8Slogwang * Check security policy requirements against the actual 1229*a9643ea8Slogwang * packet contents. Return one if the packet should be 1230*a9643ea8Slogwang * reject as "invalid"; otherwiser return zero to have the 1231*a9643ea8Slogwang * packet treated as "valid". 1232*a9643ea8Slogwang * 1233*a9643ea8Slogwang * OUT: 1234*a9643ea8Slogwang * 0: valid 1235*a9643ea8Slogwang * 1: invalid 1236*a9643ea8Slogwang */ 1237*a9643ea8Slogwang static int 1238*a9643ea8Slogwang ipsec_in_reject(struct secpolicy *sp, const struct mbuf *m) 1239*a9643ea8Slogwang { 1240*a9643ea8Slogwang struct ipsecrequest *isr; 1241*a9643ea8Slogwang int need_auth; 1242*a9643ea8Slogwang 1243*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DATA, 1244*a9643ea8Slogwang printf("%s: using SP\n", __func__); kdebug_secpolicy(sp)); 1245*a9643ea8Slogwang 1246*a9643ea8Slogwang /* Check policy. */ 1247*a9643ea8Slogwang switch (sp->policy) { 1248*a9643ea8Slogwang case IPSEC_POLICY_DISCARD: 1249*a9643ea8Slogwang return (1); 1250*a9643ea8Slogwang case IPSEC_POLICY_BYPASS: 1251*a9643ea8Slogwang case IPSEC_POLICY_NONE: 1252*a9643ea8Slogwang return (0); 1253*a9643ea8Slogwang } 1254*a9643ea8Slogwang 1255*a9643ea8Slogwang IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC, 1256*a9643ea8Slogwang ("invalid policy %u", sp->policy)); 1257*a9643ea8Slogwang 1258*a9643ea8Slogwang /* XXX Should compare policy against IPsec header history. */ 1259*a9643ea8Slogwang 1260*a9643ea8Slogwang need_auth = 0; 1261*a9643ea8Slogwang for (isr = sp->req; isr != NULL; isr = isr->next) { 1262*a9643ea8Slogwang if (ipsec_get_reqlevel(isr) != IPSEC_LEVEL_REQUIRE) 1263*a9643ea8Slogwang continue; 1264*a9643ea8Slogwang switch (isr->saidx.proto) { 1265*a9643ea8Slogwang case IPPROTO_ESP: 1266*a9643ea8Slogwang if ((m->m_flags & M_DECRYPTED) == 0) { 1267*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 1268*a9643ea8Slogwang printf("%s: ESP m_flags:%x\n", __func__, 1269*a9643ea8Slogwang m->m_flags)); 1270*a9643ea8Slogwang return (1); 1271*a9643ea8Slogwang } 1272*a9643ea8Slogwang 1273*a9643ea8Slogwang if (!need_auth && 1274*a9643ea8Slogwang isr->sav != NULL && 1275*a9643ea8Slogwang isr->sav->tdb_authalgxform != NULL && 1276*a9643ea8Slogwang (m->m_flags & M_AUTHIPDGM) == 0) { 1277*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 1278*a9643ea8Slogwang printf("%s: ESP/AH m_flags:%x\n", __func__, 1279*a9643ea8Slogwang m->m_flags)); 1280*a9643ea8Slogwang return (1); 1281*a9643ea8Slogwang } 1282*a9643ea8Slogwang break; 1283*a9643ea8Slogwang case IPPROTO_AH: 1284*a9643ea8Slogwang need_auth = 1; 1285*a9643ea8Slogwang if ((m->m_flags & M_AUTHIPHDR) == 0) { 1286*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DUMP, 1287*a9643ea8Slogwang printf("%s: AH m_flags:%x\n", __func__, 1288*a9643ea8Slogwang m->m_flags)); 1289*a9643ea8Slogwang return (1); 1290*a9643ea8Slogwang } 1291*a9643ea8Slogwang break; 1292*a9643ea8Slogwang case IPPROTO_IPCOMP: 1293*a9643ea8Slogwang /* 1294*a9643ea8Slogwang * We don't really care, as IPcomp document 1295*a9643ea8Slogwang * says that we shouldn't compress small 1296*a9643ea8Slogwang * packets. IPComp policy should always be 1297*a9643ea8Slogwang * treated as being in "use" level. 1298*a9643ea8Slogwang */ 1299*a9643ea8Slogwang break; 1300*a9643ea8Slogwang } 1301*a9643ea8Slogwang } 1302*a9643ea8Slogwang return (0); /* Valid. */ 1303*a9643ea8Slogwang } 1304*a9643ea8Slogwang 1305*a9643ea8Slogwang /* 1306*a9643ea8Slogwang * Non zero return value means security policy DISCARD or policy violation. 1307*a9643ea8Slogwang */ 1308*a9643ea8Slogwang static int 1309*a9643ea8Slogwang ipsec46_in_reject(const struct mbuf *m, struct inpcb *inp) 1310*a9643ea8Slogwang { 1311*a9643ea8Slogwang struct secpolicy *sp; 1312*a9643ea8Slogwang int error; 1313*a9643ea8Slogwang int result; 1314*a9643ea8Slogwang 1315*a9643ea8Slogwang if (!key_havesp(IPSEC_DIR_INBOUND)) 1316*a9643ea8Slogwang return 0; 1317*a9643ea8Slogwang 1318*a9643ea8Slogwang IPSEC_ASSERT(m != NULL, ("null mbuf")); 1319*a9643ea8Slogwang 1320*a9643ea8Slogwang /* Get SP for this packet. */ 1321*a9643ea8Slogwang if (inp == NULL) 1322*a9643ea8Slogwang sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, &error); 1323*a9643ea8Slogwang else 1324*a9643ea8Slogwang sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND, inp, &error); 1325*a9643ea8Slogwang 1326*a9643ea8Slogwang if (sp != NULL) { 1327*a9643ea8Slogwang result = ipsec_in_reject(sp, m); 1328*a9643ea8Slogwang KEY_FREESP(&sp); 1329*a9643ea8Slogwang } else { 1330*a9643ea8Slogwang result = 1; /* treat errors as policy violation */ 1331*a9643ea8Slogwang } 1332*a9643ea8Slogwang return (result); 1333*a9643ea8Slogwang } 1334*a9643ea8Slogwang 1335*a9643ea8Slogwang /* 1336*a9643ea8Slogwang * Check AH/ESP integrity. 1337*a9643ea8Slogwang * This function is called from tcp_input(), udp_input(), 1338*a9643ea8Slogwang * and {ah,esp}4_input for tunnel mode. 1339*a9643ea8Slogwang */ 1340*a9643ea8Slogwang int 1341*a9643ea8Slogwang ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp) 1342*a9643ea8Slogwang { 1343*a9643ea8Slogwang int result; 1344*a9643ea8Slogwang 1345*a9643ea8Slogwang result = ipsec46_in_reject(m, inp); 1346*a9643ea8Slogwang if (result) 1347*a9643ea8Slogwang IPSECSTAT_INC(ips_in_polvio); 1348*a9643ea8Slogwang 1349*a9643ea8Slogwang return (result); 1350*a9643ea8Slogwang } 1351*a9643ea8Slogwang 1352*a9643ea8Slogwang #ifdef INET6 1353*a9643ea8Slogwang /* 1354*a9643ea8Slogwang * Check AH/ESP integrity. 1355*a9643ea8Slogwang * This function is called from tcp6_input(), udp6_input(), 1356*a9643ea8Slogwang * and {ah,esp}6_input for tunnel mode. 1357*a9643ea8Slogwang */ 1358*a9643ea8Slogwang int 1359*a9643ea8Slogwang ipsec6_in_reject(const struct mbuf *m, struct inpcb *inp) 1360*a9643ea8Slogwang { 1361*a9643ea8Slogwang int result; 1362*a9643ea8Slogwang 1363*a9643ea8Slogwang result = ipsec46_in_reject(m, inp); 1364*a9643ea8Slogwang if (result) 1365*a9643ea8Slogwang IPSEC6STAT_INC(ips_in_polvio); 1366*a9643ea8Slogwang 1367*a9643ea8Slogwang return (result); 1368*a9643ea8Slogwang } 1369*a9643ea8Slogwang #endif 1370*a9643ea8Slogwang 1371*a9643ea8Slogwang /* 1372*a9643ea8Slogwang * Compute the byte size to be occupied by IPsec header. 1373*a9643ea8Slogwang * In case it is tunnelled, it includes the size of outer IP header. 1374*a9643ea8Slogwang * NOTE: SP passed is freed in this function. 1375*a9643ea8Slogwang */ 1376*a9643ea8Slogwang static size_t 1377*a9643ea8Slogwang ipsec_hdrsiz_internal(struct secpolicy *sp) 1378*a9643ea8Slogwang { 1379*a9643ea8Slogwang struct ipsecrequest *isr; 1380*a9643ea8Slogwang size_t size; 1381*a9643ea8Slogwang 1382*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DATA, 1383*a9643ea8Slogwang printf("%s: using SP\n", __func__); kdebug_secpolicy(sp)); 1384*a9643ea8Slogwang 1385*a9643ea8Slogwang switch (sp->policy) { 1386*a9643ea8Slogwang case IPSEC_POLICY_DISCARD: 1387*a9643ea8Slogwang case IPSEC_POLICY_BYPASS: 1388*a9643ea8Slogwang case IPSEC_POLICY_NONE: 1389*a9643ea8Slogwang return (0); 1390*a9643ea8Slogwang } 1391*a9643ea8Slogwang 1392*a9643ea8Slogwang IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC, 1393*a9643ea8Slogwang ("invalid policy %u", sp->policy)); 1394*a9643ea8Slogwang 1395*a9643ea8Slogwang size = 0; 1396*a9643ea8Slogwang for (isr = sp->req; isr != NULL; isr = isr->next) { 1397*a9643ea8Slogwang size_t clen = 0; 1398*a9643ea8Slogwang 1399*a9643ea8Slogwang switch (isr->saidx.proto) { 1400*a9643ea8Slogwang case IPPROTO_ESP: 1401*a9643ea8Slogwang clen = esp_hdrsiz(isr->sav); 1402*a9643ea8Slogwang break; 1403*a9643ea8Slogwang case IPPROTO_AH: 1404*a9643ea8Slogwang clen = ah_hdrsiz(isr->sav); 1405*a9643ea8Slogwang break; 1406*a9643ea8Slogwang case IPPROTO_IPCOMP: 1407*a9643ea8Slogwang clen = sizeof(struct ipcomp); 1408*a9643ea8Slogwang break; 1409*a9643ea8Slogwang } 1410*a9643ea8Slogwang 1411*a9643ea8Slogwang if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { 1412*a9643ea8Slogwang switch (isr->saidx.dst.sa.sa_family) { 1413*a9643ea8Slogwang case AF_INET: 1414*a9643ea8Slogwang clen += sizeof(struct ip); 1415*a9643ea8Slogwang break; 1416*a9643ea8Slogwang #ifdef INET6 1417*a9643ea8Slogwang case AF_INET6: 1418*a9643ea8Slogwang clen += sizeof(struct ip6_hdr); 1419*a9643ea8Slogwang break; 1420*a9643ea8Slogwang #endif 1421*a9643ea8Slogwang default: 1422*a9643ea8Slogwang ipseclog((LOG_ERR, "%s: unknown AF %d in " 1423*a9643ea8Slogwang "IPsec tunnel SA\n", __func__, 1424*a9643ea8Slogwang ((struct sockaddr *)&isr->saidx.dst)->sa_family)); 1425*a9643ea8Slogwang break; 1426*a9643ea8Slogwang } 1427*a9643ea8Slogwang } 1428*a9643ea8Slogwang size += clen; 1429*a9643ea8Slogwang } 1430*a9643ea8Slogwang 1431*a9643ea8Slogwang return (size); 1432*a9643ea8Slogwang } 1433*a9643ea8Slogwang 1434*a9643ea8Slogwang /* 1435*a9643ea8Slogwang * This function is called from ipsec_hdrsiz_tcp(), ip_ipsec_mtu(), 1436*a9643ea8Slogwang * disabled ip6_ipsec_mtu() and ip6_forward(). 1437*a9643ea8Slogwang */ 1438*a9643ea8Slogwang size_t 1439*a9643ea8Slogwang ipsec_hdrsiz(const struct mbuf *m, u_int dir, struct inpcb *inp) 1440*a9643ea8Slogwang { 1441*a9643ea8Slogwang struct secpolicy *sp; 1442*a9643ea8Slogwang int error; 1443*a9643ea8Slogwang size_t size; 1444*a9643ea8Slogwang 1445*a9643ea8Slogwang if (!key_havesp(dir)) 1446*a9643ea8Slogwang return 0; 1447*a9643ea8Slogwang 1448*a9643ea8Slogwang IPSEC_ASSERT(m != NULL, ("null mbuf")); 1449*a9643ea8Slogwang 1450*a9643ea8Slogwang /* Get SP for this packet. */ 1451*a9643ea8Slogwang if (inp == NULL) 1452*a9643ea8Slogwang sp = ipsec_getpolicybyaddr(m, dir, &error); 1453*a9643ea8Slogwang else 1454*a9643ea8Slogwang sp = ipsec_getpolicybysock(m, dir, inp, &error); 1455*a9643ea8Slogwang 1456*a9643ea8Slogwang if (sp != NULL) { 1457*a9643ea8Slogwang size = ipsec_hdrsiz_internal(sp); 1458*a9643ea8Slogwang KEYDEBUG(KEYDEBUG_IPSEC_DATA, 1459*a9643ea8Slogwang printf("%s: size:%lu.\n", __func__, 1460*a9643ea8Slogwang (unsigned long)size)); 1461*a9643ea8Slogwang 1462*a9643ea8Slogwang KEY_FREESP(&sp); 1463*a9643ea8Slogwang } else { 1464*a9643ea8Slogwang size = 0; /* XXX Should be panic? 1465*a9643ea8Slogwang * -> No, we are called w/o knowing if 1466*a9643ea8Slogwang * IPsec processing is needed. */ 1467*a9643ea8Slogwang } 1468*a9643ea8Slogwang return (size); 1469*a9643ea8Slogwang } 1470*a9643ea8Slogwang 1471*a9643ea8Slogwang /* 1472*a9643ea8Slogwang * Check the variable replay window. 1473*a9643ea8Slogwang * ipsec_chkreplay() performs replay check before ICV verification. 1474*a9643ea8Slogwang * ipsec_updatereplay() updates replay bitmap. This must be called after 1475*a9643ea8Slogwang * ICV verification (it also performs replay check, which is usually done 1476*a9643ea8Slogwang * beforehand). 1477*a9643ea8Slogwang * 0 (zero) is returned if packet disallowed, 1 if packet permitted. 1478*a9643ea8Slogwang * 1479*a9643ea8Slogwang * Based on RFC 2401. 1480*a9643ea8Slogwang */ 1481*a9643ea8Slogwang int 1482*a9643ea8Slogwang ipsec_chkreplay(u_int32_t seq, struct secasvar *sav) 1483*a9643ea8Slogwang { 1484*a9643ea8Slogwang const struct secreplay *replay; 1485*a9643ea8Slogwang u_int32_t diff; 1486*a9643ea8Slogwang int fr; 1487*a9643ea8Slogwang u_int32_t wsizeb; /* Constant: bits of window size. */ 1488*a9643ea8Slogwang int frlast; /* Constant: last frame. */ 1489*a9643ea8Slogwang 1490*a9643ea8Slogwang IPSEC_ASSERT(sav != NULL, ("Null SA")); 1491*a9643ea8Slogwang IPSEC_ASSERT(sav->replay != NULL, ("Null replay state")); 1492*a9643ea8Slogwang 1493*a9643ea8Slogwang replay = sav->replay; 1494*a9643ea8Slogwang 1495*a9643ea8Slogwang if (replay->wsize == 0) 1496*a9643ea8Slogwang return (1); /* No need to check replay. */ 1497*a9643ea8Slogwang 1498*a9643ea8Slogwang /* Constant. */ 1499*a9643ea8Slogwang frlast = replay->wsize - 1; 1500*a9643ea8Slogwang wsizeb = replay->wsize << 3; 1501*a9643ea8Slogwang 1502*a9643ea8Slogwang /* Sequence number of 0 is invalid. */ 1503*a9643ea8Slogwang if (seq == 0) 1504*a9643ea8Slogwang return (0); 1505*a9643ea8Slogwang 1506*a9643ea8Slogwang /* First time is always okay. */ 1507*a9643ea8Slogwang if (replay->count == 0) 1508*a9643ea8Slogwang return (1); 1509*a9643ea8Slogwang 1510*a9643ea8Slogwang if (seq > replay->lastseq) { 1511*a9643ea8Slogwang /* Larger sequences are okay. */ 1512*a9643ea8Slogwang return (1); 1513*a9643ea8Slogwang } else { 1514*a9643ea8Slogwang /* seq is equal or less than lastseq. */ 1515*a9643ea8Slogwang diff = replay->lastseq - seq; 1516*a9643ea8Slogwang 1517*a9643ea8Slogwang /* Over range to check, i.e. too old or wrapped. */ 1518*a9643ea8Slogwang if (diff >= wsizeb) 1519*a9643ea8Slogwang return (0); 1520*a9643ea8Slogwang 1521*a9643ea8Slogwang fr = frlast - diff / 8; 1522*a9643ea8Slogwang 1523*a9643ea8Slogwang /* This packet already seen? */ 1524*a9643ea8Slogwang if ((replay->bitmap)[fr] & (1 << (diff % 8))) 1525*a9643ea8Slogwang return (0); 1526*a9643ea8Slogwang 1527*a9643ea8Slogwang /* Out of order but good. */ 1528*a9643ea8Slogwang return (1); 1529*a9643ea8Slogwang } 1530*a9643ea8Slogwang } 1531*a9643ea8Slogwang 1532*a9643ea8Slogwang /* 1533*a9643ea8Slogwang * Check replay counter whether to update or not. 1534*a9643ea8Slogwang * OUT: 0: OK 1535*a9643ea8Slogwang * 1: NG 1536*a9643ea8Slogwang */ 1537*a9643ea8Slogwang int 1538*a9643ea8Slogwang ipsec_updatereplay(u_int32_t seq, struct secasvar *sav) 1539*a9643ea8Slogwang { 1540*a9643ea8Slogwang char buf[128]; 1541*a9643ea8Slogwang struct secreplay *replay; 1542*a9643ea8Slogwang u_int32_t diff; 1543*a9643ea8Slogwang int fr; 1544*a9643ea8Slogwang u_int32_t wsizeb; /* Constant: bits of window size. */ 1545*a9643ea8Slogwang int frlast; /* Constant: last frame. */ 1546*a9643ea8Slogwang 1547*a9643ea8Slogwang IPSEC_ASSERT(sav != NULL, ("Null SA")); 1548*a9643ea8Slogwang IPSEC_ASSERT(sav->replay != NULL, ("Null replay state")); 1549*a9643ea8Slogwang 1550*a9643ea8Slogwang replay = sav->replay; 1551*a9643ea8Slogwang 1552*a9643ea8Slogwang if (replay->wsize == 0) 1553*a9643ea8Slogwang goto ok; /* No need to check replay. */ 1554*a9643ea8Slogwang 1555*a9643ea8Slogwang /* Constant. */ 1556*a9643ea8Slogwang frlast = replay->wsize - 1; 1557*a9643ea8Slogwang wsizeb = replay->wsize << 3; 1558*a9643ea8Slogwang 1559*a9643ea8Slogwang /* Sequence number of 0 is invalid. */ 1560*a9643ea8Slogwang if (seq == 0) 1561*a9643ea8Slogwang return (1); 1562*a9643ea8Slogwang 1563*a9643ea8Slogwang /* First time. */ 1564*a9643ea8Slogwang if (replay->count == 0) { 1565*a9643ea8Slogwang replay->lastseq = seq; 1566*a9643ea8Slogwang bzero(replay->bitmap, replay->wsize); 1567*a9643ea8Slogwang (replay->bitmap)[frlast] = 1; 1568*a9643ea8Slogwang goto ok; 1569*a9643ea8Slogwang } 1570*a9643ea8Slogwang 1571*a9643ea8Slogwang if (seq > replay->lastseq) { 1572*a9643ea8Slogwang /* seq is larger than lastseq. */ 1573*a9643ea8Slogwang diff = seq - replay->lastseq; 1574*a9643ea8Slogwang 1575*a9643ea8Slogwang /* New larger sequence number. */ 1576*a9643ea8Slogwang if (diff < wsizeb) { 1577*a9643ea8Slogwang /* In window. */ 1578*a9643ea8Slogwang /* Set bit for this packet. */ 1579*a9643ea8Slogwang vshiftl(replay->bitmap, diff, replay->wsize); 1580*a9643ea8Slogwang (replay->bitmap)[frlast] |= 1; 1581*a9643ea8Slogwang } else { 1582*a9643ea8Slogwang /* This packet has a "way larger". */ 1583*a9643ea8Slogwang bzero(replay->bitmap, replay->wsize); 1584*a9643ea8Slogwang (replay->bitmap)[frlast] = 1; 1585*a9643ea8Slogwang } 1586*a9643ea8Slogwang replay->lastseq = seq; 1587*a9643ea8Slogwang 1588*a9643ea8Slogwang /* Larger is good. */ 1589*a9643ea8Slogwang } else { 1590*a9643ea8Slogwang /* seq is equal or less than lastseq. */ 1591*a9643ea8Slogwang diff = replay->lastseq - seq; 1592*a9643ea8Slogwang 1593*a9643ea8Slogwang /* Over range to check, i.e. too old or wrapped. */ 1594*a9643ea8Slogwang if (diff >= wsizeb) 1595*a9643ea8Slogwang return (1); 1596*a9643ea8Slogwang 1597*a9643ea8Slogwang fr = frlast - diff / 8; 1598*a9643ea8Slogwang 1599*a9643ea8Slogwang /* This packet already seen? */ 1600*a9643ea8Slogwang if ((replay->bitmap)[fr] & (1 << (diff % 8))) 1601*a9643ea8Slogwang return (1); 1602*a9643ea8Slogwang 1603*a9643ea8Slogwang /* Mark as seen. */ 1604*a9643ea8Slogwang (replay->bitmap)[fr] |= (1 << (diff % 8)); 1605*a9643ea8Slogwang 1606*a9643ea8Slogwang /* Out of order but good. */ 1607*a9643ea8Slogwang } 1608*a9643ea8Slogwang 1609*a9643ea8Slogwang ok: 1610*a9643ea8Slogwang if (replay->count == ~0) { 1611*a9643ea8Slogwang 1612*a9643ea8Slogwang /* Set overflow flag. */ 1613*a9643ea8Slogwang replay->overflow++; 1614*a9643ea8Slogwang 1615*a9643ea8Slogwang /* Don't increment, no more packets accepted. */ 1616*a9643ea8Slogwang if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) 1617*a9643ea8Slogwang return (1); 1618*a9643ea8Slogwang 1619*a9643ea8Slogwang ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n", 1620*a9643ea8Slogwang __func__, replay->overflow, 1621*a9643ea8Slogwang ipsec_logsastr(sav, buf, sizeof(buf)))); 1622*a9643ea8Slogwang } 1623*a9643ea8Slogwang 1624*a9643ea8Slogwang replay->count++; 1625*a9643ea8Slogwang 1626*a9643ea8Slogwang return (0); 1627*a9643ea8Slogwang } 1628*a9643ea8Slogwang 1629*a9643ea8Slogwang /* 1630*a9643ea8Slogwang * Shift variable length buffer to left. 1631*a9643ea8Slogwang * IN: bitmap: pointer to the buffer 1632*a9643ea8Slogwang * nbit: the number of to shift. 1633*a9643ea8Slogwang * wsize: buffer size (bytes). 1634*a9643ea8Slogwang */ 1635*a9643ea8Slogwang static void 1636*a9643ea8Slogwang vshiftl(unsigned char *bitmap, int nbit, int wsize) 1637*a9643ea8Slogwang { 1638*a9643ea8Slogwang int s, j, i; 1639*a9643ea8Slogwang unsigned char over; 1640*a9643ea8Slogwang 1641*a9643ea8Slogwang for (j = 0; j < nbit; j += 8) { 1642*a9643ea8Slogwang s = (nbit - j < 8) ? (nbit - j): 8; 1643*a9643ea8Slogwang bitmap[0] <<= s; 1644*a9643ea8Slogwang for (i = 1; i < wsize; i++) { 1645*a9643ea8Slogwang over = (bitmap[i] >> (8 - s)); 1646*a9643ea8Slogwang bitmap[i] <<= s; 1647*a9643ea8Slogwang bitmap[i-1] |= over; 1648*a9643ea8Slogwang } 1649*a9643ea8Slogwang } 1650*a9643ea8Slogwang } 1651*a9643ea8Slogwang 1652*a9643ea8Slogwang /* Return a printable string for the address. */ 1653*a9643ea8Slogwang char* 1654*a9643ea8Slogwang ipsec_address(union sockaddr_union* sa, char *buf, socklen_t size) 1655*a9643ea8Slogwang { 1656*a9643ea8Slogwang 1657*a9643ea8Slogwang switch (sa->sa.sa_family) { 1658*a9643ea8Slogwang #ifdef INET 1659*a9643ea8Slogwang case AF_INET: 1660*a9643ea8Slogwang return (inet_ntop(AF_INET, &sa->sin.sin_addr, buf, size)); 1661*a9643ea8Slogwang #endif /* INET */ 1662*a9643ea8Slogwang #ifdef INET6 1663*a9643ea8Slogwang case AF_INET6: 1664*a9643ea8Slogwang return (inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, size)); 1665*a9643ea8Slogwang #endif /* INET6 */ 1666*a9643ea8Slogwang default: 1667*a9643ea8Slogwang return ("(unknown address family)"); 1668*a9643ea8Slogwang } 1669*a9643ea8Slogwang } 1670*a9643ea8Slogwang 1671*a9643ea8Slogwang char * 1672*a9643ea8Slogwang ipsec_logsastr(struct secasvar *sav, char *buf, size_t size) 1673*a9643ea8Slogwang { 1674*a9643ea8Slogwang char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN]; 1675*a9643ea8Slogwang 1676*a9643ea8Slogwang IPSEC_ASSERT(sav->sah->saidx.src.sa.sa_family == 1677*a9643ea8Slogwang sav->sah->saidx.dst.sa.sa_family, ("address family mismatch")); 1678*a9643ea8Slogwang 1679*a9643ea8Slogwang snprintf(buf, size, "SA(SPI=%08lx src=%s dst=%s)", 1680*a9643ea8Slogwang (u_long)ntohl(sav->spi), 1681*a9643ea8Slogwang ipsec_address(&sav->sah->saidx.src, sbuf, sizeof(sbuf)), 1682*a9643ea8Slogwang ipsec_address(&sav->sah->saidx.dst, dbuf, sizeof(dbuf))); 1683*a9643ea8Slogwang return (buf); 1684*a9643ea8Slogwang } 1685*a9643ea8Slogwang 1686*a9643ea8Slogwang void 1687*a9643ea8Slogwang ipsec_dumpmbuf(const struct mbuf *m) 1688*a9643ea8Slogwang { 1689*a9643ea8Slogwang const u_char *p; 1690*a9643ea8Slogwang int totlen; 1691*a9643ea8Slogwang int i; 1692*a9643ea8Slogwang 1693*a9643ea8Slogwang totlen = 0; 1694*a9643ea8Slogwang printf("---\n"); 1695*a9643ea8Slogwang while (m) { 1696*a9643ea8Slogwang p = mtod(m, const u_char *); 1697*a9643ea8Slogwang for (i = 0; i < m->m_len; i++) { 1698*a9643ea8Slogwang printf("%02x ", p[i]); 1699*a9643ea8Slogwang totlen++; 1700*a9643ea8Slogwang if (totlen % 16 == 0) 1701*a9643ea8Slogwang printf("\n"); 1702*a9643ea8Slogwang } 1703*a9643ea8Slogwang m = m->m_next; 1704*a9643ea8Slogwang } 1705*a9643ea8Slogwang if (totlen % 16 != 0) 1706*a9643ea8Slogwang printf("\n"); 1707*a9643ea8Slogwang printf("---\n"); 1708*a9643ea8Slogwang } 1709*a9643ea8Slogwang 1710*a9643ea8Slogwang static void 1711*a9643ea8Slogwang def_policy_init(const void *unused __unused) 1712*a9643ea8Slogwang { 1713*a9643ea8Slogwang 1714*a9643ea8Slogwang bzero(&V_def_policy, sizeof(struct secpolicy)); 1715*a9643ea8Slogwang V_def_policy.policy = IPSEC_POLICY_NONE; 1716*a9643ea8Slogwang V_def_policy.refcnt = 1; 1717*a9643ea8Slogwang } 1718*a9643ea8Slogwang VNET_SYSINIT(def_policy_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, 1719*a9643ea8Slogwang def_policy_init, NULL); 1720*a9643ea8Slogwang 1721*a9643ea8Slogwang 1722*a9643ea8Slogwang /* XXX This stuff doesn't belong here... */ 1723*a9643ea8Slogwang 1724*a9643ea8Slogwang static struct xformsw* xforms = NULL; 1725*a9643ea8Slogwang 1726*a9643ea8Slogwang /* 1727*a9643ea8Slogwang * Register a transform; typically at system startup. 1728*a9643ea8Slogwang */ 1729*a9643ea8Slogwang void 1730*a9643ea8Slogwang xform_register(struct xformsw* xsp) 1731*a9643ea8Slogwang { 1732*a9643ea8Slogwang 1733*a9643ea8Slogwang xsp->xf_next = xforms; 1734*a9643ea8Slogwang xforms = xsp; 1735*a9643ea8Slogwang } 1736*a9643ea8Slogwang 1737*a9643ea8Slogwang /* 1738*a9643ea8Slogwang * Initialize transform support in an sav. 1739*a9643ea8Slogwang */ 1740*a9643ea8Slogwang int 1741*a9643ea8Slogwang xform_init(struct secasvar *sav, int xftype) 1742*a9643ea8Slogwang { 1743*a9643ea8Slogwang struct xformsw *xsp; 1744*a9643ea8Slogwang 1745*a9643ea8Slogwang if (sav->tdb_xform != NULL) /* Previously initialized. */ 1746*a9643ea8Slogwang return (0); 1747*a9643ea8Slogwang for (xsp = xforms; xsp; xsp = xsp->xf_next) 1748*a9643ea8Slogwang if (xsp->xf_type == xftype) 1749*a9643ea8Slogwang return ((*xsp->xf_init)(sav, xsp)); 1750*a9643ea8Slogwang return (EINVAL); 1751*a9643ea8Slogwang } 1752