diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libssl/ssl_tlsext.c | 94 | ||||
-rw-r--r-- | src/lib/libssl/ssl_tlsext.h | 3 |
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 | */ | ||
682 | int | ||
683 | tlsext_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 | |||
675 | int | 723 | int |
676 | tlsext_sni_server_parse(SSL *s, CBS *cbs, int *alert) | 724 | tlsext_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); | |||
58 | int tlsext_sni_server_needs(SSL *s); | 58 | int tlsext_sni_server_needs(SSL *s); |
59 | int tlsext_sni_server_build(SSL *s, CBB *cbb); | 59 | int tlsext_sni_server_build(SSL *s, CBB *cbb); |
60 | int tlsext_sni_server_parse(SSL *s, CBS *cbs, int *alert); | 60 | int tlsext_sni_server_parse(SSL *s, CBS *cbs, int *alert); |
61 | int tlsext_sni_is_valid_hostname(CBS *cbs); | ||
61 | 62 | ||
62 | int tlsext_supportedgroups_client_needs(SSL *s); | 63 | int tlsext_supportedgroups_client_needs(SSL *s); |
63 | int tlsext_supportedgroups_client_build(SSL *s, CBB *cbb); | 64 | int tlsext_supportedgroups_client_build(SSL *s, CBB *cbb); |