diff options
-rw-r--r-- | lib/ssluse.c | 32 | ||||
-rw-r--r-- | lib/url.c | 6 | ||||
-rw-r--r-- | lib/urldata.h | 1 |
3 files changed, 36 insertions, 3 deletions
diff --git a/lib/ssluse.c b/lib/ssluse.c index a35b05140..3d3e9bf84 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -374,15 +374,39 @@ Curl_SSLConnect(struct connectdata *conn) NULL, 0); if(!str) { failf(data, "SSL: couldn't get X509-subject!"); + X509_free(conn->ssl.server_cert); return CURLE_SSL_CONNECT_ERROR; } infof(data, "\t subject: %s\n", str); CRYPTO_free(str); + if (data->ssl.verifyhost) { + char peer_CN[257]; + if (X509_NAME_get_text_by_NID(X509_get_subject_name(conn->ssl.server_cert), NID_commonName, peer_CN, sizeof(peer_CN)) < 0) { + failf(data, "SSL: unable to obtain common name from peer certificate"); + X509_free(conn->ssl.server_cert); + return CURLE_SSL_PEER_CERTIFICATE; + } + + if (strcasecmp(peer_CN, conn->hostname) != 0) { + if (data->ssl.verifyhost > 1) { + failf(data, "SSL: certificate subject name '%s' does not match target host name '%s'", + peer_CN, conn->hostname); + X509_free(conn->ssl.server_cert); + return CURLE_SSL_PEER_CERTIFICATE; + } + else + infof(data, "\t common name: %s (does not match '%s')\n", peer_CN, conn->hostname); + } + else + infof(data, "\t common name: %s (matched)\n", peer_CN); + } + str = X509_NAME_oneline (X509_get_issuer_name (conn->ssl.server_cert), NULL, 0); if(!str) { failf(data, "SSL: couldn't get X509-issuer name!"); + X509_free(conn->ssl.server_cert); return CURLE_SSL_CONNECT_ERROR; } infof(data, "\t issuer: %s\n", str); @@ -393,9 +417,11 @@ Curl_SSLConnect(struct connectdata *conn) if(data->ssl.verifypeer) { data->ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle); - failf(data, "SSL certificate verify result: %d\n", - data->ssl.certverifyresult); - retcode = CURLE_SSL_PEER_CERTIFICATE; + if (data->ssl.certverifyresult != X509_V_OK) { + failf(data, "SSL certificate verify result: %d\n", + data->ssl.certverifyresult); + retcode = CURLE_SSL_PEER_CERTIFICATE; + } } else data->ssl.certverifyresult=0; @@ -792,6 +792,12 @@ CURLcode Curl_setopt(CURL *curl, CURLoption option, ...) */ data->ssl.verifypeer = va_arg(param, long); break; + case CURLOPT_SSL_VERIFYHOST: + /* + * Enable verification of the CN contained in the peer certificate + */ + data->ssl.verifyhost = va_arg(param, long); + break; case CURLOPT_CAINFO: /* * Set CA info for SSL connection. Specify file name of the CA certificate diff --git a/lib/urldata.h b/lib/urldata.h index 21b225a58..3916b86da 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -129,6 +129,7 @@ struct ssl_config_data { long version; /* what version the client wants to use */ long certverifyresult; /* result from the certificate verification */ long verifypeer; /* set TRUE if this is desired */ + long verifyhost; /* 0: no verif, 1: check that CN exists, 2: CN must match hostname */ char *CApath; /* DOES NOT WORK ON WINDOWS */ char *CAfile; /* cerficate to verify peer against */ char *random_file; /* path to file containing "random" data */ |