-/* $OpenBSD: ssl_tlsext.c,v 1.100 2021/10/25 10:01:46 jsing Exp $ */
+/* $OpenBSD: ssl_tlsext.c,v 1.101 2021/11/01 16:37:17 jsing Exp $ */
/*
* Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
#include <ctype.h>
#include <openssl/ocsp.h>
return 1;
}
+static int
+tlsext_sni_is_ip_literal(CBS *cbs, int *is_ip)
+{
+ union {
+ struct in_addr ip4;
+ struct in6_addr ip6;
+ } addrbuf;
+ char *hostname = NULL;
+
+ *is_ip = 0;
+
+ if (!CBS_strdup(cbs, &hostname))
+ return 0;
+
+ if (inet_pton(AF_INET, hostname, &addrbuf) == 1 ||
+ inet_pton(AF_INET6, hostname, &addrbuf) == 1)
+ *is_ip = 1;
+
+ free(hostname);
+
+ return 1;
+}
+
/*
* Validate that the CBS contains only a hostname consisting of RFC 5890
* compliant A-labels (see RFC 6066 section 3). Not a complete check
* correct structure and character set.
*/
int
-tlsext_sni_is_valid_hostname(CBS *cbs)
+tlsext_sni_is_valid_hostname(CBS *cbs, int *is_ip)
{
uint8_t prev, c = 0;
int component = 0;
if (CBS_len(&hostname) > TLSEXT_MAXLEN_host_name)
return 0;
- while(CBS_len(&hostname) > 0) {
+ /* An IP literal is invalid as a host name (RFC 6066 section 3). */
+ if (!tlsext_sni_is_ip_literal(&hostname, is_ip))
+ return 0;
+ if (*is_ip)
+ return 0;
+
+ while (CBS_len(&hostname) > 0) {
prev = c;
if (!CBS_get_u8(&hostname, &c))
return 0;
{
CBS server_name_list, host_name;
uint8_t name_type;
+ int is_ip;
if (!CBS_get_u16_length_prefixed(cbs, &server_name_list))
goto err;
if (!CBS_get_u8(&server_name_list, &name_type))
goto err;
+
/*
* RFC 6066 section 3, only one type (host_name) is specified.
* We do not tolerate unknown types, neither does BoringSSL.
goto err;
}
-
- if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name))
- goto err;
/*
* RFC 6066 section 3 specifies a host name must be at least 1 byte
* so 0 length is a decode error.
*/
+ if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name))
+ goto err;
if (CBS_len(&host_name) < 1)
goto err;
- if (!tlsext_sni_is_valid_hostname(&host_name)) {
+ if (!tlsext_sni_is_valid_hostname(&host_name, &is_ip)) {
+ /*
+ * Various pieces of software have been known to set the SNI
+ * host name to an IP address, even though that violates the
+ * RFC. If this is the case, pretend the SNI extension does
+ * not exist.
+ */
+ if (is_ip)
+ goto done;
+
*alert = SSL_AD_ILLEGAL_PARAMETER;
goto err;
}
}
}
+ done:
/*
* RFC 6066 section 3 forbids multiple host names with the same type,
* therefore we allow only one entry.
-/* $OpenBSD: ssl_tlsext.h,v 1.26 2020/10/11 01:13:04 guenther Exp $ */
+/* $OpenBSD: ssl_tlsext.h,v 1.27 2021/11/01 16:37:17 jsing Exp $ */
/*
* Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
int tlsext_sni_server_needs(SSL *s, uint16_t msg_type);
int tlsext_sni_server_build(SSL *s, uint16_t msg_type, CBB *cbb);
int tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert);
-int tlsext_sni_is_valid_hostname(CBS *cbs);
+int tlsext_sni_is_valid_hostname(CBS *cbs, int *is_ip);
int tlsext_supportedgroups_client_needs(SSL *s, uint16_t msg_type);
int tlsext_supportedgroups_client_build(SSL *s, uint16_t msg_type, CBB *cbb);