setopt: add CURLOPT_PROTOCOLS_STR and CURLOPT_REDIR_PROTOCOLS_STR

... as replacements for deprecated CURLOPT_PROTOCOLS and
CURLOPT_REDIR_PROTOCOLS as these new ones do not risk running into the
32 bit limit the old ones are facing.

CURLINFO_PROTCOOL is now deprecated.

The curl tool is updated to use the new options.

Added test 1597 to verify the libcurl protocol parser.

Closes #8992
This commit is contained in:
Daniel Stenberg 2022-06-13 09:30:45 +02:00
parent 193215db3c
commit e6f8445ede
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
24 changed files with 487 additions and 45 deletions

View File

@ -167,9 +167,14 @@ URL to work on. See \fICURLOPT_URL(3)\fP
.IP CURLOPT_PATH_AS_IS
Disable squashing /../ and /./ sequences in the path. See \fICURLOPT_PATH_AS_IS(3)\fP
.IP CURLOPT_PROTOCOLS
Allowed protocols. See \fICURLOPT_PROTOCOLS(3)\fP
\fBDeprecated option\fP Allowed protocols. See \fICURLOPT_PROTOCOLS(3)\fP
.IP CURLOPT_PROTOCOLS_STR
Allowed protocols. See \fICURLOPT_PROTOCOLS_STR(3)\fP
.IP CURLOPT_REDIR_PROTOCOLS
Protocols to allow redirects to. See \fICURLOPT_REDIR_PROTOCOLS(3)\fP
\fBDeprecated option\fP Protocols to allow redirects to. See
\fICURLOPT_REDIR_PROTOCOLS(3)\fP
.IP CURLOPT_REDIR_PROTOCOLS_STR
Protocols to allow redirects to. See \fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP
.IP CURLOPT_DEFAULT_PROTOCOL
Default protocol. See \fICURLOPT_DEFAULT_PROTOCOL(3)\fP
.IP CURLOPT_PROXY

View File

@ -32,6 +32,10 @@ CURLINFO_PROTOCOL \- get the protocol used in the connection
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
.fi
.SH DESCRIPTION
This option is deprecated. We strongly recommend using
\fICURLINFO_SCHEME(3)\fP instead, because this option cannot return all
possible protocols!
Pass a pointer to a long to receive the version used in the last http
connection. The returned value will be exactly one of the CURLPROTO_* values:

View File

@ -32,6 +32,10 @@ CURLOPT_PROTOCOLS \- allowed protocols
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS, long bitmask);
.fi
.SH DESCRIPTION
This option is deprecated. We strongly recommend using
\fICURLOPT_PROTOCOLS_STR(3)\fP instead because this option cannot control all
available protocols!
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
limits what protocols libcurl may use in the transfer. This allows you to have
a libcurl built to support a wide range of protocols but still limit specific
@ -71,7 +75,7 @@ CURLPROTO_TELNET
CURLPROTO_TFTP
.fi
.SH DEFAULT
All protocols built-in
All protocols built-in.
.SH PROTOCOLS
All
.SH EXAMPLE

View File

@ -0,0 +1,82 @@
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
.\" * are also available at https://curl.se/docs/copyright.html.
.\" *
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
.\" * copies of the Software, and permit persons to whom the Software is
.\" * furnished to do so, under the terms of the COPYING file.
.\" *
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PROTOCOLS_STR 3 "11 Jun 2022" "libcurl 7.85.0" "curl_easy_setopt options"
.SH NAME
CURLOPT_PROTOCOLS_STR \- allowed protocols
.SH SYNOPSIS
.nf
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS_STR, char *spec);
.fi
.SH DESCRIPTION
Pass a pointer to a string that holds a comma-separated list of case
insensitive protocol names (URL schemes) to allow in the transfer. This
option allows applications to use libcurl built to support a wide range of
protocols but still limit specific transfers to only be allowed to use a
subset of them. By default, libcurl accepts all protocols it was built with
support for. See also \fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP.
If trying to set a non-existing protocol or if no matching protocol at all is
set, it returns error.
These are the available protocols:
DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP, SMB,
SMBS, SMTP, SMTPS, TELNET, TFTP
You can set "ALL" as a short-cut to enable all protocols. Note that by setting
all, you may enable protocols that were not supported the day you write this
but are introduced in a future libcurl version.
\fIcurl_version_info(3)\fP can be used to get a list of all supported
protocols in the current libcurl. \fICURLINFO_SCHEME(3)\fP is the recommended
way to figure out the protocol used in a previous transfer.
.SH DEFAULT
All protocols built-in
.SH PROTOCOLS
All
.SH EXAMPLE
.nf
curl = curl_easy_init();
if(curl) {
/* pass in the URL from an external source */
curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
/* only allow HTTP, TFTP and SFTP */
curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "http,tftp,sftp");
/* Perform the request */
curl_easy_perform(curl);
}
.fi
.SH AVAILABILITY
Added in 7.85.0
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
.BR CURLOPT_REDIR_PROTOCOLS_STR "(3), " CURLOPT_URL "(3), "
.BR curl_version_info "(3), " CURLINFO_SCHEME "(3), "

View File

@ -32,6 +32,10 @@ CURLOPT_REDIR_PROTOCOLS \- protocols allowed to redirect to
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS, long bitmask);
.fi
.SH DESCRIPTION
This option is deprecated. We strongly recommend using
\fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP instead because this option cannot
control all available protocols!
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
limits what protocols libcurl may use in a transfer that it follows to in a
redirect when \fICURLOPT_FOLLOWLOCATION(3)\fP is enabled. This allows you to

View File

@ -0,0 +1,89 @@
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
.\" * are also available at https://curl.se/docs/copyright.html.
.\" *
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
.\" * copies of the Software, and permit persons to whom the Software is
.\" * furnished to do so, under the terms of the COPYING file.
.\" *
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_REDIR_PROTOCOLS_STR 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
.SH NAME
CURLOPT_REDIR_PROTOCOLS_STR \- protocols allowed to redirect to
.SH SYNOPSIS
.nf
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS_STR,
char *spec);
.fi
.SH DESCRIPTION
Pass a pointer to a string that holds a comma-separated list of case
insensitive protocol names (URL schemes). That list limits what protocols
libcurl may use in a transfer that it follows to in a redirect when
\fICURLOPT_FOLLOWLOCATION(3)\fP is enabled. This option allows applications to
limit specific transfers to only be allowed to use a subset of protocols in
redirections.
Protocols denied by \fICURLOPT_PROTOCOLS_STR(3)\fP are not overridden by this
option.
By default libcurl will allow HTTP, HTTPS, FTP and FTPS on redirects (since
7.65.2). Older versions of libcurl allowed all protocols on redirect except
several disabled for security reasons: Since 7.19.4 FILE and SCP are disabled,
and since 7.40.0 SMB and SMBS are also disabled.
These are the available protocols:
DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP, SMB,
SMBS, SMTP, SMTPS, TELNET, TFTP
You can set "ALL" as a short-cut to enable all protocols. Note that by setting
all, you may enable protocols that were not supported the day you write this
but are introduced in a future libcurl version.
If trying to set a non-existing protocol or if no matching protocol at all is
set, it returns error.
.SH DEFAULT
HTTP, HTTPS, FTP and FTPS (Added in 7.65.2).
Older versions defaulted to all protocols except FILE, SCP and since 7.40.0
SMB and SMBS.
.SH PROTOCOLS
All
.SH EXAMPLE
.nf
curl = curl_easy_init();
if(curl) {
/* pass in the URL from an external source */
curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
/* only allow redirects to HTTP and HTTPS URLs */
curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https");
/* Perform the request */
curl_easy_perform(curl);
}
.fi
.SH AVAILABILITY
Added in 7.85.0.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
.BR CURLOPT_PROTOCOLS_STR "(3), "

View File

@ -267,6 +267,7 @@ man_MANS = \
CURLOPT_PROGRESSDATA.3 \
CURLOPT_PROGRESSFUNCTION.3 \
CURLOPT_PROTOCOLS.3 \
CURLOPT_PROTOCOLS_STR.3 \
CURLOPT_PROXY.3 \
CURLOPT_PROXYAUTH.3 \
CURLOPT_PROXYHEADER.3 \
@ -307,6 +308,7 @@ man_MANS = \
CURLOPT_READDATA.3 \
CURLOPT_READFUNCTION.3 \
CURLOPT_REDIR_PROTOCOLS.3 \
CURLOPT_REDIR_PROTOCOLS_STR.3 \
CURLOPT_REFERER.3 \
CURLOPT_REQUEST_TARGET.3 \
CURLOPT_RESOLVE.3 \

View File

@ -722,6 +722,7 @@ CURLOPT_PRIVATE 7.10.3
CURLOPT_PROGRESSDATA 7.1
CURLOPT_PROGRESSFUNCTION 7.1 7.32.0
CURLOPT_PROTOCOLS 7.19.4
CURLOPT_PROTOCOLS_STR 7.85.0
CURLOPT_PROXY 7.1
CURLOPT_PROXY_CAINFO 7.52.0
CURLOPT_PROXY_CAINFO_BLOB 7.77.0
@ -762,6 +763,7 @@ CURLOPT_RANGE 7.1
CURLOPT_READDATA 7.9.7
CURLOPT_READFUNCTION 7.1
CURLOPT_REDIR_PROTOCOLS 7.19.4
CURLOPT_REDIR_PROTOCOLS_STR 7.85.0
CURLOPT_REFERER 7.1
CURLOPT_REQUEST_TARGET 7.55.0
CURLOPT_RESOLVE 7.21.3

View File

@ -1010,7 +1010,8 @@ typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy,
#define CURLHSTS_ENABLE (long)(1<<0)
#define CURLHSTS_READONLYFILE (long)(1<<1)
/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
/* The CURLPROTO_ defines below are for the **deprecated** CURLOPT_*PROTOCOLS
options. Do not use. */
#define CURLPROTO_HTTP (1<<0)
#define CURLPROTO_HTTPS (1<<1)
#define CURLPROTO_FTP (1<<2)
@ -2144,6 +2145,15 @@ typedef enum {
/* set the SSH host key callback custom pointer */
CURLOPT(CURLOPT_SSH_HOSTKEYDATA, CURLOPTTYPE_CBPOINT, 317),
/* specify which protocols that are allowed to be used for the transfer,
which thus helps the app which takes URLs from users or other external
inputs and want to restrict what protocol(s) to deal with. Defaults to
all built-in protocols. */
CURLOPT(CURLOPT_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 318),
/* specify which protocols that libcurl is allowed to follow directs to */
CURLOPT(CURLOPT_REDIR_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 319),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

View File

@ -272,9 +272,9 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_HSTS || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
@ -288,10 +288,8 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_PASSWORD || \
(option) == CURLOPT_PINNEDPUBLICKEY || \
(option) == CURLOPT_PRE_PROXY || \
(option) == CURLOPT_PROTOCOLS_STR || \
(option) == CURLOPT_PROXY || \
(option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_PROXY_CAINFO || \
(option) == CURLOPT_PROXY_CAPATH || \
(option) == CURLOPT_PROXY_CRLFILE || \
@ -299,17 +297,21 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_PROXY_KEYPASSWD || \
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_SSLCERT || \
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
(option) == CURLOPT_PROXY_SSLKEY || \
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_TLS13_CIPHERS || \
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
(option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \
(option) == CURLOPT_REDIR_PROTOCOLS_STR || \
(option) == CURLOPT_REFERER || \
(option) == CURLOPT_REQUEST_TARGET || \
(option) == CURLOPT_RTSP_SESSION_ID || \

View File

@ -203,6 +203,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"PROGRESSDATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
{"PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION, CURLOT_FUNCTION, 0},
{"PROTOCOLS", CURLOPT_PROTOCOLS, CURLOT_LONG, 0},
{"PROTOCOLS_STR", CURLOPT_PROTOCOLS_STR, CURLOT_STRING, 0},
{"PROXY", CURLOPT_PROXY, CURLOT_STRING, 0},
{"PROXYAUTH", CURLOPT_PROXYAUTH, CURLOT_VALUES, 0},
{"PROXYHEADER", CURLOPT_PROXYHEADER, CURLOT_SLIST, 0},
@ -245,6 +246,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"READDATA", CURLOPT_READDATA, CURLOT_CBPTR, 0},
{"READFUNCTION", CURLOPT_READFUNCTION, CURLOT_FUNCTION, 0},
{"REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS, CURLOT_LONG, 0},
{"REDIR_PROTOCOLS_STR", CURLOPT_REDIR_PROTOCOLS_STR, CURLOT_STRING, 0},
{"REFERER", CURLOPT_REFERER, CURLOT_STRING, 0},
{"REQUEST_TARGET", CURLOPT_REQUEST_TARGET, CURLOT_STRING, 0},
{"RESOLVE", CURLOPT_RESOLVE, CURLOT_SLIST, 0},
@ -275,14 +277,14 @@ struct curl_easyoption Curl_easyopts[] = {
{"SOCKS5_GSSAPI_SERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOT_STRING, 0},
{"SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES, CURLOT_VALUES, 0},
{"SSH_COMPRESSION", CURLOPT_SSH_COMPRESSION, CURLOT_LONG, 0},
{"SSH_HOSTKEYDATA", CURLOPT_SSH_HOSTKEYDATA, CURLOT_CBPTR, 0},
{"SSH_HOSTKEYFUNCTION", CURLOPT_SSH_HOSTKEYFUNCTION, CURLOT_FUNCTION, 0},
{"SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
CURLOT_STRING, 0},
{"SSH_HOST_PUBLIC_KEY_SHA256", CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
CURLOT_STRING, 0},
{"SSH_KEYDATA", CURLOPT_SSH_KEYDATA, CURLOT_CBPTR, 0},
{"SSH_KEYFUNCTION", CURLOPT_SSH_KEYFUNCTION, CURLOT_FUNCTION, 0},
{"SSH_HOSTKEYDATA", CURLOPT_SSH_HOSTKEYDATA, CURLOT_CBPTR, 0},
{"SSH_HOSTKEYFUNCTION", CURLOPT_SSH_HOSTKEYFUNCTION, CURLOT_FUNCTION, 0},
{"SSH_KNOWNHOSTS", CURLOPT_SSH_KNOWNHOSTS, CURLOT_STRING, 0},
{"SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE, CURLOT_STRING, 0},
{"SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE, CURLOT_STRING, 0},
@ -364,6 +366,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
return ((CURLOPT_LASTENTRY%10000) != (317 + 1));
return ((CURLOPT_LASTENTRY%10000) != (319 + 1));
}
#endif

View File

@ -148,6 +148,85 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
#define C_SSLVERSION_VALUE(x) (x & 0xffff)
#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
static CURLcode protocol2num(char *str, curl_off_t *val)
{
bool found_comma = FALSE;
static struct scheme {
const char *name;
long bit;
} const protos[] = {
{ "dict", CURLPROTO_DICT },
{ "file", CURLPROTO_FILE },
{ "ftp", CURLPROTO_FTP },
{ "ftps", CURLPROTO_FTPS },
{ "gopher", CURLPROTO_GOPHER },
{ "gophers", CURLPROTO_GOPHERS },
{ "http", CURLPROTO_HTTP },
{ "https", CURLPROTO_HTTPS },
{ "imap", CURLPROTO_IMAP },
{ "imaps", CURLPROTO_IMAPS },
{ "ldap", CURLPROTO_LDAP },
{ "ldaps", CURLPROTO_LDAPS },
{ "mqtt", CURLPROTO_MQTT },
{ "pop3", CURLPROTO_POP3 },
{ "pop3s", CURLPROTO_POP3S },
{ "rtmp", CURLPROTO_RTMP },
{ "rtmpe", CURLPROTO_RTMPE },
{ "rtmps", CURLPROTO_RTMPS },
{ "rtmpt", CURLPROTO_RTMPT },
{ "rtmpte", CURLPROTO_RTMPTE },
{ "rtmpts", CURLPROTO_RTMPTS },
{ "rtsp", CURLPROTO_RTSP },
{ "scp", CURLPROTO_SCP },
{ "sftp", CURLPROTO_SFTP },
{ "smb", CURLPROTO_SMB },
{ "smbs", CURLPROTO_SMBS },
{ "smtp", CURLPROTO_SMTP },
{ "smtps", CURLPROTO_SMTPS },
{ "telnet", CURLPROTO_TELNET },
{ "tftp", CURLPROTO_TFTP },
{ NULL, 0 }
};
if(!str)
return CURLE_BAD_FUNCTION_ARGUMENT;
else if(curl_strequal(str, "all")) {
*val = ~0;
return CURLE_OK;
}
*val = 0;
do {
size_t tlen;
struct scheme const *pp;
char *token;
token = strchr(str, ',');
found_comma = token ? TRUE : FALSE;
if(!token)
token = strchr(str, '\0');
tlen = token - str;
if(tlen) {
for(pp = protos; pp->name; pp++) {
if((strlen(pp->name) == tlen) &&
curl_strnequal(str, pp->name, tlen)) {
*val |= pp->bit;
break;
}
}
if(!(pp->name))
/* protocol name didn't match */
return CURLE_BAD_FUNCTION_ARGUMENT;
}
if(found_comma)
str = token + 1;
} while(found_comma);
if(!*val)
/* no matching protocol */
return CURLE_BAD_FUNCTION_ARGUMENT;
return CURLE_OK;
}
/*
* Do not make Curl_vsetopt() static: it is called from
* packages/OS400/ccsidcurl.c.
@ -2560,14 +2639,30 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
transfer, which thus helps the app which takes URLs from users or other
external inputs and want to restrict what protocol(s) to deal
with. Defaults to CURLPROTO_ALL. */
data->set.allowed_protocols = (unsigned int)va_arg(param, long);
data->set.allowed_protocols = (curl_off_t)va_arg(param, long);
break;
case CURLOPT_REDIR_PROTOCOLS:
/* set the bitmask for the protocols that libcurl is allowed to follow to,
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
to be set in both bitmasks to be allowed to get redirected to. */
data->set.redir_protocols = (unsigned int)va_arg(param, long);
data->set.redir_protocols = (curl_off_t)va_arg(param, long);
break;
case CURLOPT_PROTOCOLS_STR:
argptr = va_arg(param, char *);
result = protocol2num(argptr, &bigsize);
if(result)
return result;
data->set.allowed_protocols = bigsize;
break;
case CURLOPT_REDIR_PROTOCOLS_STR:
argptr = va_arg(param, char *);
result = protocol2num(argptr, &bigsize);
if(result)
return result;
data->set.redir_protocols = bigsize;
break;
case CURLOPT_DEFAULT_PROTOCOL:

View File

@ -1782,8 +1782,8 @@ struct UserDefined {
#ifdef ENABLE_IPV6
unsigned int scope_id; /* Scope id for IPv6 */
#endif
unsigned int allowed_protocols;
unsigned int redir_protocols;
curl_off_t allowed_protocols;
curl_off_t redir_protocols;
unsigned int mime_options; /* Mime option flags. */
#ifndef CURL_DISABLE_RTSP

View File

@ -36,11 +36,7 @@ void config_init(struct OperationConfig *config)
config->use_httpget = FALSE;
config->create_dirs = FALSE;
config->maxredirs = DEFAULT_MAXREDIRS;
config->proto = CURLPROTO_ALL;
config->proto_present = FALSE;
config->proto_redir = CURLPROTO_ALL & /* All except FILE, SCP and SMB */
~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
CURLPROTO_SMBS);
config->proto_redir_present = FALSE;
config->proto_default = NULL;
config->tcp_nodelay = TRUE; /* enabled by default */
@ -172,6 +168,8 @@ static void free_config_fields(struct OperationConfig *config)
Curl_safefree(config->ftp_alternative_to_user);
Curl_safefree(config->aws_sigv4);
Curl_safefree(config->proto_str);
Curl_safefree(config->proto_redir_str);
}
void config_free(struct OperationConfig *config)

View File

@ -67,9 +67,9 @@ struct OperationConfig {
bool disable_epsv;
bool disable_eprt;
bool ftp_pret;
long proto;
char *proto_str;
bool proto_present;
long proto_redir;
char *proto_redir_str;
bool proto_redir_present;
char *proto_default;
curl_off_t resume_from;

View File

@ -1184,12 +1184,16 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
break;
case 'D': /* --proto */
config->proto_present = TRUE;
if(proto2num(config, &config->proto, nextarg))
return PARAM_BAD_USE;
err = proto2num(config, (unsigned int)CURLPROTO_ALL,
&config->proto_str, nextarg);
if(err)
return err;
break;
case 'E': /* --proto-redir */
config->proto_redir_present = TRUE;
if(proto2num(config, &config->proto_redir, nextarg))
if(proto2num(config, CURLPROTO_HTTP|CURLPROTO_HTTPS|
CURLPROTO_FTP|CURLPROTO_FTPS,
&config->proto_redir_str, nextarg))
return PARAM_BAD_USE;
break;
case 'F': /* --resolve */

View File

@ -1989,9 +1989,10 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode);
if(config->proto_present)
my_setopt_flags(curl, CURLOPT_PROTOCOLS, config->proto);
my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str);
if(config->proto_redir_present)
my_setopt_flags(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR,
config->proto_redir_str);
if(config->content_disposition
&& (urlnode->flags & GETOUT_USEREMOTE))

View File

@ -275,8 +275,8 @@ ParameterError str2udouble(double *valp, const char *str, long max)
}
/*
* Parse the string and modify the long in the given address. Return
* non-zero on failure, zero on success.
* Parse the string and provide an allocated libcurl compatible protocol
* string output. Return non-zero on failure, zero on success.
*
* The string is a list of protocols
*
@ -285,17 +285,22 @@ ParameterError str2udouble(double *valp, const char *str, long max)
* data.
*/
long proto2num(struct OperationConfig *config, long *val, const char *str)
ParameterError proto2num(struct OperationConfig *config,
unsigned int 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;
static struct sprotos {
const char *name;
long bit;
unsigned int bit;
} const protos[] = {
{ "all", CURLPROTO_ALL },
{ "all", (unsigned int)CURLPROTO_ALL },
{ "http", CURLPROTO_HTTP },
{ "https", CURLPROTO_HTTPS },
{ "ftp", CURLPROTO_FTP },
@ -305,6 +310,7 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
{ "telnet", CURLPROTO_TELNET },
{ "ldap", CURLPROTO_LDAP },
{ "ldaps", CURLPROTO_LDAPS },
{ "mqtt", CURLPROTO_MQTT },
{ "dict", CURLPROTO_DICT },
{ "file", CURLPROTO_FILE },
{ "tftp", CURLPROTO_TFTP },
@ -316,6 +322,7 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
{ "smtps", CURLPROTO_SMTPS },
{ "rtsp", CURLPROTO_RTSP },
{ "gopher", CURLPROTO_GOPHER },
{ "gophers", CURLPROTO_GOPHERS },
{ "smb", CURLPROTO_SMB },
{ "smbs", CURLPROTO_SMBS },
{ NULL, 0 }
@ -335,8 +342,6 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
token = strtok(NULL, sep)) {
enum e_action { allow, deny, set } action = allow;
struct sprotos const *pp;
/* Process token modifiers */
while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
switch (*token++) {
@ -359,13 +364,13 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
if(curl_strequal(token, pp->name)) {
switch(action) {
case deny:
*val &= ~(pp->bit);
val &= ~(pp->bit);
break;
case allow:
*val |= pp->bit;
val |= pp->bit;
break;
case set:
*val = pp->bit;
val = pp->bit;
break;
}
break;
@ -376,12 +381,25 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
/* If they have specified only this protocol, we say treat it as
if no protocols are allowed */
if(action == set)
*val = 0;
val = 0;
warnf(config->global, "unrecognized protocol '%s'\n", token);
}
}
Curl_safefree(buffer);
return 0;
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);
return *ostr ? PARAM_OK : PARAM_NO_MEM;
}
/**

View File

@ -39,7 +39,9 @@ ParameterError oct2nummax(long *val, const char *str, long max);
ParameterError str2unummax(long *val, const char *str, long max);
ParameterError str2udouble(double *val, const char *str, long max);
long proto2num(struct OperationConfig *config, long *val, const char *str);
ParameterError proto2num(struct OperationConfig *config,
unsigned int val, char **obuf,
const char *str);
int check_protocol(const char *str);

View File

@ -201,7 +201,7 @@ test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
test1566 test1567 test1568 test1569 test1570 \
\
test1590 test1591 test1592 test1593 test1594 test1595 test1596 \
test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \
\
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
test1608 test1609 test1610 test1611 test1612 test1613 \

View File

@ -91,9 +91,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
%endif
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE |
(long)CURLPROTO_FTP |
(long)CURLPROTO_HTTP);
curl_easy_setopt(hnd, CURLOPT_PROTOCOLS_STR, "http,ftp,file");
/* Here is a list of options the curl code used that cannot get generated
as source easily. You may choose to either not use them or implement

32
tests/data/test1597 Normal file
View File

@ -0,0 +1,32 @@
<testcase>
<info>
<keywords>
CURLOPT_PROTOCOLS_STR
</keywords>
</info>
# Server-side
<reply>
</reply>
# Client-side
<client>
<server>
none
</server>
<name>
CURLOPT_PROTOCOLS_STR
</name>
<tool>
lib%TESTNUMBER
</tool>
<command>
-
</command>
</client>
<verify>
<stdout>
Tested 15 strings
</stdout>
</verify>
</testcase>

View File

@ -60,7 +60,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
lib1540 lib1542 lib1543 \
lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 \
lib1591 lib1592 lib1593 lib1594 lib1596 \
lib1591 lib1592 lib1593 lib1594 lib1596 lib1597 \
lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \
lib1915 lib1916 lib1917 lib1918 lib1919 \
lib1933 lib1934 lib1935 lib1936 lib1937 lib1938 lib1939 lib1940 \
@ -657,6 +657,9 @@ lib1596_SOURCES = lib1594.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1596_LDADD = $(TESTUTIL_LIBS)
lib1596_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1596
lib1597_SOURCES = lib1597.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1597_LDADD = $(TESTUTIL_LIBS)
lib1905_SOURCES = lib1905.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1905_LDADD = $(TESTUTIL_LIBS)
lib1905_CPPFLAGS = $(AM_CPPFLAGS)

85
tests/libtest/lib1597.c Normal file
View File

@ -0,0 +1,85 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* Testing CURLOPT_PROTOCOLS_STR */
#include "test.h"
#include "memdebug.h"
struct pair {
const char *in;
CURLcode exp;
};
int test(char *URL)
{
CURL *curl = NULL;
int res = 0;
CURLcode result = CURLE_OK;
int i;
struct pair prots[] = {
{"goobar", CURLE_BAD_FUNCTION_ARGUMENT},
{"http ", CURLE_BAD_FUNCTION_ARGUMENT},
{" http", CURLE_BAD_FUNCTION_ARGUMENT},
{"http", CURLE_OK},
{"http,", CURLE_OK},
{"https,", CURLE_OK},
{"https,http", CURLE_OK},
{"http,http", CURLE_OK},
{"HTTP,HTTP", CURLE_OK},
{",HTTP,HTTP", CURLE_OK},
{"http,http,ft", CURLE_BAD_FUNCTION_ARGUMENT},
{"", CURLE_BAD_FUNCTION_ARGUMENT},
{",,", CURLE_BAD_FUNCTION_ARGUMENT},
{"DICT,FILE,FTP,FTPS,GOPHER,GOPHERS,HTTP,HTTPS,IMAP,IMAPS,LDAP,LDAPS,"
"POP3,POP3S,RTMP,RTMPE,RTMPS,RTMPT,RTMPTE,RTMPTS,RTSP,SCP,SFTP,SMB,"
"SMBS,SMTP,SMTPS,TELNET,TFTP", CURLE_OK},
{"all", CURLE_OK},
{NULL, FALSE},
};
(void)URL;
global_init(CURL_GLOBAL_ALL);
easy_init(curl);
for(i = 0; prots[i].in; i++) {
result = curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, prots[i].in);
if(result != prots[i].exp) {
printf("unexpectedly '%s' returned %u\n",
prots[i].in, result);
break;
}
}
printf("Tested %u strings\n", i);
res = (int)result;
test_cleanup:
curl_easy_cleanup(curl);
curl_global_cleanup();
return (int)result;
}