rustls: tidy up

Closes #16796
This commit is contained in:
Daniel McCarney 2025-03-21 14:43:07 -04:00 committed by Daniel Stenberg
parent e601668154
commit 088f0e6a5b
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2

View file

@ -8,6 +8,7 @@
* Copyright (C) Jacob Hoffman-Andrews,
* <github@hoffman-andrews.com>
* Copyright (C) kpcyrd, <kpcyrd@archlinux.org>
* Copyright (C) Daniel McCarney, <daniel@binaryparadox.net>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -37,12 +38,8 @@
#include "vtls.h"
#include "vtls_int.h"
#include "rustls.h"
#include "select.h"
#include "strerror.h"
#include "multiif.h"
#include "connect.h" /* for the connect timeout */
#include "cipher_suite.h"
#include "rand.h"
#include "x509asn1.h"
struct rustls_ssl_backend_data
@ -55,7 +52,7 @@ struct rustls_ssl_backend_data
};
/* For a given rustls_result error code, return the best-matching CURLcode. */
static CURLcode map_error(rustls_result r)
static CURLcode map_error(const rustls_result r)
{
if(rustls_result_is_cert_error(r)) {
return CURLE_PEER_FAILED_VERIFICATION;
@ -70,10 +67,19 @@ static CURLcode map_error(rustls_result r)
}
}
static void
rustls_failf(struct Curl_easy *data, const rustls_result rr, const char *msg)
{
char errorbuf[STRERROR_LEN];
size_t errorlen;
rustls_error(rr, errorbuf, sizeof(errorbuf), &errorlen);
failf(data, "%s: %.*s", msg, (int)errorlen, errorbuf);
}
static bool
cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
{
struct ssl_connect_data *ctx = cf->ctx;
const struct ssl_connect_data *ctx = cf->ctx;
struct rustls_ssl_backend_data *backend;
(void)data;
@ -90,7 +96,7 @@ struct io_ctx {
static int
read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
{
struct io_ctx *io_ctx = userdata;
const struct io_ctx *io_ctx = userdata;
struct ssl_connect_data *const connssl = io_ctx->cf->ctx;
CURLcode result;
int ret = 0;
@ -115,7 +121,7 @@ read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
static int
write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
{
struct io_ctx *io_ctx = userdata;
const struct io_ctx *io_ctx = userdata;
CURLcode result;
int ret = 0;
ssize_t nwritten = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data,
@ -137,7 +143,7 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
static ssize_t tls_recv_more(struct Curl_cfilter *cf,
struct Curl_easy *data, CURLcode *err)
{
struct ssl_connect_data *const connssl = cf->ctx;
const struct ssl_connect_data *const connssl = cf->ctx;
struct rustls_ssl_backend_data *const backend =
(struct rustls_ssl_backend_data *)connssl->backend;
struct io_ctx io_ctx;
@ -163,11 +169,7 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf,
rresult = rustls_connection_process_new_packets(backend->conn);
if(rresult != RUSTLS_RESULT_OK) {
char errorbuf[255];
size_t errorlen;
rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
failf(data, "rustls_connection_process_new_packets: %.*s",
(int)errorlen, errorbuf);
rustls_failf(data, rresult, "rustls_connection_process_new_packets");
*err = map_error(rresult);
return -1;
}
@ -193,7 +195,7 @@ static ssize_t
cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *plainbuf, size_t plainlen, CURLcode *err)
{
struct ssl_connect_data *const connssl = cf->ctx;
const struct ssl_connect_data *const connssl = cf->ctx;
struct rustls_ssl_backend_data *const backend =
(struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
@ -233,10 +235,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
}
else if(rresult != RUSTLS_RESULT_OK) {
/* n always equals 0 in this case, do not need to check it */
char errorbuf[255];
size_t errorlen;
rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
failf(data, "rustls_connection_read: %.*s", (int)errorlen, errorbuf);
rustls_failf(data, rresult, "rustls_connection_read");
*err = CURLE_RECV_ERROR;
nread = -1;
goto out;
@ -279,7 +278,6 @@ static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data,
rustls_io_result io_error;
size_t tlswritten = 0;
size_t tlswritten_total = 0;
CURLcode result = CURLE_OK;
io_ctx.cf = cf;
io_ctx.data = data;
@ -305,7 +303,7 @@ static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data,
CURL_TRC_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten);
tlswritten_total += tlswritten;
}
return result;
return CURLE_OK;
}
/*
@ -322,14 +320,11 @@ static ssize_t
cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *plainbuf, size_t plainlen, CURLcode *err)
{
struct ssl_connect_data *const connssl = cf->ctx;
const struct ssl_connect_data *const connssl = cf->ctx;
struct rustls_ssl_backend_data *const backend =
(struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
size_t plainwritten = 0;
rustls_result rresult;
char errorbuf[256];
size_t errorlen;
const unsigned char *buf = plainbuf;
size_t blen = plainlen;
ssize_t nwritten = 0;
@ -361,11 +356,11 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
}
if(blen > 0) {
rustls_result rresult;
CURL_TRC_CF(data, cf, "cf_send: adding %zu plain bytes to Rustls", blen);
rresult = rustls_connection_write(rconn, buf, blen, &plainwritten);
if(rresult != RUSTLS_RESULT_OK) {
rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
failf(data, "rustls_connection_write: %.*s", (int)errorlen, errorbuf);
rustls_failf(data, rresult, "rustls_connection_write");
*err = CURLE_WRITE_ERROR;
return -1;
}
@ -419,7 +414,7 @@ read_file_into(const char *filename,
while(!feof(f)) {
uint8_t buf[256];
size_t rr = fread(buf, 1, sizeof(buf), f);
const size_t rr = fread(buf, 1, sizeof(buf), f);
if(rr == 0 ||
CURLE_OK != Curl_dyn_addn(out, buf, rr)) {
fclose(f);
@ -437,8 +432,8 @@ cr_get_selected_ciphers(struct Curl_easy *data,
const struct rustls_supported_ciphersuite **selected,
size_t *selected_size)
{
size_t supported_len = *selected_size;
size_t default_len = rustls_default_crypto_provider_ciphersuites_len();
const size_t supported_len = *selected_size;
const size_t default_len = rustls_default_crypto_provider_ciphersuites_len();
const struct rustls_supported_ciphersuite *entry;
const char *ciphers = ciphers12;
size_t count = 0, default13_count = 0, i, j;
@ -524,246 +519,329 @@ add_ciphers:
}
static CURLcode
cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
struct rustls_ssl_backend_data *const backend)
init_config_builder(struct Curl_easy *data,
const struct ssl_primary_config *conn_config,
struct rustls_client_config_builder **config_builder)
{
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
const struct rustls_supported_ciphersuite **cipher_suites = NULL;
struct rustls_crypto_provider_builder *custom_provider_builder = NULL;
const struct rustls_crypto_provider *custom_provider = NULL;
struct rustls_connection *rconn = NULL;
struct rustls_client_config_builder *config_builder = NULL;
uint16_t tls_versions[2] = {
RUSTLS_TLS_VERSION_TLSV1_2,
RUSTLS_TLS_VERSION_TLSV1_3,
};
size_t tls_versions_len = 2;
size_t cipher_suites_len =
rustls_default_crypto_provider_ciphersuites_len();
CURLcode result = CURLE_OK;
rustls_result rr;
switch(conn_config->version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
break;
case CURL_SSLVERSION_TLSv1_3:
tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3;
tls_versions_len = 1;
break;
default:
failf(data, "rustls: unsupported minimum TLS version value");
result = CURLE_BAD_FUNCTION_ARGUMENT;
goto cleanup;
}
switch(conn_config->version_max) {
case CURL_SSLVERSION_MAX_DEFAULT:
case CURL_SSLVERSION_MAX_NONE:
case CURL_SSLVERSION_MAX_TLSv1_3:
break;
case CURL_SSLVERSION_MAX_TLSv1_2:
if(tls_versions[0] == RUSTLS_TLS_VERSION_TLSV1_2) {
tls_versions_len = 1;
break;
}
FALLTHROUGH();
case CURL_SSLVERSION_MAX_TLSv1_1:
case CURL_SSLVERSION_MAX_TLSv1_0:
default:
failf(data, "rustls: unsupported maximum TLS version value");
result = CURLE_BAD_FUNCTION_ARGUMENT;
goto cleanup;
}
cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len));
if(!cipher_suites) {
result = CURLE_OUT_OF_MEMORY;
goto cleanup;
}
cr_get_selected_ciphers(data,
conn_config->cipher_list,
conn_config->cipher_list13,
cipher_suites, &cipher_suites_len);
if(cipher_suites_len == 0) {
failf(data, "rustls: no supported cipher in list");
result = CURLE_SSL_CIPHER;
goto cleanup;
}
rr = rustls_crypto_provider_builder_new_from_default(
&custom_provider_builder);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr,
"failed to create crypto provider builder from default");
result = CURLE_SSL_CIPHER;
goto cleanup;
}
rr =
rustls_crypto_provider_builder_set_cipher_suites(
custom_provider_builder,
cipher_suites,
cipher_suites_len);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr,
"failed to set ciphersuites for crypto provider builder");
result = CURLE_SSL_CIPHER;
goto cleanup;
}
rr = rustls_crypto_provider_builder_build(
custom_provider_builder, &custom_provider);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to build custom crypto provider");
result = CURLE_SSL_CIPHER;
goto cleanup;
}
rr = rustls_client_config_builder_new_custom(custom_provider,
tls_versions,
tls_versions_len,
config_builder);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to create client config builder");
result = CURLE_SSL_CIPHER;
goto cleanup;
}
cleanup:
if(cipher_suites) {
free(cipher_suites);
}
if(custom_provider_builder) {
rustls_crypto_provider_builder_free(custom_provider_builder);
}
if(custom_provider) {
rustls_crypto_provider_free(custom_provider);
}
return result;
}
static void
init_config_builder_alpn(struct Curl_easy *data,
const struct ssl_connect_data *connssl,
struct rustls_client_config_builder *config_builder) {
struct alpn_proto_buf proto;
rustls_slice_bytes alpn[ALPN_ENTRIES_MAX];
size_t i;
for(i = 0; i < connssl->alpn->count; ++i) {
alpn[i].data = (const uint8_t *)connssl->alpn->entries[i];
alpn[i].len = strlen(connssl->alpn->entries[i]);
}
rustls_client_config_builder_set_alpn_protocols(config_builder, alpn,
connssl->alpn->count);
Curl_alpn_to_proto_str(&proto, connssl->alpn);
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
static CURLcode
init_config_builder_verifier_crl(
struct Curl_easy *data,
const struct ssl_primary_config *conn_config,
struct rustls_web_pki_server_cert_verifier_builder *builder)
{
CURLcode result = CURLE_OK;
struct dynbuf crl_contents;
rustls_result rr;
Curl_dyn_init(&crl_contents, DYN_CRLFILE_SIZE);
if(!read_file_into(conn_config->CRLfile, &crl_contents)) {
failf(data, "rustls: failed to read revocation list file");
result = CURLE_SSL_CRL_BADFILE;
goto cleanup;
}
rr = rustls_web_pki_server_cert_verifier_builder_add_crl(
builder,
Curl_dyn_uptr(&crl_contents),
Curl_dyn_len(&crl_contents));
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to parse revocation list");
result = CURLE_SSL_CRL_BADFILE;
goto cleanup;
}
cleanup:
Curl_dyn_free(&crl_contents);
return result;
}
static CURLcode
init_config_builder_verifier(struct Curl_easy *data,
struct rustls_client_config_builder *builder,
const struct ssl_primary_config *conn_config,
const struct curl_blob *ca_info_blob,
const char * const ssl_cafile) {
const struct rustls_root_cert_store *roots = NULL;
struct rustls_root_cert_store_builder *roots_builder = NULL;
struct rustls_web_pki_server_cert_verifier_builder *verifier_builder = NULL;
struct rustls_server_cert_verifier *server_cert_verifier = NULL;
rustls_result rr = RUSTLS_RESULT_OK;
CURLcode result = CURLE_OK;
roots_builder = rustls_root_cert_store_builder_new();
if(ca_info_blob) {
rr = rustls_root_cert_store_builder_add_pem(roots_builder,
ca_info_blob->data,
ca_info_blob->len,
1);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to parse trusted certificates from blob");
result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
}
else if(ssl_cafile) {
rr = rustls_root_cert_store_builder_load_roots_from_file(roots_builder,
ssl_cafile,
1);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to load trusted certificates");
result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
}
rr = rustls_root_cert_store_builder_build(roots_builder, &roots);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to build trusted root certificate store");
result = CURLE_SSL_CACERT_BADFILE;
}
verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots);
if(conn_config->CRLfile) {
result = init_config_builder_verifier_crl(data,
conn_config,
verifier_builder);
if(result != CURLE_OK) {
goto cleanup;
}
}
rr = rustls_web_pki_server_cert_verifier_builder_build(
verifier_builder, &server_cert_verifier);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to build certificate verifier");
result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
rustls_client_config_builder_set_server_verifier(builder,
server_cert_verifier);
cleanup:
if(roots_builder) {
rustls_root_cert_store_builder_free(roots_builder);
}
if(roots) {
rustls_root_cert_store_free(roots);
}
if(verifier_builder) {
rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
}
if(server_cert_verifier) {
rustls_server_cert_verifier_free(server_cert_verifier);
}
return result;
}
static CURLcode
cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
struct rustls_ssl_backend_data *const backend)
{
const struct ssl_connect_data *connssl = cf->ctx;
const struct ssl_primary_config *conn_config =
Curl_ssl_cf_get_primary_config(cf);
struct rustls_connection *rconn = NULL;
struct rustls_client_config_builder *config_builder = NULL;
const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
const char * const ssl_cafile =
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
(ca_info_blob ? NULL : conn_config->CAfile);
const bool verifypeer = conn_config->verifypeer;
char errorbuf[256];
size_t errorlen;
rustls_result result;
CURLcode result = CURLE_OK;
rustls_result rr;
DEBUGASSERT(backend);
rconn = backend->conn;
{
uint16_t tls_versions[2] = {
RUSTLS_TLS_VERSION_TLSV1_2,
RUSTLS_TLS_VERSION_TLSV1_3,
};
size_t tls_versions_len = 2;
const struct rustls_supported_ciphersuite **cipher_suites;
size_t cipher_suites_len =
rustls_default_crypto_provider_ciphersuites_len();
switch(conn_config->version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
break;
case CURL_SSLVERSION_TLSv1_3:
tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3;
tls_versions_len = 1;
break;
default:
failf(data, "rustls: unsupported minimum TLS version value");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
switch(conn_config->version_max) {
case CURL_SSLVERSION_MAX_DEFAULT:
case CURL_SSLVERSION_MAX_NONE:
case CURL_SSLVERSION_MAX_TLSv1_3:
break;
case CURL_SSLVERSION_MAX_TLSv1_2:
if(tls_versions[0] == RUSTLS_TLS_VERSION_TLSV1_2) {
tls_versions_len = 1;
break;
}
FALLTHROUGH();
case CURL_SSLVERSION_MAX_TLSv1_1:
case CURL_SSLVERSION_MAX_TLSv1_0:
default:
failf(data, "rustls: unsupported maximum TLS version value");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len));
if(!cipher_suites)
return CURLE_OUT_OF_MEMORY;
cr_get_selected_ciphers(data,
conn_config->cipher_list,
conn_config->cipher_list13,
cipher_suites, &cipher_suites_len);
if(cipher_suites_len == 0) {
failf(data, "rustls: no supported cipher in list");
free(cipher_suites);
return CURLE_SSL_CIPHER;
}
result = rustls_crypto_provider_builder_new_from_default(
&custom_provider_builder);
if(result != RUSTLS_RESULT_OK) {
failf(data,
"rustls: failed to create crypto provider builder from default");
return CURLE_SSL_CIPHER;
}
result =
rustls_crypto_provider_builder_set_cipher_suites(
custom_provider_builder,
cipher_suites,
cipher_suites_len);
if(result != RUSTLS_RESULT_OK) {
failf(data,
"rustls: failed to set ciphersuites for crypto provider builder");
rustls_crypto_provider_builder_free(custom_provider_builder);
return CURLE_SSL_CIPHER;
}
result = rustls_crypto_provider_builder_build(
custom_provider_builder, &custom_provider);
if(result != RUSTLS_RESULT_OK) {
failf(data, "rustls: failed to build custom crypto provider");
rustls_crypto_provider_builder_free(custom_provider_builder);
return CURLE_SSL_CIPHER;
}
result = rustls_client_config_builder_new_custom(custom_provider,
tls_versions,
tls_versions_len,
&config_builder);
free(cipher_suites);
if(result != RUSTLS_RESULT_OK) {
failf(data, "rustls: failed to create client config");
return CURLE_SSL_CIPHER;
}
result = init_config_builder(data, conn_config, &config_builder);
if(result != CURLE_OK) {
return result;
}
rustls_crypto_provider_builder_free(custom_provider_builder);
rustls_crypto_provider_free(custom_provider);
if(connssl->alpn) {
struct alpn_proto_buf proto;
rustls_slice_bytes alpn[ALPN_ENTRIES_MAX];
size_t i;
for(i = 0; i < connssl->alpn->count; ++i) {
alpn[i].data = (const uint8_t *)connssl->alpn->entries[i];
alpn[i].len = strlen(connssl->alpn->entries[i]);
}
rustls_client_config_builder_set_alpn_protocols(config_builder, alpn,
connssl->alpn->count);
Curl_alpn_to_proto_str(&proto, connssl->alpn);
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
init_config_builder_alpn(data, connssl, config_builder);
}
if(!verifypeer) {
if(!conn_config->verifypeer) {
rustls_client_config_builder_dangerous_set_certificate_verifier(
config_builder, cr_verify_none);
}
else if(ca_info_blob || ssl_cafile) {
roots_builder = rustls_root_cert_store_builder_new();
if(ca_info_blob) {
/* Enable strict parsing only if verification is not disabled. */
result = rustls_root_cert_store_builder_add_pem(roots_builder,
ca_info_blob->data,
ca_info_blob->len,
verifypeer);
if(result != RUSTLS_RESULT_OK) {
failf(data, "rustls: failed to parse trusted certificates from blob");
rustls_root_cert_store_builder_free(roots_builder);
rustls_client_config_builder_free(config_builder);
return CURLE_SSL_CACERT_BADFILE;
}
}
else if(ssl_cafile) {
/* Enable strict parsing only if verification is not disabled. */
result = rustls_root_cert_store_builder_load_roots_from_file(
roots_builder, ssl_cafile, verifypeer);
if(result != RUSTLS_RESULT_OK) {
failf(data, "rustls: failed to load trusted certificates");
rustls_root_cert_store_builder_free(roots_builder);
rustls_client_config_builder_free(config_builder);
return CURLE_SSL_CACERT_BADFILE;
}
}
result = rustls_root_cert_store_builder_build(roots_builder, &roots);
rustls_root_cert_store_builder_free(roots_builder);
if(result != RUSTLS_RESULT_OK) {
failf(data, "rustls: failed to build trusted root certificate store");
result = init_config_builder_verifier(data,
config_builder,
conn_config,
ca_info_blob,
ssl_cafile);
if(result != CURLE_OK) {
rustls_client_config_builder_free(config_builder);
return CURLE_SSL_CACERT_BADFILE;
return result;
}
verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots);
rustls_root_cert_store_free(roots);
if(conn_config->CRLfile) {
struct dynbuf crl_contents;
Curl_dyn_init(&crl_contents, DYN_CRLFILE_SIZE);
if(!read_file_into(conn_config->CRLfile, &crl_contents)) {
failf(data, "rustls: failed to read revocation list file");
Curl_dyn_free(&crl_contents);
rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
return CURLE_SSL_CRL_BADFILE;
}
result = rustls_web_pki_server_cert_verifier_builder_add_crl(
verifier_builder,
Curl_dyn_uptr(&crl_contents),
Curl_dyn_len(&crl_contents));
Curl_dyn_free(&crl_contents);
if(result != RUSTLS_RESULT_OK) {
failf(data, "rustls: failed to parse revocation list");
rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
return CURLE_SSL_CRL_BADFILE;
}
}
result = rustls_web_pki_server_cert_verifier_builder_build(
verifier_builder, &server_cert_verifier);
rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
if(result != RUSTLS_RESULT_OK) {
failf(data, "rustls: failed to build certificate verifier");
rustls_server_cert_verifier_free(server_cert_verifier);
rustls_client_config_builder_free(config_builder);
return CURLE_SSL_CACERT_BADFILE;
}
rustls_client_config_builder_set_server_verifier(config_builder,
server_cert_verifier);
rustls_server_cert_verifier_free(server_cert_verifier);
}
result = rustls_client_config_builder_build(
rr = rustls_client_config_builder_build(
config_builder,
&backend->config);
if(result != RUSTLS_RESULT_OK) {
failf(data, "rustls: failed to build client config");
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to build client config");
rustls_client_config_builder_free(config_builder);
rustls_client_config_free(backend->config);
return CURLE_SSL_CONNECT_ERROR;
}
DEBUGASSERT(rconn == NULL);
result = rustls_client_connection_new(backend->config,
connssl->peer.hostname, &rconn);
if(result != RUSTLS_RESULT_OK) {
rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
failf(data, "rustls_client_connection_new: %.*s", (int)errorlen, errorbuf);
rr = rustls_client_connection_new(backend->config,
connssl->peer.hostname,
&rconn);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, result, "rustls_client_connection_new");
return CURLE_COULDNT_CONNECT;
}
DEBUGASSERT(rconn);
rustls_connection_set_userdata(rconn, backend);
backend->conn = rconn;
return CURLE_OK;
return result;
}
static void
@ -788,9 +866,9 @@ cr_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, bool *done)
{
struct ssl_connect_data *const connssl = cf->ctx;
struct rustls_ssl_backend_data *const backend =
const struct rustls_ssl_backend_data *const backend =
(struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
const struct rustls_connection *rconn = NULL;
CURLcode tmperr = CURLE_OK;
int result;
bool wants_read;
@ -835,8 +913,10 @@ cr_connect(struct Curl_cfilter *cf,
}
/* REALLY Done with the handshake. */
{
uint16_t proto = rustls_connection_get_protocol_version(rconn);
uint16_t cipher = rustls_connection_get_negotiated_ciphersuite(rconn);
const uint16_t proto =
rustls_connection_get_protocol_version(rconn);
const uint16_t cipher =
rustls_connection_get_negotiated_ciphersuite(rconn);
char buf[64] = "";
const char *ver = "TLS version unknown";
if(proto == RUSTLS_TLS_VERSION_TLSV1_3)
@ -944,14 +1024,13 @@ cr_get_internals(struct ssl_connect_data *connssl,
static CURLcode
cr_shutdown(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool send_shutdown, bool *done)
const bool send_shutdown, bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
struct rustls_ssl_backend_data *backend =
(struct rustls_ssl_backend_data *)connssl->backend;
CURLcode result = CURLE_OK;
ssize_t nwritten, nread;
char buf[1024];
size_t i;
DEBUGASSERT(backend);
@ -984,6 +1063,7 @@ cr_shutdown(struct Curl_cfilter *cf,
}
for(i = 0; i < 10; ++i) {
char buf[1024];
nread = cr_recv(cf, data, buf, (int)sizeof(buf), &result);
if(nread <= 0)
break;
@ -1013,7 +1093,7 @@ out:
static void
cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
const struct ssl_connect_data *connssl = cf->ctx;
struct rustls_ssl_backend_data *backend =
(struct rustls_ssl_backend_data *)connssl->backend;
@ -1031,7 +1111,7 @@ cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
static size_t cr_version(char *buffer, size_t size)
{
struct rustls_str ver = rustls_version();
const struct rustls_str ver = rustls_version();
return msnprintf(buffer, size, "%.*s", (int)ver.len, ver.data);
}