mirror of
https://github.com/curl/curl.git
synced 2026-08-04 07:49:59 +03:00
ECH: cleanups
- passing an unknown string to CURLOPT_ECH now returns error To properly allow applications to spot if they pass in a typo or something to libcurl. - CURLECH_DISABLE is now a plain zero internally, not a dedicated bit which simplifies checks for when ECH is enabled - Dropped the CURLECH_CLA_CFG bit, and just check STRING_ECH_CONFIG - Turn grease/enable/hard into three different numerical values, no bitmask needed - Convert the struct field 'tls_ech' from an int to a byte. Closes #21532
This commit is contained in:
parent
cda0268593
commit
b174b8b326
7 changed files with 75 additions and 68 deletions
73
lib/setopt.c
73
lib/setopt.c
|
|
@ -1858,6 +1858,45 @@ static CURLcode setopt_copypostfields(const char *ptr, struct UserDefined *s)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_ECH
|
||||
static CURLcode setopt_ech(struct Curl_easy *data, const char *ptr)
|
||||
{
|
||||
struct UserDefined *s = &data->set;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(!ptr || !strcmp(ptr, "false"))
|
||||
s->tls_ech = CURLECH_DISABLE;
|
||||
else {
|
||||
size_t plen = strlen(ptr);
|
||||
if(plen > CURL_MAX_INPUT_LENGTH)
|
||||
result = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
else {
|
||||
if(!strcmp(ptr, "grease"))
|
||||
s->tls_ech = CURLECH_GREASE;
|
||||
else if(!strcmp(ptr, "true"))
|
||||
s->tls_ech = CURLECH_ENABLE;
|
||||
else if(!strcmp(ptr, "hard"))
|
||||
s->tls_ech = CURLECH_HARD;
|
||||
else if(plen > 4 && !strncmp(ptr, "ecl:", 4)) {
|
||||
if(!s->tls_ech)
|
||||
s->tls_ech = CURLECH_HARD;
|
||||
result = Curl_setstropt(&s->str[STRING_ECH_CONFIG], ptr + 4);
|
||||
}
|
||||
else if(plen > 3 && !strncmp(ptr, "pn:", 3)) {
|
||||
if(!s->tls_ech)
|
||||
s->tls_ech = CURLECH_HARD;
|
||||
result = Curl_setstropt(&s->str[STRING_ECH_PUBLIC], ptr + 3);
|
||||
}
|
||||
else
|
||||
result = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
#define setopt_ech(x,y) CURLE_NOT_BUILT_IN
|
||||
#endif
|
||||
|
||||
static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
char *ptr)
|
||||
{
|
||||
|
|
@ -2495,38 +2534,8 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
|||
return Curl_altsvc_load(data->asi, ptr);
|
||||
break;
|
||||
#endif /* !CURL_DISABLE_ALTSVC */
|
||||
#ifdef USE_ECH
|
||||
case CURLOPT_ECH: {
|
||||
size_t plen = 0;
|
||||
|
||||
if(!ptr) {
|
||||
s->tls_ech = CURLECH_DISABLE;
|
||||
break;
|
||||
}
|
||||
plen = strlen(ptr);
|
||||
if(plen > CURL_MAX_INPUT_LENGTH) {
|
||||
s->tls_ech = CURLECH_DISABLE;
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
/* set tls_ech flag value, preserving CLA_CFG bit */
|
||||
if(!strcmp(ptr, "false"))
|
||||
s->tls_ech = (s->tls_ech & CURLECH_CLA_CFG) | CURLECH_DISABLE;
|
||||
else if(!strcmp(ptr, "grease"))
|
||||
s->tls_ech = (s->tls_ech & CURLECH_CLA_CFG) | CURLECH_GREASE;
|
||||
else if(!strcmp(ptr, "true"))
|
||||
s->tls_ech = (s->tls_ech & CURLECH_CLA_CFG) | CURLECH_ENABLE;
|
||||
else if(!strcmp(ptr, "hard"))
|
||||
s->tls_ech = (s->tls_ech & CURLECH_CLA_CFG) | CURLECH_HARD;
|
||||
else if(plen > 5 && !strncmp(ptr, "ecl:", 4)) {
|
||||
result = Curl_setstropt(&s->str[STRING_ECH_CONFIG], ptr + 4);
|
||||
if(!result)
|
||||
s->tls_ech |= CURLECH_CLA_CFG;
|
||||
}
|
||||
else if(plen > 4 && !strncmp(ptr, "pn:", 3))
|
||||
result = Curl_setstropt(&s->str[STRING_ECH_PUBLIC], ptr + 3);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case CURLOPT_ECH:
|
||||
return setopt_ech(data, ptr);
|
||||
default:
|
||||
return CURLE_UNKNOWN_OPTION;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1157,9 +1157,6 @@ struct UserDefined {
|
|||
struct curl_slist *mail_rcpt; /* linked list of mail recipients */
|
||||
#endif
|
||||
uint32_t maxconnects; /* Max idle connections in the connection cache */
|
||||
#ifdef USE_ECH
|
||||
int tls_ech; /* TLS ECH configuration */
|
||||
#endif
|
||||
short maxredirs; /* maximum no. of http(s) redirects to follow,
|
||||
set to -1 for infinity */
|
||||
uint16_t expect_100_timeout; /* in milliseconds */
|
||||
|
|
@ -1174,6 +1171,9 @@ struct UserDefined {
|
|||
#ifndef CURL_DISABLE_TFTP
|
||||
uint16_t tftp_blksize; /* in bytes, 0 means use default */
|
||||
#endif
|
||||
#ifdef USE_ECH
|
||||
uint8_t tls_ech; /* TLS ECH configuration */
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_NETRC
|
||||
uint8_t use_netrc; /* enum CURL_NETRC_OPTION values */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3430,9 +3430,9 @@ bool Curl_ossl_need_httpsrr(struct Curl_easy *data)
|
|||
{
|
||||
if(!CURLECH_ENABLED(data))
|
||||
return FALSE;
|
||||
if((data->set.tls_ech & CURLECH_GREASE) ||
|
||||
(data->set.tls_ech & CURLECH_CLA_CFG))
|
||||
return FALSE;
|
||||
if((data->set.tls_ech == CURLECH_GREASE) ||
|
||||
data->set.str[STRING_ECH_CONFIG])
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -3450,7 +3450,7 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
|
|||
if(!CURLECH_ENABLED(data))
|
||||
return CURLE_OK;
|
||||
|
||||
if(data->set.tls_ech & CURLECH_GREASE) {
|
||||
if(data->set.tls_ech == CURLECH_GREASE) {
|
||||
infof(data, "ECH: will GREASE ClientHello");
|
||||
#ifdef HAVE_BORINGSSL_LIKE
|
||||
SSL_set_enable_ech_grease(octx->ssl, 1);
|
||||
|
|
@ -3458,7 +3458,7 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
|
|||
SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE);
|
||||
#endif
|
||||
}
|
||||
else if(data->set.tls_ech & CURLECH_CLA_CFG) {
|
||||
else if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) {
|
||||
#ifdef HAVE_BORINGSSL_LIKE
|
||||
/* have to do base64 decode here for BoringSSL */
|
||||
const char *b64 = data->set.str[STRING_ECH_CONFIG];
|
||||
|
|
@ -3471,12 +3471,12 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
|
|||
result = curlx_base64_decode(b64, &ech_config, &ech_config_len);
|
||||
if(result || !ech_config) {
|
||||
infof(data, "ECH: cannot base64 decode ECHConfig from command line");
|
||||
if(data->set.tls_ech & CURLECH_HARD)
|
||||
if(data->set.tls_ech == CURLECH_HARD)
|
||||
return result;
|
||||
}
|
||||
if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) {
|
||||
infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
|
||||
if(data->set.tls_ech & CURLECH_HARD) {
|
||||
if(data->set.tls_ech == CURLECH_HARD) {
|
||||
curlx_free(ech_config);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
|
@ -3492,7 +3492,7 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
|
|||
ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]);
|
||||
if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) {
|
||||
infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
|
||||
if(data->set.tls_ech & CURLECH_HARD)
|
||||
if(data->set.tls_ech == CURLECH_HARD)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
else
|
||||
|
|
@ -3511,7 +3511,7 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
|
|||
infof(data, "ECH: ECHConfig from HTTPS RR");
|
||||
if(SSL_set1_ech_config_list(octx->ssl, ecl, elen) != 1) {
|
||||
infof(data, "ECH: SSL_set1_ech_config_list failed");
|
||||
if(data->set.tls_ech & CURLECH_HARD)
|
||||
if(data->set.tls_ech == CURLECH_HARD)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
else {
|
||||
|
|
@ -3521,7 +3521,7 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx,
|
|||
}
|
||||
else {
|
||||
infof(data, "ECH: requested but no ECHConfig available");
|
||||
if(data->set.tls_ech & CURLECH_HARD)
|
||||
if(data->set.tls_ech == CURLECH_HARD)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -4335,7 +4335,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
|
|||
/* trace retry_configs if we got some */
|
||||
ossl_trace_ech_retry_configs(data, octx->ssl, 0);
|
||||
}
|
||||
if(rv != SSL_ECH_STATUS_SUCCESS && (data->set.tls_ech & CURLECH_HARD)) {
|
||||
if(rv != SSL_ECH_STATUS_SUCCESS && (data->set.tls_ech == CURLECH_HARD)) {
|
||||
infof(data, "ECH: ech-hard failed");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -915,9 +915,9 @@ static bool cr_ech_need_httpsrr(struct Curl_easy *data)
|
|||
{
|
||||
if(!CURLECH_ENABLED(data))
|
||||
return FALSE;
|
||||
if((data->set.tls_ech & CURLECH_GREASE) ||
|
||||
(data->set.tls_ech & CURLECH_CLA_CFG))
|
||||
return FALSE;
|
||||
if((data->set.tls_ech == CURLECH_GREASE) ||
|
||||
data->set.str[STRING_ECH_CONFIG])
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -957,7 +957,7 @@ init_config_builder_ech(struct Curl_easy *data,
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
if(data->set.tls_ech & CURLECH_CLA_CFG && data->set.str[STRING_ECH_CONFIG]) {
|
||||
if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) {
|
||||
const char *b64 = data->set.str[STRING_ECH_CONFIG];
|
||||
size_t decode_result;
|
||||
if(!b64) {
|
||||
|
|
@ -997,7 +997,7 @@ init_config_builder_ech(struct Curl_easy *data,
|
|||
}
|
||||
cleanup:
|
||||
/* if we base64 decoded, we can free now */
|
||||
if(data->set.tls_ech & CURLECH_CLA_CFG && data->set.str[STRING_ECH_CONFIG]) {
|
||||
if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) {
|
||||
curlx_free(ech_config);
|
||||
}
|
||||
if(dns) {
|
||||
|
|
@ -1074,7 +1074,7 @@ static CURLcode cr_init_backend(struct Curl_cfilter *cf,
|
|||
#ifdef USE_ECH
|
||||
if(CURLECH_ENABLED(data)) {
|
||||
result = init_config_builder_ech(data, cf, config_builder);
|
||||
if(result != CURLE_OK && data->set.tls_ech & CURLECH_HARD) {
|
||||
if((result != CURLE_OK) && (data->set.tls_ech == CURLECH_HARD)) {
|
||||
rustls_client_config_builder_free(config_builder);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,15 +49,13 @@ struct dynbuf;
|
|||
#define SSLSUPP_ISSUERCERT_BLOB (1 << 14) /* CURLOPT_ISSUERCERT_BLOB */
|
||||
|
||||
#ifdef USE_ECH
|
||||
/* CURLECH_ bits for the tls_ech option */
|
||||
#define CURLECH_DISABLE (1 << 0)
|
||||
#define CURLECH_GREASE (1 << 1)
|
||||
#define CURLECH_ENABLE (1 << 2)
|
||||
#define CURLECH_HARD (1 << 3)
|
||||
#define CURLECH_CLA_CFG (1 << 4)
|
||||
/* CURLECH_ values for the tls_ech option */
|
||||
#define CURLECH_DISABLE 0
|
||||
#define CURLECH_GREASE 1
|
||||
#define CURLECH_ENABLE 2
|
||||
#define CURLECH_HARD 3
|
||||
|
||||
#define CURLECH_ENABLED(data) \
|
||||
((data)->set.tls_ech && !((data)->set.tls_ech & CURLECH_DISABLE))
|
||||
#define CURLECH_ENABLED(data) ((data)->set.tls_ech)
|
||||
#endif /* USE_ECH */
|
||||
|
||||
#define ALPN_ACCEPTED "ALPN: server accepted "
|
||||
|
|
|
|||
|
|
@ -1273,15 +1273,14 @@ static CURLcode wssl_init_ech(struct wssl_ctx *wctx,
|
|||
infof(data, "ECH: GREASE is done by default by"
|
||||
" wolfSSL: no need to ask");
|
||||
}
|
||||
if(data->set.tls_ech & CURLECH_CLA_CFG &&
|
||||
data->set.str[STRING_ECH_CONFIG]) {
|
||||
if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) {
|
||||
char *b64val = data->set.str[STRING_ECH_CONFIG];
|
||||
word32 b64len = 0;
|
||||
|
||||
b64len = (word32)strlen(b64val);
|
||||
if(b64len && wolfSSL_SetEchConfigsBase64(wctx->ssl, b64val,
|
||||
b64len) != WOLFSSL_SUCCESS) {
|
||||
if(data->set.tls_ech & CURLECH_HARD)
|
||||
if(data->set.tls_ech == CURLECH_HARD)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
else {
|
||||
|
|
@ -1301,7 +1300,7 @@ static CURLcode wssl_init_ech(struct wssl_ctx *wctx,
|
|||
if(wolfSSL_SetEchConfigs(wctx->ssl, ecl, (word32)elen) !=
|
||||
WOLFSSL_SUCCESS) {
|
||||
infof(data, "ECH: wolfSSL_SetEchConfigs failed");
|
||||
if(data->set.tls_ech & CURLECH_HARD) {
|
||||
if(data->set.tls_ech == CURLECH_HARD) {
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -1312,7 +1311,7 @@ static CURLcode wssl_init_ech(struct wssl_ctx *wctx,
|
|||
}
|
||||
else {
|
||||
infof(data, "ECH: requested but no ECHConfig available");
|
||||
if(data->set.tls_ech & CURLECH_HARD) {
|
||||
if(data->set.tls_ech == CURLECH_HARD) {
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -1492,9 +1491,9 @@ bool Curl_wssl_need_httpsrr(struct Curl_easy *data)
|
|||
#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
|
||||
if(!CURLECH_ENABLED(data))
|
||||
return FALSE;
|
||||
if((data->set.tls_ech & CURLECH_GREASE) ||
|
||||
(data->set.tls_ech & CURLECH_CLA_CFG))
|
||||
return FALSE;
|
||||
if((data->set.tls_ech == CURLECH_GREASE) ||
|
||||
data->set.str[STRING_ECH_CONFIG])
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
#else
|
||||
(void)data;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ my @bad_function_argument = (
|
|||
'CURLOPT_DNS_LOCAL_IP4',
|
||||
'CURLOPT_DNS_LOCAL_IP6',
|
||||
'CURLOPT_DNS_SERVERS',
|
||||
'CURLOPT_ECH',
|
||||
'CURLOPT_PROXY_TLSAUTH_TYPE',
|
||||
'CURLOPT_SSLENGINE',
|
||||
'CURLOPT_TLSAUTH_TYPE',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue