Support IP while verifying SSL certificates

This commit is contained in:
Alexey Sokolov
2018-04-02 11:35:45 +01:00
parent 10c98e01a8
commit e2b5c691af

View File

@@ -16,6 +16,7 @@
#include <znc/SSLVerifyHost.h>
#include <znc/Translation.h>
#include <arpa/inet.h>
#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<int>(strlen(dns_name))) {
static_cast<int>(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<const char*>(
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);