Tue Mar 13 17:47:13 2018 UTC ()
Pull up following revision(s) (requested by maxv in ticket #1536):
	sys/netipsec/ipsec_input.c: 1.57-1.58
Extend these #ifdef notyet. The m_copydata's in these branches are wrong,
we are not guaranteed to have enough room for another struct ip, and we
may crash here. Triggerable remotely, but after authentication, by sending
an AH packet that has a one-byte-sized IPIP payload.
--
Argh, in my previous commit in this file I forgot to fix the IPv6
entry point; apply the same fix there.


(snj)
diff -r1.29 -r1.29.16.1 src/sys/netipsec/ipsec_input.c

cvs diff -r1.29 -r1.29.16.1 src/sys/netipsec/ipsec_input.c (expand / switch to unified diff)

--- src/sys/netipsec/ipsec_input.c 2012/01/25 21:58:10 1.29
+++ src/sys/netipsec/ipsec_input.c 2018/03/13 17:47:12 1.29.16.1
@@ -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) {