1 /* $OpenBSD: ipsec_output.c,v 1.36 2006/12/19 11:31:10 itojun 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 "pf.h" 24 25 #include <sys/param.h> 26 #include <sys/systm.h> 27 #include <sys/mbuf.h> 28 #include <sys/socket.h> 29 #include <sys/kernel.h> 30 31 #include <net/if.h> 32 #include <net/route.h> 33 34 #if NPF > 0 35 #include <net/pfvar.h> 36 #endif 37 38 #ifdef INET 39 #include <netinet/in.h> 40 #include <netinet/in_systm.h> 41 #include <netinet/ip.h> 42 #include <netinet/in_pcb.h> 43 #include <netinet/ip_var.h> 44 #endif /* INET */ 45 46 #ifdef INET6 47 #ifndef INET 48 #include <netinet/in.h> 49 #endif 50 #include <netinet6/in6_var.h> 51 #endif /* INET6 */ 52 53 #include <netinet/udp.h> 54 #include <netinet/ip_ipsp.h> 55 #include <netinet/ip_ah.h> 56 #include <netinet/ip_esp.h> 57 #include <netinet/ip_ipcomp.h> 58 #include <crypto/xform.h> 59 60 #ifdef ENCDEBUG 61 #define DPRINTF(x) if (encdebug) printf x 62 #else 63 #define DPRINTF(x) 64 #endif 65 66 int udpencap_enable = 1; /* enabled by default */ 67 int udpencap_port = 4500; /* triggers decapsulation */ 68 69 /* 70 * Loop over a tdb chain, taking into consideration protocol tunneling. The 71 * fourth argument is set if the first encapsulation header is already in 72 * place. 73 */ 74 int 75 ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready) 76 { 77 struct timeval tv; 78 int i, off, error; 79 struct mbuf *mp; 80 81 #ifdef INET 82 int setdf = 0; 83 struct ip *ip; 84 #endif /* INET */ 85 #ifdef INET6 86 struct ip6_hdr *ip6; 87 #endif /* INET6 */ 88 89 /* Check that the transform is allowed by the administrator. */ 90 if ((tdb->tdb_sproto == IPPROTO_ESP && !esp_enable) || 91 (tdb->tdb_sproto == IPPROTO_AH && !ah_enable) || 92 (tdb->tdb_sproto == IPPROTO_IPCOMP && !ipcomp_enable)) { 93 DPRINTF(("ipsp_process_packet(): IPsec outbound packet " 94 "dropped due to policy (check your sysctls)\n")); 95 m_freem(m); 96 return EHOSTUNREACH; 97 } 98 99 /* Sanity check. */ 100 if (!tdb->tdb_xform) { 101 DPRINTF(("ipsp_process_packet(): uninitialized TDB\n")); 102 m_freem(m); 103 return EHOSTUNREACH; 104 } 105 106 /* Check if the SPI is invalid. */ 107 if (tdb->tdb_flags & TDBF_INVALID) { 108 DPRINTF(("ipsp_process_packet(): attempt to use invalid " 109 "SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst), 110 ntohl(tdb->tdb_spi), tdb->tdb_sproto)); 111 m_freem(m); 112 return ENXIO; 113 } 114 115 /* Check that the network protocol is supported */ 116 switch (tdb->tdb_dst.sa.sa_family) { 117 #ifdef INET 118 case AF_INET: 119 break; 120 #endif /* INET */ 121 122 #ifdef INET6 123 case AF_INET6: 124 break; 125 #endif /* INET6 */ 126 127 default: 128 DPRINTF(("ipsp_process_packet(): attempt to use " 129 "SA %s/%08x/%u for protocol family %d\n", 130 ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), 131 tdb->tdb_sproto, tdb->tdb_dst.sa.sa_family)); 132 m_freem(m); 133 return ENXIO; 134 } 135 136 /* 137 * Register first use if applicable, setup relevant expiration timer. 138 */ 139 if (tdb->tdb_first_use == 0) { 140 tdb->tdb_first_use = time_second; 141 142 tv.tv_usec = 0; 143 144 tv.tv_sec = tdb->tdb_first_use + tdb->tdb_exp_first_use; 145 if (tdb->tdb_flags & TDBF_FIRSTUSE) 146 timeout_add(&tdb->tdb_first_tmo, 147 hzto(&tv)); 148 149 tv.tv_sec = tdb->tdb_first_use + tdb->tdb_soft_first_use; 150 if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) 151 timeout_add(&tdb->tdb_sfirst_tmo, 152 hzto(&tv)); 153 } 154 155 /* 156 * Check for tunneling if we don't have the first header in place. 157 * When doing Ethernet-over-IP, we are handed an already-encapsulated 158 * frame, so we don't need to re-encapsulate. 159 */ 160 if (tunalready == 0) { 161 /* 162 * If the target protocol family is different, we know we'll be 163 * doing tunneling. 164 */ 165 if (af == tdb->tdb_dst.sa.sa_family) { 166 #ifdef INET 167 if (af == AF_INET) 168 i = sizeof(struct ip); 169 #endif /* INET */ 170 171 #ifdef INET6 172 if (af == AF_INET6) 173 i = sizeof(struct ip6_hdr); 174 #endif /* INET6 */ 175 176 /* Bring the network header in the first mbuf. */ 177 if (m->m_len < i) { 178 if ((m = m_pullup(m, i)) == NULL) 179 return ENOBUFS; 180 } 181 182 #ifdef INET 183 ip = mtod(m, struct ip *); 184 185 /* 186 * This is not a bridge packet, remember if we 187 * had IP_DF. 188 */ 189 setdf = ip->ip_off & htons(IP_DF); 190 #endif /* INET */ 191 192 #ifdef INET6 193 ip6 = mtod(m, struct ip6_hdr *); 194 #endif /* INET6 */ 195 } 196 197 /* Do the appropriate encapsulation, if necessary. */ 198 if ((tdb->tdb_dst.sa.sa_family != af) || /* PF mismatch */ 199 (tdb->tdb_flags & TDBF_TUNNELING) || /* Tunneling needed */ 200 (tdb->tdb_xform->xf_type == XF_IP4) || /* ditto */ 201 #ifdef INET 202 ((tdb->tdb_dst.sa.sa_family == AF_INET) && 203 (tdb->tdb_dst.sin.sin_addr.s_addr != INADDR_ANY) && 204 (tdb->tdb_dst.sin.sin_addr.s_addr != ip->ip_dst.s_addr)) || 205 #endif /* INET */ 206 #ifdef INET6 207 ((tdb->tdb_dst.sa.sa_family == AF_INET6) && 208 (!IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr)) && 209 (!IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr, 210 &ip6->ip6_dst))) || 211 #endif /* INET6 */ 212 0) { 213 #ifdef INET 214 /* Fix IPv4 header checksum and length. */ 215 if (af == AF_INET) { 216 if (m->m_len < sizeof(struct ip)) 217 if ((m = m_pullup(m, 218 sizeof(struct ip))) == NULL) 219 return ENOBUFS; 220 221 ip = mtod(m, struct ip *); 222 ip->ip_len = htons(m->m_pkthdr.len); 223 ip->ip_sum = 0; 224 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 225 } 226 #endif /* INET */ 227 228 #ifdef INET6 229 /* Fix IPv6 header payload length. */ 230 if (af == AF_INET6) { 231 if (m->m_len < sizeof(struct ip6_hdr)) 232 if ((m = m_pullup(m, 233 sizeof(struct ip6_hdr))) == NULL) 234 return ENOBUFS; 235 236 if (m->m_pkthdr.len - sizeof(*ip6) > 237 IPV6_MAXPACKET) { 238 /* No jumbogram support. */ 239 m_freem(m); 240 return ENXIO; /*?*/ 241 } 242 ip6 = mtod(m, struct ip6_hdr *); 243 ip6->ip6_plen = htons(m->m_pkthdr.len 244 - sizeof(*ip6)); 245 } 246 #endif /* INET6 */ 247 248 /* Encapsulate -- the last two arguments are unused. */ 249 error = ipip_output(m, tdb, &mp, 0, 0); 250 if ((mp == NULL) && (!error)) 251 error = EFAULT; 252 if (error) { 253 if (mp) { 254 m_freem(mp); 255 mp = NULL; 256 } 257 return error; 258 } 259 260 m = mp; 261 mp = NULL; 262 263 #ifdef INET 264 if (tdb->tdb_dst.sa.sa_family == AF_INET && setdf) { 265 if (m->m_len < sizeof(struct ip)) 266 if ((m = m_pullup(m, 267 sizeof(struct ip))) == NULL) 268 return ENOBUFS; 269 270 ip = mtod(m, struct ip *); 271 ip->ip_off |= htons(IP_DF); 272 } 273 #endif 274 275 /* Remember that we appended a tunnel header. */ 276 tdb->tdb_flags |= TDBF_USEDTUNNEL; 277 } 278 279 /* We may be done with this TDB */ 280 if (tdb->tdb_xform->xf_type == XF_IP4) 281 return ipsp_process_done(m, tdb); 282 } else { 283 /* 284 * If this is just an IP-IP TDB and we're told there's 285 * already an encapsulation header, move on. 286 */ 287 if (tdb->tdb_xform->xf_type == XF_IP4) 288 return ipsp_process_done(m, tdb); 289 } 290 291 /* Extract some information off the headers. */ 292 switch (tdb->tdb_dst.sa.sa_family) { 293 #ifdef INET 294 case AF_INET: 295 ip = mtod(m, struct ip *); 296 i = ip->ip_hl << 2; 297 off = offsetof(struct ip, ip_p); 298 break; 299 #endif /* INET */ 300 301 #ifdef INET6 302 case AF_INET6: 303 ip6 = mtod(m, struct ip6_hdr *); 304 i = sizeof(struct ip6_hdr); 305 off = offsetof(struct ip6_hdr, ip6_nxt); 306 break; 307 #endif /* INET6 */ 308 } 309 310 /* Non expansion policy for IPCOMP */ 311 if (tdb->tdb_sproto == IPPROTO_IPCOMP) { 312 if ((m->m_pkthdr.len - i) < tdb->tdb_compalgxform->minlen) { 313 extern struct ipcompstat ipcompstat; 314 315 /* No need to compress, leave the packet untouched */ 316 ipcompstat.ipcomps_minlen++; 317 return ipsp_process_done(m, tdb); 318 } 319 } 320 321 /* Invoke the IPsec transform. */ 322 return (*(tdb->tdb_xform->xf_output))(m, tdb, NULL, i, off); 323 } 324 325 /* 326 * Called by the IPsec output transform callbacks, to transmit the packet 327 * or do further processing, as necessary. 328 */ 329 int 330 ipsp_process_done(struct mbuf *m, struct tdb *tdb) 331 { 332 #ifdef INET 333 struct ip *ip; 334 #endif /* INET */ 335 336 #ifdef INET6 337 struct ip6_hdr *ip6; 338 #endif /* INET6 */ 339 340 struct tdb_ident *tdbi; 341 struct m_tag *mtag; 342 343 tdb->tdb_last_used = time_second; 344 345 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) { 346 struct mbuf *mi; 347 struct udphdr *uh; 348 349 if (!udpencap_enable || !udpencap_port) { 350 m_freem(m); 351 return ENXIO; 352 } 353 mi = m_inject(m, sizeof(struct ip), sizeof(struct udphdr), 354 M_DONTWAIT); 355 if (mi == NULL) { 356 m_freem(m); 357 return ENOMEM; 358 } 359 uh = mtod(mi, struct udphdr *); 360 uh->uh_sport = uh->uh_dport = htons(udpencap_port); 361 if (tdb->tdb_udpencap_port) 362 uh->uh_dport = tdb->tdb_udpencap_port; 363 364 uh->uh_ulen = htons(m->m_pkthdr.len - sizeof(struct ip)); 365 uh->uh_sum = 0; 366 espstat.esps_udpencout++; 367 } 368 369 switch (tdb->tdb_dst.sa.sa_family) { 370 #ifdef INET 371 case AF_INET: 372 /* Fix the header length, for AH processing. */ 373 ip = mtod(m, struct ip *); 374 ip->ip_len = htons(m->m_pkthdr.len); 375 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) 376 ip->ip_p = IPPROTO_UDP; 377 break; 378 #endif /* INET */ 379 380 #ifdef INET6 381 case AF_INET6: 382 /* Fix the header length, for AH processing. */ 383 if (m->m_pkthdr.len < sizeof(*ip6)) { 384 m_freem(m); 385 return ENXIO; 386 } 387 if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) { 388 /* No jumbogram support. */ 389 m_freem(m); 390 return ENXIO; 391 } 392 ip6 = mtod(m, struct ip6_hdr *); 393 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); 394 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) 395 ip6->ip6_nxt = IPPROTO_UDP; 396 break; 397 #endif /* INET6 */ 398 399 default: 400 m_freem(m); 401 DPRINTF(("ipsp_process_done(): unknown protocol family (%d)\n", 402 tdb->tdb_dst.sa.sa_family)); 403 return ENXIO; 404 } 405 406 /* 407 * Add a record of what we've done or what needs to be done to the 408 * packet. 409 */ 410 if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0) 411 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, 412 sizeof(struct tdb_ident), 413 M_NOWAIT); 414 else 415 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, 416 sizeof(struct tdb_ident), M_NOWAIT); 417 418 if (mtag == NULL) { 419 m_freem(m); 420 DPRINTF(("ipsp_process_done(): could not allocate packet " 421 "tag\n")); 422 return ENOMEM; 423 } 424 425 tdbi = (struct tdb_ident *)(mtag + 1); 426 bcopy(&tdb->tdb_dst, &tdbi->dst, sizeof(union sockaddr_union)); 427 tdbi->proto = tdb->tdb_sproto; 428 tdbi->spi = tdb->tdb_spi; 429 430 m_tag_prepend(m, mtag); 431 432 /* If there's another (bundled) TDB to apply, do so. */ 433 if (tdb->tdb_onext) 434 return ipsp_process_packet(m, tdb->tdb_onext, 435 tdb->tdb_dst.sa.sa_family, 0); 436 437 #if NPF > 0 438 /* Add pf tag if requested. */ 439 if (pf_tag_packet(m, NULL, tdb->tdb_tag, -1)) 440 DPRINTF(("failed to tag ipsec packet\n")); 441 #endif 442 443 /* 444 * We're done with IPsec processing, transmit the packet using the 445 * appropriate network protocol (IP or IPv6). SPD lookup will be 446 * performed again there. 447 */ 448 switch (tdb->tdb_dst.sa.sa_family) { 449 #ifdef INET 450 case AF_INET: 451 return ip_output(m, (void *)NULL, (void *)NULL, IP_RAWOUTPUT, (void *)NULL, (void *)NULL); 452 #endif /* INET */ 453 454 #ifdef INET6 455 case AF_INET6: 456 /* 457 * We don't need massage, IPv6 header fields are always in 458 * net endian. 459 */ 460 return ip6_output(m, NULL, NULL, 0, NULL, NULL); 461 #endif /* INET6 */ 462 } 463 return EINVAL; /* Not reached. */ 464 } 465 466 ssize_t 467 ipsec_hdrsz(struct tdb *tdbp) 468 { 469 ssize_t adjust; 470 471 switch (tdbp->tdb_sproto) { 472 case IPPROTO_IPIP: 473 adjust = 0; 474 break; 475 476 case IPPROTO_ESP: 477 if (tdbp->tdb_encalgxform == NULL) 478 return (-1); 479 480 /* Header length */ 481 if (tdbp->tdb_flags & TDBF_NOREPLAY) 482 adjust = sizeof(u_int32_t) + tdbp->tdb_ivlen; 483 else 484 adjust = 2 * sizeof(u_int32_t) + tdbp->tdb_ivlen; 485 if (tdbp->tdb_flags & TDBF_UDPENCAP) 486 adjust += sizeof(struct udphdr); 487 /* Authenticator */ 488 if (tdbp->tdb_authalgxform != NULL) 489 adjust += AH_HMAC_HASHLEN; 490 /* Padding */ 491 adjust += tdbp->tdb_encalgxform->blocksize; 492 break; 493 494 case IPPROTO_AH: 495 if (tdbp->tdb_authalgxform == NULL) 496 return (-1); 497 498 if (!(tdbp->tdb_flags & TDBF_NOREPLAY)) 499 adjust = AH_FLENGTH + sizeof(u_int32_t); 500 else 501 adjust = AH_FLENGTH; 502 adjust += tdbp->tdb_authalgxform->authsize; 503 break; 504 505 default: 506 return (-1); 507 } 508 509 if (!(tdbp->tdb_flags & TDBF_TUNNELING) && 510 !(tdbp->tdb_flags & TDBF_USEDTUNNEL)) 511 return (adjust); 512 513 switch (tdbp->tdb_dst.sa.sa_family) { 514 #ifdef INET 515 case AF_INET: 516 adjust += sizeof(struct ip); 517 break; 518 #endif /* INET */ 519 #ifdef INET6 520 case AF_INET6: 521 adjust += sizeof(struct ip6_hdr); 522 break; 523 #endif /* INET6 */ 524 } 525 526 return (adjust); 527 } 528 529 void 530 ipsec_adjust_mtu(struct mbuf *m, u_int32_t mtu) 531 { 532 struct tdb_ident *tdbi; 533 struct tdb *tdbp; 534 struct m_tag *mtag; 535 ssize_t adjust; 536 int s; 537 538 s = spltdb(); 539 540 for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL); mtag; 541 mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, mtag)) { 542 tdbi = (struct tdb_ident *)(mtag + 1); 543 tdbp = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); 544 if (tdbp == NULL) 545 break; 546 547 if ((adjust = ipsec_hdrsz(tdbp)) == -1) 548 break; 549 550 mtu -= adjust; 551 tdbp->tdb_mtu = mtu; 552 tdbp->tdb_mtutimeout = time_second + ip_mtudisc_timeout; 553 DPRINTF(("ipsec_adjust_mtu: " 554 "spi %08x mtu %d adjust %d mbuf %p\n", 555 ntohl(tdbp->tdb_spi), tdbp->tdb_mtu, 556 adjust, m)); 557 } 558 559 splx(s); 560 } 561