From e2b5c691afafbd591deb495cd7d47ed0acfd3ce5 Mon Sep 17 00:00:00 2001 From: Alexey Sokolov Date: Mon, 2 Apr 2018 11:35:45 +0100 Subject: [PATCH] Support IP while verifying SSL certificates --- src/SSLVerifyHost.cpp | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/SSLVerifyHost.cpp b/src/SSLVerifyHost.cpp index 30d9487c..c1f515d8 100644 --- a/src/SSLVerifyHost.cpp +++ b/src/SSLVerifyHost.cpp @@ -16,6 +16,7 @@ #include #include +#include #ifdef HAVE_LIBSSL #if defined(OPENSSL_VERSION_NUMBER) && !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100007 @@ -369,6 +370,14 @@ static HostnameValidationResult matches_subject_alternative_name( } san_names_nb = sk_GENERAL_NAME_num(san_names); + // Precompute binary representation of hostname in case if it's IP address. + // Not the other way around, because there can be multiple text + // representation of the same IP. + char ip4[4] = {}; + char ip6[16] = {}; + const int ip4try = inet_pton(AF_INET, hostname, ip4); + const int ip6try = inet_pton(AF_INET6, hostname, ip6); + // Check each name within the extension for (i = 0; i < san_names_nb; i++) { const GENERAL_NAME* current_name = sk_GENERAL_NAME_value(san_names, i); @@ -381,16 +390,40 @@ static HostnameValidationResult matches_subject_alternative_name( // Make sure there isn't an embedded NUL character in the DNS name if (ASN1_STRING_length(current_name->d.dNSName) != - static_cast(strlen(dns_name))) { + static_cast(strnlen( + dns_name, ASN1_STRING_length(current_name->d.dNSName)))) { + DEBUG("SSLVerifyHost: embedded null in DNS SAN"); result = MalformedCertificate; break; } else { // Compare expected hostname with the DNS name - DEBUG("SSLVerifyHost: Found SAN " << dns_name); + DEBUG("SSLVerifyHost: Found DNS SAN " << dns_name); if (ZNC_Curl::Curl_cert_hostcheck(dns_name, hostname)) { result = MatchFound; break; } } + } else if (current_name->type == GEN_IPADD) { + CString ip(reinterpret_cast( + ASN1_STRING_get0_data(current_name->d.iPAddress)), + ASN1_STRING_length(current_name->d.iPAddress)); + DEBUG("SSLVerifyHost: Found IP SAN " + << ip.Escape_n(CString::EHEXCOLON)); + if (ip4try && ASN1_STRING_length(current_name->d.iPAddress) == 4) { + if (memcmp(ip4, + ASN1_STRING_get0_data(current_name->d.iPAddress), + 4) == 0) { + result = MatchFound; + break; + } + } else if (ip6try && + ASN1_STRING_length(current_name->d.iPAddress) == 16) { + if (memcmp(ip6, + ASN1_STRING_get0_data(current_name->d.iPAddress), + 16) == 0) { + result = MatchFound; + break; + } + } } } sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);