aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/curl.146
-rw-r--r--src/main.c131
2 files changed, 177 insertions, 0 deletions
diff --git a/docs/curl.1 b/docs/curl.1
index 02cc3fb63..aec3e48f5 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -927,6 +927,52 @@ in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using \fI-L/--location\fP
(Added in 7.19.1)
+.IP "--proto <protocols>"
+Tells curl to use the listed protocols for its initial retrieval. Protocols
+are evaluated left to right, are comma separated, and are each a protocol
+name or 'all', optionally prefixed by zero or more modifiers. Available
+modifiers are:
+.RS
+.TP 3
+.B +
+Permit this protocol in addition to protocols already permitted (this is
+the default if no modifier is used).
+.TP
+.B -
+Deny this protocol, removing it from the list of protocols already permitted.
+.TP
+.B =
+Permit only this protocol (ignoring the list already permitted), though
+subject to later modification by subsequent entries in the comma separated
+list.
+.RE
+.IP
+For example:
+.RS
+.TP 15
+.B --proto -ftps
+uses the default protocols, but disables ftps
+.TP
+.B --proto -all,https,+http
+only enables http and https
+.TP
+.B --proto =http,https
+also only enables http and https
+.RE
+.IP
+Unknown protocols produce a warning. This allows scripts to safely rely on
+being able to disable potentially dangerous protocols, without relying upon
+support for that protocol being built into curl to avoid an error.
+
+This option can be used multiple times, in which case the effect is the same
+as concatenating the protocols into one instance of the option.
+
+(Added in 7.20.2)
+.IP "--proto-redir <protocols>"
+Tells curl to use the listed protocols after a redirect. See --proto for
+how protocols are represented.
+
+(Added in 7.20.2)
.IP "--proxy-anyauth"
Tells curl to pick a suitable authentication method when communicating with
the given proxy. This might cause an extra request/response round-trip. (Added
diff --git a/src/main.c b/src/main.c
index 2dd6dc873..684869379 100644
--- a/src/main.c
+++ b/src/main.c
@@ -478,6 +478,10 @@ struct Configurable {
bool disable_epsv;
bool disable_eprt;
bool ftp_pret;
+ long proto;
+ bool proto_present;
+ long proto_redir;
+ bool proto_redir_present;
curl_off_t resume_from;
char *postfields;
curl_off_t postfieldsize;
@@ -841,6 +845,8 @@ static void help(void)
" --post301 Do not switch to GET after following a 301 redirect (H)",
" --post302 Do not switch to GET after following a 302 redirect (H)",
" -#/--progress-bar Display transfer progress as a progress bar",
+ " --proto <protocols> Enable/disable specified protocols",
+ " --proto-redir <protocols> Enable/disable specified protocols on redirect",
" -x/--proxy <host[:port]> Use HTTP proxy on given port",
" --proxy-anyauth Pick \"any\" proxy authentication method (H)",
" --proxy-basic Use Basic authentication on the proxy (H)",
@@ -1492,6 +1498,109 @@ static int str2num(long *val, const char *str)
return retcode;
}
+/*
+ * Parse the string and modify the long in the given address. Return
+ * non-zero on failure, zero on success.
+ *
+ * The string is a list of protocols
+ *
+ * Since this function gets called with the 'nextarg' pointer from within the
+ * getparameter a lot, we must check it for NULL before accessing the str
+ * data.
+ */
+
+static long proto2num(struct Configurable *config, long *val, const char *str)
+{
+ char *buffer;
+ const char *sep = ",";
+ char *token;
+
+ static struct sprotos {
+ const char *name;
+ long bit;
+ } const protos[] = {
+ { "all", 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 },
+ { "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 },
+ { NULL, 0 }
+ };
+
+ if(!str)
+ return 1;
+
+ buffer = strdup(str); /* because strtok corrupts it */
+
+ for (token = strtok(buffer, sep);
+ token;
+ 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++) {
+ case '=':
+ action = set;
+ break;
+ case '-':
+ action = deny;
+ break;
+ case '+':
+ action = allow;
+ break;
+ default: /* Includes case of terminating NULL */
+ free(buffer);
+ return 1;
+ }
+ }
+
+ for (pp=protos; pp->name; pp++) {
+ if (curlx_raw_equal(token, pp->name)) {
+ switch (action) {
+ case deny:
+ *val &= ~(pp->bit);
+ break;
+ case allow:
+ *val |= pp->bit;
+ break;
+ case set:
+ *val = pp->bit;
+ break;
+ }
+ 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, "unrecognized protocol '%s'\n", token);
+ }
+ }
+ free(buffer);
+ return 0;
+}
+
/**
* Parses the given string looking for an offset (which may be
* a larger-than-integer value).
@@ -1752,6 +1861,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$A", "mail-from", TRUE},
{"$B", "mail-rcpt", TRUE},
{"$C", "ftp-pret", FALSE},
+ {"$D", "proto", TRUE},
+ {"$E", "proto-redir", TRUE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
{"2", "sslv2", FALSE},
@@ -2294,6 +2405,16 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'C': /* --ftp-pret */
config->ftp_pret = toggle;
break;
+ case 'D': /* --proto */
+ config->proto_present = 1;
+ if(proto2num(config, &config->proto, nextarg))
+ return PARAM_BAD_USE;
+ break;
+ case 'E': /* --proto-redir */
+ config->proto_redir_present = 1;
+ if(proto2num(config, &config->proto_redir, nextarg))
+ return PARAM_BAD_USE;
+ break;
}
break;
case '#': /* --progress-bar */
@@ -4362,6 +4483,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
config->use_httpget=FALSE;
config->create_dirs=FALSE;
config->maxredirs = DEFAULT_MAXREDIRS;
+ config->proto = CURLPROTO_ALL; /* FIXME: better to read from library */
+ config->proto_present = FALSE;
+ config->proto_redir =
+ CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
+ config->proto_redir_present = FALSE;
if(argc>1 &&
(!curlx_strnequal("--", argv[1], 2) && (argv[1][0] == '-')) &&
@@ -5200,6 +5326,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
if(config->ftp_pret)
my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);
+ if (config->proto_present)
+ my_setopt(curl, CURLOPT_PROTOCOLS, config->proto);
+ if (config->proto_redir_present)
+ my_setopt(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
+
if ((urlnode->flags & GETOUT_USEREMOTE)
&& config->content_disposition) {
my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);