aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ssluse.c32
-rw-r--r--lib/url.c6
-rw-r--r--lib/urldata.h1
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;
diff --git a/lib/url.c b/lib/url.c
index 48e1d6b06..a40d1bbe9 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -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 */