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