escape: make the URL decode able to reject only %00 bytes
... or all "control codes" or nothing. Assisted-by: Nicolas Sterchele
This commit is contained in:
Родитель
646cc574f0
Коммит
31e53584db
|
@ -5,7 +5,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
|
@ -42,7 +42,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
|
|||
size_t working_path_len;
|
||||
CURLcode result =
|
||||
Curl_urldecode(data, data->state.up.path, 0, &working_path,
|
||||
&working_path_len, FALSE);
|
||||
&working_path_len, REJECT_ZERO);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -99,7 +99,8 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
|
|||
char *dictp;
|
||||
size_t len;
|
||||
|
||||
CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
|
||||
CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len,
|
||||
REJECT_NADA);
|
||||
if(!newp || result)
|
||||
return NULL;
|
||||
|
||||
|
|
21
lib/escape.c
21
lib/escape.c
|
@ -123,19 +123,26 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
|
|||
/*
|
||||
* Curl_urldecode() URL decodes the given string.
|
||||
*
|
||||
* Optionally detects control characters (byte codes lower than 32) in the
|
||||
* data and rejects such data.
|
||||
*
|
||||
* Returns a pointer to a malloced string in *ostring with length given in
|
||||
* *olen. If length == 0, the length is assumed to be strlen(string).
|
||||
*
|
||||
* 'data' can be set to NULL but then this function can't convert network
|
||||
* data to host for non-ascii.
|
||||
*
|
||||
* ctrl options:
|
||||
* - REJECT_NADA: accept everything
|
||||
* - REJECT_CTRL: rejects control characters (byte codes lower than 32) in
|
||||
* the data
|
||||
* - REJECT_ZERO: rejects decoded zero bytes
|
||||
*
|
||||
* The values for the enum starts at 2, to make the assert detect legacy
|
||||
* invokes that used TRUE/FALSE (0 and 1).
|
||||
*/
|
||||
|
||||
CURLcode Curl_urldecode(struct Curl_easy *data,
|
||||
const char *string, size_t length,
|
||||
char **ostring, size_t *olen,
|
||||
bool reject_ctrl)
|
||||
enum urlreject ctrl)
|
||||
{
|
||||
size_t alloc;
|
||||
char *ns;
|
||||
|
@ -144,6 +151,7 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
|
|||
CURLcode result = CURLE_OK;
|
||||
|
||||
DEBUGASSERT(string);
|
||||
DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */
|
||||
|
||||
alloc = (length?length:strlen(string)) + 1;
|
||||
ns = malloc(alloc);
|
||||
|
@ -179,7 +187,8 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
|
|||
alloc -= 2;
|
||||
}
|
||||
|
||||
if(reject_ctrl && (in < 0x20)) {
|
||||
if(((ctrl == REJECT_CTRL) && (in < 0x20)) ||
|
||||
((ctrl == REJECT_ZERO) && (in == 0))) {
|
||||
free(ns);
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
@ -213,7 +222,7 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string,
|
|||
size_t inputlen = length;
|
||||
size_t outputlen;
|
||||
CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
|
||||
FALSE);
|
||||
REJECT_NADA);
|
||||
if(res)
|
||||
return NULL;
|
||||
|
||||
|
|
11
lib/escape.h
11
lib/escape.h
|
@ -7,7 +7,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
|
@ -25,9 +25,16 @@
|
|||
* allocated string or NULL if an error occurred. */
|
||||
|
||||
bool Curl_isunreserved(unsigned char in);
|
||||
|
||||
enum urlreject {
|
||||
REJECT_NADA = 2,
|
||||
REJECT_CTRL,
|
||||
REJECT_ZERO
|
||||
};
|
||||
|
||||
CURLcode Curl_urldecode(struct Curl_easy *data,
|
||||
const char *string, size_t length,
|
||||
char **ostring, size_t *olen,
|
||||
bool reject_crlf);
|
||||
enum urlreject ctrl);
|
||||
|
||||
#endif /* HEADER_CURL_ESCAPE_H */
|
||||
|
|
|
@ -144,7 +144,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
|
|||
size_t real_path_len;
|
||||
|
||||
CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path,
|
||||
&real_path_len, FALSE);
|
||||
&real_path_len, REJECT_ZERO);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -1452,7 +1452,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
|
|||
/* url-decode before evaluation: e.g. paths starting/ending with %2f */
|
||||
const char *slashPos = NULL;
|
||||
char *rawPath = NULL;
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, TRUE);
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, REJECT_CTRL);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -3194,7 +3194,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
|||
|
||||
if(!result)
|
||||
/* get the url-decoded "raw" path */
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen,
|
||||
REJECT_CTRL);
|
||||
if(result) {
|
||||
/* We can limp along anyway (and should try to since we may already be in
|
||||
* the error path) */
|
||||
|
@ -4110,7 +4111,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|||
ftpc->cwdfail = FALSE;
|
||||
|
||||
/* url-decode ftp path before further evaluation */
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, REJECT_CTRL);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
|
|||
newp += 2;
|
||||
|
||||
/* ... and finally unescape */
|
||||
result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
|
||||
result = Curl_urldecode(data, newp, 0, &sel, &len, REJECT_ZERO);
|
||||
free(gopherpath);
|
||||
if(result)
|
||||
return result;
|
||||
|
|
10
lib/imap.c
10
lib/imap.c
|
@ -1957,7 +1957,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
|
|||
end--;
|
||||
|
||||
result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL,
|
||||
TRUE);
|
||||
REJECT_CTRL);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
@ -1979,7 +1979,8 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
|
|||
return CURLE_URL_MALFORMAT;
|
||||
|
||||
/* Decode the name parameter */
|
||||
result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE);
|
||||
result = Curl_urldecode(data, begin, ptr - begin, &name, NULL,
|
||||
REJECT_CTRL);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -1989,7 +1990,8 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
|
|||
ptr++;
|
||||
|
||||
/* Decode the value parameter */
|
||||
result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE);
|
||||
result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen,
|
||||
REJECT_CTRL);
|
||||
if(result) {
|
||||
free(name);
|
||||
return result;
|
||||
|
@ -2077,7 +2079,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
|
|||
|
||||
if(custom) {
|
||||
/* URL decode the custom request */
|
||||
result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE);
|
||||
result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, REJECT_CTRL);
|
||||
|
||||
/* Extract the parameters if specified */
|
||||
if(!result) {
|
||||
|
|
|
@ -883,7 +883,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
|
|||
LDAP_TRACE(("DN '%s'\n", dn));
|
||||
|
||||
/* Unescape the DN */
|
||||
result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
|
||||
result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, REJECT_ZERO);
|
||||
if(result) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
|
||||
|
@ -949,7 +949,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
|
|||
|
||||
/* Unescape the attribute */
|
||||
result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
|
||||
FALSE);
|
||||
REJECT_ZERO);
|
||||
if(result) {
|
||||
free(attributes);
|
||||
|
||||
|
@ -1018,7 +1018,8 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
|
|||
LDAP_TRACE(("filter '%s'\n", filter));
|
||||
|
||||
/* Unescape the filter */
|
||||
result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
|
||||
result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL,
|
||||
REJECT_ZERO);
|
||||
if(result) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
|
||||
|
|
|
@ -211,7 +211,8 @@ static CURLcode mqtt_get_topic(struct connectdata *conn,
|
|||
char *path = conn->data->state.up.path;
|
||||
|
||||
if(strlen(path) > 1) {
|
||||
result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen, FALSE);
|
||||
result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen,
|
||||
REJECT_NADA);
|
||||
}
|
||||
else {
|
||||
failf(conn->data, "Error: No topic specified.");
|
||||
|
|
|
@ -1390,7 +1390,7 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
|
|||
const char *path = &data->state.up.path[1]; /* skip leading path */
|
||||
|
||||
/* URL decode the path for the message ID */
|
||||
return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
|
||||
return Curl_urldecode(data, path, 0, &pop3->id, NULL, REJECT_CTRL);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1408,7 +1408,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
|
|||
|
||||
/* URL decode the custom request */
|
||||
if(custom)
|
||||
result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
|
||||
result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, REJECT_CTRL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
|
||||
* Copyright (C) 2016-2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2016-2020, 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
|
||||
|
@ -964,7 +964,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
|
|||
|
||||
/* URL decode the path */
|
||||
CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL,
|
||||
TRUE);
|
||||
REJECT_CTRL);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -1689,7 +1689,8 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
|
|||
}
|
||||
|
||||
/* URL decode the path and use it as the domain in our EHLO */
|
||||
return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
|
||||
return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL,
|
||||
REJECT_CTRL);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1707,7 +1708,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn)
|
|||
|
||||
/* URL decode the custom request */
|
||||
if(custom)
|
||||
result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE);
|
||||
result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, REJECT_CTRL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -487,7 +487,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
|
|||
file name so we skip the always-present first letter of the path
|
||||
string. */
|
||||
result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
|
||||
&filename, NULL, FALSE);
|
||||
&filename, NULL, REJECT_ZERO);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -2373,10 +2373,10 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
|
|||
|
||||
if(proxyuser)
|
||||
result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
|
||||
FALSE);
|
||||
REJECT_ZERO);
|
||||
if(!result && proxypasswd)
|
||||
result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
|
||||
NULL, FALSE);
|
||||
NULL, REJECT_ZERO);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1185,7 +1185,10 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
|
|||
if(urldecode) {
|
||||
char *decoded;
|
||||
size_t dlen;
|
||||
CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen, TRUE);
|
||||
/* this unconditional rejection of control bytes is documented
|
||||
API behavior */
|
||||
CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen,
|
||||
REJECT_CTRL);
|
||||
free(*part);
|
||||
if(res) {
|
||||
*part = NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче