Patrick Bihan-Faou introduced CURLOPT_SSL_VERIFYHOST and code to deal with
authorDaniel Stenberg <daniel@haxx.se>
Wed, 8 Aug 2001 07:16:47 +0000 (07:16 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 8 Aug 2001 07:16:47 +0000 (07:16 +0000)
it.

lib/ssluse.c
lib/url.c
lib/urldata.h

index a35b051403a8178151c585a9a8e602c6e8b18f75..3d3e9bf84dfbdd6d51b538c48dab572a7c66a63e 100644 (file)
@@ -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;
index 48e1d6b069e10359a6b7bff5c079d18b54f807dc..a40d1bbe9f5bff3e451e0e966262bd90c8d71ef1 100644 (file)
--- 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
index 21b225a589a8c17a4ab7f1464ab097c0063e549b..3916b86da464d27a3cad7882bc6e9f96c047eec1 100644 (file)
@@ -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 */