]> granicus.if.org Git - curl/commitdiff
SSL: Add an option to disable certificate revocation checks
authorJay Satiro <raysatiro@yahoo.com>
Fri, 17 Jul 2015 06:40:16 +0000 (02:40 -0400)
committerJay Satiro <raysatiro@yahoo.com>
Fri, 17 Jul 2015 06:40:16 +0000 (02:40 -0400)
New tool option --ssl-no-revoke.
New value CURLSSLOPT_NO_REVOKE for CURLOPT_SSL_OPTIONS.

Currently this option applies only to WinSSL where we have automatic
certificate revocation checking by default. According to the
ssl-compared chart there are other backends that have automatic checking
(NSS, wolfSSL and DarwinSSL) so we could possibly accommodate them at
some later point.

Bug: https://github.com/bagder/curl/issues/264
Reported-by: zenden2k <zenden2k@gmail.com>
15 files changed:
docs/SSL-PROBLEMS
docs/curl.1
docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
include/curl/curl.h
lib/url.c
lib/urldata.h
lib/vtls/schannel.c
src/tool_cfgable.h
src/tool_getparam.c
src/tool_help.c
src/tool_operate.c
src/tool_setopt.c
src/tool_setopt.h
tests/data/Makefile.inc
tests/data/test2043 [new file with mode: 0644]

index 5a56d3da57520f173f96f8e745020a394982f72b..45faa241c5d8391240dd300ffa0d6b76c1f20752 100644 (file)
@@ -71,3 +71,17 @@ Allow BEAST
   introduced. Exactly as it sounds, it re-introduces the BEAST vulnerability
   but on the other hand it allows curl to connect to that kind of strange
   servers.
+
+Disabling certificate revocation checks
+
+  Some SSL backends may do certificate revocation checks (CRL, OCSP, etc)
+  depending on the OS or build configuration. The --ssl-no-revoke option was
+  introduced in 7.44.0 to disable revocation checking but currently is only
+  supported for WinSSL (the native Windows SSL library), with an exception in
+  the case of Windows' Untrusted Publishers blacklist which it seems can't be
+  bypassed. This option may have broader support to accommodate other SSL
+  backends in the future.
+
+  References:
+
+  http://curl.haxx.se/docs/ssl-compared.html
index afd4e8c352f022bcb0d0273f9b15c948fcc44a44..69ab9781d70045cdf75ce6be9befe82a0be77c21 100644 (file)
@@ -1545,6 +1545,10 @@ and TLS1.0 protocols known as BEAST.  If this option isn't used, the SSL layer
 may use workarounds known to cause interoperability problems with some older
 SSL implementations. WARNING: this option loosens the SSL security, and by
 using this flag you ask for exactly that.  (Added in 7.25.0)
+.IP "--ssl-no-revoke"
+(WinSSL) This option tells curl to disable certificate revocation checks.
+WARNING: this option loosens the SSL security, and by using this flag you ask
+for exactly that.  (Added in 7.44.0)
 .IP "--socks4 <host[:port]>"
 Use the specified SOCKS4 proxy. If the port number is not specified, it is
 assumed at port 1080. (Added in 7.15.2)
index 09bcb96cfd1f9279829d39606440f589c902a9ce..0afd2fb6a3f2cadd1f0de25884a736e3c7901f6a 100644 (file)
@@ -30,13 +30,25 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_OPTIONS, long bitmask);
 .SH DESCRIPTION
 Pass a long with a bitmask to tell libcurl about specific SSL behaviors.
 
-\fICURLSSLOPT_ALLOW_BEAST\fP is the only supported bit and by setting this the
-user will tell libcurl to not attempt to use any workarounds for a security
-flaw in the SSL3 and TLS1.0 protocols.  If this option isn't used or this bit
-is set to 0, the SSL layer libcurl uses may use a work-around for this flaw
-although it might cause interoperability problems with some (older) SSL
-implementations. WARNING: avoiding this work-around lessens the security, and
-by setting this option to 1 you ask for exactly that.
+\fICURLSSLOPT_ALLOW_BEAST\fP tells libcurl to not attempt to use any
+workarounds for a security flaw in the SSL3 and TLS1.0 protocols.  If this
+option isn't used or this bit is set to 0, the SSL layer libcurl uses may use a
+work-around for this flaw although it might cause interoperability problems
+with some (older) SSL implementations. WARNING: avoiding this work-around
+lessens the security, and by setting this option to 1 you ask for exactly that.
+This option is only supported for DarwinSSL, NSS and OpenSSL.
+
+Added in 7.44.0:
+
+\fICURLSSLOPT_NO_REVOKE\fP tells libcurl to disable certificate revocation
+checks for those SSL backends where such behavior is present. \fBCurrently this
+option is only supported for WinSSL (the native Windows SSL library), with an
+exception in the case of Windows' Untrusted Publishers blacklist which it seems
+can't be bypassed.\fP This option may have broader support to accommodate other
+SSL backends in the future.
+http://curl.haxx.se/docs/ssl-compared.html
+
+
 .SH DEFAULT
 0
 .SH PROTOCOLS
index eab2f6e99a541cd4148949f540f7ee2728c6c2ae..64f926142a17f3b9f654ef2384964208244c5d10 100644 (file)
@@ -725,6 +725,10 @@ typedef enum {
    servers, a user can this way allow the vulnerability back. */
 #define CURLSSLOPT_ALLOW_BEAST (1<<0)
 
+/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those
+   SSL backends where such behavior is present. */
+#define CURLSSLOPT_NO_REVOKE (1<<1)
+
 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
                           the obsolete stuff removed! */
 
index 4e949525173381588592919ed7a84c2636543df2..406c1f02c96406b416cab2235e42977064ec42b7 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -2234,7 +2234,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
 
   case CURLOPT_SSL_OPTIONS:
     arg = va_arg(param, long);
-    data->set.ssl_enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+    data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
+    data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
     break;
 
 #endif
index 59c704e0da6f5cf2d5c1b4d3446d850d156273f8..06559229bdd1cf95cb242336cf264eff07e92201 100644 (file)
@@ -1582,6 +1582,7 @@ struct UserDefined {
   bool connect_only;     /* make connection, let application use the socket */
   bool ssl_enable_beast; /* especially allow this flaw for interoperability's
                             sake*/
+  bool ssl_no_revoke;    /* disable SSL certificate revocation checks */
   long ssh_auth_types;   /* allowed SSH auth types */
   bool http_te_skip;     /* pass the raw body data to the user, even when
                             transfer-encoded (chunked, compressed) */
index 19aff8f07ca7e9cab5f8a70cb012c3f3f090ad6e..fe35a278b8af7cbeb80ea487bb732a593bfba860 100644 (file)
@@ -128,16 +128,24 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
         SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
         SCH_CRED_IGNORE_REVOCATION_OFFLINE;
 #else
-      schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
-        SCH_CRED_REVOCATION_CHECK_CHAIN;
+      schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+      if(data->set.ssl_no_revoke)
+        schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+                                 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+      else
+        schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
 #endif
-      infof(data, "schannel: checking server certificate revocation\n");
+      if(data->set.ssl_no_revoke)
+        infof(data, "schannel: disabled server certificate revocation "
+                    "checks\n");
+      else
+        infof(data, "schannel: checking server certificate revocation\n");
     }
     else {
       schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
         SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
         SCH_CRED_IGNORE_REVOCATION_OFFLINE;
-      infof(data, "schannel: disable server certificate revocation checks\n");
+      infof(data, "schannel: disabled server certificate revocation checks\n");
     }
 
     if(!data->set.ssl.verifyhost) {
@@ -1384,7 +1392,8 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
                                 NULL,
                                 pCertContextServer->hCertStore,
                                 &ChainPara,
-                                0,
+                                (data->set.ssl_no_revoke ? 0 :
+                                 CERT_CHAIN_REVOCATION_CHECK_CHAIN),
                                 NULL,
                                 &pChainContext)) {
       failf(data, "schannel: CertGetCertificateChain failed: %s",
@@ -1395,21 +1404,24 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
 
     if(result == CURLE_OK) {
       CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
-      DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED|
-                                        CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
+      DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
       dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
       if(dwTrustErrorMask) {
-        if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
+        if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED)
+          failf(data, "schannel: CertGetCertificateChain trust error"
+                " CERT_TRUST_IS_REVOKED");
+        else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
           failf(data, "schannel: CertGetCertificateChain trust error"
                 " CERT_TRUST_IS_PARTIAL_CHAIN");
-        if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
+        else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
           failf(data, "schannel: CertGetCertificateChain trust error"
                 " CERT_TRUST_IS_UNTRUSTED_ROOT");
-        if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
+        else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
           failf(data, "schannel: CertGetCertificateChain trust error"
                 " CERT_TRUST_IS_NOT_TIME_VALID");
-        failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
-              dwTrustErrorMask);
+        else
+          failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
+                dwTrustErrorMask);
         result = CURLE_PEER_FAILED_VERIFICATION;
       }
     }
@@ -1425,6 +1437,14 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
       cert_hostname.const_tchar_ptr = cert_hostname_buff;
       hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name);
 
+      /* TODO: Fix this for certificates with multiple alternative names.
+      Right now we're only asking for the first preferred alternative name.
+      Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG
+      (if WinCE supports that?) and run this section in a loop for each.
+      https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx
+      curl: (51) schannel: CertGetNameString() certificate hostname
+      (.google.com) did not match connection (google.com)
+      */
       len = CertGetNameString(pCertContextServer,
                               CERT_NAME_DNS_TYPE,
                               0,
index 048eb4ffe66522059e456959c8248642c50c328b..c6a691447d2153029cfcebafa91cb7c3eada69a4 100644 (file)
@@ -199,6 +199,7 @@ struct OperationConfig {
   bool xattr;               /* store metadata in extended attributes */
   long gssapi_delegation;
   bool ssl_allow_beast;     /* allow this SSL vulnerability */
+  bool ssl_no_revoke;       /* disable SSL certificate revocation checks */
 
   bool use_metalink;        /* process given URLs as metalink XML file */
   metalinkfile *metalinkfile_list; /* point to the first node */
index 339fb7b5d4356ebefacb09540211a43de451eefe..4405bce878c1aac404c1f77ead2d00b290b06367 100644 (file)
@@ -221,6 +221,7 @@ static const struct LongShort aliases[]= {
   {"Ep", "pinnedpubkey",             TRUE},
   {"Eq", "cert-status",              FALSE},
   {"Er", "false-start",              FALSE},
+  {"Es", "ssl-no-revoke",            FALSE},
   {"f",  "fail",                     FALSE},
   {"F",  "form",                     TRUE},
   {"Fs", "form-string",              TRUE},
@@ -1382,6 +1383,11 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */
         config->falsestart = TRUE;
         break;
 
+      case 's': /* --ssl-no-revoke */
+        if(curlinfo->features & CURL_VERSION_SSL)
+          config->ssl_no_revoke = TRUE;
+        break;
+
       default: /* certificate file */
       {
         char *certname, *passphrase;
index e0c45954b304757edbb10247026c5e85df333c3a..6ad51cb5b85caef2015d64c188257de172d14079 100644 (file)
@@ -214,6 +214,7 @@ static const char *const helptext[] = {
   " -2, --sslv2         Use SSLv2 (SSL)",
   " -3, --sslv3         Use SSLv3 (SSL)",
   "     --ssl-allow-beast  Allow security flaw to improve interop (SSL)",
+  "     --ssl-no-revoke    Disable cert revocation checks (WinSSL)",
   "     --stderr FILE   Where to redirect stderr (use \"-\" for stdout)",
   "     --tcp-nodelay   Use the TCP_NODELAY option",
   " -t, --telnet-option OPT=VAL  Set telnet option",
index 4c6ff854cef220f3ecb13000b97daa223c27a906..1180555fac0589a0a55c21e9ac909a07e6819224 100644 (file)
@@ -1328,8 +1328,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
                         config->gssapi_delegation);
 
         /* new in 7.25.0 */
-        if(config->ssl_allow_beast)
-          my_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST);
+        my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS,
+          (long)((config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
+                 (config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0)));
 
         if(config->mail_auth)
           my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
index a53fdc835d6094d2c1db04e77df2138b69f3f84f..7eb64b0397183adc8d889ed5b3e06541dcf8233c 100644 (file)
@@ -107,6 +107,12 @@ const NameValue setopt_nv_CURLUSESSL[] = {
   NVEND,
 };
 
+const NameValueUnsigned setopt_nv_CURLSSLOPT[] = {
+  NV(CURLSSLOPT_ALLOW_BEAST),
+  NV(CURLSSLOPT_NO_REVOKE),
+  NVEND,
+};
+
 const NameValue setopt_nv_CURL_NETRC[] = {
   NV(CURL_NETRC_IGNORED),
   NV(CURL_NETRC_OPTIONAL),
index fcba94cb261fbe9318e91c3544995dd1f133ca6c..b32adf988639d395bbdc89a944cdf323b8398795 100644 (file)
@@ -52,6 +52,7 @@ extern const NameValue setopt_nv_CURL_SSLVERSION[];
 extern const NameValue setopt_nv_CURL_TIMECOND[];
 extern const NameValue setopt_nv_CURLFTPSSL_CCC[];
 extern const NameValue setopt_nv_CURLUSESSL[];
+extern const NameValueUnsigned setopt_nv_CURLSSLOPT[];
 extern const NameValue setopt_nv_CURL_NETRC[];
 extern const NameValue setopt_nv_CURLPROTO[];
 extern const NameValueUnsigned setopt_nv_CURLAUTH[];
@@ -63,6 +64,7 @@ extern const NameValueUnsigned setopt_nv_CURLAUTH[];
 #define setopt_nv_CURLOPT_TIMECONDITION setopt_nv_CURL_TIMECOND
 #define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC
 #define setopt_nv_CURLOPT_USE_SSL setopt_nv_CURLUSESSL
+#define setopt_nv_CURLOPT_SSL_OPTIONS setopt_nv_CURLSSLOPT
 #define setopt_nv_CURLOPT_NETRC setopt_nv_CURL_NETRC
 #define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO
 #define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO
index 51823fe886f6719511074e237c1ad8804dc7708a..f39db40da296e7e2527c8cead33d06d68b6d0738 100644 (file)
@@ -166,4 +166,4 @@ test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
 test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
 test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
 test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
-test2040 test2041 test2042
+test2040 test2041 test2042 test2043
diff --git a/tests/data/test2043 b/tests/data/test2043
new file mode 100644 (file)
index 0000000..7a91f5b
--- /dev/null
@@ -0,0 +1,33 @@
+<testcase>
+<info>
+<keywords>
+HTTPS
+HTTP GET
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<features>
+WinSSL
+</features>
+<server>
+none
+</server>
+ <name>
+Disable certificate revocation checks
+ </name>
+ <command>
+--ssl-no-revoke -I https://revoked.grc.com/
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+0
+</errorcode>
+</verify>
+</testcase>