From d4643d6e799b088e0a7e9b768facc0d1e1e86257 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 15 Jun 2016 15:36:40 +0200 Subject: [PATCH] openssl: fix cert check with non-DNS name fields present Regression introduced in 5f5b62635 (released in 7.48.0) Reported-by: Fabian Ruff Fixes #875 --- lib/vtls/openssl.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index f702653cd..2f69790e9 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -1082,6 +1082,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) struct in_addr addr; #endif CURLcode result = CURLE_OK; + bool dNSName = FALSE; /* if a dNSName field exists in the cert */ #ifdef ENABLE_IPV6 if(conn->bits.ipv6_ip && @@ -1102,16 +1103,23 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) if(altnames) { int numalts; int i; + bool dnsmatched = FALSE; + bool ipmatched = FALSE; /* get amount of alternatives, RFC2459 claims there MUST be at least one, but we don't depend on it... */ numalts = sk_GENERAL_NAME_num(altnames); - /* loop through all alternatives while none has matched */ - for(i=0; (itype == GEN_DNS) + dNSName = TRUE; + /* only check alternatives of the same type the target is */ if(check->type == target) { /* get data and length */ @@ -1134,7 +1142,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) /* if this isn't true, there was an embedded zero in the name string and we cannot match it. */ Curl_cert_hostcheck(altptr, conn->host.name)) { - matched = TRUE; + dnsmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n", conn->host.dispname, altptr); @@ -1145,7 +1153,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) /* compare alternative IP address if the data chunk is the same size our server IP address is */ if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) { - matched = TRUE; + ipmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's IP address!\n", conn->host.dispname); @@ -1155,14 +1163,19 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) } } GENERAL_NAMES_free(altnames); + + if(dnsmatched || (!dNSName && ipmatched)) { + /* count as a match if the dnsname matched or if there was no dnsname + fields at all AND there was an IP field match */ + matched = TRUE; + } } if(matched) /* an alternative name matched */ ; - else if(altnames) { - /* an alternative name field existed, but didn't match and then we MUST - fail */ + else if(dNSName) { + /* an dNSName field existed, but didn't match and then we MUST fail */ infof(data, " subjectAltName does not match %s\n", conn->host.dispname); failf(data, "SSL: no alternative certificate subject name matches " "target host name '%s'", conn->host.dispname);