}
#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)
{
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;
}
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 */
#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
{
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;
}
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);
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];
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;
}
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
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 {
}
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;
}
}
/* 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;
}
{
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;
}
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) {
}
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) {
#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;
}
#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)
-
-#define CURLECH_ENABLED(data) \
- ((data)->set.tls_ech && !((data)->set.tls_ech & CURLECH_DISABLE))
+/* 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)
#endif /* USE_ECH */
#define ALPN_ACCEPTED "ALPN: server accepted "
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 {
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;
}
}
}
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;
}
}
#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;
'CURLOPT_DNS_LOCAL_IP4',
'CURLOPT_DNS_LOCAL_IP6',
'CURLOPT_DNS_SERVERS',
+ 'CURLOPT_ECH',
'CURLOPT_PROXY_TLSAUTH_TYPE',
'CURLOPT_SSLENGINE',
'CURLOPT_TLSAUTH_TYPE',