summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Satiro <raysatiro@yahoo.com>2021-02-27 16:27:31 -0500
committerJay Satiro <raysatiro@yahoo.com>2021-04-22 16:53:37 -0400
commit54e747501626b81149b1b44949119d365db82004 (patch)
tree6c89f73c8eb7bbb96877a83e27b3b3916d5534e7
parente4ba999646ed7a974813ecf8405651d300554eba (diff)
downloadcurl-54e747501626b81149b1b44949119d365db82004.tar.gz
schannel: Disable auto credentials; add an option to enable it
- Disable auto credentials by default. This is a breaking change for clients that are using it, wittingly or not. - New libcurl ssl option value CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use a client certificate for authentication, when requested by the server. - New curl tool options --ssl-auto-client-cert and --proxy-ssl-auto-client-cert map to CURLSSLOPT_AUTO_CLIENT_CERT. This option is only supported for Schannel (the native Windows SSL library). Prior to this change Schannel would, with no notification to the client, attempt to locate a client certificate and send it to the server, when requested by the server. Since the server can request any certificate that supports client authentication in the OS certificate store it could be a privacy violation and unexpected. Fixes https://github.com/curl/curl/issues/2262 Reported-by: Jeroen Ooms Assisted-by: Wes Hinsley Assisted-by: Rich FitzJohn Ref: https://curl.se/mail/lib-2021-02/0066.html Reported-by: Morten Minde Neergaard Closes https://github.com/curl/curl/pull/6673
-rw-r--r--docs/TODO14
-rw-r--r--docs/cmdline-opts/Makefile.inc2
-rw-r--r--docs/cmdline-opts/proxy-ssl-auto-client-cert.d6
-rw-r--r--docs/cmdline-opts/ssl-auto-client-cert.d12
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.39
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_OPTIONS.38
-rw-r--r--docs/libcurl/symbols-in-versions1
-rw-r--r--docs/options-in-versions2
-rw-r--r--include/curl/curl.h4
-rw-r--r--lib/doh.c5
-rw-r--r--lib/setopt.c5
-rw-r--r--lib/urldata.h2
-rw-r--r--lib/vtls/schannel.c19
-rw-r--r--packages/OS400/curl.inc.in2
-rw-r--r--src/tool_cfgable.h3
-rw-r--r--src/tool_getparam.c13
-rw-r--r--src/tool_help.c6
-rw-r--r--src/tool_operate.c21
-rw-r--r--src/tool_setopt.c1
-rw-r--r--src/tool_setopt.h1
20 files changed, 108 insertions, 28 deletions
diff --git a/docs/TODO b/docs/TODO
index b2b082292..04511bb3b 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -126,7 +126,6 @@
15. Schannel
15.1 Extend support for client certificate authentication
15.2 Extend support for the --ciphers option
- 15.3 Add option to disable client certificate auto-send
15.4 Add option to allow abrupt server closure
16. SASL
@@ -861,19 +860,6 @@
- Specifying Schannel Ciphers and Cipher Strengths
https://msdn.microsoft.com/en-us/library/windows/desktop/aa380161.aspx
-15.3 Add option to disable client certificate auto-send
-
- Microsoft says "By default, Schannel will, with no notification to the client,
- attempt to locate a client certificate and send it to the server." That could
- be considered a privacy violation and unexpected.
-
- Some Windows users have come to expect that default behavior and to change the
- default to make it consistent with other SSL backends would be a breaking
- change. An option should be added that can be used to disable the default
- Schannel auto-send behavior.
-
- https://github.com/curl/curl/issues/2262
-
15.4 Add option to allow abrupt server closure
libcurl w/schannel will error without a known termination point from the
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index 7ca0f3268..6e04552e9 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -180,6 +180,7 @@ DPAGES = \
proxy-pinnedpubkey.d \
proxy-service-name.d \
proxy-ssl-allow-beast.d \
+ proxy-ssl-auto-client-cert.d \
proxy-tls13-ciphers.d \
proxy-tlsauthtype.d \
proxy-tlspassword.d \
@@ -223,6 +224,7 @@ DPAGES = \
speed-limit.d \
speed-time.d \
ssl-allow-beast.d \
+ ssl-auto-client-cert.d \
ssl-no-revoke.d \
ssl-reqd.d \
ssl-revoke-best-effort.d \
diff --git a/docs/cmdline-opts/proxy-ssl-auto-client-cert.d b/docs/cmdline-opts/proxy-ssl-auto-client-cert.d
new file mode 100644
index 000000000..054175457
--- /dev/null
+++ b/docs/cmdline-opts/proxy-ssl-auto-client-cert.d
@@ -0,0 +1,6 @@
+Long: proxy-ssl-auto-client-cert
+Help: Use auto client certificate for proxy (Schannel)
+Added: 7.77.0
+Category: proxy tls
+---
+Same as --ssl-auto-client-cert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/ssl-auto-client-cert.d b/docs/cmdline-opts/ssl-auto-client-cert.d
new file mode 100644
index 000000000..16108aef1
--- /dev/null
+++ b/docs/cmdline-opts/ssl-auto-client-cert.d
@@ -0,0 +1,12 @@
+Long: ssl-auto-client-cert
+Help: Use auto client certificate (Schannel)
+Added: 7.77.0
+See-also: proxy-ssl-auto-client-cert
+Category: tls
+---
+Tell libcurl to automatically locate and use a client certificate for
+authentication, when requested by the server. This option is only supported
+for Schannel (the native Windows SSL library). Prior to 7.77.0 this was the
+default behavior in libcurl with Schannel. Since the server can request any
+certificate that supports client authentication in the OS certificate store it
+could be a privacy violation and unexpected.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
index dbc701eeb..e5963dc4d 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
@@ -49,13 +49,20 @@ Tells libcurl to not accept "partial" certificate chains, which it otherwise
does by default. This option is only supported for OpenSSL and will fail the
certificate verification if the chain ends with an intermediate certificate
and not with a root cert. (Added in 7.68.0)
-
.IP CURLSSLOPT_REVOKE_BEST_EFFORT
Tells libcurl to ignore certificate revocation checks in case of missing or
offline distribution points for those SSL backends where such behavior is
present. This option is only supported for Schannel (the native Windows SSL
library). If combined with \fICURLSSLOPT_NO_REVOKE\fP, the latter takes
precedence. (Added in 7.70.0)
+.IP CURLSSLOPT_AUTO_CLIENT_CERT
+Tell libcurl to automatically locate and use a client certificate for
+authentication, when requested by the server. This option is only supported
+for Schannel (the native Windows SSL library). Prior to 7.77.0 this was the
+default behavior in libcurl with Schannel. Since the server can request any
+certificate that supports client authentication in the OS certificate store it
+could be a privacy violation and unexpected.
+(Added in 7.77.0)
.SH DEFAULT
0
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
index 9bfe577d5..163320b59 100644
--- a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
@@ -60,6 +60,14 @@ Tell libcurl to use the operating system's native CA store for certificate
verification. Works only on Windows when built to use OpenSSL. This option is
experimental and behavior is subject to change.
(Added in 7.71.0)
+.IP CURLSSLOPT_AUTO_CLIENT_CERT
+Tell libcurl to automatically locate and use a client certificate for
+authentication, when requested by the server. This option is only supported
+for Schannel (the native Windows SSL library). Prior to 7.77.0 this was the
+default behavior in libcurl with Schannel. Since the server can request any
+certificate that supports client authentication in the OS certificate store it
+could be a privacy violation and unexpected.
+(Added in 7.77.0)
.SH DEFAULT
0
.SH PROTOCOLS
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index 5ff3a3503..0f5e95740 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -816,6 +816,7 @@ CURLSSLBACKEND_SCHANNEL 7.34.0
CURLSSLBACKEND_SECURETRANSPORT 7.64.1
CURLSSLBACKEND_WOLFSSL 7.49.0
CURLSSLOPT_ALLOW_BEAST 7.25.0
+CURLSSLOPT_AUTO_CLIENT_CERT 7.77.0
CURLSSLOPT_NATIVE_CA 7.71.0
CURLSSLOPT_NO_PARTIALCHAIN 7.68.0
CURLSSLOPT_NO_REVOKE 7.44.0
diff --git a/docs/options-in-versions b/docs/options-in-versions
index 27497b7c1..6fada9381 100644
--- a/docs/options-in-versions
+++ b/docs/options-in-versions
@@ -169,6 +169,7 @@
--proxy-pinnedpubkey 7.59.0
--proxy-service-name 7.43.0
--proxy-ssl-allow-beast 7.52.0
+--proxy-ssl-auto-client-cert 7.77.0
--proxy-tls13-ciphers 7.61.0
--proxy-tlsauthtype 7.52.0
--proxy-tlspassword 7.52.0
@@ -212,6 +213,7 @@
--speed-time (-y) 4.7
--ssl 7.20.0
--ssl-allow-beast 7.25.0
+--ssl-auto-client-cert 7.77.0
--ssl-no-revoke 7.44.0
--ssl-reqd 7.20.0
--ssl-revoke-best-effort 7.70.0
diff --git a/include/curl/curl.h b/include/curl/curl.h
index bed8068b0..40b5ed129 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -888,6 +888,10 @@ typedef enum {
operating system. Currently implemented under MS-Windows. */
#define CURLSSLOPT_NATIVE_CA (1<<4)
+/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use
+ a client certificate for authentication. (Schannel) */
+#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5)
+
/* The default connection attempt delay in milliseconds for happy eyeballs.
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
this value, keep them in sync. */
diff --git a/lib/doh.c b/lib/doh.c
index 52388cba3..8ea53ff8d 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -351,7 +351,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
(data->set.ssl.revoke_best_effort ?
CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
(data->set.ssl.native_ca_store ?
- CURLSSLOPT_NATIVE_CA : 0);
+ CURLSSLOPT_NATIVE_CA : 0) |
+ (data->set.ssl.auto_client_cert ?
+ CURLSSLOPT_AUTO_CLIENT_CERT : 0);
+
curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask);
}
diff --git a/lib/setopt.c b/lib/setopt.c
index ff6cb4276..16b83321d 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -2290,6 +2290,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
+ data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
/* If a setting is added here it should also be added in dohprobe()
which sets its own CURLOPT_SSL_OPTIONS based on these settings. */
break;
@@ -2301,9 +2302,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
(bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
- data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
data->set.proxy_ssl.revoke_best_effort =
!!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
+ data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
+ data->set.proxy_ssl.auto_client_cert =
+ !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
break;
#endif
diff --git a/lib/urldata.h b/lib/urldata.h
index b7b17e30c..c8797698a 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -286,6 +286,8 @@ struct ssl_config_data {
BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation
list errors */
BIT(native_ca_store); /* use the native ca store of operating system */
+ BIT(auto_client_cert); /* automatically locate and use a client
+ certificate for authentication (Schannel) */
};
struct ssl_general_config {
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index b944bbd49..7d96cf7fc 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -553,6 +553,20 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
"names in server certificates.\n"));
}
+ /* security request flags */
+ BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
+ ISC_REQ_STREAM;
+
+ if(!SSL_SET_OPTION(auto_client_cert)) {
+ schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS;
+ schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
+ BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
+ infof(data, "schannel: disabled automatic use of client certificate\n");
+ }
+ else
+ infof(data, "schannel: enabled automatic use of client certificate\n");
+
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
@@ -886,11 +900,6 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
- /* setup request flags */
- BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
- ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
- ISC_REQ_STREAM;
-
/* allocate memory for the security context handle */
BACKEND->ctxt = (struct Curl_schannel_ctxt *)
calloc(1, sizeof(struct Curl_schannel_ctxt));
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index 23e3af204..979820650 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -870,6 +870,8 @@
d c X'0008'
d CURLSSLOPT_NATIVE_CA...
d c X'0010'
+ d CURLSSLOPT_AUTO_CLIENT_CERT...
+ d c X'0020'
*
d CURL_HET_DEFAULT...
d c 200
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 95c66d081..c7c8dfea5 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -267,6 +267,9 @@ struct OperationConfig {
revocation list errors */
bool native_ca_store; /* use the native os ca store */
+ bool ssl_auto_client_cert; /* automatically locate and use a client
+ certificate for authentication (Schannel) */
+ bool proxy_ssl_auto_client_cert; /* proxy version of ssl_auto_client_cert */
bool use_metalink; /* process given URLs as metalink XML file */
struct metalinkfile *metalinkfile_list; /* point to the first node */
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index ad89ea312..d616b255c 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -247,7 +247,8 @@ static const struct LongShort aliases[]= {
{"El", "tlspassword", ARG_STRING},
{"Em", "tlsauthtype", ARG_STRING},
{"En", "ssl-allow-beast", ARG_BOOL},
- /* Eo */
+ {"Eo", "ssl-auto-client-cert", ARG_BOOL},
+ {"EO", "proxy-ssl-auto-client-cert", ARG_BOOL},
{"Ep", "pinnedpubkey", ARG_STRING},
{"EP", "proxy-pinnedpubkey", ARG_STRING},
{"Eq", "cert-status", ARG_BOOL},
@@ -1651,6 +1652,16 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
config->ssl_allow_beast = toggle;
break;
+ case 'o': /* --ssl-auto-client-cert */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->ssl_auto_client_cert = toggle;
+ break;
+
+ case 'O': /* --proxy-ssl-auto-client-cert */
+ if(curlinfo->features & CURL_VERSION_SSL)
+ config->proxy_ssl_auto_client_cert = toggle;
+ break;
+
case 'p': /* Pinned public key DER file */
GetStr(&config->pinnedpubkey, nextarg);
break;
diff --git a/src/tool_help.c b/src/tool_help.c
index 32893547d..78c441e77 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -598,6 +598,9 @@ static const struct helptxt helptext[] = {
{" --proxy-ssl-allow-beast",
"Allow security flaw for interop for HTTPS proxy",
CURLHELP_PROXY | CURLHELP_TLS},
+ {" --proxy-ssl-auto-client-cert",
+ "Use auto client certificate for proxy (Schannel)",
+ CURLHELP_PROXY | CURLHELP_TLS},
{" --proxy-tls13-ciphers <ciphersuite list>",
"TLS 1.3 proxy cipher suites",
CURLHELP_PROXY | CURLHELP_TLS},
@@ -727,6 +730,9 @@ static const struct helptxt helptext[] = {
{" --ssl-allow-beast",
"Allow security flaw to improve interop",
CURLHELP_TLS},
+ {" --ssl-auto-client-cert",
+ "Use auto client certificate (Schannel)",
+ CURLHELP_TLS},
{" --ssl-no-revoke",
"Disable cert revocation checks (Schannel)",
CURLHELP_TLS},
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 5e7a9fa87..cd6131692 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -1720,20 +1720,31 @@ static CURLcode single_transfer(struct GlobalConfig *global,
{
long mask =
- (config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
+ (config->ssl_allow_beast ?
+ CURLSSLOPT_ALLOW_BEAST : 0) |
+ (config->ssl_no_revoke ?
+ CURLSSLOPT_NO_REVOKE : 0) |
(config->ssl_revoke_best_effort ?
CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
(config->native_ca_store ?
CURLSSLOPT_NATIVE_CA : 0) |
- (config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0);
+ (config->ssl_auto_client_cert ?
+ CURLSSLOPT_AUTO_CLIENT_CERT : 0);
if(mask)
my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
}
- if(config->proxy_ssl_allow_beast)
- my_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS,
- (long)CURLSSLOPT_ALLOW_BEAST);
+ {
+ long mask =
+ (config->proxy_ssl_allow_beast ?
+ CURLSSLOPT_ALLOW_BEAST : 0) |
+ (config->proxy_ssl_auto_client_cert ?
+ CURLSSLOPT_AUTO_CLIENT_CERT : 0);
+
+ if(mask)
+ my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask);
+ }
}
if(config->path_as_is)
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
index 196affc04..673f6b35d 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -133,6 +133,7 @@ const struct NameValueUnsigned setopt_nv_CURLSSLOPT[] = {
NV(CURLSSLOPT_NO_PARTIALCHAIN),
NV(CURLSSLOPT_REVOKE_BEST_EFFORT),
NV(CURLSSLOPT_NATIVE_CA),
+ NV(CURLSSLOPT_AUTO_CLIENT_CERT),
NVEND,
};
diff --git a/src/tool_setopt.h b/src/tool_setopt.h
index a54e34639..a2711fb00 100644
--- a/src/tool_setopt.h
+++ b/src/tool_setopt.h
@@ -76,6 +76,7 @@ extern const struct NameValueUnsigned setopt_nv_CURLHSTS[];
#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_PROXY_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