summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libssl/ssl_tlsext.c94
-rw-r--r--src/lib/libssl/ssl_tlsext.h3
2 files changed, 80 insertions, 17 deletions
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c
index f5343c81ab..2184e65a2c 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.71 2020/05/23 08:47:19 tb Exp $ */ 1/* $OpenBSD: ssl_tlsext.c,v 1.72 2020/05/23 17:13:24 beck 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>
@@ -18,6 +18,7 @@
18 */ 18 */
19 19
20#include <openssl/ocsp.h> 20#include <openssl/ocsp.h>
21#include <ctype.h>
21 22
22#include "ssl_locl.h" 23#include "ssl_locl.h"
23 24
@@ -672,6 +673,53 @@ tlsext_sni_client_build(SSL *s, CBB *cbb)
672 return 1; 673 return 1;
673} 674}
674 675
676/*
677 * Does the CBS contain only of a hostname consisting of RFC 5890
678 * compliant A-labels? (see RFC 6066 section 3). Not a complete check
679 * since we don't parse punycode to verify its validity but limits to
680 * correct structure and character set.
681 */
682int
683tlsext_sni_is_valid_hostname(CBS *cbs)
684{
685 uint8_t prev, c = 0;
686 int component = 0;
687 CBS hostname;
688
689 if (CBS_len(cbs) > TLSEXT_MAXLEN_host_name)
690 return 0;
691
692 CBS_dup(cbs, &hostname);
693 while(CBS_len(&hostname) > 0) {
694 prev = c;
695 if (!CBS_get_u8(&hostname, &c))
696 return 0;
697 /* Everything has to be ASCII, with no NUL byte. */
698 if (!isascii(c) || c == '\0')
699 return 0;
700 /* It must be alphanumeric, a '-', or a '.' */
701 if (!(isalnum(c) || c == '-' || c == '.'))
702 return 0;
703 /* '-' and '.' must not start a component or be at the end. */
704 if (component == 0 || CBS_len(&hostname) == 0) {
705 if (c == '-' || c == '.')
706 return 0;
707 }
708 if (c == '.') {
709 /* Components can not end with a dash. */
710 if (prev == '-')
711 return 0;
712 /* Start new component */
713 component = 0;
714 continue;
715 }
716 /* Components must be 63 chars or less. */
717 if (++component > 63)
718 return 0;
719 }
720 return 1;
721}
722
675int 723int
676tlsext_sni_server_parse(SSL *s, CBS *cbs, int *alert) 724tlsext_sni_server_parse(SSL *s, CBS *cbs, int *alert)
677{ 725{
@@ -681,52 +729,66 @@ tlsext_sni_server_parse(SSL *s, CBS *cbs, int *alert)
681 if (!CBS_get_u16_length_prefixed(cbs, &server_name_list)) 729 if (!CBS_get_u16_length_prefixed(cbs, &server_name_list))
682 goto err; 730 goto err;
683 731
684 /*
685 * RFC 6066 section 3 forbids multiple host names with the same type.
686 * Additionally, only one type (host_name) is specified.
687 */
688 if (!CBS_get_u8(&server_name_list, &name_type)) 732 if (!CBS_get_u8(&server_name_list, &name_type))
689 goto err; 733 goto err;
690 if (name_type != TLSEXT_NAMETYPE_host_name) 734 /*
735 * RFC 6066 section 3, only one type (host_name) is specified.
736 * We do not tolerate unknown types, neither does BoringSSL.
737 * other implementations appear more tolerant.
738 */
739 if (name_type != TLSEXT_NAMETYPE_host_name) {
740 *alert = SSL3_AD_ILLEGAL_PARAMETER;
691 goto err; 741 goto err;
742 }
743
692 744
693 if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name)) 745 if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name))
694 goto err; 746 goto err;
695 if (CBS_len(&host_name) == 0 || 747 /*
696 CBS_len(&host_name) > TLSEXT_MAXLEN_host_name || 748 * RFC 6066 section 3 specifies a host name must be at least 1 byte
697 CBS_contains_zero_byte(&host_name)) { 749 * so 0 length is a decode error.
698 *alert = TLS1_AD_UNRECOGNIZED_NAME; 750 */
699 return 0; 751 if (CBS_len(&host_name) == 0)
752 goto err;
753
754 if (!tlsext_sni_is_valid_hostname(&host_name)) {
755 *alert = SSL3_AD_ILLEGAL_PARAMETER;
756 goto err;
700 } 757 }
701 758
702 if (s->internal->hit || S3I(s)->hs_tls13.hrr) { 759 if (s->internal->hit || S3I(s)->hs_tls13.hrr) {
703 if (s->session->tlsext_hostname == NULL) { 760 if (s->session->tlsext_hostname == NULL) {
704 *alert = TLS1_AD_UNRECOGNIZED_NAME; 761 *alert = TLS1_AD_UNRECOGNIZED_NAME;
705 return 0; 762 goto err;
706 } 763 }
707 if (!CBS_mem_equal(&host_name, s->session->tlsext_hostname, 764 if (!CBS_mem_equal(&host_name, s->session->tlsext_hostname,
708 strlen(s->session->tlsext_hostname))) { 765 strlen(s->session->tlsext_hostname))) {
709 *alert = TLS1_AD_UNRECOGNIZED_NAME; 766 *alert = TLS1_AD_UNRECOGNIZED_NAME;
710 return 0; 767 goto err;
711 } 768 }
712 } else { 769 } else {
713 if (s->session->tlsext_hostname != NULL) 770 if (s->session->tlsext_hostname != NULL)
714 goto err; 771 goto err;
715 if (!CBS_strdup(&host_name, &s->session->tlsext_hostname)) { 772 if (!CBS_strdup(&host_name, &s->session->tlsext_hostname)) {
716 *alert = TLS1_AD_INTERNAL_ERROR; 773 *alert = TLS1_AD_INTERNAL_ERROR;
717 return 0; 774 goto err;
718 } 775 }
719 } 776 }
720 777
721 if (CBS_len(&server_name_list) != 0) 778 /*
779 * RFC 6066 section 3 forbids multiple host names with the same type,
780 * therefore we allow only one entry.
781 */
782 if (CBS_len(&server_name_list) != 0) {
783 *alert = SSL3_AD_ILLEGAL_PARAMETER;
722 goto err; 784 goto err;
785 }
723 if (CBS_len(cbs) != 0) 786 if (CBS_len(cbs) != 0)
724 goto err; 787 goto err;
725 788
726 return 1; 789 return 1;
727 790
728 err: 791 err:
729 *alert = SSL_AD_DECODE_ERROR;
730 return 0; 792 return 0;
731} 793}
732 794
diff --git a/src/lib/libssl/ssl_tlsext.h b/src/lib/libssl/ssl_tlsext.h
index aa40f6b1a6..15e0257e63 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.22 2020/01/25 12:58:27 jsing Exp $ */ 1/* $OpenBSD: ssl_tlsext.h,v 1.23 2020/05/23 17:13:24 beck 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>
@@ -58,6 +58,7 @@ int tlsext_sni_client_parse(SSL *s, CBS *cbs, int *alert);
58int tlsext_sni_server_needs(SSL *s); 58int tlsext_sni_server_needs(SSL *s);
59int tlsext_sni_server_build(SSL *s, CBB *cbb); 59int tlsext_sni_server_build(SSL *s, CBB *cbb);
60int tlsext_sni_server_parse(SSL *s, CBS *cbs, int *alert); 60int tlsext_sni_server_parse(SSL *s, CBS *cbs, int *alert);
61int tlsext_sni_is_valid_hostname(CBS *cbs);
61 62
62int tlsext_supportedgroups_client_needs(SSL *s); 63int tlsext_supportedgroups_client_needs(SSL *s);
63int tlsext_supportedgroups_client_build(SSL *s, CBB *cbb); 64int tlsext_supportedgroups_client_build(SSL *s, CBB *cbb);