diff options
-rw-r--r-- | lib/ssluse.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/lib/ssluse.c b/lib/ssluse.c index a79a9a71b..e24f8cb30 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -673,6 +673,44 @@ static int Curl_ASN1_UTCTIME_output(struct connectdata *conn, #endif /* ====================================================== */ +static int +cert_hostcheck(const char *certname, const char *hostname) +{ + char *tmp; + const char *certdomain; + + if(!certname || + strlen(certname)<3 || + !hostname || + !strlen(hostname)) /* sanity check */ + return 0; + + if(strequal(certname, hostname)) /* trivial case */ + return 1; + + certdomain = certname + 1; + + if((certname[0] != '*') || (certdomain[0] != '.')) + return 0; /* not a wildcard certificate, check failed */ + + if(!strchr(certdomain+1, '.')) + return 0; /* the certificate must have at least another dot in its name */ + + /* find 'certdomain' within 'hostname' */ + tmp = strstr(hostname, certdomain); + if(tmp) { + /* ok the certname's domain matches the hostname, let's check that it's a + tail-match */ + if(strequal(tmp, certdomain)) + /* looks like a match. Just check we havent swallowed a '.' */ + return tmp == strchr(hostname, '.'); + else + return 0; + } + return 0; +} + +/* ====================================================== */ CURLcode Curl_SSLConnect(struct connectdata *conn) { @@ -910,7 +948,7 @@ Curl_SSLConnect(struct connectdata *conn) return CURLE_SSL_PEER_CERTIFICATE; } - if (!strequal(peer_CN, conn->hostname)) { + if (!cert_hostcheck(peer_CN, conn->hostname)) { if (data->set.ssl.verifyhost > 1) { failf(data, "SSL: certificate subject name '%s' does not match " "target host name '%s'", |