From: Nikos Mavrogiannopoulos Date: Fri, 27 Jun 2014 09:06:34 +0000 (+0200) Subject: gnutls_x509_crt_check_hostname() checks text ip addresses as well. X-Git-Tag: gnutls_3_3_6~100 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=982cb9d7460e8a95eaa628f8cf4c3c9fb346736d;p=thirdparty%2Fgnutls.git gnutls_x509_crt_check_hostname() checks text ip addresses as well. That aligns the documentation with the implementation. Reported by David Woodhouse. --- diff --git a/lib/x509/rfc2818_hostname.c b/lib/x509/rfc2818_hostname.c index 814114f0c4..725a861bc8 100644 --- a/lib/x509/rfc2818_hostname.c +++ b/lib/x509/rfc2818_hostname.c @@ -24,6 +24,7 @@ #include #include #include +#include /** * gnutls_x509_crt_check_hostname: @@ -50,6 +51,40 @@ gnutls_x509_crt_check_hostname(gnutls_x509_crt_t cert, return gnutls_x509_crt_check_hostname2(cert, hostname, 0); } +static int +check_ip(gnutls_x509_crt_t cert, const void *ip, unsigned ip_size, unsigned flags) +{ + char temp[16]; + size_t temp_size; + unsigned i; + int ret; + + /* try matching against: + * 1) a IPaddress alternative name (subjectAltName) extension + * in the certificate + */ + + /* Check through all included subjectAltName extensions, comparing + * against all those of type IPAddress. + */ + for (i = 0; !(ret < 0); i++) { + temp_size = sizeof(temp); + ret = gnutls_x509_crt_get_subject_alt_name(cert, i, + temp, + &temp_size, + NULL); + + if (ret == GNUTLS_SAN_IPADDRESS) { + if (temp_size == ip_size && memcmp(temp, ip, ip_size) == 0) + return 1; + } + } + + /* not found a matching IP + */ + return 0; +} + /** * gnutls_x509_crt_check_hostname: * @cert: should contain an gnutls_x509_crt_t structure @@ -81,7 +116,29 @@ gnutls_x509_crt_check_hostname2(gnutls_x509_crt_t cert, int found_dnsname = 0; int ret = 0; int i = 0; + struct in_addr ipv4; + char *p = NULL; + + /* check whether @hostname is an ip address */ + if ((p=strchr(hostname, ':')) != NULL || inet_aton(hostname, &ipv4) != 0) { + + if (p != NULL) { +#ifdef AF_INET6 + struct in6_addr ipv6; + + ret = inet_pton(AF_INET6, hostname, &ipv6); + if (ret == 0) { + gnutls_assert(); + goto hostname_fallback; + } + return check_ip(cert, &ipv6, 16, flags); +#endif + } else { + return check_ip(cert, &ipv4, 4, flags); + } + } + hostname_fallback: /* try matching against: * 1) a DNS name as an alternative name (subjectAltName) extension * in the certificate