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:
Daniel Stenberg 2020-06-23 16:13:50 +02:00
Родитель 646cc574f0
Коммит 31e53584db
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 5CC908FDB71E12C2
16 изменённых файлов: 60 добавлений и 34 удалений

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;