ip6_ipsec.c revision 171732
1/*- 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: head/sys/netinet6/ip6_ipsec.c 171732 2007-08-05 16:16:15Z bz $ 30 */ 31 32#include "opt_ipsec.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/mac.h> 38#include <sys/malloc.h> 39#include <sys/mbuf.h> 40#include <sys/protosw.h> 41#include <sys/socket.h> 42#include <sys/socketvar.h> 43#include <sys/sysctl.h> 44 45#include <net/if.h> 46#include <net/route.h> 47 48#include <netinet/in.h> 49#include <netinet/in_systm.h> 50#include <netinet/in_var.h> 51#include <netinet/ip.h> 52#include <netinet/in_pcb.h> 53#include <netinet/ip_var.h> 54#include <netinet/ip_options.h> 55 56#include <machine/in_cksum.h> 57 58#ifdef IPSEC 59#include <netipsec/ipsec.h> 60#include <netipsec/ipsec6.h> 61#include <netipsec/xform.h> 62#include <netipsec/key.h> 63#ifdef IPSEC_DEBUG 64#include <netipsec/key_debug.h> 65#else 66#define KEYDEBUG(lev,arg) 67#endif 68#endif /*IPSEC*/ 69 70#include <netinet6/ip6_ipsec.h> 71 72extern struct protosw inet6sw[]; 73 74/* 75 * Check if we have to jump over firewall processing for this packet. 76 * Called from ip_input(). 77 * 1 = jump over firewall, 0 = packet goes through firewall. 78 */ 79int 80ip6_ipsec_filtertunnel(struct mbuf *m) 81{ 82#if defined(IPSEC) && !defined(IPSEC_FILTERTUNNEL) 83 /* 84 * Bypass packet filtering for packets from a tunnel. 85 */ 86 if (m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL) 87 return 1; 88#endif 89 return 0; 90} 91 92/* 93 * Check if this packet has an active SA and needs to be dropped instead 94 * of forwarded. 95 * Called from ip_input(). 96 * 1 = drop packet, 0 = forward packet. 97 */ 98int 99ip6_ipsec_fwd(struct mbuf *m) 100{ 101#ifdef IPSEC 102 struct m_tag *mtag; 103 struct tdb_ident *tdbi; 104 struct secpolicy *sp; 105 int s, error; 106 mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); 107 s = splnet(); 108 if (mtag != NULL) { 109 tdbi = (struct tdb_ident *)(mtag + 1); 110 sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); 111 } else { 112 sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, 113 IP_FORWARDING, &error); 114 } 115 if (sp == NULL) { /* NB: can happen if error */ 116 splx(s); 117 /*XXX error stat???*/ 118 DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/ 119 return 1; 120 } 121 122 /* 123 * Check security policy against packet attributes. 124 */ 125 error = ipsec_in_reject(sp, m); 126 KEY_FREESP(&sp); 127 splx(s); 128 if (error) { 129 ipstat.ips_cantforward++; 130 return 1; 131 } 132#endif /* IPSEC */ 133 return 0; 134} 135 136/* 137 * Check if protocol type doesn't have a further header and do IPSEC 138 * decryption or reject right now. Protocols with further headers get 139 * their IPSEC treatment within the protocol specific processing. 140 * Called from ip_input(). 141 * 1 = drop packet, 0 = continue processing packet. 142 */ 143int 144ip6_ipsec_input(struct mbuf *m, int nxt) 145{ 146#ifdef IPSEC 147 struct m_tag *mtag; 148 struct tdb_ident *tdbi; 149 struct secpolicy *sp; 150 int s, error; 151 /* 152 * enforce IPsec policy checking if we are seeing last header. 153 * note that we do not visit this with protocols with pcb layer 154 * code - like udp/tcp/raw ip. 155 */ 156 if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && 157 ipsec6_in_reject(m, NULL)) { 158 159 /* 160 * Check if the packet has already had IPsec processing 161 * done. If so, then just pass it along. This tag gets 162 * set during AH, ESP, etc. input handling, before the 163 * packet is returned to the ip input queue for delivery. 164 */ 165 mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); 166 s = splnet(); 167 if (mtag != NULL) { 168 tdbi = (struct tdb_ident *)(mtag + 1); 169 sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); 170 } else { 171 sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, 172 IP_FORWARDING, &error); 173 } 174 if (sp != NULL) { 175 /* 176 * Check security policy against packet attributes. 177 */ 178 error = ipsec_in_reject(sp, m); 179 KEY_FREESP(&sp); 180 } else { 181 /* XXX error stat??? */ 182 error = EINVAL; 183 DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/ 184 return 1; 185 } 186 splx(s); 187 if (error) 188 return 1; 189 } 190#endif /* IPSEC */ 191 return 0; 192} 193 194/* 195 * Called from ip6_output(). 196 * 1 = drop packet, 0 = continue processing packet, 197 * -1 = packet was reinjected and stop processing packet 198 */ 199 200int 201ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error, 202 struct ifnet **ifp, struct secpolicy **sp) 203{ 204#ifdef IPSEC 205 struct tdb_ident *tdbi; 206 struct m_tag *mtag; 207 /* XXX int s; */ 208 if (sp == NULL) 209 return 1; 210 mtag = m_tag_find(*m, PACKET_TAG_IPSEC_PENDING_TDB, NULL); 211 if (mtag != NULL) { 212 tdbi = (struct tdb_ident *)(mtag + 1); 213 *sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND); 214 if (*sp == NULL) 215 *error = -EINVAL; /* force silent drop */ 216 m_tag_delete(*m, mtag); 217 } else { 218 *sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, *flags, 219 error, inp); 220 } 221 222 /* 223 * There are four return cases: 224 * sp != NULL apply IPsec policy 225 * sp == NULL, error == 0 no IPsec handling needed 226 * sp == NULL, error == -EINVAL discard packet w/o error 227 * sp == NULL, error != 0 discard packet, report error 228 */ 229 if (*sp != NULL) { 230 /* Loop detection, check if ipsec processing already done */ 231 KASSERT((*sp)->req != NULL, ("ip_output: no ipsec request")); 232 for (mtag = m_tag_first(*m); mtag != NULL; 233 mtag = m_tag_next(*m, mtag)) { 234 if (mtag->m_tag_cookie != MTAG_ABI_COMPAT) 235 continue; 236 if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE && 237 mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED) 238 continue; 239 /* 240 * Check if policy has an SA associated with it. 241 * This can happen when an SP has yet to acquire 242 * an SA; e.g. on first reference. If it occurs, 243 * then we let ipsec4_process_packet do its thing. 244 */ 245 if ((*sp)->req->sav == NULL) 246 break; 247 tdbi = (struct tdb_ident *)(mtag + 1); 248 if (tdbi->spi == (*sp)->req->sav->spi && 249 tdbi->proto == (*sp)->req->sav->sah->saidx.proto && 250 bcmp(&tdbi->dst, &(*sp)->req->sav->sah->saidx.dst, 251 sizeof (union sockaddr_union)) == 0) { 252 /* 253 * No IPsec processing is needed, free 254 * reference to SP. 255 * 256 * NB: null pointer to avoid free at 257 * done: below. 258 */ 259 KEY_FREESP(sp), sp = NULL; 260 /* XXX splx(s); */ 261 goto done; 262 } 263 } 264 265 /* 266 * Do delayed checksums now because we send before 267 * this is done in the normal processing path. 268 */ 269 if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 270 in_delayed_cksum(*m); 271 (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 272 } 273 274 /* 275 * Preserve KAME behaviour: ENOENT can be returned 276 * when an SA acquire is in progress. Don't propagate 277 * this to user-level; it confuses applications. 278 * 279 * XXX this will go away when the SADB is redone. 280 */ 281 if (*error == ENOENT) 282 *error = 0; 283 goto do_ipsec; 284 } else { /* sp == NULL */ 285 if (*error != 0) { 286 /* 287 * Hack: -EINVAL is used to signal that a packet 288 * should be silently discarded. This is typically 289 * because we asked key management for an SA and 290 * it was delayed (e.g. kicked up to IKE). 291 */ 292 if (*error == -EINVAL) 293 *error = 0; 294 goto bad; 295 } else { 296 /* No IPsec processing for this packet. */ 297 } 298 } 299done: 300 if (sp != NULL) 301 if (*sp != NULL) 302 KEY_FREESP(sp); 303 return 0; 304do_ipsec: 305 return -1; 306bad: 307 if (sp != NULL) 308 if (*sp != NULL) 309 KEY_FREESP(sp); 310 return 1; 311#endif /* IPSEC */ 312 return 0; 313} 314 315/* 316 * Compute the MTU for a forwarded packet that gets IPSEC encapsulated. 317 * Called from ip_forward(). 318 * Returns MTU suggestion for ICMP needfrag reply. 319 */ 320int 321ip6_ipsec_mtu(struct mbuf *m) 322{ 323 int mtu = 0; 324 /* 325 * If the packet is routed over IPsec tunnel, tell the 326 * originator the tunnel MTU. 327 * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz 328 * XXX quickhack!!! 329 */ 330 struct secpolicy *sp = NULL; 331 int ipsecerror; 332 int ipsechdr; 333 struct route *ro; 334#ifdef IPSEC 335 sp = ipsec_getpolicybyaddr(m, 336 IPSEC_DIR_OUTBOUND, 337 IP_FORWARDING, 338 &ipsecerror); 339#endif /* IPSEC */ 340 if (sp != NULL) { 341 /* count IPsec header size */ 342 ipsechdr = ipsec4_hdrsiz(m, 343 IPSEC_DIR_OUTBOUND, 344 NULL); 345 346 /* 347 * find the correct route for outer IPv4 348 * header, compute tunnel MTU. 349 */ 350 if (sp->req != NULL && 351 sp->req->sav != NULL && 352 sp->req->sav->sah != NULL) { 353 ro = &sp->req->sav->sah->sa_route; 354 if (ro->ro_rt && ro->ro_rt->rt_ifp) { 355 mtu = 356 ro->ro_rt->rt_rmx.rmx_mtu ? 357 ro->ro_rt->rt_rmx.rmx_mtu : 358 ro->ro_rt->rt_ifp->if_mtu; 359 mtu -= ipsechdr; 360 } 361 } 362#ifdef IPSEC 363 KEY_FREESP(&sp); 364#endif /* IPSEC */ 365 } 366 return mtu; 367} 368 369