| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ipsec_input.c,v 1.29 2012/01/25 21:58:10 drochner Exp $ */ | | 1 | /* $NetBSD: ipsec_input.c,v 1.29.16.1 2018/03/13 17:47:12 snj Exp $ */ |
2 | /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec_input.c,v 1.2.4.2 2003/03/28 20:32:53 sam Exp $ */ | | 2 | /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec_input.c,v 1.2.4.2 2003/03/28 20:32:53 sam Exp $ */ |
3 | /* $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $ */ | | 3 | /* $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $ */ |
4 | | | 4 | |
5 | /* | | 5 | /* |
6 | * The authors of this code are John Ioannidis (ji@tla.org), | | 6 | * The authors of this code are John Ioannidis (ji@tla.org), |
7 | * Angelos D. Keromytis (kermit@csd.uch.gr) and | | 7 | * Angelos D. Keromytis (kermit@csd.uch.gr) and |
8 | * Niels Provos (provos@physnet.uni-hamburg.de). | | 8 | * Niels Provos (provos@physnet.uni-hamburg.de). |
9 | * | | 9 | * |
10 | * This code was written by John Ioannidis for BSD/OS in Athens, Greece, | | 10 | * This code was written by John Ioannidis for BSD/OS in Athens, Greece, |
11 | * in November 1995. | | 11 | * in November 1995. |
12 | * | | 12 | * |
13 | * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, | | 13 | * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, |
14 | * by Angelos D. Keromytis. | | 14 | * by Angelos D. Keromytis. |
| @@ -29,27 +29,27 @@ | | | @@ -29,27 +29,27 @@ |
29 | * You may use this code under the GNU public license if you so wish. Please | | 29 | * You may use this code under the GNU public license if you so wish. Please |
30 | * contribute changes back to the authors under this freer than GPL license | | 30 | * contribute changes back to the authors under this freer than GPL license |
31 | * so that we may further the use of strong encryption without limitations to | | 31 | * so that we may further the use of strong encryption without limitations to |
32 | * all. | | 32 | * all. |
33 | * | | 33 | * |
34 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR | | 34 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR |
35 | * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY | | 35 | * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY |
36 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE | | 36 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE |
37 | * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR | | 37 | * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR |
38 | * PURPOSE. | | 38 | * PURPOSE. |
39 | */ | | 39 | */ |
40 | | | 40 | |
41 | #include <sys/cdefs.h> | | 41 | #include <sys/cdefs.h> |
42 | __KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.29 2012/01/25 21:58:10 drochner Exp $"); | | 42 | __KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.29.16.1 2018/03/13 17:47:12 snj Exp $"); |
43 | | | 43 | |
44 | /* | | 44 | /* |
45 | * IPsec input processing. | | 45 | * IPsec input processing. |
46 | */ | | 46 | */ |
47 | | | 47 | |
48 | #include "opt_inet.h" | | 48 | #include "opt_inet.h" |
49 | #ifdef __FreeBSD__ | | 49 | #ifdef __FreeBSD__ |
50 | #include "opt_inet6.h" | | 50 | #include "opt_inet6.h" |
51 | #endif | | 51 | #endif |
52 | #include "opt_ipsec.h" | | 52 | #include "opt_ipsec.h" |
53 | | | 53 | |
54 | #include <sys/param.h> | | 54 | #include <sys/param.h> |
55 | #include <sys/systm.h> | | 55 | #include <sys/systm.h> |
| @@ -322,34 +322,35 @@ ipsec4_common_input_cb(struct mbuf *m, s | | | @@ -322,34 +322,35 @@ ipsec4_common_input_cb(struct mbuf *m, s |
322 | "for SA %s/%08lx\n", | | 322 | "for SA %s/%08lx\n", |
323 | ipsec_address(&sav->sah->saidx.dst), | | 323 | ipsec_address(&sav->sah->saidx.dst), |
324 | (u_long) ntohl(sav->spi))); | | 324 | (u_long) ntohl(sav->spi))); |
325 | IPSEC_ISTAT(sproto, ESP_STAT_HDROPS, AH_STAT_HDROPS, | | 325 | IPSEC_ISTAT(sproto, ESP_STAT_HDROPS, AH_STAT_HDROPS, |
326 | IPCOMP_STAT_HDROPS); | | 326 | IPCOMP_STAT_HDROPS); |
327 | error = ENOBUFS; | | 327 | error = ENOBUFS; |
328 | goto bad; | | 328 | goto bad; |
329 | } | | 329 | } |
330 | | | 330 | |
331 | ip = mtod(m, struct ip *); | | 331 | ip = mtod(m, struct ip *); |
332 | ip->ip_len = htons(m->m_pkthdr.len); | | 332 | ip->ip_len = htons(m->m_pkthdr.len); |
333 | prot = ip->ip_p; | | 333 | prot = ip->ip_p; |
334 | | | 334 | |
| | | 335 | #ifdef notyet |
335 | /* IP-in-IP encapsulation */ | | 336 | /* IP-in-IP encapsulation */ |
336 | if (prot == IPPROTO_IPIP) { | | 337 | if (prot == IPPROTO_IPIP) { |
337 | struct ip ipn; | | 338 | struct ip ipn; |
338 | | | 339 | |
339 | /* ipn will now contain the inner IPv4 header */ | | 340 | /* ipn will now contain the inner IPv4 header */ |
| | | 341 | /* XXX: check m_pkthdr.len */ |
340 | m_copydata(m, ip->ip_hl << 2, sizeof(struct ip), &ipn); | | 342 | m_copydata(m, ip->ip_hl << 2, sizeof(struct ip), &ipn); |
341 | | | 343 | |
342 | #ifdef notyet | | | |
343 | /* XXX PROXY address isn't recorded in SAH */ | | 344 | /* XXX PROXY address isn't recorded in SAH */ |
344 | /* | | 345 | /* |
345 | * Check that the inner source address is the same as | | 346 | * Check that the inner source address is the same as |
346 | * the proxy address, if available. | | 347 | * the proxy address, if available. |
347 | */ | | 348 | */ |
348 | if ((saidx->proxy.sa.sa_family == AF_INET && | | 349 | if ((saidx->proxy.sa.sa_family == AF_INET && |
349 | saidx->proxy.sin.sin_addr.s_addr != | | 350 | saidx->proxy.sin.sin_addr.s_addr != |
350 | INADDR_ANY && | | 351 | INADDR_ANY && |
351 | ipn.ip_src.s_addr != | | 352 | ipn.ip_src.s_addr != |
352 | saidx->proxy.sin.sin_addr.s_addr) || | | 353 | saidx->proxy.sin.sin_addr.s_addr) || |
353 | (saidx->proxy.sa.sa_family != AF_INET && | | 354 | (saidx->proxy.sa.sa_family != AF_INET && |
354 | saidx->proxy.sa.sa_family != 0)) { | | 355 | saidx->proxy.sa.sa_family != 0)) { |
355 | | | 356 | |
| @@ -357,65 +358,64 @@ ipsec4_common_input_cb(struct mbuf *m, s | | | @@ -357,65 +358,64 @@ ipsec4_common_input_cb(struct mbuf *m, s |
357 | "source address %s doesn't correspond to " | | 358 | "source address %s doesn't correspond to " |
358 | "expected proxy source %s, SA %s/%08lx\n", | | 359 | "expected proxy source %s, SA %s/%08lx\n", |
359 | inet_ntoa4(ipn.ip_src), | | 360 | inet_ntoa4(ipn.ip_src), |
360 | ipsp_address(saidx->proxy), | | 361 | ipsp_address(saidx->proxy), |
361 | ipsp_address(saidx->dst), | | 362 | ipsp_address(saidx->dst), |
362 | (u_long) ntohl(sav->spi))); | | 363 | (u_long) ntohl(sav->spi))); |
363 | | | 364 | |
364 | IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, | | 365 | IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, |
365 | AH_STAT_PDROPS, | | 366 | AH_STAT_PDROPS, |
366 | IPCOMP_STAT_PDROPS); | | 367 | IPCOMP_STAT_PDROPS); |
367 | error = EACCES; | | 368 | error = EACCES; |
368 | goto bad; | | 369 | goto bad; |
369 | } | | 370 | } |
370 | #endif /*XXX*/ | | | |
371 | } | | 371 | } |
372 | #if INET6 | | 372 | #if INET6 |
373 | /* IPv6-in-IP encapsulation. */ | | 373 | /* IPv6-in-IP encapsulation. */ |
374 | if (prot == IPPROTO_IPV6) { | | 374 | if (prot == IPPROTO_IPV6) { |
375 | struct ip6_hdr ip6n; | | 375 | struct ip6_hdr ip6n; |
376 | | | 376 | |
377 | /* ip6n will now contain the inner IPv6 header. */ | | 377 | /* ip6n will now contain the inner IPv6 header. */ |
| | | 378 | /* XXX: check m_pkthdr.len */ |
378 | m_copydata(m, ip->ip_hl << 2, sizeof(struct ip6_hdr), &ip6n); | | 379 | m_copydata(m, ip->ip_hl << 2, sizeof(struct ip6_hdr), &ip6n); |
379 | | | 380 | |
380 | #ifdef notyet | | | |
381 | /* | | 381 | /* |
382 | * Check that the inner source address is the same as | | 382 | * Check that the inner source address is the same as |
383 | * the proxy address, if available. | | 383 | * the proxy address, if available. |
384 | */ | | 384 | */ |
385 | if ((saidx->proxy.sa.sa_family == AF_INET6 && | | 385 | if ((saidx->proxy.sa.sa_family == AF_INET6 && |
386 | !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) && | | 386 | !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) && |
387 | !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src, | | 387 | !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src, |
388 | &saidx->proxy.sin6.sin6_addr)) || | | 388 | &saidx->proxy.sin6.sin6_addr)) || |
389 | (saidx->proxy.sa.sa_family != AF_INET6 && | | 389 | (saidx->proxy.sa.sa_family != AF_INET6 && |
390 | saidx->proxy.sa.sa_family != 0)) { | | 390 | saidx->proxy.sa.sa_family != 0)) { |
391 | | | 391 | |
392 | DPRINTF(("ipsec4_common_input_cb: inner " | | 392 | DPRINTF(("ipsec4_common_input_cb: inner " |
393 | "source address %s doesn't correspond to " | | 393 | "source address %s doesn't correspond to " |
394 | "expected proxy source %s, SA %s/%08lx\n", | | 394 | "expected proxy source %s, SA %s/%08lx\n", |
395 | ip6_sprintf(&ip6n.ip6_src), | | 395 | ip6_sprintf(&ip6n.ip6_src), |
396 | ipsec_address(&saidx->proxy), | | 396 | ipsec_address(&saidx->proxy), |
397 | ipsec_address(&saidx->dst), | | 397 | ipsec_address(&saidx->dst), |
398 | (u_long) ntohl(sav->spi))); | | 398 | (u_long) ntohl(sav->spi))); |
399 | | | 399 | |
400 | IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, | | 400 | IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, |
401 | AH_STAT_PDROPS, | | 401 | AH_STAT_PDROPS, |
402 | IPCOMP_STAT_PDROPS); | | 402 | IPCOMP_STAT_PDROPS); |
403 | error = EACCES; | | 403 | error = EACCES; |
404 | goto bad; | | 404 | goto bad; |
405 | } | | 405 | } |
406 | #endif /*XXX*/ | | | |
407 | } | | 406 | } |
408 | #endif /* INET6 */ | | 407 | #endif /* INET6 */ |
| | | 408 | #endif /* notyet */ |
409 | | | 409 | |
410 | /* | | 410 | /* |
411 | * Record what we've done to the packet (under what SA it was | | 411 | * Record what we've done to the packet (under what SA it was |
412 | * processed). If we've been passed an mtag, it means the packet | | 412 | * processed). If we've been passed an mtag, it means the packet |
413 | * was already processed by an ethernet/crypto combo card and | | 413 | * was already processed by an ethernet/crypto combo card and |
414 | * thus has a tag attached with all the right information, but | | 414 | * thus has a tag attached with all the right information, but |
415 | * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to | | 415 | * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to |
416 | * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type. | | 416 | * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type. |
417 | */ | | 417 | */ |
418 | if (mt == NULL && sproto != IPPROTO_IPCOMP) { | | 418 | if (mt == NULL && sproto != IPPROTO_IPCOMP) { |
419 | mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, | | 419 | mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, |
420 | sizeof(struct tdb_ident), M_NOWAIT); | | 420 | sizeof(struct tdb_ident), M_NOWAIT); |
421 | if (mtag == NULL) { | | 421 | if (mtag == NULL) { |
| @@ -641,96 +641,95 @@ ipsec6_common_input_cb(struct mbuf *m, s | | | @@ -641,96 +641,95 @@ ipsec6_common_input_cb(struct mbuf *m, s |
641 | | | 641 | |
642 | IPSEC_ISTAT(sproto, ESP_STAT_HDROPS, AH_STAT_HDROPS, | | 642 | IPSEC_ISTAT(sproto, ESP_STAT_HDROPS, AH_STAT_HDROPS, |
643 | IPCOMP_STAT_HDROPS); | | 643 | IPCOMP_STAT_HDROPS); |
644 | error = EACCES; | | 644 | error = EACCES; |
645 | goto bad; | | 645 | goto bad; |
646 | } | | 646 | } |
647 | | | 647 | |
648 | ip6 = mtod(m, struct ip6_hdr *); | | 648 | ip6 = mtod(m, struct ip6_hdr *); |
649 | ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); | | 649 | ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); |
650 | | | 650 | |
651 | /* Save protocol */ | | 651 | /* Save protocol */ |
652 | m_copydata(m, protoff, 1, &prot); | | 652 | m_copydata(m, protoff, 1, &prot); |
653 | | | 653 | |
| | | 654 | #ifdef notyet |
654 | #ifdef INET | | 655 | #ifdef INET |
655 | /* IP-in-IP encapsulation */ | | 656 | /* IP-in-IP encapsulation */ |
656 | if (prot == IPPROTO_IPIP) { | | 657 | if (prot == IPPROTO_IPIP) { |
657 | struct ip ipn; | | 658 | struct ip ipn; |
658 | | | 659 | |
659 | /* ipn will now contain the inner IPv4 header */ | | 660 | /* ipn will now contain the inner IPv4 header */ |
| | | 661 | /* XXX: check m_pkthdr.len */ |
660 | m_copydata(m, skip, sizeof(struct ip), &ipn); | | 662 | m_copydata(m, skip, sizeof(struct ip), &ipn); |
661 | | | 663 | |
662 | #ifdef notyet | | | |
663 | /* | | 664 | /* |
664 | * Check that the inner source address is the same as | | 665 | * Check that the inner source address is the same as |
665 | * the proxy address, if available. | | 666 | * the proxy address, if available. |
666 | */ | | 667 | */ |
667 | if ((saidx->proxy.sa.sa_family == AF_INET && | | 668 | if ((saidx->proxy.sa.sa_family == AF_INET && |
668 | saidx->proxy.sin.sin_addr.s_addr != INADDR_ANY && | | 669 | saidx->proxy.sin.sin_addr.s_addr != INADDR_ANY && |
669 | ipn.ip_src.s_addr != saidx->proxy.sin.sin_addr.s_addr) || | | 670 | ipn.ip_src.s_addr != saidx->proxy.sin.sin_addr.s_addr) || |
670 | (saidx->proxy.sa.sa_family != AF_INET && | | 671 | (saidx->proxy.sa.sa_family != AF_INET && |
671 | saidx->proxy.sa.sa_family != 0)) { | | 672 | saidx->proxy.sa.sa_family != 0)) { |
672 | | | 673 | |
673 | DPRINTF(("ipsec6_common_input_cb: inner " | | 674 | DPRINTF(("ipsec6_common_input_cb: inner " |
674 | "source address %s doesn't correspond to " | | 675 | "source address %s doesn't correspond to " |
675 | "expected proxy source %s, SA %s/%08lx\n", | | 676 | "expected proxy source %s, SA %s/%08lx\n", |
676 | inet_ntoa4(ipn.ip_src), | | 677 | inet_ntoa4(ipn.ip_src), |
677 | ipsec_address(&saidx->proxy), | | 678 | ipsec_address(&saidx->proxy), |
678 | ipsec_address(&saidx->dst), | | 679 | ipsec_address(&saidx->dst), |
679 | (u_long) ntohl(sav->spi))); | | 680 | (u_long) ntohl(sav->spi))); |
680 | | | 681 | |
681 | IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, | | 682 | IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, |
682 | AH_STAT_PDROPS, IPCOMP_STAT_PDROPS); | | 683 | AH_STAT_PDROPS, IPCOMP_STAT_PDROPS); |
683 | error = EACCES; | | 684 | error = EACCES; |
684 | goto bad; | | 685 | goto bad; |
685 | } | | 686 | } |
686 | #endif /*XXX*/ | | | |
687 | } | | 687 | } |
688 | #endif /* INET */ | | 688 | #endif /* INET */ |
689 | | | | |
690 | /* IPv6-in-IP encapsulation */ | | 689 | /* IPv6-in-IP encapsulation */ |
691 | if (prot == IPPROTO_IPV6) { | | 690 | if (prot == IPPROTO_IPV6) { |
692 | struct ip6_hdr ip6n; | | 691 | struct ip6_hdr ip6n; |
693 | | | 692 | |
694 | /* ip6n will now contain the inner IPv6 header. */ | | 693 | /* ip6n will now contain the inner IPv6 header. */ |
| | | 694 | /* XXX: check m_pkthdr.len */ |
695 | m_copydata(m, skip, sizeof(struct ip6_hdr), &ip6n); | | 695 | m_copydata(m, skip, sizeof(struct ip6_hdr), &ip6n); |
696 | | | 696 | |
697 | #ifdef notyet | | | |
698 | /* | | 697 | /* |
699 | * Check that the inner source address is the same as | | 698 | * Check that the inner source address is the same as |
700 | * the proxy address, if available. | | 699 | * the proxy address, if available. |
701 | */ | | 700 | */ |
702 | if ((saidx->proxy.sa.sa_family == AF_INET6 && | | 701 | if ((saidx->proxy.sa.sa_family == AF_INET6 && |
703 | !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) && | | 702 | !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) && |
704 | !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src, | | 703 | !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src, |
705 | &saidx->proxy.sin6.sin6_addr)) || | | 704 | &saidx->proxy.sin6.sin6_addr)) || |
706 | (saidx->proxy.sa.sa_family != AF_INET6 && | | 705 | (saidx->proxy.sa.sa_family != AF_INET6 && |
707 | saidx->proxy.sa.sa_family != 0)) { | | 706 | saidx->proxy.sa.sa_family != 0)) { |
708 | | | 707 | |
709 | DPRINTF(("ipsec6_common_input_cb: inner " | | 708 | DPRINTF(("ipsec6_common_input_cb: inner " |
710 | "source address %s doesn't correspond to " | | 709 | "source address %s doesn't correspond to " |
711 | "expected proxy source %s, SA %s/%08lx\n", | | 710 | "expected proxy source %s, SA %s/%08lx\n", |
712 | ip6_sprintf(&ip6n.ip6_src), | | 711 | ip6_sprintf(&ip6n.ip6_src), |
713 | ipsec_address(&saidx->proxy), | | 712 | ipsec_address(&saidx->proxy), |
714 | ipsec_address(&saidx->dst), | | 713 | ipsec_address(&saidx->dst), |
715 | (u_long) ntohl(sav->spi))); | | 714 | (u_long) ntohl(sav->spi))); |
716 | | | 715 | |
717 | IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, | | 716 | IPSEC_ISTAT(sproto, ESP_STAT_PDROPS, |
718 | AH_STAT_PDROPS, IPCOMP_STAT_PDROPS); | | 717 | AH_STAT_PDROPS, IPCOMP_STAT_PDROPS); |
719 | error = EACCES; | | 718 | error = EACCES; |
720 | goto bad; | | 719 | goto bad; |
721 | } | | 720 | } |
722 | #endif /*XXX*/ | | | |
723 | } | | 721 | } |
| | | 722 | #endif /* notyet */ |
724 | | | 723 | |
725 | /* | | 724 | /* |
726 | * Record what we've done to the packet (under what SA it was | | 725 | * Record what we've done to the packet (under what SA it was |
727 | * processed). If we've been passed an mtag, it means the packet | | 726 | * processed). If we've been passed an mtag, it means the packet |
728 | * was already processed by an ethernet/crypto combo card and | | 727 | * was already processed by an ethernet/crypto combo card and |
729 | * thus has a tag attached with all the right information, but | | 728 | * thus has a tag attached with all the right information, but |
730 | * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to | | 729 | * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to |
731 | * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type. | | 730 | * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type. |
732 | */ | | 731 | */ |
733 | if (mt == NULL && sproto != IPPROTO_IPCOMP) { | | 732 | if (mt == NULL && sproto != IPPROTO_IPCOMP) { |
734 | mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, | | 733 | mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, |
735 | sizeof(struct tdb_ident), M_NOWAIT); | | 734 | sizeof(struct tdb_ident), M_NOWAIT); |
736 | if (mtag == NULL) { | | 735 | if (mtag == NULL) { |