mirror of
https://github.com/curl/curl.git
synced 2026-08-24 23:23:32 +03:00
tool_getparam: verify that a file exists for some options
Passing the option as-is to libcurl is fine, but checking that the file exists allows the tool to better provide a helpful message. This now done for the following options: --cacert, --crlfile, --knownhosts, --netrc-file, --proxy-cacert amd --proxy-crlfile Bonus: bail out properly on OOM errors in the --cert parser. Reported-by: Wesley Moore Fixes #19583 Closes #19585
This commit is contained in:
parent
54a3f63520
commit
88024c6d39
6 changed files with 121 additions and 79 deletions
|
|
@ -385,20 +385,21 @@ static const struct LongShort aliases[]= {
|
|||
#ifndef UNITTESTS
|
||||
static
|
||||
#endif
|
||||
void parse_cert_parameter(const char *cert_parameter,
|
||||
char **certname,
|
||||
char **passphrase)
|
||||
ParameterError parse_cert_parameter(const char *cert_parameter,
|
||||
char **certname,
|
||||
char **passphrase)
|
||||
{
|
||||
size_t param_length = strlen(cert_parameter);
|
||||
size_t span;
|
||||
const char *param_place = NULL;
|
||||
char *certname_place = NULL;
|
||||
ParameterError err = PARAM_OK;
|
||||
*certname = NULL;
|
||||
*passphrase = NULL;
|
||||
|
||||
/* most trivial assumption: cert_parameter is empty */
|
||||
if(param_length == 0)
|
||||
return;
|
||||
return PARAM_BLANK_STRING;
|
||||
|
||||
/* next less trivial: cert_parameter starts 'pkcs11:' and thus
|
||||
* looks like a RFC7512 PKCS#11 URI which can be used as-is.
|
||||
|
|
@ -407,12 +408,16 @@ void parse_cert_parameter(const char *cert_parameter,
|
|||
if(curl_strnequal(cert_parameter, "pkcs11:", 7) ||
|
||||
!strpbrk(cert_parameter, ":\\")) {
|
||||
*certname = strdup(cert_parameter);
|
||||
return;
|
||||
if(!*certname)
|
||||
return PARAM_NO_MEM;
|
||||
return PARAM_OK;
|
||||
}
|
||||
/* deal with escaped chars; find unescaped colon if it exists */
|
||||
certname_place = malloc(param_length + 1);
|
||||
if(!certname_place)
|
||||
return;
|
||||
if(!certname_place) {
|
||||
err = PARAM_NO_MEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*certname = certname_place;
|
||||
param_place = cert_parameter;
|
||||
|
|
@ -471,12 +476,19 @@ void parse_cert_parameter(const char *cert_parameter,
|
|||
param_place++;
|
||||
if(*param_place) {
|
||||
*passphrase = strdup(param_place);
|
||||
if(!*passphrase)
|
||||
err = PARAM_NO_MEM;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
done:
|
||||
*certname_place = '\0';
|
||||
if(err) {
|
||||
tool_safefree(*certname);
|
||||
}
|
||||
else
|
||||
*certname_place = '\0';
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Replace (in-place) '%20' by '+' according to RFC1866 */
|
||||
|
|
@ -507,18 +519,22 @@ static size_t replace_url_encoded_space_by_plus(char *url)
|
|||
return new_index; /* new size */
|
||||
}
|
||||
|
||||
static void
|
||||
static ParameterError
|
||||
GetFileAndPassword(const char *nextarg, char **file, char **password)
|
||||
{
|
||||
char *certname, *passphrase;
|
||||
ParameterError err;
|
||||
/* nextarg is never NULL here */
|
||||
parse_cert_parameter(nextarg, &certname, &passphrase);
|
||||
free(*file);
|
||||
*file = certname;
|
||||
if(passphrase) {
|
||||
free(*password);
|
||||
*password = passphrase;
|
||||
err = parse_cert_parameter(nextarg, &certname, &passphrase);
|
||||
if(!err) {
|
||||
free(*file);
|
||||
*file = certname;
|
||||
if(passphrase) {
|
||||
free(*password);
|
||||
*password = passphrase;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get a size parameter for '--limit-rate' or '--max-filesize'.
|
||||
|
|
@ -2164,6 +2180,19 @@ static ParameterError opt_bool(struct OperationConfig *config,
|
|||
return PARAM_OK;
|
||||
}
|
||||
|
||||
static ParameterError existingfile(char **store,
|
||||
const struct LongShort *a,
|
||||
const char *filename)
|
||||
{
|
||||
struct_stat info;
|
||||
if(curlx_stat(filename, &info)) {
|
||||
errorf("The file '%s' provided to --%s does not exist",
|
||||
filename, a->lname);
|
||||
return PARAM_BAD_USE;
|
||||
}
|
||||
return getstr(store, filename, DENY_BLANK);
|
||||
}
|
||||
|
||||
/* opt_file handles file options */
|
||||
static ParameterError opt_file(struct OperationConfig *config,
|
||||
const struct LongShort *a,
|
||||
|
|
@ -2181,13 +2210,13 @@ static ParameterError opt_file(struct OperationConfig *config,
|
|||
err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
|
||||
break;
|
||||
case C_CACERT: /* --cacert */
|
||||
err = getstr(&config->cacert, nextarg, DENY_BLANK);
|
||||
err = existingfile(&config->cacert, a, nextarg);
|
||||
break;
|
||||
case C_CAPATH: /* --capath */
|
||||
err = getstr(&config->capath, nextarg, DENY_BLANK);
|
||||
break;
|
||||
case C_CERT: /* --cert */
|
||||
GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
|
||||
err = GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
|
||||
break;
|
||||
case C_CONFIG: /* --config */
|
||||
if(--max_recursive < 0) {
|
||||
|
|
@ -2200,7 +2229,7 @@ static ParameterError opt_file(struct OperationConfig *config,
|
|||
}
|
||||
break;
|
||||
case C_CRLFILE: /* --crlfile */
|
||||
err = getstr(&config->crlfile, nextarg, DENY_BLANK);
|
||||
err = existingfile(&config->crlfile, a, nextarg);
|
||||
break;
|
||||
case C_DUMP_HEADER: /* --dump-header */
|
||||
err = getstr(&config->headerfile, nextarg, DENY_BLANK);
|
||||
|
|
@ -2225,26 +2254,26 @@ static ParameterError opt_file(struct OperationConfig *config,
|
|||
err = getstr(&config->key, nextarg, DENY_BLANK);
|
||||
break;
|
||||
case C_KNOWNHOSTS: /* --knownhosts */
|
||||
err = getstr(&config->knownhosts, nextarg, DENY_BLANK);
|
||||
err = existingfile(&config->knownhosts, a, nextarg);
|
||||
break;
|
||||
case C_NETRC_FILE: /* --netrc-file */
|
||||
err = getstr(&config->netrc_file, nextarg, DENY_BLANK);
|
||||
err = existingfile(&config->netrc_file, a, nextarg);
|
||||
break;
|
||||
case C_OUTPUT: /* --output */
|
||||
err = parse_output(config, nextarg);
|
||||
break;
|
||||
case C_PROXY_CACERT: /* --proxy-cacert */
|
||||
err = getstr(&config->proxy_cacert, nextarg, DENY_BLANK);
|
||||
err = existingfile(&config->proxy_cacert, a, nextarg);
|
||||
break;
|
||||
case C_PROXY_CAPATH: /* --proxy-capath */
|
||||
err = getstr(&config->proxy_capath, nextarg, DENY_BLANK);
|
||||
break;
|
||||
case C_PROXY_CERT: /* --proxy-cert */
|
||||
GetFileAndPassword(nextarg, &config->proxy_cert,
|
||||
&config->proxy_key_passwd);
|
||||
err = GetFileAndPassword(nextarg, &config->proxy_cert,
|
||||
&config->proxy_key_passwd);
|
||||
break;
|
||||
case C_PROXY_CRLFILE: /* --proxy-crlfile */
|
||||
err = getstr(&config->proxy_crlfile, nextarg, DENY_BLANK);
|
||||
err = existingfile(&config->proxy_crlfile, a, nextarg);
|
||||
break;
|
||||
case C_PROXY_KEY: /* --proxy-key */
|
||||
err = getstr(&config->proxy_key, nextarg, ALLOW_BLANK);
|
||||
|
|
|
|||
|
|
@ -372,9 +372,9 @@ ParameterError getparameter(const char *flag, const char *nextarg,
|
|||
int max_recursive);
|
||||
|
||||
#ifdef UNITTESTS
|
||||
void parse_cert_parameter(const char *cert_parameter,
|
||||
char **certname,
|
||||
char **passphrase);
|
||||
ParameterError parse_cert_parameter(const char *cert_parameter,
|
||||
char **certname,
|
||||
char **passphrase);
|
||||
#endif
|
||||
|
||||
ParameterError parse_args(int argc, argv_item_t argv[]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue