Skip to content

Commit

Permalink
escape: make the URL decode able to reject only %00 bytes
Browse files Browse the repository at this point in the history
... or all "control codes" or nothing.

Assisted-by: Nicolas Sterchele
  • Loading branch information
bagder committed Jun 25, 2020
1 parent 646cc57 commit 31e5358
Show file tree
Hide file tree
Showing 16 changed files with 60 additions and 34 deletions.
4 changes: 2 additions & 2 deletions lib/curl_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down
3 changes: 2 additions & 1 deletion lib/dict.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
21 changes: 15 additions & 6 deletions lib/escape.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down
11 changes: 9 additions & 2 deletions lib/escape.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 */
2 changes: 1 addition & 1 deletion lib/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
7 changes: 4 additions & 3 deletions lib/ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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) */
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion lib/gopher.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 6 additions & 4 deletions lib/imap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 4 additions & 3 deletions lib/ldap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand Down
3 changes: 2 additions & 1 deletion lib/mqtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
Expand Down
4 changes: 2 additions & 2 deletions lib/pop3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/***********************************************************************
Expand All @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/smb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down
5 changes: 3 additions & 2 deletions lib/smtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/***********************************************************************
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/tftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions lib/url.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
5 changes: 4 additions & 1 deletion lib/urlapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 31e5358

Please sign in to comment.