diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2014-07-14 20:04:55 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2014-07-14 20:14:15 +0200 |
commit | 98866008a98da437998f72d38be06495cf91d319 (patch) | |
tree | 7c08951f9b502090284c1c4b8482256dbd30790a | |
parent | 08c8d5b89a24531addff8674fe241be7cf17b31d (diff) |
gnutls: handle IP address in cert name check
Before GnuTLS 3.3.6, the gnutls_x509_crt_check_hostname() function
didn't actually check IP addresses in SubjectAltName, even though it was
explicitly documented as doing so. So do it ourselves...
-rw-r--r-- | lib/vtls/gtls.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 3bdd28547..ac00d2f3f 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -781,7 +781,48 @@ gtls_connect_step3(struct connectdata *conn, alternative name PKIX extension. Returns non zero on success, and zero on failure. */ rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name); +#if GNUTLS_VERSION_NUMBER < 0x030306 + /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP + addresses. */ + if(!rc) { +#ifdef ENABLE_IPV6 + #define use_addr in6_addr +#else + #define use_addr in_addr +#endif + unsigned char addrbuf[sizeof(struct use_addr)]; + unsigned char certaddr[sizeof(struct use_addr)]; + size_t addrlen = 0, certaddrlen; + int i; + int ret = 0; + + if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0) + addrlen = 4; +#ifdef ENABLE_IPV6 + else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0) + addrlen = 16; +#endif + if(addrlen) { + for(i=0; ; i++) { + certaddrlen = sizeof(certaddr); + ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr, + &certaddrlen, NULL); + /* If this happens, it wasn't an IP address. */ + if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) + continue; + if(ret < 0) + break; + if(ret != GNUTLS_SAN_IPADDRESS) + continue; + if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) { + rc = 1; + break; + } + } + } + } +#endif if(!rc) { if(data->set.ssl.verifyhost) { failf(data, "SSL: certificate subject name (%s) does not match " |