summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen M. Coakley <me@stephencoakley.com>2022-01-09 15:59:30 -0600
committerDaniel Stenberg <daniel@haxx.se>2022-01-10 09:30:12 +0100
commit3be94d84fcff2a154d6eca8e7807b5813587fb24 (patch)
tree11622fa621ccc884fd8e61e1d8934c33e88ac623
parentdbde76bdd6018ba68bf7192a514e4048f014cea3 (diff)
downloadcurl-3be94d84fcff2a154d6eca8e7807b5813587fb24.tar.gz
rustls: add CURLOPT_CAINFO_BLOB support
Add support for `CURLOPT_CAINFO_BLOB` `CURLOPT_PROXY_CAINFO_BLOB` to the rustls TLS backend. Multiple certificates in a single PEM string are supported just like OpenSSL does with this option. This is compatible at least with rustls-ffi 0.8+ which is our new minimum version anyway. I was able to build and run this on Windows, pulling trusted certs from the system and then add them to rustls by setting `CURLOPT_CAINFO_BLOB`. Handy! Closes #8255
-rw-r--r--docs/libcurl/opts/CURLOPT_CAINFO_BLOB.32
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.32
-rw-r--r--lib/vtls/rustls.c34
3 files changed, 33 insertions, 5 deletions
diff --git a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3 b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3
index 777b2e336..deae4ee06 100644
--- a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3
@@ -62,7 +62,7 @@ if(curl) {
Added in 7.77.0.
This option is supported by the BearSSL (since 7.79.0), mbedTLS (since 7.81.0),
-OpenSSL, Secure Transport and Schannel backends.
+rustls (since 7.82.0), OpenSSL, Secure Transport and Schannel backends.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3
index df6ebe16f..a85552e56 100644
--- a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3
@@ -65,7 +65,7 @@ if(curl) {
.SH AVAILABILITY
Added in 7.77.0.
-This option is supported by the OpenSSL, Secure
+This option is supported by the rustls (since 7.82.0), OpenSSL, Secure
Transport and Schannel backends.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c
index 6dbb1ef3c..51230b196 100644
--- a/lib/vtls/rustls.c
+++ b/lib/vtls/rustls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020 - 2021, Jacob Hoffman-Andrews,
+ * Copyright (C) 2020 - 2022, Jacob Hoffman-Andrews,
* <github@hoffman-andrews.com>
*
* This software is licensed as described in the file COPYING, which
@@ -297,7 +297,11 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
{
struct rustls_connection *rconn = backend->conn;
struct rustls_client_config_builder *config_builder = NULL;
- const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ struct rustls_root_cert_store *roots = NULL;
+ const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ const char * const ssl_cafile =
+ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+ (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const char *hostname = conn->host.name;
char errorbuf[256];
@@ -328,6 +332,29 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
hostname = "example.invalid";
}
}
+ else if(ca_info_blob) {
+ roots = rustls_root_cert_store_new();
+
+ /* Enable strict parsing only if verification isn't disabled. */
+ result = rustls_root_cert_store_add_pem(roots, ca_info_blob->data,
+ ca_info_blob->len, verifypeer);
+ if(result != RUSTLS_RESULT_OK) {
+ failf(data, "failed to parse trusted certificates from blob");
+ rustls_root_cert_store_free(roots);
+ rustls_client_config_free(
+ rustls_client_config_builder_build(config_builder));
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+
+ result = rustls_client_config_builder_use_roots(config_builder, roots);
+ rustls_root_cert_store_free(roots);
+ if(result != RUSTLS_RESULT_OK) {
+ failf(data, "failed to load trusted certificates");
+ rustls_client_config_free(
+ rustls_client_config_builder_build(config_builder));
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
else if(ssl_cafile) {
result = rustls_client_config_builder_load_roots_from_file(
config_builder, ssl_cafile);
@@ -550,7 +577,8 @@ static size_t cr_version(char *buffer, size_t size)
const struct Curl_ssl Curl_ssl_rustls = {
{ CURLSSLBACKEND_RUSTLS, "rustls" },
- SSLSUPP_TLS13_CIPHERSUITES, /* supports */
+ SSLSUPP_CAINFO_BLOB | /* supports */
+ SSLSUPP_TLS13_CIPHERSUITES,
sizeof(struct ssl_backend_data),
Curl_none_init, /* init */