aboutsummaryrefslogtreecommitdiff
path: root/lib/ssluse.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssluse.c')
-rw-r--r--lib/ssluse.c40
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'",