cli tool: do not use disabled protocols

As they are now rejected by the library, take care of not passing
disabled protocol names to CURLOPT_PROTOCOLS_STR and
CURLOPT_REDIR_PROTOCOLS_STR.

Rather than using the CURLPROTO_* constants, dynamically assign protocol
numbers based on the order they are listed by curl_version_info().

New type proto_set_t implements prototype bit masks: it should therefore
be large enough to accomodate all library-enabled protocols. If not,
protocol numbers beyond the bit count of proto_set_t are recognized but
"inaccessible": when used, a warning is displayed and the value is
ignored. Should proto_set_t overflows, enabled protocols are reordered to
force those having a public CURLPROTO_* representation to be accessible.

Code has been added to subordinate RTMP?* protocols to the presence of
RTMP in the enabled protocol list, being returned by curl_version_info()
or not.
This commit is contained in:
Patrick Monnerat 2022-09-15 14:31:36 +02:00 committed by Daniel Stenberg
parent 9d51329047
commit dd2a024323
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
10 changed files with 274 additions and 197 deletions

View file

@ -34,6 +34,7 @@
#include "tool_getpass.h"
#include "tool_msgs.h"
#include "tool_paramhlp.h"
#include "tool_libinfo.h"
#include "tool_version.h"
#include "dynbuf.h"
@ -270,48 +271,19 @@ ParameterError str2udouble(double *valp, const char *str, long max)
* data.
*/
#define MAX_PROTOSTRING (64*11) /* Enough room for 64 10-chars proto names. */
ParameterError proto2num(struct OperationConfig *config,
unsigned int val, char **ostr, const char *str)
proto_set_t val, char **ostr, const char *str)
{
char *buffer;
const char *sep = ",";
char *token;
char obuf[256] = "";
size_t olen = sizeof(obuf);
char *optr;
struct sprotos const *pp;
struct curlx_dynbuf obuf;
proto_t proto;
CURLcode result;
static struct sprotos {
const char *name;
unsigned int bit;
} const protos[] = {
{ "all", (unsigned int)CURLPROTO_ALL },
{ "http", CURLPROTO_HTTP },
{ "https", CURLPROTO_HTTPS },
{ "ftp", CURLPROTO_FTP },
{ "ftps", CURLPROTO_FTPS },
{ "scp", CURLPROTO_SCP },
{ "sftp", CURLPROTO_SFTP },
{ "telnet", CURLPROTO_TELNET },
{ "ldap", CURLPROTO_LDAP },
{ "ldaps", CURLPROTO_LDAPS },
{ "mqtt", CURLPROTO_MQTT },
{ "dict", CURLPROTO_DICT },
{ "file", CURLPROTO_FILE },
{ "tftp", CURLPROTO_TFTP },
{ "imap", CURLPROTO_IMAP },
{ "imaps", CURLPROTO_IMAPS },
{ "pop3", CURLPROTO_POP3 },
{ "pop3s", CURLPROTO_POP3S },
{ "smtp", CURLPROTO_SMTP },
{ "smtps", CURLPROTO_SMTPS },
{ "rtsp", CURLPROTO_RTSP },
{ "gopher", CURLPROTO_GOPHER },
{ "gophers", CURLPROTO_GOPHERS },
{ "smb", CURLPROTO_SMB },
{ "smbs", CURLPROTO_SMBS },
{ NULL, 0 }
};
curlx_dyn_init(&obuf, MAX_PROTOSTRING);
if(!str)
return PARAM_OPTION_AMBIGUOUS;
@ -345,44 +317,52 @@ ParameterError proto2num(struct OperationConfig *config,
}
}
for(pp = protos; pp->name; pp++) {
if(curl_strequal(token, pp->name)) {
switch(action) {
case deny:
val &= ~(pp->bit);
break;
case allow:
val |= pp->bit;
break;
case set:
val = pp->bit;
break;
}
if(curl_strequal(token, "all")) {
switch(action) {
case deny:
val = 0;
break;
case allow:
case set:
val = PROTO_ALL;
break;
}
}
if(!(pp->name)) { /* unknown protocol */
/* If they have specified only this protocol, we say treat it as
if no protocols are allowed */
if(action == set)
val = 0;
warnf(config->global, "unrecognized protocol '%s'\n", token);
else {
proto = scheme2protocol(token);
if(proto != PROTO_NONE) {
switch(action) {
case deny:
val &= ~PROTO_BIT(proto);
break;
case set:
val = 0;
/* FALLTHROUGH */
case allow:
if(proto >= PROTO_MAX)
warnf(config->global, "protocol '%s' enabled but not accessible\n",
token);
val |= PROTO_BIT(proto);
break;
}
}
else { /* unknown protocol */
/* If they have specified only this protocol, we say treat it as
if no protocols are allowed */
if(action == set)
val = 0;
warnf(config->global, "unrecognized protocol '%s'\n", token);
}
}
}
Curl_safefree(buffer);
optr = obuf;
for(pp = &protos[1]; pp->name; pp++) {
if(val & pp->bit) {
size_t n = msnprintf(optr, olen, "%s%s",
olen != sizeof(obuf) ? "," : "",
pp->name);
olen -= n;
optr += n;
}
}
*ostr = strdup(obuf);
result = curlx_dyn_addn(&obuf, "", 0);
for(proto = 0; proto < proto_last && proto < PROTO_MAX && !result; proto++)
if(val & PROTO_BIT(proto))
result = curlx_dyn_addf(&obuf, "%s,", protocol2scheme(proto));
curlx_dyn_setlen(&obuf, curlx_dyn_len(&obuf) - 1);
*ostr = curlx_dyn_ptr(&obuf);
return *ostr ? PARAM_OK : PARAM_NO_MEM;
}
@ -397,14 +377,14 @@ ParameterError proto2num(struct OperationConfig *config,
*/
ParameterError check_protocol(const char *str)
{
const char * const *pp;
const curl_version_info_data *curlinfo = curl_version_info(CURLVERSION_NOW);
proto_t proto;
if(!str)
return PARAM_REQUIRES_PARAMETER;
for(pp = curlinfo->protocols; *pp; pp++) {
if(curl_strequal(*pp, str))
return PARAM_OK;
}
proto = scheme2protocol(str);
if(proto < proto_last)
return PARAM_OK;
return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL;
}