1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

SSL: Add an option to disable certificate revocation checks

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>
This commit is contained in:
Jay Satiro 2015-07-17 02:40:16 -04:00
parent 606b29fe0d
commit 172b2beba6
15 changed files with 129 additions and 23 deletions

View File

@ -71,3 +71,17 @@ Allow BEAST
introduced. Exactly as it sounds, it re-introduces the BEAST vulnerability 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 but on the other hand it allows curl to connect to that kind of strange
servers. 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

View 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 may use workarounds known to cause interoperability problems with some older
SSL implementations. WARNING: this option loosens the SSL security, and by SSL implementations. WARNING: this option loosens the SSL security, and by
using this flag you ask for exactly that. (Added in 7.25.0) 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]>" .IP "--socks4 <host[:port]>"
Use the specified SOCKS4 proxy. If the port number is not specified, it is Use the specified SOCKS4 proxy. If the port number is not specified, it is
assumed at port 1080. (Added in 7.15.2) assumed at port 1080. (Added in 7.15.2)

View File

@ -30,13 +30,25 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_OPTIONS, long bitmask);
.SH DESCRIPTION .SH DESCRIPTION
Pass a long with a bitmask to tell libcurl about specific SSL behaviors. 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 \fICURLSSLOPT_ALLOW_BEAST\fP tells libcurl to not attempt to use any
user will tell libcurl to not attempt to use any workarounds for a security workarounds for a security flaw in the SSL3 and TLS1.0 protocols. If this
flaw in the SSL3 and TLS1.0 protocols. If this option isn't used or this bit option isn't used or this bit is set to 0, the SSL layer libcurl uses may use a
is set to 0, the SSL layer libcurl uses may use a work-around for this flaw work-around for this flaw although it might cause interoperability problems
although it might cause interoperability problems with some (older) SSL with some (older) SSL implementations. WARNING: avoiding this work-around
implementations. WARNING: avoiding this work-around lessens the security, and lessens the security, and by setting this option to 1 you ask for exactly that.
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 .SH DEFAULT
0 0
.SH PROTOCOLS .SH PROTOCOLS

View File

@ -725,6 +725,10 @@ typedef enum {
servers, a user can this way allow the vulnerability back. */ servers, a user can this way allow the vulnerability back. */
#define CURLSSLOPT_ALLOW_BEAST (1<<0) #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 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */ the obsolete stuff removed! */

View File

@ -2234,7 +2234,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
case CURLOPT_SSL_OPTIONS: case CURLOPT_SSL_OPTIONS:
arg = va_arg(param, long); 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; break;
#endif #endif

View File

@ -1582,6 +1582,7 @@ struct UserDefined {
bool connect_only; /* make connection, let application use the socket */ bool connect_only; /* make connection, let application use the socket */
bool ssl_enable_beast; /* especially allow this flaw for interoperability's bool ssl_enable_beast; /* especially allow this flaw for interoperability's
sake*/ sake*/
bool ssl_no_revoke; /* disable SSL certificate revocation checks */
long ssh_auth_types; /* allowed SSH auth types */ long ssh_auth_types; /* allowed SSH auth types */
bool http_te_skip; /* pass the raw body data to the user, even when bool http_te_skip; /* pass the raw body data to the user, even when
transfer-encoded (chunked, compressed) */ transfer-encoded (chunked, compressed) */

View File

@ -128,16 +128,24 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE; SCH_CRED_IGNORE_REVOCATION_OFFLINE;
#else #else
schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION | schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
SCH_CRED_REVOCATION_CHECK_CHAIN; 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 #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 { else {
schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE; 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) { if(!data->set.ssl.verifyhost) {
@ -1384,7 +1392,8 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
NULL, NULL,
pCertContextServer->hCertStore, pCertContextServer->hCertStore,
&ChainPara, &ChainPara,
0, (data->set.ssl_no_revoke ? 0 :
CERT_CHAIN_REVOCATION_CHECK_CHAIN),
NULL, NULL,
&pChainContext)) { &pChainContext)) {
failf(data, "schannel: CertGetCertificateChain failed: %s", failf(data, "schannel: CertGetCertificateChain failed: %s",
@ -1395,21 +1404,24 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
if(result == CURLE_OK) { if(result == CURLE_OK) {
CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0]; CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED| DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
if(dwTrustErrorMask) { 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" failf(data, "schannel: CertGetCertificateChain trust error"
" CERT_TRUST_IS_PARTIAL_CHAIN"); " 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" failf(data, "schannel: CertGetCertificateChain trust error"
" CERT_TRUST_IS_UNTRUSTED_ROOT"); " 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" failf(data, "schannel: CertGetCertificateChain trust error"
" CERT_TRUST_IS_NOT_TIME_VALID"); " CERT_TRUST_IS_NOT_TIME_VALID");
failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x", else
dwTrustErrorMask); failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
dwTrustErrorMask);
result = CURLE_PEER_FAILED_VERIFICATION; 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; cert_hostname.const_tchar_ptr = cert_hostname_buff;
hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name); 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, len = CertGetNameString(pCertContextServer,
CERT_NAME_DNS_TYPE, CERT_NAME_DNS_TYPE,
0, 0,

View File

@ -199,6 +199,7 @@ struct OperationConfig {
bool xattr; /* store metadata in extended attributes */ bool xattr; /* store metadata in extended attributes */
long gssapi_delegation; long gssapi_delegation;
bool ssl_allow_beast; /* allow this SSL vulnerability */ 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 */ bool use_metalink; /* process given URLs as metalink XML file */
metalinkfile *metalinkfile_list; /* point to the first node */ metalinkfile *metalinkfile_list; /* point to the first node */

View File

@ -221,6 +221,7 @@ static const struct LongShort aliases[]= {
{"Ep", "pinnedpubkey", TRUE}, {"Ep", "pinnedpubkey", TRUE},
{"Eq", "cert-status", FALSE}, {"Eq", "cert-status", FALSE},
{"Er", "false-start", FALSE}, {"Er", "false-start", FALSE},
{"Es", "ssl-no-revoke", FALSE},
{"f", "fail", FALSE}, {"f", "fail", FALSE},
{"F", "form", TRUE}, {"F", "form", TRUE},
{"Fs", "form-string", TRUE}, {"Fs", "form-string", TRUE},
@ -1382,6 +1383,11 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
config->falsestart = TRUE; config->falsestart = TRUE;
break; break;
case 's': /* --ssl-no-revoke */
if(curlinfo->features & CURL_VERSION_SSL)
config->ssl_no_revoke = TRUE;
break;
default: /* certificate file */ default: /* certificate file */
{ {
char *certname, *passphrase; char *certname, *passphrase;

View File

@ -214,6 +214,7 @@ static const char *const helptext[] = {
" -2, --sslv2 Use SSLv2 (SSL)", " -2, --sslv2 Use SSLv2 (SSL)",
" -3, --sslv3 Use SSLv3 (SSL)", " -3, --sslv3 Use SSLv3 (SSL)",
" --ssl-allow-beast Allow security flaw to improve interop (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)", " --stderr FILE Where to redirect stderr (use \"-\" for stdout)",
" --tcp-nodelay Use the TCP_NODELAY option", " --tcp-nodelay Use the TCP_NODELAY option",
" -t, --telnet-option OPT=VAL Set telnet option", " -t, --telnet-option OPT=VAL Set telnet option",

View File

@ -1328,8 +1328,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
config->gssapi_delegation); config->gssapi_delegation);
/* new in 7.25.0 */ /* new in 7.25.0 */
if(config->ssl_allow_beast) my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS,
my_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST); (long)((config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
(config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0)));
if(config->mail_auth) if(config->mail_auth)
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth); my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);

View File

@ -107,6 +107,12 @@ const NameValue setopt_nv_CURLUSESSL[] = {
NVEND, NVEND,
}; };
const NameValueUnsigned setopt_nv_CURLSSLOPT[] = {
NV(CURLSSLOPT_ALLOW_BEAST),
NV(CURLSSLOPT_NO_REVOKE),
NVEND,
};
const NameValue setopt_nv_CURL_NETRC[] = { const NameValue setopt_nv_CURL_NETRC[] = {
NV(CURL_NETRC_IGNORED), NV(CURL_NETRC_IGNORED),
NV(CURL_NETRC_OPTIONAL), NV(CURL_NETRC_OPTIONAL),

View File

@ -52,6 +52,7 @@ extern const NameValue setopt_nv_CURL_SSLVERSION[];
extern const NameValue setopt_nv_CURL_TIMECOND[]; extern const NameValue setopt_nv_CURL_TIMECOND[];
extern const NameValue setopt_nv_CURLFTPSSL_CCC[]; extern const NameValue setopt_nv_CURLFTPSSL_CCC[];
extern const NameValue setopt_nv_CURLUSESSL[]; extern const NameValue setopt_nv_CURLUSESSL[];
extern const NameValueUnsigned setopt_nv_CURLSSLOPT[];
extern const NameValue setopt_nv_CURL_NETRC[]; extern const NameValue setopt_nv_CURL_NETRC[];
extern const NameValue setopt_nv_CURLPROTO[]; extern const NameValue setopt_nv_CURLPROTO[];
extern const NameValueUnsigned setopt_nv_CURLAUTH[]; 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_TIMECONDITION setopt_nv_CURL_TIMECOND
#define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC #define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC
#define setopt_nv_CURLOPT_USE_SSL setopt_nv_CURLUSESSL #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_NETRC setopt_nv_CURL_NETRC
#define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO #define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO
#define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO #define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO

View File

@ -166,4 +166,4 @@ test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \ test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \ test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \ test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
test2040 test2041 test2042 test2040 test2041 test2042 test2043

33
tests/data/test2043 Normal file
View File

@ -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>