mirror of
https://github.com/curl/curl.git
synced 2026-08-24 19:03:40 +03:00
TLS: add support for ECH (Encrypted Client Hello)
An EXPERIMENTAL feature used with CURLOPT_ECH and --ech. Closes #11922
This commit is contained in:
parent
565d28dc8e
commit
a362962b72
40 changed files with 3122 additions and 16 deletions
|
|
@ -176,6 +176,14 @@ static void free_config_fields(struct OperationConfig *config)
|
|||
Curl_safefree(config->aws_sigv4);
|
||||
Curl_safefree(config->proto_str);
|
||||
Curl_safefree(config->proto_redir_str);
|
||||
#ifdef USE_ECH
|
||||
Curl_safefree(config->ech);
|
||||
config->ech = NULL;
|
||||
Curl_safefree(config->ech_config);
|
||||
config->ech_config = NULL;
|
||||
Curl_safefree(config->ech_public);
|
||||
config->ech_public = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void config_free(struct OperationConfig *config)
|
||||
|
|
|
|||
|
|
@ -298,6 +298,12 @@ struct OperationConfig {
|
|||
struct State state; /* for create_transfer() */
|
||||
bool rm_partial; /* on error, remove partially written output
|
||||
files */
|
||||
#ifdef USE_ECH
|
||||
char *ech; /* Config set by --ech keywords */
|
||||
char *ech_config; /* Config set by "--ech esl:" option */
|
||||
char *ech_public; /* Config set by "--ech pn:" option */
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct GlobalConfig {
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ typedef enum {
|
|||
C_DOH_INSECURE,
|
||||
C_DOH_URL,
|
||||
C_DUMP_HEADER,
|
||||
C_ECH,
|
||||
C_EGD_FILE,
|
||||
C_ENGINE,
|
||||
C_EPRT,
|
||||
|
|
@ -404,6 +405,7 @@ static const struct LongShort aliases[]= {
|
|||
{"doh-insecure", ARG_BOOL, ' ', C_DOH_INSECURE},
|
||||
{"doh-url" , ARG_STRG, ' ', C_DOH_URL},
|
||||
{"dump-header", ARG_FILE, 'D', C_DUMP_HEADER},
|
||||
{"ech", ARG_STRG, ' ', C_ECH},
|
||||
{"egd-file", ARG_STRG, ' ', C_EGD_FILE},
|
||||
{"engine", ARG_STRG, ' ', C_ENGINE},
|
||||
{"eprt", ARG_BOOL, ' ', C_EPRT},
|
||||
|
|
@ -2079,6 +2081,57 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
|||
err = PARAM_ENGINES_REQUESTED;
|
||||
}
|
||||
break;
|
||||
#ifndef USE_ECH
|
||||
case C_ECH: /* --ech, not implemented by default */
|
||||
err = PARAM_LIBCURL_DOESNT_SUPPORT;
|
||||
break;
|
||||
#else
|
||||
case C_ECH: /* --ech */
|
||||
if(strlen(nextarg) > 4 && strncasecompare("pn:", nextarg, 3)) {
|
||||
/* a public_name */
|
||||
err = getstr(&config->ech_public, nextarg, DENY_BLANK);
|
||||
}
|
||||
else if(strlen(nextarg) > 5 && strncasecompare("ecl:", nextarg, 4)) {
|
||||
/* an ECHConfigList */
|
||||
if('@' != *(nextarg + 4)) {
|
||||
err = getstr(&config->ech_config, nextarg, DENY_BLANK);
|
||||
}
|
||||
else {
|
||||
/* Indirect case: @filename or @- for stdin */
|
||||
char *tmpcfg = NULL;
|
||||
FILE *file;
|
||||
|
||||
nextarg++; /* skip over '@' */
|
||||
if(!strcmp("-", nextarg)) {
|
||||
file = stdin;
|
||||
}
|
||||
else {
|
||||
file = fopen(nextarg, FOPEN_READTEXT);
|
||||
}
|
||||
if(!file) {
|
||||
warnf(global,
|
||||
"Couldn't read file \"%s\" "
|
||||
"specified for \"--ech ecl:\" option",
|
||||
nextarg);
|
||||
return PARAM_BAD_USE; /* */
|
||||
}
|
||||
err = file2string(&tmpcfg, file);
|
||||
if(file != stdin)
|
||||
fclose(file);
|
||||
if(err)
|
||||
return err;
|
||||
config->ech_config = aprintf("ecl:%s",tmpcfg);
|
||||
if(!config->ech_config)
|
||||
return PARAM_NO_MEM;
|
||||
free(tmpcfg);
|
||||
} /* file done */
|
||||
}
|
||||
else {
|
||||
/* Simple case: just a string, with a keyword */
|
||||
err = getstr(&config->ech, nextarg, DENY_BLANK);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case C_CAPATH: /* --capath */
|
||||
err = getstr(&config->capath, nextarg, DENY_BLANK);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ static const struct category_descriptors categories[] = {
|
|||
{"telnet", "TELNET protocol options", CURLHELP_TELNET},
|
||||
{"tftp", "TFTP protocol options", CURLHELP_TFTP},
|
||||
{"tls", "All TLS/SSL related options", CURLHELP_TLS},
|
||||
{"ech", "All Encrypted Client Hello (ECH) options", CURLHELP_ECH},
|
||||
{"upload", "All options for uploads",
|
||||
CURLHELP_UPLOAD},
|
||||
{"verbose", "Options related to any kind of command line output of curl",
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ struct helptxt {
|
|||
#define CURLHELP_TLS 1u << 22u
|
||||
#define CURLHELP_UPLOAD 1u << 23u
|
||||
#define CURLHELP_VERBOSE 1u << 24u
|
||||
#define CURLHELP_ECH 1u << 25u
|
||||
|
||||
extern const struct helptxt helptext[];
|
||||
|
||||
|
|
|
|||
|
|
@ -168,6 +168,9 @@ const struct helptxt helptext[] = {
|
|||
{"-D, --dump-header <filename>",
|
||||
"Write the received headers to <filename>",
|
||||
CURLHELP_HTTP | CURLHELP_FTP},
|
||||
{" --ech <config>",
|
||||
"Configure Encrypted Client Hello (ECH) for use with the TLS session",
|
||||
CURLHELP_TLS | CURLHELP_ECH},
|
||||
{" --egd-file <file>",
|
||||
"EGD socket path for random data",
|
||||
CURLHELP_TLS},
|
||||
|
|
|
|||
|
|
@ -2187,6 +2187,16 @@ static CURLcode single_transfer(struct GlobalConfig *global,
|
|||
if(config->hsts)
|
||||
my_setopt_str(curl, CURLOPT_HSTS, config->hsts);
|
||||
|
||||
#ifdef USE_ECH
|
||||
/* only if enabled in configure */
|
||||
if(config->ech) /* only if set (optional) */
|
||||
my_setopt_str(curl, CURLOPT_ECH, config->ech);
|
||||
if(config->ech_public) /* only if set (optional) */
|
||||
my_setopt_str(curl, CURLOPT_ECH, config->ech_public);
|
||||
if(config->ech_config) /* only if set (optional) */
|
||||
my_setopt_str(curl, CURLOPT_ECH, config->ech_config);
|
||||
#endif
|
||||
|
||||
/* initialize retry vars for loop below */
|
||||
per->retry_sleep_default = (config->retry_delay) ?
|
||||
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue