mirror of
https://github.com/curl/curl.git
synced 2025-04-12 16:20:35 +08:00
rustls: support ECH w/ DoH lookup for config
E.g. `curl --tlsv1.3 --doh-url https://one.one.one.one/dns-query --ech true ...` Closes #16828
This commit is contained in:
parent
b1ba919676
commit
07addb54f4
@ -900,58 +900,94 @@ cleanup:
|
||||
#if defined(USE_ECH)
|
||||
static CURLcode
|
||||
init_config_builder_ech(struct Curl_easy *data,
|
||||
const struct ssl_connect_data *connssl,
|
||||
struct rustls_client_config_builder *builder)
|
||||
{
|
||||
const rustls_hpke *hpke = rustls_supported_hpke();
|
||||
unsigned char *ech_config = NULL;
|
||||
size_t ech_config_len = 0;
|
||||
struct Curl_dns_entry *dns = NULL;
|
||||
struct Curl_https_rrinfo *rinfo = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
rustls_result rr;
|
||||
|
||||
if(!hpke) {
|
||||
failf(data,
|
||||
"rustls: ECH unavailable, rustls-ffi built without "
|
||||
"HPKE compatible crypto provider");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_ECH_PUBLIC]) {
|
||||
failf(data, "rustls: ECH outername not supported");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if(data->set.tls_ech == CURLECH_GREASE) {
|
||||
rustls_result rr;
|
||||
rr = rustls_client_config_builder_enable_ech_grease(builder, hpke);
|
||||
if(rr != RUSTLS_RESULT_OK) {
|
||||
rustls_failf(data, rr, "rustls: failed to configure ECH GREASE");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
else if(data->set.tls_ech & CURLECH_CLA_CFG
|
||||
|
||||
if(data->set.tls_ech & CURLECH_CLA_CFG
|
||||
&& data->set.str[STRING_ECH_CONFIG]) {
|
||||
const char *b64 = data->set.str[STRING_ECH_CONFIG];
|
||||
size_t decode_result;
|
||||
rustls_result rr;
|
||||
if(!b64) {
|
||||
infof(data, "rustls: ECHConfig from command line empty");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
/* rustls-ffi expects the raw TLS encoded ECHConfigList bytes */
|
||||
decode_result = Curl_base64_decode(b64, &ech_config, &ech_config_len);
|
||||
if(decode_result || !ech_config) {
|
||||
infof(data, "rustls: cannot base64 decode ECHConfig from command line");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
rr = rustls_client_config_builder_enable_ech(builder,
|
||||
ech_config,
|
||||
ech_config_len,
|
||||
hpke);
|
||||
if(rr != RUSTLS_RESULT_OK) {
|
||||
rustls_failf(data, rr, "rustls: failed to configure ECH");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(connssl->peer.hostname) {
|
||||
dns = Curl_fetch_addr(
|
||||
data,
|
||||
connssl->peer.hostname,
|
||||
connssl->peer.port);
|
||||
}
|
||||
if(!dns) {
|
||||
failf(data, "rustls: ECH requested but no DNS info available");
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
rinfo = dns->hinfo;
|
||||
if(!rinfo || !rinfo->echconfiglist) {
|
||||
failf(data, "rustls: ECH requested but no ECHConfig available");
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
ech_config = rinfo->echconfiglist;
|
||||
ech_config_len = rinfo->echconfiglist_len;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
rr = rustls_client_config_builder_enable_ech(builder,
|
||||
ech_config,
|
||||
ech_config_len,
|
||||
hpke);
|
||||
if(rr != RUSTLS_RESULT_OK) {
|
||||
rustls_failf(data, rr, "rustls: failed to configure ECH");
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
cleanup:
|
||||
if(dns) {
|
||||
Curl_resolv_unlink(data, &dns);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif /* USE_ECH */
|
||||
|
||||
@ -1014,7 +1050,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
|
||||
#if defined(USE_ECH)
|
||||
if(ECH_ENABLED(data)) {
|
||||
result = init_config_builder_ech(data, config_builder);
|
||||
result = init_config_builder_ech(data, connssl, config_builder);
|
||||
if(result != CURLE_OK && data->set.tls_ech & CURLECH_HARD) {
|
||||
rustls_client_config_builder_free(config_builder);
|
||||
return result;
|
||||
|
Loading…
x
Reference in New Issue
Block a user