summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2021-11-01 16:37:17 +0000
committerjsing <>2021-11-01 16:37:17 +0000
commite7fdd9de6f9def3087be965eae19cc67a8da47dd (patch)
treea3c71ae24931ccb437c44d27f9d1ed00b1095976 /src
parenta70e39e12d0c283caba589c494e6ab2aad779422 (diff)
downloadopenbsd-e7fdd9de6f9def3087be965eae19cc67a8da47dd.tar.gz
openbsd-e7fdd9de6f9def3087be965eae19cc67a8da47dd.tar.bz2
openbsd-e7fdd9de6f9def3087be965eae19cc67a8da47dd.zip
Improve SNI hostname validation.
For some time now we've validated the hostname provided to the server in the SNI extension. Per RFC 6066, an IP literal is invalid as a hostname - the current code rejects IPv6 literals, but allows IPv4 literals through. Improve this check to explicitly detect both IPv4 and IPv6 literals. Some software has been historically known to include IP literals in SNI, so rather than rejecting this outright (and failing with a decode error), pretend that the SNI extension does not exist (such that we do not break some older clients). ok inoguchi@ tb@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libssl/ssl_tlsext.c59
-rw-r--r--src/lib/libssl/ssl_tlsext.h4
2 files changed, 54 insertions, 9 deletions
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c
index d8143ce1be..3da8ebc46c 100644
--- a/src/lib/libssl/ssl_tlsext.c
+++ b/src/lib/libssl/ssl_tlsext.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_tlsext.c,v 1.100 2021/10/25 10:01:46 jsing Exp $ */ 1/* $OpenBSD: ssl_tlsext.c,v 1.101 2021/11/01 16:37:17 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -17,6 +17,11 @@
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */ 18 */
19 19
20#include <sys/socket.h>
21
22#include <arpa/inet.h>
23#include <netinet/in.h>
24
20#include <ctype.h> 25#include <ctype.h>
21 26
22#include <openssl/ocsp.h> 27#include <openssl/ocsp.h>
@@ -673,6 +678,29 @@ tlsext_sni_client_build(SSL *s, uint16_t msg_type, CBB *cbb)
673 return 1; 678 return 1;
674} 679}
675 680
681static int
682tlsext_sni_is_ip_literal(CBS *cbs, int *is_ip)
683{
684 union {
685 struct in_addr ip4;
686 struct in6_addr ip6;
687 } addrbuf;
688 char *hostname = NULL;
689
690 *is_ip = 0;
691
692 if (!CBS_strdup(cbs, &hostname))
693 return 0;
694
695 if (inet_pton(AF_INET, hostname, &addrbuf) == 1 ||
696 inet_pton(AF_INET6, hostname, &addrbuf) == 1)
697 *is_ip = 1;
698
699 free(hostname);
700
701 return 1;
702}
703
676/* 704/*
677 * Validate that the CBS contains only a hostname consisting of RFC 5890 705 * Validate that the CBS contains only a hostname consisting of RFC 5890
678 * compliant A-labels (see RFC 6066 section 3). Not a complete check 706 * compliant A-labels (see RFC 6066 section 3). Not a complete check
@@ -680,7 +708,7 @@ tlsext_sni_client_build(SSL *s, uint16_t msg_type, CBB *cbb)
680 * correct structure and character set. 708 * correct structure and character set.
681 */ 709 */
682int 710int
683tlsext_sni_is_valid_hostname(CBS *cbs) 711tlsext_sni_is_valid_hostname(CBS *cbs, int *is_ip)
684{ 712{
685 uint8_t prev, c = 0; 713 uint8_t prev, c = 0;
686 int component = 0; 714 int component = 0;
@@ -691,7 +719,13 @@ tlsext_sni_is_valid_hostname(CBS *cbs)
691 if (CBS_len(&hostname) > TLSEXT_MAXLEN_host_name) 719 if (CBS_len(&hostname) > TLSEXT_MAXLEN_host_name)
692 return 0; 720 return 0;
693 721
694 while(CBS_len(&hostname) > 0) { 722 /* An IP literal is invalid as a host name (RFC 6066 section 3). */
723 if (!tlsext_sni_is_ip_literal(&hostname, is_ip))
724 return 0;
725 if (*is_ip)
726 return 0;
727
728 while (CBS_len(&hostname) > 0) {
695 prev = c; 729 prev = c;
696 if (!CBS_get_u8(&hostname, &c)) 730 if (!CBS_get_u8(&hostname, &c))
697 return 0; 731 return 0;
@@ -727,12 +761,14 @@ tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert)
727{ 761{
728 CBS server_name_list, host_name; 762 CBS server_name_list, host_name;
729 uint8_t name_type; 763 uint8_t name_type;
764 int is_ip;
730 765
731 if (!CBS_get_u16_length_prefixed(cbs, &server_name_list)) 766 if (!CBS_get_u16_length_prefixed(cbs, &server_name_list))
732 goto err; 767 goto err;
733 768
734 if (!CBS_get_u8(&server_name_list, &name_type)) 769 if (!CBS_get_u8(&server_name_list, &name_type))
735 goto err; 770 goto err;
771
736 /* 772 /*
737 * RFC 6066 section 3, only one type (host_name) is specified. 773 * RFC 6066 section 3, only one type (host_name) is specified.
738 * We do not tolerate unknown types, neither does BoringSSL. 774 * We do not tolerate unknown types, neither does BoringSSL.
@@ -743,17 +779,25 @@ tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert)
743 goto err; 779 goto err;
744 } 780 }
745 781
746
747 if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name))
748 goto err;
749 /* 782 /*
750 * RFC 6066 section 3 specifies a host name must be at least 1 byte 783 * RFC 6066 section 3 specifies a host name must be at least 1 byte
751 * so 0 length is a decode error. 784 * so 0 length is a decode error.
752 */ 785 */
786 if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name))
787 goto err;
753 if (CBS_len(&host_name) < 1) 788 if (CBS_len(&host_name) < 1)
754 goto err; 789 goto err;
755 790
756 if (!tlsext_sni_is_valid_hostname(&host_name)) { 791 if (!tlsext_sni_is_valid_hostname(&host_name, &is_ip)) {
792 /*
793 * Various pieces of software have been known to set the SNI
794 * host name to an IP address, even though that violates the
795 * RFC. If this is the case, pretend the SNI extension does
796 * not exist.
797 */
798 if (is_ip)
799 goto done;
800
757 *alert = SSL_AD_ILLEGAL_PARAMETER; 801 *alert = SSL_AD_ILLEGAL_PARAMETER;
758 goto err; 802 goto err;
759 } 803 }
@@ -777,6 +821,7 @@ tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert)
777 } 821 }
778 } 822 }
779 823
824 done:
780 /* 825 /*
781 * RFC 6066 section 3 forbids multiple host names with the same type, 826 * RFC 6066 section 3 forbids multiple host names with the same type,
782 * therefore we allow only one entry. 827 * therefore we allow only one entry.
diff --git a/src/lib/libssl/ssl_tlsext.h b/src/lib/libssl/ssl_tlsext.h
index 8e0742aa2c..b4c135fdf1 100644
--- a/src/lib/libssl/ssl_tlsext.h
+++ b/src/lib/libssl/ssl_tlsext.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_tlsext.h,v 1.26 2020/10/11 01:13:04 guenther Exp $ */ 1/* $OpenBSD: ssl_tlsext.h,v 1.27 2021/11/01 16:37:17 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -60,7 +60,7 @@ int tlsext_sni_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert);
60int tlsext_sni_server_needs(SSL *s, uint16_t msg_type); 60int tlsext_sni_server_needs(SSL *s, uint16_t msg_type);
61int tlsext_sni_server_build(SSL *s, uint16_t msg_type, CBB *cbb); 61int tlsext_sni_server_build(SSL *s, uint16_t msg_type, CBB *cbb);
62int tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); 62int tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert);
63int tlsext_sni_is_valid_hostname(CBS *cbs); 63int tlsext_sni_is_valid_hostname(CBS *cbs, int *is_ip);
64 64
65int tlsext_supportedgroups_client_needs(SSL *s, uint16_t msg_type); 65int tlsext_supportedgroups_client_needs(SSL *s, uint16_t msg_type);
66int tlsext_supportedgroups_client_build(SSL *s, uint16_t msg_type, CBB *cbb); 66int tlsext_supportedgroups_client_build(SSL *s, uint16_t msg_type, CBB *cbb);