From 65f5b958c95d538a9b205e2753a476d1a7c89179 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 12 Sep 2019 17:50:21 +0200 Subject: [PATCH] FTP: allow "rubbish" prepended to the SIZE response This is a protocol violation but apparently there are legacy proprietary servers doing this. Added test 336 and 337 to verify. Reported-by: Philippe Marguinaud Closes #4339 --- lib/ftp.c | 20 ++++++++++++-- tests/data/Makefile.inc | 2 +- tests/data/test336 | 58 +++++++++++++++++++++++++++++++++++++++++ tests/data/test337 | 58 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 tests/data/test336 create mode 100644 tests/data/test337 diff --git a/lib/ftp.c b/lib/ftp.c index 0793dc1f3..00233a80d 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -2244,9 +2244,25 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn, char *buf = data->state.buffer; /* get the size from the ascii string: */ - if(ftpcode == 213) + if(ftpcode == 213) { + /* To allow servers to prepend "rubbish" in the response string, we scan + for all the digits at the end of the response and parse only those as a + number. */ + char *start = &buf[4]; + char *fdigit = strchr(start, '\r'); + if(fdigit) { + do + fdigit--; + while(ISDIGIT(*fdigit) && (fdigit > start)); + if(!ISDIGIT(*fdigit)) + fdigit++; + } + else + fdigit = start; /* ignores parsing errors, which will make the size remain unknown */ - (void)curlx_strtoofft(buf + 4, NULL, 0, &filesize); + (void)curlx_strtoofft(fdigit, NULL, 0, &filesize); + + } if(instate == FTP_SIZE) { #ifdef CURL_FTP_HTTPSTYLE_HEAD diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index fc22c2f17..3733bd6b9 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -57,7 +57,7 @@ test298 test299 test300 test301 test302 test303 test304 test305 test306 \ test307 test308 test309 test310 test311 test312 test313 test314 test315 \ test316 test317 test318 test319 test320 test321 test322 test323 test324 \ test325 test326 test327 test328 test329 test330 test331 test332 test333 \ -test334 test335 \ +test334 test335 test336 test337 \ test340 \ \ test350 test351 test352 test353 test354 test355 test356 \ diff --git a/tests/data/test336 b/tests/data/test336 new file mode 100644 index 000000000..85477c96c --- /dev/null +++ b/tests/data/test336 @@ -0,0 +1,58 @@ + + + +FTP +PASV +TYPE A +RETR + + +# Server-side + + +data + to + see +that FTP +works + so does it? + + +data + + +REPLY EPSV 500 no such command +REPLY SIZE 500 no such command + + + +# Client-side + + +ftp + + +FTP range download when SIZE doesn't work + + +ftp://%HOSTIP:%FTPPORT/336 --use-ascii --range 3-6 + + + +# Verify data after the test has been "shot" + + +USER anonymous +PASS ftp@example.com +PWD +EPSV +PASV +TYPE A +SIZE 336 +REST 3 +RETR 336 +ABOR +QUIT + + + diff --git a/tests/data/test337 b/tests/data/test337 new file mode 100644 index 000000000..80086dda7 --- /dev/null +++ b/tests/data/test337 @@ -0,0 +1,58 @@ + + + +FTP +PASV +TYPE A +RETR + + +# Server-side + + +data + to + see +that FTP +works + so does it? + + +data + + +REPLY EPSV 500 no such command +REPLY SIZE 213 file: 213, Size =51 + + + +# Client-side + + +ftp + + +FTP range download with SIZE returning extra crap + + +ftp://%HOSTIP:%FTPPORT/337 --use-ascii --range 3-6 + + + +# Verify data after the test has been "shot" + + +USER anonymous +PASS ftp@example.com +PWD +EPSV +PASV +TYPE A +SIZE 337 +REST 3 +RETR 337 +ABOR +QUIT + + +