Dear all,

Openssl defines a flag, -trusted_first, which causes it to verify certificates using a trusted certificate store, even if an untrusted store is also available. This is described in a patch at <http://marc.info/?l=openssl-cvs&m=126710063626226>.

I've created a patch for cURL that adds a --trusted_first flag, allowing (lib)curl to use this openssl functionality.

It's probably not perfect, and I haven't updated all the man pages and help, but it seems to work and I hope it's useful.

The patch applies cleanly to cURL 7.23.1.

Rob Foreman
--
Rob Foreman
BBC Future Media & Technology
D221 Centre House, 56 Wood Lane, LONDON W12 7SB
+44 303 040 9587
robert.fore...@rd.bbc.co.uk
diff -urp curl-7.23.1/include/curl/curl.h 
curl-7.23.1-patched/include/curl/curl.h
--- curl-7.23.1/include/curl/curl.h     2011-11-04 22:32:55.000000000 +0000
+++ curl-7.23.1-patched/include/curl/curl.h     2011-12-15 15:41:58.053984680 
+0000
@@ -1486,6 +1486,9 @@ typedef enum {
   /* allow GSSAPI credential delegation */
   CINIT(GSSAPI_DELEGATION, LONG, 210),
 
+  /* Use trusted certificates before untrusted */
+  CINIT(SSL_TRUSTED_FIRST, LONG, 211),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
diff -urp curl-7.23.1/lib/sslgen.c curl-7.23.1-patched/lib/sslgen.c
--- curl-7.23.1/lib/sslgen.c    2011-11-04 22:32:57.000000000 +0000
+++ curl-7.23.1-patched/lib/sslgen.c    2011-12-15 15:51:41.815989950 +0000
@@ -83,6 +83,7 @@ Curl_ssl_config_matches(struct ssl_confi
   if((data->version == needle->version) &&
      (data->verifypeer == needle->verifypeer) &&
      (data->verifyhost == needle->verifyhost) &&
+     (data->trusted_first == needle->trusted_first) &&
      safe_strequal(data->CApath, needle->CApath) &&
      safe_strequal(data->CAfile, needle->CAfile) &&
      safe_strequal(data->random_file, needle->random_file) &&
@@ -100,6 +101,7 @@ Curl_clone_ssl_config(struct ssl_config_
   dest->sessionid = source->sessionid;
   dest->verifyhost = source->verifyhost;
   dest->verifypeer = source->verifypeer;
+  dest->trusted_first = source->trusted_first;
   dest->version = source->version;
 
   if(source->CAfile) {
diff -urp curl-7.23.1/lib/ssluse.c curl-7.23.1-patched/lib/ssluse.c
--- curl-7.23.1/lib/ssluse.c    2011-11-06 15:58:24.000000000 +0000
+++ curl-7.23.1-patched/lib/ssluse.c    2011-12-15 16:50:44.959533790 +0000
@@ -1650,6 +1650,14 @@ ossl_connect_step1(struct connectdata *c
           data->set.str[STRING_SSL_CRLFILE]: "none");
   }
 
+  if(data->set.ssl.trusted_first) {
+    X509_VERIFY_PARAM *x509_param;
+    x509_param = X509_VERIFY_PARAM_new();
+    X509_VERIFY_PARAM_set_flags(x509_param, X509_V_FLAG_TRUSTED_FIRST);
+    SSL_CTX_set1_param(connssl->ctx, x509_param);
+    X509_VERIFY_PARAM_free(x509_param);
+  }
+
   /* SSL always tries to verify the peer, this only says whether it should
    * fail to connect if the verification fails, or if it should continue
    * anyway. In the latter case the result of the verification is checked with
diff -urp curl-7.23.1/lib/url.c curl-7.23.1-patched/lib/url.c
--- curl-7.23.1/lib/url.c       2011-11-04 22:32:57.000000000 +0000
+++ curl-7.23.1-patched/lib/url.c       2011-12-15 15:32:05.713606912 +0000
@@ -2267,6 +2267,10 @@ CURLcode Curl_setopt(struct SessionHandl
     data->set.ssl.sessionid = (0 != va_arg(param, long))?TRUE:FALSE;
     break;
 
+  case CURLOPT_SSL_TRUSTED_FIRST:
+    data->set.ssl.trusted_first = (0 != va_arg(param, long))?TRUE:FALSE;
+    break;
+
 #ifdef USE_LIBSSH2
     /* we only include SSH options if explicitly built to support SSH */
   case CURLOPT_SSH_AUTH_TYPES:
diff -urp curl-7.23.1/lib/urldata.h curl-7.23.1-patched/lib/urldata.h
--- curl-7.23.1/lib/urldata.h   2011-11-04 22:32:57.000000000 +0000
+++ curl-7.23.1-patched/lib/urldata.h   2011-12-15 15:39:54.838556511 +0000
@@ -288,6 +288,7 @@ struct ssl_connect_data {
 struct ssl_config_data {
   long version;          /* what version the client wants to use */
   long certverifyresult; /* result from the certificate verification */
+  long trusted_first;    /* use trusted certificates first */
   long verifypeer;       /* set TRUE if this is desired */
   long verifyhost;       /* 0: no verify
                             1: check that CN exists
diff -urp curl-7.23.1/src/tool_cfgable.h curl-7.23.1-patched/src/tool_cfgable.h
--- curl-7.23.1/src/tool_cfgable.h      2011-11-04 22:32:58.000000000 +0000
+++ curl-7.23.1-patched/src/tool_cfgable.h      2011-12-15 15:00:48.710028375 
+0000
@@ -103,6 +103,7 @@ struct Configurable {
   char *cert;
   char *cert_type;
   char *cacert;
+  bool trusted_first;
   char *capath;
   char *crlfile;
   char *key;
diff -urp curl-7.23.1/src/tool_getparam.c 
curl-7.23.1-patched/src/tool_getparam.c
--- curl-7.23.1/src/tool_getparam.c     2011-11-04 22:32:58.000000000 +0000
+++ curl-7.23.1-patched/src/tool_getparam.c     2011-12-15 15:24:13.855493085 
+0000
@@ -202,6 +202,7 @@ static const struct LongShort aliases[]=
   {"Ek", "tlsuser",                  TRUE},
   {"El", "tlspassword",              TRUE},
   {"Em", "tlsauthtype",              TRUE},
+  {"En", "trusted_first",            FALSE},
   {"f",  "fail",                     FALSE},
   {"F",  "form",                     TRUE},
   {"Fs", "form-string",              TRUE},
@@ -1144,6 +1145,11 @@ ParameterError getparameter(char *flag, 
         else
           return PARAM_LIBCURL_DOESNT_SUPPORT;
         break;
+      case 'n': /* Use trusted certificates before untrusted */
+        if(curlinfo->features & CURL_VERSION_SSL) {
+          config->trusted_first = TRUE;
+        }
+        break;
       default: /* certificate file */
       {
         char *ptr = strchr(nextarg, ':');
diff -urp curl-7.23.1/src/tool_help.c curl-7.23.1-patched/src/tool_help.c
--- curl-7.23.1/src/tool_help.c 2011-11-04 22:32:58.000000000 +0000
+++ curl-7.23.1-patched/src/tool_help.c 2011-12-15 14:57:07.664456861 +0000
@@ -204,6 +204,7 @@ static const char *const helptext[] = {
   "     --tlsuser USER  TLS username",
   "     --tlspassword STRING TLS password",
   "     --tlsauthtype STRING  TLS authentication type (default SRP)",
+  "     --trusted_first Use trusted certificates before untrusted (SSL)",
   " -A, --user-agent STRING  User-Agent to send to server (H)",
   " -v, --verbose       Make the operation more talkative",
   " -V, --version       Show version number and quit",
diff -urp curl-7.23.1/src/tool_operate.c curl-7.23.1-patched/src/tool_operate.c
--- curl-7.23.1/src/tool_operate.c      2011-11-04 22:32:58.000000000 +0000
+++ curl-7.23.1-patched/src/tool_operate.c      2011-12-15 15:32:34.461840653 
+0000
@@ -953,6 +953,9 @@ int operate(struct Configurable *config,
             /* libcurl default is strict verifyhost -> 2L   */
             /* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
           }
+          if(config->trusted_first) {
+            my_setopt(curl, CURLOPT_SSL_TRUSTED_FIRST, 1L);
+          }
         }
 
         if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
diff -urp curl-7.23.1/docs/libcurl/symbols-in-versions 
curl-7.23.1-patched/docs/libcurl/symbols-in-versions
--- curl-7.23.1/docs/libcurl/symbols-in-versions        2011-11-04 
22:32:58.000000000 +0000
+++ curl-7.23.1-patched/docs/libcurl/symbols-in-versions        2011-12-15 
15:32:34.461840653 +0000
@@ -479,6 +479,7 @@ CURLOPT_SSL_CIPHER_LIST         7.9
 CURLOPT_SSL_CTX_DATA            7.10.6
 CURLOPT_SSL_CTX_FUNCTION        7.10.6
 CURLOPT_SSL_SESSIONID_CACHE     7.16.0
+CURLOPT_SSL_TRUSTED_FIRST       7.23.1
 CURLOPT_SSL_VERIFYHOST          7.8.1
 CURLOPT_SSL_VERIFYPEER          7.4.2
 CURLOPT_STDERR                  7.1
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to