|
|
f0f8d7 |
From 5452fdc5ae93f3571074c591fdf28cdf630796a0 Mon Sep 17 00:00:00 2001
|
|
|
f0f8d7 |
From: Daniel Stenberg <daniel@haxx.se>
|
|
|
f0f8d7 |
Date: Tue, 12 Sep 2017 09:29:01 +0200
|
|
|
f0f8d7 |
Subject: [PATCH 1/3] FTP: URL decode path for dir listing in nocwd mode
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Reported-by: Zenju on github
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Test 244 added to verify
|
|
|
f0f8d7 |
Fixes #1974
|
|
|
f0f8d7 |
Closes #1976
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Upstream-commit: ecf21c551fa3426579463abe34b623111b8d487c
|
|
|
f0f8d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f0f8d7 |
---
|
|
|
f0f8d7 |
lib/ftp.c | 93 +++++++++++++++++++++++---------------------------
|
|
|
f0f8d7 |
tests/data/Makefile.am | 3 +-
|
|
|
f0f8d7 |
tests/data/test244 | 54 +++++++++++++++++++++++++++++
|
|
|
f0f8d7 |
3 files changed, 99 insertions(+), 51 deletions(-)
|
|
|
f0f8d7 |
create mode 100644 tests/data/test244
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
diff --git a/lib/ftp.c b/lib/ftp.c
|
|
|
f0f8d7 |
index bcba6bb..fb3a716 100644
|
|
|
f0f8d7 |
--- a/lib/ftp.c
|
|
|
f0f8d7 |
+++ b/lib/ftp.c
|
|
|
f0f8d7 |
@@ -1003,7 +1003,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|
|
f0f8d7 |
char *port_start = NULL;
|
|
|
f0f8d7 |
char *port_sep = NULL;
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
- addr = calloc(addrlen+1, 1);
|
|
|
f0f8d7 |
+ addr = calloc(addrlen + 1, 1);
|
|
|
f0f8d7 |
if(!addr)
|
|
|
f0f8d7 |
return CURLE_OUT_OF_MEMORY;
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
@@ -1041,7 +1041,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|
|
f0f8d7 |
/* parse the port */
|
|
|
f0f8d7 |
if(ip_end != NULL) {
|
|
|
f0f8d7 |
if((port_start = strchr(ip_end, ':')) != NULL) {
|
|
|
f0f8d7 |
- port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
|
|
|
f0f8d7 |
+ port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10));
|
|
|
f0f8d7 |
if((port_sep = strchr(port_start, '-')) != NULL) {
|
|
|
f0f8d7 |
port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
@@ -1469,25 +1469,22 @@ static CURLcode ftp_state_post_listtype(struct connectdata *conn)
|
|
|
f0f8d7 |
then just do LIST (in that case: nothing to do here)
|
|
|
f0f8d7 |
*/
|
|
|
f0f8d7 |
char *cmd,*lstArg,*slashPos;
|
|
|
f0f8d7 |
+ const char *inpath = data->state.path;
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
lstArg = NULL;
|
|
|
f0f8d7 |
if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
|
|
|
f0f8d7 |
- data->state.path &&
|
|
|
f0f8d7 |
- data->state.path[0] &&
|
|
|
f0f8d7 |
- strchr(data->state.path,'/')) {
|
|
|
f0f8d7 |
-
|
|
|
f0f8d7 |
- lstArg = strdup(data->state.path);
|
|
|
f0f8d7 |
- if(!lstArg)
|
|
|
f0f8d7 |
- return CURLE_OUT_OF_MEMORY;
|
|
|
f0f8d7 |
+ inpath && inpath[0] && strchr(inpath, '/')) {
|
|
|
f0f8d7 |
+ size_t n = strlen(inpath);
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
/* Check if path does not end with /, as then we cut off the file part */
|
|
|
f0f8d7 |
- if(lstArg[strlen(lstArg) - 1] != '/') {
|
|
|
f0f8d7 |
-
|
|
|
f0f8d7 |
+ if(inpath[n - 1] != '/') {
|
|
|
f0f8d7 |
/* chop off the file part if format is dir/dir/file */
|
|
|
f0f8d7 |
- slashPos = strrchr(lstArg,'/');
|
|
|
f0f8d7 |
- if(slashPos)
|
|
|
f0f8d7 |
- *(slashPos+1) = '\0';
|
|
|
f0f8d7 |
+ slashPos = strrchr(inpath, '/');
|
|
|
f0f8d7 |
+ n = slashPos - inpath;
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
+ result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE);
|
|
|
f0f8d7 |
+ if(result)
|
|
|
f0f8d7 |
+ return result;
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
cmd = aprintf( "%s%s%s",
|
|
|
b7b705 |
@@ -3328,12 +3325,10 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
/* get the "raw" path */
|
|
|
f0f8d7 |
- path = curl_easy_unescape(data, path_to_use, 0, NULL);
|
|
|
f0f8d7 |
- if(!path) {
|
|
|
f0f8d7 |
+ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
|
|
|
f0f8d7 |
+ if(result) {
|
|
|
f0f8d7 |
/* out of memory, but we can limp along anyway (and should try to
|
|
|
f0f8d7 |
* since we may already be in the out of memory cleanup path) */
|
|
|
f0f8d7 |
- if(!result)
|
|
|
f0f8d7 |
- result = CURLE_OUT_OF_MEMORY;
|
|
|
f0f8d7 |
ftpc->ctl_valid = FALSE; /* mark control connection as bad */
|
|
|
f0f8d7 |
conn->bits.close = TRUE; /* mark for connection closure */
|
|
|
f0f8d7 |
ftpc->prevpath = NULL; /* no path remembering */
|
|
|
b7b705 |
@@ -3644,7 +3639,7 @@ static CURLcode ftp_range(struct connectdata *conn)
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
else {
|
|
|
f0f8d7 |
/* X-Y */
|
|
|
f0f8d7 |
- data->req.maxdownload = (to-from)+1; /* include last byte */
|
|
|
f0f8d7 |
+ data->req.maxdownload = (to - from) + 1; /* include last byte */
|
|
|
f0f8d7 |
data->state.resume_from = from;
|
|
|
f0f8d7 |
DEBUGF(infof(conn->data, "FTP RANGE from %" FORMAT_OFF_T
|
|
|
f0f8d7 |
" getting %" FORMAT_OFF_T " bytes\n",
|
|
|
b7b705 |
@@ -4333,20 +4328,22 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
slash_pos=strrchr(cur_pos, '/');
|
|
|
f0f8d7 |
if(slash_pos || !*cur_pos) {
|
|
|
f0f8d7 |
+ CURLcode result;
|
|
|
f0f8d7 |
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
|
|
|
f0f8d7 |
if(!ftpc->dirs)
|
|
|
f0f8d7 |
return CURLE_OUT_OF_MEMORY;
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
- ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
|
|
|
f0f8d7 |
- slash_pos ?
|
|
|
f0f8d7 |
- curlx_sztosi(slash_pos-cur_pos) : 1,
|
|
|
f0f8d7 |
- NULL);
|
|
|
f0f8d7 |
- if(!ftpc->dirs[0]) {
|
|
|
f0f8d7 |
+ result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
|
|
|
f0f8d7 |
+ slash_pos ?
|
|
|
f0f8d7 |
+ curlx_sztosi(slash_pos-cur_pos) : 1,
|
|
|
f0f8d7 |
+ &ftpc->dirs[0], NULL,
|
|
|
f0f8d7 |
+ FALSE);
|
|
|
f0f8d7 |
+ if(result) {
|
|
|
f0f8d7 |
freedirs(ftpc);
|
|
|
f0f8d7 |
- return CURLE_OUT_OF_MEMORY;
|
|
|
f0f8d7 |
+ return result;
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
ftpc->dirdepth = 1; /* we consider it to be a single dir */
|
|
|
f0f8d7 |
- filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
|
|
|
f0f8d7 |
+ filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
else
|
|
|
f0f8d7 |
filename = cur_pos; /* this is a file name only */
|
|
|
b7b705 |
@@ -4378,18 +4375,15 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|
|
f0f8d7 |
/* we skip empty path components, like "x//y" since the FTP command
|
|
|
f0f8d7 |
CWD requires a parameter and a non-existent parameter a) doesn't
|
|
|
f0f8d7 |
work on many servers and b) has no effect on the others. */
|
|
|
f0f8d7 |
- int len = curlx_sztosi(slash_pos - cur_pos + absolute_dir);
|
|
|
f0f8d7 |
- ftpc->dirs[ftpc->dirdepth] =
|
|
|
f0f8d7 |
- curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL);
|
|
|
f0f8d7 |
- if(!ftpc->dirs[ftpc->dirdepth]) { /* run out of memory ... */
|
|
|
f0f8d7 |
- failf(data, "no memory");
|
|
|
f0f8d7 |
- freedirs(ftpc);
|
|
|
f0f8d7 |
- return CURLE_OUT_OF_MEMORY;
|
|
|
f0f8d7 |
- }
|
|
|
f0f8d7 |
- if(isBadFtpString(ftpc->dirs[ftpc->dirdepth])) {
|
|
|
f0f8d7 |
+ size_t len = slash_pos - cur_pos + absolute_dir;
|
|
|
f0f8d7 |
+ CURLcode result =
|
|
|
f0f8d7 |
+ Curl_urldecode(conn->data, cur_pos - absolute_dir, len,
|
|
|
f0f8d7 |
+ &ftpc->dirs[ftpc->dirdepth], NULL,
|
|
|
f0f8d7 |
+ TRUE);
|
|
|
f0f8d7 |
+ if(result) {
|
|
|
f0f8d7 |
free(ftpc->dirs[ftpc->dirdepth]);
|
|
|
f0f8d7 |
freedirs(ftpc);
|
|
|
f0f8d7 |
- return CURLE_URL_MALFORMAT;
|
|
|
f0f8d7 |
+ return result;
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
else {
|
|
|
b7b705 |
@@ -4416,15 +4410,12 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|
|
f0f8d7 |
} /* switch */
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
if(filename && *filename) {
|
|
|
f0f8d7 |
- ftpc->file = curl_easy_unescape(conn->data, filename, 0, NULL);
|
|
|
f0f8d7 |
- if(NULL == ftpc->file) {
|
|
|
f0f8d7 |
- freedirs(ftpc);
|
|
|
f0f8d7 |
- failf(data, "no memory");
|
|
|
f0f8d7 |
- return CURLE_OUT_OF_MEMORY;
|
|
|
f0f8d7 |
- }
|
|
|
f0f8d7 |
- if(isBadFtpString(ftpc->file)) {
|
|
|
f0f8d7 |
+ CURLcode result =
|
|
|
f0f8d7 |
+ Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE);
|
|
|
f0f8d7 |
+
|
|
|
f0f8d7 |
+ if(result) {
|
|
|
f0f8d7 |
freedirs(ftpc);
|
|
|
f0f8d7 |
- return CURLE_URL_MALFORMAT;
|
|
|
f0f8d7 |
+ return result;
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
else
|
|
|
b7b705 |
@@ -4442,15 +4433,17 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|
|
f0f8d7 |
if(ftpc->prevpath) {
|
|
|
f0f8d7 |
/* prevpath is "raw" so we convert the input path before we compare the
|
|
|
f0f8d7 |
strings */
|
|
|
f0f8d7 |
- int dlen;
|
|
|
f0f8d7 |
- char *path = curl_easy_unescape(conn->data, data->state.path, 0, &dlen);
|
|
|
f0f8d7 |
- if(!path) {
|
|
|
f0f8d7 |
+ size_t dlen;
|
|
|
f0f8d7 |
+ char *path;
|
|
|
f0f8d7 |
+ CURLcode result =
|
|
|
f0f8d7 |
+ Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
|
|
|
f0f8d7 |
+ if(result) {
|
|
|
f0f8d7 |
freedirs(ftpc);
|
|
|
f0f8d7 |
- return CURLE_OUT_OF_MEMORY;
|
|
|
f0f8d7 |
+ return result;
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
- dlen -= ftpc->file?curlx_uztosi(strlen(ftpc->file)):0;
|
|
|
f0f8d7 |
- if((dlen == curlx_uztosi(strlen(ftpc->prevpath))) &&
|
|
|
f0f8d7 |
+ dlen -= ftpc->file?strlen(ftpc->file):0;
|
|
|
f0f8d7 |
+ if((dlen == strlen(ftpc->prevpath)) &&
|
|
|
f0f8d7 |
strnequal(path, ftpc->prevpath, dlen)) {
|
|
|
f0f8d7 |
infof(data, "Request has same path as previous transfer\n");
|
|
|
f0f8d7 |
ftpc->cwddone = TRUE;
|
|
|
f0f8d7 |
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
|
|
|
f0f8d7 |
index 56cb286..e7955ee 100644
|
|
|
f0f8d7 |
--- a/tests/data/Makefile.am
|
|
|
f0f8d7 |
+++ b/tests/data/Makefile.am
|
|
|
f0f8d7 |
@@ -28,7 +28,8 @@ test200 test201 test202 test203 test204 test205 test206 test207 test208 \
|
|
|
f0f8d7 |
test209 test210 test211 test212 test213 test214 test215 test216 test217 \
|
|
|
f0f8d7 |
test218 test220 test221 test222 test223 test224 test225 test226 test227 \
|
|
|
f0f8d7 |
test228 test229 test231 test233 test234 test235 test236 test237 test238 \
|
|
|
f0f8d7 |
-test239 test240 test241 test242 test243 test245 test246 test247 test248 \
|
|
|
f0f8d7 |
+test239 test240 test241 test242 test243 \
|
|
|
f0f8d7 |
+test244 test245 test246 test247 test248 \
|
|
|
f0f8d7 |
test249 test250 test251 test252 test253 test254 test255 test256 test257 \
|
|
|
f0f8d7 |
test258 test259 test260 test261 test262 test263 test264 test265 test266 \
|
|
|
f0f8d7 |
test267 test268 test269 test270 test271 test272 test273 test274 test275 \
|
|
|
f0f8d7 |
diff --git a/tests/data/test244 b/tests/data/test244
|
|
|
f0f8d7 |
new file mode 100644
|
|
|
f0f8d7 |
index 0000000..8ce4b63
|
|
|
f0f8d7 |
--- /dev/null
|
|
|
f0f8d7 |
+++ b/tests/data/test244
|
|
|
f0f8d7 |
@@ -0,0 +1,54 @@
|
|
|
f0f8d7 |
+<testcase>
|
|
|
f0f8d7 |
+<info>
|
|
|
f0f8d7 |
+<keywords>
|
|
|
f0f8d7 |
+FTP
|
|
|
f0f8d7 |
+PASV
|
|
|
f0f8d7 |
+CWD
|
|
|
f0f8d7 |
+--ftp-method
|
|
|
f0f8d7 |
+nocwd
|
|
|
f0f8d7 |
+</keywords>
|
|
|
f0f8d7 |
+</info>
|
|
|
f0f8d7 |
+#
|
|
|
f0f8d7 |
+# Server-side
|
|
|
f0f8d7 |
+<reply>
|
|
|
f0f8d7 |
+<data mode="text">
|
|
|
f0f8d7 |
+total 20
|
|
|
f0f8d7 |
+drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
|
|
|
f0f8d7 |
+drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
|
|
|
f0f8d7 |
+drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
|
|
|
f0f8d7 |
+-r--r--r-- 1 0 1 35 Jul 16 1996 README
|
|
|
f0f8d7 |
+lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
|
|
|
f0f8d7 |
+dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
|
|
|
f0f8d7 |
+drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
|
|
|
f0f8d7 |
+dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
|
|
|
f0f8d7 |
+drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
|
|
|
f0f8d7 |
+dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
|
|
|
f0f8d7 |
+</data>
|
|
|
f0f8d7 |
+</reply>
|
|
|
f0f8d7 |
+
|
|
|
f0f8d7 |
+# Client-side
|
|
|
f0f8d7 |
+<client>
|
|
|
f0f8d7 |
+<server>
|
|
|
f0f8d7 |
+ftp
|
|
|
f0f8d7 |
+</server>
|
|
|
f0f8d7 |
+ <name>
|
|
|
f0f8d7 |
+FTP dir listing with nocwd and URL encoded path
|
|
|
f0f8d7 |
+ </name>
|
|
|
f0f8d7 |
+ <command>
|
|
|
f0f8d7 |
+--ftp-method nocwd ftp://%HOSTIP:%FTPPORT/fir%23t/th%69rd/244/
|
|
|
f0f8d7 |
+</command>
|
|
|
f0f8d7 |
+</client>
|
|
|
f0f8d7 |
+
|
|
|
f0f8d7 |
+# Verify data after the test has been "shot"
|
|
|
f0f8d7 |
+<verify>
|
|
|
f0f8d7 |
+<protocol>
|
|
|
f0f8d7 |
+USER anonymous
|
|
|
f0f8d7 |
+PASS ftp@example.com
|
|
|
f0f8d7 |
+PWD
|
|
|
f0f8d7 |
+EPSV
|
|
|
f0f8d7 |
+TYPE A
|
|
|
f0f8d7 |
+LIST fir#t/third/244/
|
|
|
f0f8d7 |
+QUIT
|
|
|
f0f8d7 |
+</protocol>
|
|
|
f0f8d7 |
+</verify>
|
|
|
f0f8d7 |
+</testcase>
|
|
|
f0f8d7 |
--
|
|
|
f0f8d7 |
2.14.3
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
From 295fc8b0dc5c94a1cbf6688bfba768128b13cde6 Mon Sep 17 00:00:00 2001
|
|
|
f0f8d7 |
From: Daniel Stenberg <daniel@haxx.se>
|
|
|
f0f8d7 |
Date: Wed, 2 Nov 2016 07:22:27 +0100
|
|
|
f0f8d7 |
Subject: [PATCH 2/3] ftp_done: don't clobber the passed in error code
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Coverity CID 1374359 pointed out the unused result value.
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Upstream-commit: f81a8364618caf99b4691ffd494a9b2d4c9fb1f6
|
|
|
f0f8d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f0f8d7 |
---
|
|
|
f0f8d7 |
lib/ftp.c | 9 +++++----
|
|
|
f0f8d7 |
1 file changed, 5 insertions(+), 4 deletions(-)
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
diff --git a/lib/ftp.c b/lib/ftp.c
|
|
|
f0f8d7 |
index 9da5a24..0259a14 100644
|
|
|
f0f8d7 |
--- a/lib/ftp.c
|
|
|
f0f8d7 |
+++ b/lib/ftp.c
|
|
|
b7b705 |
@@ -3324,11 +3324,12 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
|
|
f0f8d7 |
ftpc->known_filesize = -1;
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
- /* get the "raw" path */
|
|
|
f0f8d7 |
- result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
|
|
|
f0f8d7 |
+ if(!result)
|
|
|
f0f8d7 |
+ /* get the "raw" path */
|
|
|
f0f8d7 |
+ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
|
|
|
f0f8d7 |
if(result) {
|
|
|
f0f8d7 |
- /* out of memory, but we can limp along anyway (and should try to
|
|
|
f0f8d7 |
- * since we may already be in the out of memory cleanup path) */
|
|
|
f0f8d7 |
+ /* We can limp along anyway (and should try to since we may already be in
|
|
|
f0f8d7 |
+ * the error path) */
|
|
|
f0f8d7 |
ftpc->ctl_valid = FALSE; /* mark control connection as bad */
|
|
|
f0f8d7 |
conn->bits.close = TRUE; /* mark for connection closure */
|
|
|
f0f8d7 |
ftpc->prevpath = NULL; /* no path remembering */
|
|
|
f0f8d7 |
--
|
|
|
f0f8d7 |
2.14.4
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
From 9534442aae1da4e6cf2ce815e47dbcd82695c3d4 Mon Sep 17 00:00:00 2001
|
|
|
f0f8d7 |
From: Daniel Stenberg <daniel@haxx.se>
|
|
|
f0f8d7 |
Date: Wed, 31 Jan 2018 08:40:11 +0100
|
|
|
f0f8d7 |
Subject: [PATCH 3/3] FTP: reject path components with control codes
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Refuse to operate when given path components featuring byte values lower
|
|
|
f0f8d7 |
than 32.
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Previously, inserting a %00 sequence early in the directory part when
|
|
|
f0f8d7 |
using the 'singlecwd' ftp method could make curl write a zero byte
|
|
|
f0f8d7 |
outside of the allocated buffer.
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Test case 340 verifies.
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
CVE-2018-1000120
|
|
|
f0f8d7 |
Reported-by: Duy Phan Thanh
|
|
|
f0f8d7 |
Bug: https://curl.haxx.se/docs/adv_2018-9cd6.html
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
Upstream-commit: 535432c0adb62fe167ec09621500470b6fa4eb0f
|
|
|
f0f8d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f0f8d7 |
---
|
|
|
f0f8d7 |
lib/ftp.c | 8 ++++----
|
|
|
f0f8d7 |
tests/data/Makefile.am | 1 +
|
|
|
f0f8d7 |
tests/data/test340 | 40 ++++++++++++++++++++++++++++++++++++++++
|
|
|
f0f8d7 |
3 files changed, 45 insertions(+), 4 deletions(-)
|
|
|
f0f8d7 |
create mode 100644 tests/data/test340
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
diff --git a/lib/ftp.c b/lib/ftp.c
|
|
|
f0f8d7 |
index fb3a716..268efdd 100644
|
|
|
f0f8d7 |
--- a/lib/ftp.c
|
|
|
f0f8d7 |
+++ b/lib/ftp.c
|
|
|
f0f8d7 |
@@ -1482,7 +1482,7 @@ static CURLcode ftp_state_post_listtype(struct connectdata *conn)
|
|
|
f0f8d7 |
slashPos = strrchr(inpath, '/');
|
|
|
f0f8d7 |
n = slashPos - inpath;
|
|
|
f0f8d7 |
}
|
|
|
f0f8d7 |
- result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE);
|
|
|
f0f8d7 |
+ result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE);
|
|
|
f0f8d7 |
if(result)
|
|
|
f0f8d7 |
return result;
|
|
|
f0f8d7 |
}
|
|
|
b7b705 |
@@ -3326,7 +3326,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
|
|
f0f8d7 |
|
|
|
f0f8d7 |
if(!result)
|
|
|
f0f8d7 |
/* get the "raw" path */
|
|
|
f0f8d7 |
- result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
|
|
|
f0f8d7 |
+ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, TRUE);
|
|
|
f0f8d7 |
if(result) {
|
|
|
f0f8d7 |
/* We can limp along anyway (and should try to since we may already be in
|
|
|
f0f8d7 |
* the error path) */
|
|
|
b7b705 |
@@ -4338,7 +4338,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|
|
f0f8d7 |
slash_pos ?
|
|
|
f0f8d7 |
curlx_sztosi(slash_pos-cur_pos) : 1,
|
|
|
f0f8d7 |
&ftpc->dirs[0], NULL,
|
|
|
f0f8d7 |
- FALSE);
|
|
|
f0f8d7 |
+ TRUE);
|
|
|
f0f8d7 |
if(result) {
|
|
|
f0f8d7 |
freedirs(ftpc);
|
|
|
f0f8d7 |
return result;
|
|
|
b7b705 |
@@ -4437,7 +4437,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|
|
f0f8d7 |
size_t dlen;
|
|
|
f0f8d7 |
char *path;
|
|
|
f0f8d7 |
CURLcode result =
|
|
|
f0f8d7 |
- Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
|
|
|
f0f8d7 |
+ Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, TRUE);
|
|
|
f0f8d7 |
if(result) {
|
|
|
f0f8d7 |
freedirs(ftpc);
|
|
|
f0f8d7 |
return result;
|
|
|
f0f8d7 |
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
|
|
|
f0f8d7 |
index e7955ee..910db5b 100644
|
|
|
f0f8d7 |
--- a/tests/data/Makefile.am
|
|
|
f0f8d7 |
+++ b/tests/data/Makefile.am
|
|
|
f0f8d7 |
@@ -39,6 +39,7 @@ test294 test295 test296 test297 test298 test299 test300 test301 test302 \
|
|
|
f0f8d7 |
test303 test304 test305 test306 test307 test308 test309 test310 test311 \
|
|
|
f0f8d7 |
test312 test313 test317 test318 \
|
|
|
f0f8d7 |
test320 test321 test322 test323 test324 test350 test351 \
|
|
|
f0f8d7 |
+test340 \
|
|
|
f0f8d7 |
test352 test353 test354 test400 test401 test402 test403 test404 test405 \
|
|
|
f0f8d7 |
test406 test407 test408 test409 test500 test501 test502 test503 test504 \
|
|
|
f0f8d7 |
test505 test506 test507 test508 test510 test511 test512 test513 test514 \
|
|
|
f0f8d7 |
diff --git a/tests/data/test340 b/tests/data/test340
|
|
|
f0f8d7 |
new file mode 100644
|
|
|
f0f8d7 |
index 0000000..d834d76
|
|
|
f0f8d7 |
--- /dev/null
|
|
|
f0f8d7 |
+++ b/tests/data/test340
|
|
|
f0f8d7 |
@@ -0,0 +1,40 @@
|
|
|
f0f8d7 |
+<testcase>
|
|
|
f0f8d7 |
+<info>
|
|
|
f0f8d7 |
+<keywords>
|
|
|
f0f8d7 |
+FTP
|
|
|
f0f8d7 |
+PASV
|
|
|
f0f8d7 |
+CWD
|
|
|
f0f8d7 |
+--ftp-method
|
|
|
f0f8d7 |
+singlecwd
|
|
|
f0f8d7 |
+</keywords>
|
|
|
f0f8d7 |
+</info>
|
|
|
f0f8d7 |
+#
|
|
|
f0f8d7 |
+# Server-side
|
|
|
f0f8d7 |
+<reply>
|
|
|
f0f8d7 |
+</reply>
|
|
|
f0f8d7 |
+
|
|
|
f0f8d7 |
+# Client-side
|
|
|
f0f8d7 |
+<client>
|
|
|
f0f8d7 |
+<server>
|
|
|
f0f8d7 |
+ftp
|
|
|
f0f8d7 |
+</server>
|
|
|
f0f8d7 |
+ <name>
|
|
|
f0f8d7 |
+FTP using %00 in path with singlecwd
|
|
|
f0f8d7 |
+ </name>
|
|
|
f0f8d7 |
+ <command>
|
|
|
f0f8d7 |
+--ftp-method singlecwd ftp://%HOSTIP:%FTPPORT/%00first/second/third/340
|
|
|
f0f8d7 |
+</command>
|
|
|
f0f8d7 |
+</client>
|
|
|
f0f8d7 |
+
|
|
|
f0f8d7 |
+# Verify data after the test has been "shot"
|
|
|
f0f8d7 |
+<verify>
|
|
|
f0f8d7 |
+<protocol>
|
|
|
f0f8d7 |
+USER anonymous
|
|
|
f0f8d7 |
+PASS ftp@example.com
|
|
|
f0f8d7 |
+PWD
|
|
|
f0f8d7 |
+</protocol>
|
|
|
f0f8d7 |
+<errorcode>
|
|
|
f0f8d7 |
+3
|
|
|
f0f8d7 |
+</errorcode>
|
|
|
f0f8d7 |
+</verify>
|
|
|
f0f8d7 |
+</testcase>
|
|
|
f0f8d7 |
--
|
|
|
f0f8d7 |
2.14.3
|
|
|
f0f8d7 |
|