1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/ftp/ftp_network_transaction.h"
6 
7 #include "base/containers/circular_deque.h"
8 #include "base/macros.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/test_completion_callback.h"
16 #include "net/dns/mock_host_resolver.h"
17 #include "net/ftp/ftp_request_info.h"
18 #include "net/socket/socket_test_util.h"
19 #include "net/test/gtest_util.h"
20 #include "net/test/test_with_task_environment.h"
21 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "testing/platform_test.h"
25 
26 using net::test::IsError;
27 using net::test::IsOk;
28 
29 namespace {
30 
31 // Size we use for IOBuffers used to receive data from the test data socket.
32 const int kBufferSize = 128;
33 
34 }  // namespace
35 
36 namespace net {
37 
38 class FtpSocketDataProvider : public SocketDataProvider {
39  public:
40   enum State {
41     NONE,
42     PRE_USER,
43     PRE_PASSWD,
44     PRE_SYST,
45     PRE_PWD,
46     PRE_TYPE,
47     PRE_SIZE,
48     PRE_LIST_EPSV,
49     PRE_LIST_PASV,
50     PRE_LIST,
51     PRE_RETR,
52     PRE_RETR_EPSV,
53     PRE_RETR_PASV,
54     PRE_CWD,
55     PRE_QUIT,
56     PRE_NOPASV,
57     QUIT
58   };
59 
FtpSocketDataProvider()60   FtpSocketDataProvider()
61       : short_read_limit_(0),
62         allow_unconsumed_reads_(false),
63         failure_injection_state_(NONE),
64         multiline_welcome_(false),
65         use_epsv_(true),
66         data_type_('I') {
67     Init();
68   }
69   ~FtpSocketDataProvider() override = default;
70 
71   // SocketDataProvider implementation.
OnRead()72   MockRead OnRead() override {
73     if (reads_.empty())
74       return MockRead(SYNCHRONOUS, ERR_UNEXPECTED);
75     MockRead result = reads_.front();
76     if (short_read_limit_ == 0 || result.data_len <= short_read_limit_) {
77       reads_.pop_front();
78     } else {
79       result.data_len = short_read_limit_;
80       reads_.front().data += result.data_len;
81       reads_.front().data_len -= result.data_len;
82     }
83     return result;
84   }
85 
OnWrite(const std::string & data)86   MockWriteResult OnWrite(const std::string& data) override {
87     if (InjectFault())
88       return MockWriteResult(ASYNC, data.length());
89     switch (state()) {
90       case PRE_USER:
91         return Verify("USER anonymous\r\n", data, PRE_PASSWD,
92                       "331 Password needed\r\n");
93       case PRE_PASSWD:
94         {
95           static const char response_one[] = "230 Welcome\r\n";
96           static const char response_multi[] =
97               "230- One\r\n230- Two\r\n230 Three\r\n";
98           return Verify("PASS chrome@example.com\r\n", data, PRE_SYST,
99                         multiline_welcome_ ? response_multi : response_one);
100         }
101       case PRE_SYST:
102         return Verify("SYST\r\n", data, PRE_PWD, "215 UNIX\r\n");
103       case PRE_PWD:
104         return Verify("PWD\r\n", data, PRE_TYPE,
105                       "257 \"/\" is your current location\r\n");
106       case PRE_TYPE:
107         return Verify(std::string("TYPE ") + data_type_ + "\r\n", data,
108                       PRE_SIZE, "200 TYPE set successfully\r\n");
109       case PRE_LIST_EPSV:
110         return Verify("EPSV\r\n", data, PRE_LIST,
111                       "227 Entering Extended Passive Mode (|||31744|)\r\n");
112       case PRE_LIST_PASV:
113         return Verify("PASV\r\n", data, PRE_LIST,
114                       "227 Entering Passive Mode 127,0,0,1,123,123\r\n");
115       case PRE_RETR_EPSV:
116         return Verify("EPSV\r\n", data, PRE_RETR,
117                       "227 Entering Extended Passive Mode (|||31744|)\r\n");
118       case PRE_RETR_PASV:
119         return Verify("PASV\r\n", data, PRE_RETR,
120                       "227 Entering Passive Mode 127,0,0,1,123,123\r\n");
121       case PRE_NOPASV:
122         // Use unallocated 599 FTP error code to make sure it falls into the
123         // generic ERR_FTP_FAILED bucket.
124         return Verify("PASV\r\n", data, PRE_QUIT,
125                       "599 fail\r\n");
126       case PRE_QUIT:
127         return Verify("QUIT\r\n", data, QUIT, "221 Goodbye.\r\n");
128       default:
129         NOTREACHED() << "State not handled " << state();
130         return MockWriteResult(ASYNC, ERR_UNEXPECTED);
131     }
132   }
133 
InjectFailure(State state,State next_state,const char * response)134   void InjectFailure(State state, State next_state, const char* response) {
135     DCHECK_EQ(NONE, failure_injection_state_);
136     DCHECK_NE(NONE, state);
137     DCHECK_NE(NONE, next_state);
138     DCHECK_NE(state, next_state);
139     failure_injection_state_ = state;
140     failure_injection_next_state_ = next_state;
141     fault_response_ = response;
142   }
143 
state() const144   State state() const {
145     return state_;
146   }
147 
Reset()148   void Reset() override {
149     reads_.clear();
150     Init();
151   }
152 
AllReadDataConsumed() const153   bool AllReadDataConsumed() const override { return state_ == QUIT; }
154 
AllWriteDataConsumed() const155   bool AllWriteDataConsumed() const override { return state_ == QUIT; }
156 
set_multiline_welcome(bool multiline)157   void set_multiline_welcome(bool multiline) { multiline_welcome_ = multiline; }
158 
use_epsv() const159   bool use_epsv() const { return use_epsv_; }
set_use_epsv(bool use_epsv)160   void set_use_epsv(bool use_epsv) { use_epsv_ = use_epsv; }
161 
set_data_type(char data_type)162   void set_data_type(char data_type) { data_type_ = data_type; }
163 
short_read_limit() const164   int short_read_limit() const { return short_read_limit_; }
set_short_read_limit(int limit)165   void set_short_read_limit(int limit) { short_read_limit_ = limit; }
166 
set_allow_unconsumed_reads(bool allow)167   void set_allow_unconsumed_reads(bool allow) {
168     allow_unconsumed_reads_ = allow;
169   }
170 
171  protected:
Init()172   void Init() {
173     state_ = PRE_USER;
174     SimulateRead("220 host TestFTPd\r\n");
175   }
176 
177   // If protocol fault injection has been requested, adjusts state and mocked
178   // read and returns true.
InjectFault()179   bool InjectFault() {
180     if (state_ != failure_injection_state_)
181       return false;
182     SimulateRead(fault_response_);
183     state_ = failure_injection_next_state_;
184     return true;
185   }
186 
Verify(const std::string & expected,const std::string & data,State next_state,const char * next_read,const size_t next_read_length)187   MockWriteResult Verify(const std::string& expected,
188                          const std::string& data,
189                          State next_state,
190                          const char* next_read,
191                          const size_t next_read_length) {
192     EXPECT_EQ(expected, data);
193     if (expected == data) {
194       state_ = next_state;
195       SimulateRead(next_read, next_read_length);
196       return MockWriteResult(ASYNC, data.length());
197     }
198     return MockWriteResult(ASYNC, ERR_UNEXPECTED);
199   }
200 
Verify(const std::string & expected,const std::string & data,State next_state,const char * next_read)201   MockWriteResult Verify(const std::string& expected,
202                          const std::string& data,
203                          State next_state,
204                          const char* next_read) {
205     return Verify(expected, data, next_state,
206                   next_read, std::strlen(next_read));
207   }
208 
209   // The next time there is a read from this socket, it will return |data|.
210   // Before calling SimulateRead next time, the previous data must be consumed.
SimulateRead(const char * data,size_t length)211   void SimulateRead(const char* data, size_t length) {
212     if (!allow_unconsumed_reads_) {
213       EXPECT_TRUE(reads_.empty()) << "Unconsumed read: " << reads_.front().data;
214     }
215     reads_.push_back(MockRead(ASYNC, data, length));
216   }
SimulateRead(const char * data)217   void SimulateRead(const char* data) { SimulateRead(data, std::strlen(data)); }
218 
219  private:
220   // List of reads to be consumed.
221   base::circular_deque<MockRead> reads_;
222 
223   // Max number of bytes we will read at a time. 0 means no limit.
224   int short_read_limit_;
225 
226   // If true, we'll not require the client to consume all data before we
227   // mock the next read.
228   bool allow_unconsumed_reads_;
229 
230   State state_;
231   State failure_injection_state_;
232   State failure_injection_next_state_;
233   const char* fault_response_;
234 
235   // If true, we will send multiple 230 lines as response after PASS.
236   bool multiline_welcome_;
237 
238   // If true, we will use EPSV command.
239   bool use_epsv_;
240 
241   // Data type to be used for TYPE command.
242   char data_type_;
243 
244   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProvider);
245 };
246 
247 class FtpSocketDataProviderDirectoryListing : public FtpSocketDataProvider {
248  public:
249   FtpSocketDataProviderDirectoryListing() = default;
250   ~FtpSocketDataProviderDirectoryListing() override = default;
251 
OnWrite(const std::string & data)252   MockWriteResult OnWrite(const std::string& data) override {
253     if (InjectFault())
254       return MockWriteResult(ASYNC, data.length());
255     switch (state()) {
256       case PRE_SIZE:
257         return Verify("SIZE /\r\n", data, PRE_CWD,
258                       "550 I can only retrieve regular files\r\n");
259       case PRE_CWD:
260         return Verify("CWD /\r\n", data,
261                       use_epsv() ? PRE_LIST_EPSV : PRE_LIST_PASV, "200 OK\r\n");
262       case PRE_LIST:
263         return Verify("LIST -l\r\n", data, PRE_QUIT, "200 OK\r\n");
264       default:
265         return FtpSocketDataProvider::OnWrite(data);
266     }
267   }
268 
269  private:
270   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderDirectoryListing);
271 };
272 
273 class FtpSocketDataProviderDirectoryListingWithPasvFallback
274     : public FtpSocketDataProviderDirectoryListing {
275  public:
276   FtpSocketDataProviderDirectoryListingWithPasvFallback() = default;
277   ~FtpSocketDataProviderDirectoryListingWithPasvFallback() override = default;
278 
OnWrite(const std::string & data)279   MockWriteResult OnWrite(const std::string& data) override {
280     if (InjectFault())
281       return MockWriteResult(ASYNC, data.length());
282     switch (state()) {
283       case PRE_LIST_EPSV:
284         return Verify("EPSV\r\n", data, PRE_LIST_PASV,
285                       "500 no EPSV for you\r\n");
286       case PRE_SIZE:
287         return Verify("SIZE /\r\n", data, PRE_CWD,
288                       "550 I can only retrieve regular files\r\n");
289       default:
290         return FtpSocketDataProviderDirectoryListing::OnWrite(data);
291     }
292   }
293 
294  private:
295   DISALLOW_COPY_AND_ASSIGN(
296       FtpSocketDataProviderDirectoryListingWithPasvFallback);
297 };
298 
299 class FtpSocketDataProviderVMSDirectoryListing : public FtpSocketDataProvider {
300  public:
301   FtpSocketDataProviderVMSDirectoryListing() = default;
302   ~FtpSocketDataProviderVMSDirectoryListing() override = default;
303 
OnWrite(const std::string & data)304   MockWriteResult OnWrite(const std::string& data) override {
305     if (InjectFault())
306       return MockWriteResult(ASYNC, data.length());
307     switch (state()) {
308       case PRE_SYST:
309         return Verify("SYST\r\n", data, PRE_PWD, "215 VMS\r\n");
310       case PRE_PWD:
311         return Verify("PWD\r\n", data, PRE_TYPE,
312                       "257 \"ANONYMOUS_ROOT:[000000]\"\r\n");
313       case PRE_LIST_EPSV:
314         return Verify("EPSV\r\n", data, PRE_LIST_PASV,
315                       "500 Invalid command\r\n");
316       case PRE_SIZE:
317         return Verify("SIZE ANONYMOUS_ROOT:[000000]dir\r\n", data, PRE_CWD,
318                       "550 I can only retrieve regular files\r\n");
319       case PRE_CWD:
320         return Verify("CWD ANONYMOUS_ROOT:[dir]\r\n", data,
321                       use_epsv() ? PRE_LIST_EPSV : PRE_LIST_PASV, "200 OK\r\n");
322       case PRE_LIST:
323         return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n");
324       default:
325         return FtpSocketDataProvider::OnWrite(data);
326     }
327   }
328 
329  private:
330   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderVMSDirectoryListing);
331 };
332 
333 class FtpSocketDataProviderVMSDirectoryListingRootDirectory
334     : public FtpSocketDataProvider {
335  public:
336   FtpSocketDataProviderVMSDirectoryListingRootDirectory() = default;
337   ~FtpSocketDataProviderVMSDirectoryListingRootDirectory() override = default;
338 
OnWrite(const std::string & data)339   MockWriteResult OnWrite(const std::string& data) override {
340     if (InjectFault())
341       return MockWriteResult(ASYNC, data.length());
342     switch (state()) {
343       case PRE_SYST:
344         return Verify("SYST\r\n", data, PRE_PWD, "215 VMS\r\n");
345       case PRE_PWD:
346         return Verify("PWD\r\n", data, PRE_TYPE,
347                       "257 \"ANONYMOUS_ROOT:[000000]\"\r\n");
348       case PRE_LIST_EPSV:
349         return Verify("EPSV\r\n", data, PRE_LIST_PASV,
350                       "500 EPSV command unknown\r\n");
351       case PRE_SIZE:
352         return Verify("SIZE ANONYMOUS_ROOT\r\n", data, PRE_CWD,
353                       "550 I can only retrieve regular files\r\n");
354       case PRE_CWD:
355         return Verify("CWD ANONYMOUS_ROOT:[000000]\r\n", data,
356                       use_epsv() ? PRE_LIST_EPSV : PRE_LIST_PASV, "200 OK\r\n");
357       case PRE_LIST:
358         return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n");
359       default:
360         return FtpSocketDataProvider::OnWrite(data);
361     }
362   }
363 
364  private:
365   DISALLOW_COPY_AND_ASSIGN(
366       FtpSocketDataProviderVMSDirectoryListingRootDirectory);
367 };
368 
369 class FtpSocketDataProviderFileDownloadWithFileTypecode
370     : public FtpSocketDataProvider {
371  public:
372   FtpSocketDataProviderFileDownloadWithFileTypecode() = default;
373   ~FtpSocketDataProviderFileDownloadWithFileTypecode() override = default;
374 
OnWrite(const std::string & data)375   MockWriteResult OnWrite(const std::string& data) override {
376     if (InjectFault())
377       return MockWriteResult(ASYNC, data.length());
378     switch (state()) {
379       case PRE_SIZE:
380         return Verify("SIZE /file\r\n", data,
381                       use_epsv() ? PRE_RETR_EPSV : PRE_RETR_PASV, "213 18\r\n");
382       case PRE_RETR:
383         return Verify("RETR /file\r\n", data, PRE_QUIT, "200 OK\r\n");
384       default:
385         return FtpSocketDataProvider::OnWrite(data);
386     }
387   }
388 
389  private:
390   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadWithFileTypecode);
391 };
392 
393 class FtpSocketDataProviderFileDownload : public FtpSocketDataProvider {
394  public:
395   FtpSocketDataProviderFileDownload() = default;
396   ~FtpSocketDataProviderFileDownload() override = default;
397 
OnWrite(const std::string & data)398   MockWriteResult OnWrite(const std::string& data) override {
399     if (InjectFault())
400       return MockWriteResult(ASYNC, data.length());
401     switch (state()) {
402       case PRE_SIZE:
403         return Verify(base::StringPrintf("SIZE %s\r\n", file_path_.c_str()),
404                       data, PRE_CWD, "213 18\r\n");
405       case PRE_CWD:
406         return Verify(base::StringPrintf("CWD %s\r\n", file_path_.c_str()),
407                       data, use_epsv() ? PRE_RETR_EPSV : PRE_RETR_PASV,
408                       "550 Not a directory\r\n");
409       case PRE_RETR:
410         return Verify(base::StringPrintf("RETR %s\r\n", file_path_.c_str()),
411                       data, PRE_QUIT, "200 OK\r\n");
412       default:
413         return FtpSocketDataProvider::OnWrite(data);
414     }
415   }
416 
set_file_path(const std::string & file_path)417   void set_file_path(const std::string& file_path) { file_path_ = file_path; }
418 
419  private:
420   std::string file_path_ = "/file";
421 
422   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownload);
423 };
424 
425 class FtpSocketDataProviderFileNotFound : public FtpSocketDataProvider {
426  public:
427   FtpSocketDataProviderFileNotFound() = default;
428   ~FtpSocketDataProviderFileNotFound() override = default;
429 
OnWrite(const std::string & data)430   MockWriteResult OnWrite(const std::string& data) override {
431     if (InjectFault())
432       return MockWriteResult(ASYNC, data.length());
433     switch (state()) {
434       case PRE_SIZE:
435         return Verify("SIZE /file\r\n", data, PRE_CWD,
436                       "550 File Not Found\r\n");
437       case PRE_CWD:
438         return Verify("CWD /file\r\n", data,
439                       use_epsv() ? PRE_RETR_EPSV : PRE_RETR_PASV,
440                       "550 File Not Found\r\n");
441       case PRE_RETR:
442         return Verify("RETR /file\r\n", data, PRE_QUIT,
443                       "550 File Not Found\r\n");
444       default:
445         return FtpSocketDataProvider::OnWrite(data);
446     }
447   }
448 
449  private:
450   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileNotFound);
451 };
452 
453 class FtpSocketDataProviderFileDownloadWithPasvFallback
454     : public FtpSocketDataProviderFileDownload {
455  public:
456   FtpSocketDataProviderFileDownloadWithPasvFallback() = default;
457   ~FtpSocketDataProviderFileDownloadWithPasvFallback() override = default;
458 
OnWrite(const std::string & data)459   MockWriteResult OnWrite(const std::string& data) override {
460     if (InjectFault())
461       return MockWriteResult(ASYNC, data.length());
462     switch (state()) {
463       case PRE_RETR_EPSV:
464         return Verify("EPSV\r\n", data, PRE_RETR_PASV, "500 No can do\r\n");
465       case PRE_CWD:
466         return Verify("CWD /file\r\n", data,
467                       use_epsv() ? PRE_RETR_EPSV : PRE_RETR_PASV,
468                       "550 Not a directory\r\n");
469       default:
470         return FtpSocketDataProviderFileDownload::OnWrite(data);
471     }
472   }
473 
474  private:
475   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadWithPasvFallback);
476 };
477 
478 class FtpSocketDataProviderFileDownloadZeroSize
479     : public FtpSocketDataProviderFileDownload {
480  public:
481   FtpSocketDataProviderFileDownloadZeroSize() = default;
482   ~FtpSocketDataProviderFileDownloadZeroSize() override = default;
483 
OnWrite(const std::string & data)484   MockWriteResult OnWrite(const std::string& data) override {
485     if (InjectFault())
486       return MockWriteResult(ASYNC, data.length());
487     switch (state()) {
488       case PRE_SIZE:
489         return Verify("SIZE /file\r\n", data, PRE_CWD,
490                       "213 0\r\n");
491       case PRE_CWD:
492         return Verify("CWD /file\r\n", data,
493                       use_epsv() ? PRE_RETR_EPSV : PRE_RETR_PASV,
494                       "550 not a directory\r\n");
495       default:
496         return FtpSocketDataProviderFileDownload::OnWrite(data);
497     }
498   }
499 
500  private:
501   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadZeroSize);
502 };
503 
504 class FtpSocketDataProviderFileDownloadCWD451
505     : public FtpSocketDataProviderFileDownload {
506  public:
507   FtpSocketDataProviderFileDownloadCWD451() = default;
508   ~FtpSocketDataProviderFileDownloadCWD451() override = default;
509 
OnWrite(const std::string & data)510   MockWriteResult OnWrite(const std::string& data) override {
511     if (InjectFault())
512       return MockWriteResult(ASYNC, data.length());
513     switch (state()) {
514       case PRE_CWD:
515         return Verify("CWD /file\r\n", data,
516                       use_epsv() ? PRE_RETR_EPSV : PRE_RETR_PASV,
517                       "451 not a directory\r\n");
518       default:
519         return FtpSocketDataProviderFileDownload::OnWrite(data);
520     }
521   }
522 
523  private:
524   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadCWD451);
525 };
526 
527 class FtpSocketDataProviderVMSFileDownload : public FtpSocketDataProvider {
528  public:
529   FtpSocketDataProviderVMSFileDownload() = default;
530   ~FtpSocketDataProviderVMSFileDownload() override = default;
531 
OnWrite(const std::string & data)532   MockWriteResult OnWrite(const std::string& data) override {
533     if (InjectFault())
534       return MockWriteResult(ASYNC, data.length());
535     switch (state()) {
536       case PRE_SYST:
537         return Verify("SYST\r\n", data, PRE_PWD, "215 VMS\r\n");
538       case PRE_PWD:
539         return Verify("PWD\r\n", data, PRE_TYPE,
540                       "257 \"ANONYMOUS_ROOT:[000000]\"\r\n");
541       case PRE_LIST_EPSV:
542         return Verify("EPSV\r\n", data, PRE_LIST_PASV,
543                       "500 EPSV command unknown\r\n");
544       case PRE_SIZE:
545         return Verify("SIZE ANONYMOUS_ROOT:[000000]file\r\n", data, PRE_CWD,
546                       "213 18\r\n");
547       case PRE_CWD:
548         return Verify("CWD ANONYMOUS_ROOT:[file]\r\n", data,
549                       use_epsv() ? PRE_RETR_EPSV : PRE_RETR_PASV,
550                       "550 Not a directory\r\n");
551       case PRE_RETR:
552         return Verify("RETR ANONYMOUS_ROOT:[000000]file\r\n", data, PRE_QUIT,
553                       "200 OK\r\n");
554       default:
555         return FtpSocketDataProvider::OnWrite(data);
556     }
557   }
558 
559  private:
560   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderVMSFileDownload);
561 };
562 
563 class FtpSocketDataProviderFileDownloadInvalidResponse
564     : public FtpSocketDataProviderFileDownload {
565  public:
566   FtpSocketDataProviderFileDownloadInvalidResponse() = default;
567   ~FtpSocketDataProviderFileDownloadInvalidResponse() override = default;
568 
OnWrite(const std::string & data)569   MockWriteResult OnWrite(const std::string& data) override {
570     if (InjectFault())
571       return MockWriteResult(ASYNC, data.length());
572     switch (state()) {
573       case PRE_SIZE:
574         // Use unallocated 599 FTP error code to make sure it falls into the
575         // generic ERR_FTP_FAILED bucket.
576         return Verify("SIZE /file\r\n", data, PRE_QUIT,
577                       "599 Evil Response\r\n"
578                       "599 More Evil\r\n");
579       default:
580         return FtpSocketDataProviderFileDownload::OnWrite(data);
581     }
582   }
583 
584  private:
585   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadInvalidResponse);
586 };
587 
588 class FtpSocketDataProviderEvilEpsv : public FtpSocketDataProviderFileDownload {
589  public:
FtpSocketDataProviderEvilEpsv(const char * epsv_response,State expected_state)590   FtpSocketDataProviderEvilEpsv(const char* epsv_response,
591                                 State expected_state)
592       : epsv_response_(epsv_response),
593         epsv_response_length_(std::strlen(epsv_response)),
594         expected_state_(expected_state) {}
595 
FtpSocketDataProviderEvilEpsv(const char * epsv_response,size_t epsv_response_length,State expected_state)596   FtpSocketDataProviderEvilEpsv(const char* epsv_response,
597                                size_t epsv_response_length,
598                                State expected_state)
599       : epsv_response_(epsv_response),
600         epsv_response_length_(epsv_response_length),
601         expected_state_(expected_state) {}
602 
603   ~FtpSocketDataProviderEvilEpsv() override = default;
604 
OnWrite(const std::string & data)605   MockWriteResult OnWrite(const std::string& data) override {
606     if (InjectFault())
607       return MockWriteResult(ASYNC, data.length());
608     switch (state()) {
609       case PRE_RETR_EPSV:
610         return Verify("EPSV\r\n", data, expected_state_,
611                       epsv_response_, epsv_response_length_);
612       default:
613         return FtpSocketDataProviderFileDownload::OnWrite(data);
614     }
615   }
616 
617  private:
618   const char* const epsv_response_;
619   const size_t epsv_response_length_;
620   const State expected_state_;
621 
622   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilEpsv);
623 };
624 
625 class FtpSocketDataProviderEvilPasv
626     : public FtpSocketDataProviderFileDownloadWithPasvFallback {
627  public:
FtpSocketDataProviderEvilPasv(const char * pasv_response,State expected_state)628   FtpSocketDataProviderEvilPasv(const char* pasv_response, State expected_state)
629       : pasv_response_(pasv_response),
630         expected_state_(expected_state) {
631   }
632   ~FtpSocketDataProviderEvilPasv() override = default;
633 
OnWrite(const std::string & data)634   MockWriteResult OnWrite(const std::string& data) override {
635     if (InjectFault())
636       return MockWriteResult(ASYNC, data.length());
637     switch (state()) {
638       case PRE_RETR_PASV:
639         return Verify("PASV\r\n", data, expected_state_, pasv_response_);
640       default:
641         return FtpSocketDataProviderFileDownloadWithPasvFallback::OnWrite(data);
642     }
643   }
644 
645  private:
646   const char* const pasv_response_;
647   const State expected_state_;
648 
649   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilPasv);
650 };
651 
652 class FtpSocketDataProviderEvilSize : public FtpSocketDataProviderFileDownload {
653  public:
FtpSocketDataProviderEvilSize(const char * size_response,State expected_state)654   FtpSocketDataProviderEvilSize(const char* size_response, State expected_state)
655       : size_response_(size_response),
656         expected_state_(expected_state) {
657   }
658   ~FtpSocketDataProviderEvilSize() override = default;
659 
OnWrite(const std::string & data)660   MockWriteResult OnWrite(const std::string& data) override {
661     if (InjectFault())
662       return MockWriteResult(ASYNC, data.length());
663     switch (state()) {
664       case PRE_SIZE:
665         return Verify("SIZE /file\r\n", data, expected_state_, size_response_);
666       default:
667         return FtpSocketDataProviderFileDownload::OnWrite(data);
668     }
669   }
670 
671  private:
672   const char* const size_response_;
673   const State expected_state_;
674 
675   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilSize);
676 };
677 
678 class FtpSocketDataProviderEvilLogin
679     : public FtpSocketDataProviderFileDownload {
680  public:
FtpSocketDataProviderEvilLogin(const char * expected_user,const char * expected_password)681   FtpSocketDataProviderEvilLogin(const char* expected_user,
682                                 const char* expected_password)
683       : expected_user_(expected_user),
684         expected_password_(expected_password) {
685   }
686   ~FtpSocketDataProviderEvilLogin() override = default;
687 
OnWrite(const std::string & data)688   MockWriteResult OnWrite(const std::string& data) override {
689     if (InjectFault())
690       return MockWriteResult(ASYNC, data.length());
691     switch (state()) {
692       case PRE_USER:
693         return Verify(std::string("USER ") + expected_user_ + "\r\n", data,
694                       PRE_PASSWD, "331 Password needed\r\n");
695       case PRE_PASSWD:
696         return Verify(std::string("PASS ") + expected_password_ + "\r\n", data,
697                       PRE_SYST, "230 Welcome\r\n");
698       default:
699         return FtpSocketDataProviderFileDownload::OnWrite(data);
700     }
701   }
702 
703  private:
704   const char* const expected_user_;
705   const char* const expected_password_;
706 
707   DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilLogin);
708 };
709 
710 class FtpNetworkTransactionTest : public PlatformTest,
711                                   public ::testing::WithParamInterface<int>,
712                                   public WithTaskEnvironment {
713  public:
FtpNetworkTransactionTest()714   FtpNetworkTransactionTest() : host_resolver_(new MockHostResolver) {
715     SetUpTransaction();
716 
717     scoped_refptr<RuleBasedHostResolverProc> rules(
718         new RuleBasedHostResolverProc(nullptr));
719     if (GetFamily() == AF_INET) {
720       rules->AddIPLiteralRule("*", "127.0.0.1", "127.0.0.1");
721     } else if (GetFamily() == AF_INET6) {
722       rules->AddIPLiteralRule("*", "::1", "::1");
723     } else {
724       NOTREACHED();
725     }
726     host_resolver_->set_rules(rules.get());
727   }
728   ~FtpNetworkTransactionTest() override = default;
729 
730   // Sets up an FtpNetworkTransaction and MocketClientSocketFactory, replacing
731   // the default one. Only needs to be called if a test runs multiple
732   // transactions.
SetUpTransaction()733   void SetUpTransaction() {
734     mock_socket_factory_ = std::make_unique<MockClientSocketFactory>();
735     transaction_ = std::make_unique<FtpNetworkTransaction>(
736         host_resolver_.get(), mock_socket_factory_.get());
737   }
738 
739  protected:
740   // Accessor to make code refactoring-friendly, e.g. when we change the way
741   // parameters are passed (like more parameters).
GetFamily()742   int GetFamily() {
743     return GetParam();
744   }
745 
GetRequestInfo(const std::string & url)746   FtpRequestInfo GetRequestInfo(const std::string& url) {
747     FtpRequestInfo info;
748     info.url = GURL(url);
749     return info;
750   }
751 
ExecuteTransaction(FtpSocketDataProvider * ctrl_socket,const char * request,int expected_result)752   void ExecuteTransaction(FtpSocketDataProvider* ctrl_socket,
753                           const char* request,
754                           int expected_result) {
755     // Expect EPSV usage for non-IPv4 control connections.
756     ctrl_socket->set_use_epsv((GetFamily() != AF_INET));
757 
758     mock_socket_factory_->AddSocketDataProvider(ctrl_socket);
759 
760     std::string mock_data("mock-data");
761     MockRead data_reads[] = {
762       // Usually FTP servers close the data connection after the entire data has
763       // been received.
764       MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
765       MockRead(mock_data.c_str()),
766     };
767 
768     std::unique_ptr<StaticSocketDataProvider> data_socket =
769         std::make_unique<StaticSocketDataProvider>(data_reads,
770                                                    base::span<MockWrite>());
771     mock_socket_factory_->AddSocketDataProvider(data_socket.get());
772     FtpRequestInfo request_info = GetRequestInfo(request);
773     EXPECT_EQ(LOAD_STATE_IDLE, transaction_->GetLoadState());
774     ASSERT_EQ(
775         ERR_IO_PENDING,
776         transaction_->Start(&request_info, callback_.callback(),
777                             NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS));
778     EXPECT_NE(LOAD_STATE_IDLE, transaction_->GetLoadState());
779     ASSERT_EQ(expected_result, callback_.WaitForResult());
780     if (expected_result == OK) {
781       scoped_refptr<IOBuffer> io_buffer =
782           base::MakeRefCounted<IOBuffer>(kBufferSize);
783       memset(io_buffer->data(), 0, kBufferSize);
784       ASSERT_EQ(ERR_IO_PENDING, transaction_->Read(io_buffer.get(), kBufferSize,
785                                                    callback_.callback()));
786       ASSERT_EQ(static_cast<int>(mock_data.length()),
787                 callback_.WaitForResult());
788       EXPECT_EQ(mock_data, std::string(io_buffer->data(), mock_data.length()));
789 
790       // Do another Read to detect that the data socket is now closed.
791       int rv = transaction_->Read(io_buffer.get(), kBufferSize,
792                                   callback_.callback());
793       if (rv == ERR_IO_PENDING) {
794         EXPECT_EQ(0, callback_.WaitForResult());
795       } else {
796         EXPECT_EQ(0, rv);
797       }
798     }
799     EXPECT_EQ(FtpSocketDataProvider::QUIT, ctrl_socket->state());
800     EXPECT_EQ(LOAD_STATE_IDLE, transaction_->GetLoadState());
801   }
802 
TransactionFailHelper(FtpSocketDataProvider * ctrl_socket,const char * request,FtpSocketDataProvider::State state,FtpSocketDataProvider::State next_state,const char * response,int expected_result)803   void TransactionFailHelper(FtpSocketDataProvider* ctrl_socket,
804                              const char* request,
805                              FtpSocketDataProvider::State state,
806                              FtpSocketDataProvider::State next_state,
807                              const char* response,
808                              int expected_result) {
809     ctrl_socket->InjectFailure(state, next_state, response);
810     ExecuteTransaction(ctrl_socket, request, expected_result);
811   }
812 
813   std::unique_ptr<MockHostResolver> host_resolver_;
814   std::unique_ptr<MockClientSocketFactory> mock_socket_factory_;
815   std::unique_ptr<FtpNetworkTransaction> transaction_;
816   TestCompletionCallback callback_;
817 };
818 
TEST_P(FtpNetworkTransactionTest,FailedLookup)819 TEST_P(FtpNetworkTransactionTest, FailedLookup) {
820   FtpRequestInfo request_info = GetRequestInfo("ftp://badhost");
821   scoped_refptr<RuleBasedHostResolverProc> rules(
822       new RuleBasedHostResolverProc(nullptr));
823   rules->AddSimulatedFailure("badhost");
824   host_resolver_->set_rules(rules.get());
825 
826   EXPECT_EQ(LOAD_STATE_IDLE, transaction_->GetLoadState());
827   ASSERT_EQ(
828       ERR_IO_PENDING,
829       transaction_->Start(&request_info, callback_.callback(),
830                           NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS));
831   ASSERT_THAT(callback_.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
832   EXPECT_EQ(LOAD_STATE_IDLE, transaction_->GetLoadState());
833 }
834 
835 // Check that when determining the host, the square brackets decorating IPv6
836 // literals in URLs are stripped.
TEST_P(FtpNetworkTransactionTest,StripBracketsFromIPv6Literals)837 TEST_P(FtpNetworkTransactionTest, StripBracketsFromIPv6Literals) {
838   // This test only makes sense for IPv6 connections.
839   if (GetFamily() != AF_INET6)
840     return;
841 
842   host_resolver_->rules()->AddSimulatedFailure("[::1]");
843 
844   // We start a transaction that is expected to fail with ERR_INVALID_RESPONSE.
845   // The important part of this test is to make sure that we don't fail with
846   // ERR_NAME_NOT_RESOLVED, since that would mean the decorated hostname
847   // was used.
848   FtpSocketDataProviderEvilSize ctrl_socket(
849       "213 99999999999999999999999999999999\r\n",
850       FtpSocketDataProvider::PRE_QUIT);
851   ExecuteTransaction(&ctrl_socket, "ftp://[::1]/file", ERR_INVALID_RESPONSE);
852 }
853 
TEST_P(FtpNetworkTransactionTest,DirectoryTransaction)854 TEST_P(FtpNetworkTransactionTest, DirectoryTransaction) {
855   FtpSocketDataProviderDirectoryListing ctrl_socket;
856   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
857 
858   EXPECT_TRUE(transaction_->GetResponseInfo()->is_directory_listing);
859   EXPECT_EQ(-1, transaction_->GetResponseInfo()->expected_content_size);
860   EXPECT_EQ(
861       (GetFamily() == AF_INET) ? "127.0.0.1" : "::1",
862       transaction_->GetResponseInfo()->remote_endpoint.ToStringWithoutPort());
863   EXPECT_EQ(21, transaction_->GetResponseInfo()->remote_endpoint.port());
864 }
865 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionWithPasvFallback)866 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithPasvFallback) {
867   FtpSocketDataProviderDirectoryListingWithPasvFallback ctrl_socket;
868   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
869 
870   EXPECT_TRUE(transaction_->GetResponseInfo()->is_directory_listing);
871   EXPECT_EQ(-1, transaction_->GetResponseInfo()->expected_content_size);
872 }
873 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionWithTypecode)874 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithTypecode) {
875   FtpSocketDataProviderDirectoryListing ctrl_socket;
876   ExecuteTransaction(&ctrl_socket, "ftp://host/;type=d", OK);
877 
878   EXPECT_TRUE(transaction_->GetResponseInfo()->is_directory_listing);
879   EXPECT_EQ(-1, transaction_->GetResponseInfo()->expected_content_size);
880 }
881 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionMultilineWelcome)882 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcome) {
883   FtpSocketDataProviderDirectoryListing ctrl_socket;
884   ctrl_socket.set_multiline_welcome(true);
885   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
886 }
887 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionShortReads2)888 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionShortReads2) {
889   FtpSocketDataProviderDirectoryListing ctrl_socket;
890   ctrl_socket.set_short_read_limit(2);
891   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
892 }
893 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionShortReads5)894 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionShortReads5) {
895   FtpSocketDataProviderDirectoryListing ctrl_socket;
896   ctrl_socket.set_short_read_limit(5);
897   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
898 }
899 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionMultilineWelcomeShort)900 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcomeShort) {
901   FtpSocketDataProviderDirectoryListing ctrl_socket;
902   // The client will not consume all three 230 lines. That's good, we want to
903   // test that scenario.
904   ctrl_socket.set_allow_unconsumed_reads(true);
905   ctrl_socket.set_multiline_welcome(true);
906   ctrl_socket.set_short_read_limit(5);
907   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
908 }
909 
910 // Regression test for http://crbug.com/60555.
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionZeroSize)911 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionZeroSize) {
912   FtpSocketDataProviderDirectoryListing ctrl_socket;
913   ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_SIZE,
914                             FtpSocketDataProvider::PRE_CWD, "213 0\r\n");
915   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
916 }
917 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionVMS)918 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionVMS) {
919   FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
920   ExecuteTransaction(&ctrl_socket, "ftp://host/dir", OK);
921 }
922 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionVMSRootDirectory)923 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionVMSRootDirectory) {
924   FtpSocketDataProviderVMSDirectoryListingRootDirectory ctrl_socket;
925   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
926 }
927 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionTransferStarting)928 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionTransferStarting) {
929   FtpSocketDataProviderDirectoryListing ctrl_socket;
930   ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_LIST,
931                             FtpSocketDataProvider::PRE_QUIT,
932                             "125-Data connection already open.\r\n"
933                             "125  Transfer starting.\r\n"
934                             "226 Transfer complete.\r\n");
935   ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
936 }
937 
TEST_P(FtpNetworkTransactionTest,DownloadTransaction)938 TEST_P(FtpNetworkTransactionTest, DownloadTransaction) {
939   FtpSocketDataProviderFileDownload ctrl_socket;
940   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
941 
942   // We pass an artificial value of 18 as a response to the SIZE command.
943   EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
944   EXPECT_EQ(
945       (GetFamily() == AF_INET) ? "127.0.0.1" : "::1",
946       transaction_->GetResponseInfo()->remote_endpoint.ToStringWithoutPort());
947   EXPECT_EQ(21, transaction_->GetResponseInfo()->remote_endpoint.port());
948 }
949 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionWithPasvFallback)950 TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithPasvFallback) {
951   FtpSocketDataProviderFileDownloadWithPasvFallback ctrl_socket;
952   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
953 
954   // We pass an artificial value of 18 as a response to the SIZE command.
955   EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
956 }
957 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionWithTypecodeA)958 TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeA) {
959   FtpSocketDataProviderFileDownloadWithFileTypecode ctrl_socket;
960   ctrl_socket.set_data_type('A');
961   ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=a", OK);
962 
963   // We pass an artificial value of 18 as a response to the SIZE command.
964   EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
965 }
966 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionWithTypecodeI)967 TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeI) {
968   FtpSocketDataProviderFileDownloadWithFileTypecode ctrl_socket;
969   ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=i", OK);
970 
971   // We pass an artificial value of 18 as a response to the SIZE command.
972   EXPECT_EQ(18, transaction_->GetResponseInfo()->expected_content_size);
973 }
974 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionMultilineWelcome)975 TEST_P(FtpNetworkTransactionTest, DownloadTransactionMultilineWelcome) {
976   FtpSocketDataProviderFileDownload ctrl_socket;
977   ctrl_socket.set_multiline_welcome(true);
978   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
979 }
980 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionShortReads2)981 TEST_P(FtpNetworkTransactionTest, DownloadTransactionShortReads2) {
982   FtpSocketDataProviderFileDownload ctrl_socket;
983   ctrl_socket.set_short_read_limit(2);
984   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
985 }
986 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionShortReads5)987 TEST_P(FtpNetworkTransactionTest, DownloadTransactionShortReads5) {
988   FtpSocketDataProviderFileDownload ctrl_socket;
989   ctrl_socket.set_short_read_limit(5);
990   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
991 }
992 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionZeroSize)993 TEST_P(FtpNetworkTransactionTest, DownloadTransactionZeroSize) {
994   FtpSocketDataProviderFileDownloadZeroSize ctrl_socket;
995   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
996 }
997 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionCWD451)998 TEST_P(FtpNetworkTransactionTest, DownloadTransactionCWD451) {
999   FtpSocketDataProviderFileDownloadCWD451 ctrl_socket;
1000   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1001 }
1002 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionVMS)1003 TEST_P(FtpNetworkTransactionTest, DownloadTransactionVMS) {
1004   FtpSocketDataProviderVMSFileDownload ctrl_socket;
1005   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1006 }
1007 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionTransferStarting)1008 TEST_P(FtpNetworkTransactionTest, DownloadTransactionTransferStarting) {
1009   FtpSocketDataProviderFileDownload ctrl_socket;
1010   ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_RETR,
1011                             FtpSocketDataProvider::PRE_QUIT,
1012                             "125-Data connection already open.\r\n"
1013                             "125  Transfer starting.\r\n"
1014                             "226 Transfer complete.\r\n");
1015   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1016 }
1017 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionInvalidResponse)1018 TEST_P(FtpNetworkTransactionTest, DownloadTransactionInvalidResponse) {
1019   FtpSocketDataProviderFileDownloadInvalidResponse ctrl_socket;
1020   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1021 }
1022 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvReallyBadFormat)1023 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvReallyBadFormat) {
1024   FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,\r\n",
1025                                             FtpSocketDataProvider::PRE_QUIT);
1026   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1027 }
1028 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvUnsafePort1)1029 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort1) {
1030   FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,0,22)\r\n",
1031                                             FtpSocketDataProvider::PRE_QUIT);
1032   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1033 }
1034 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvUnsafePort2)1035 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort2) {
1036   // Still unsafe. 1 * 256 + 2 = 258, which is < 1024.
1037   FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,1,2)\r\n",
1038                                             FtpSocketDataProvider::PRE_QUIT);
1039   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1040 }
1041 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvUnsafePort3)1042 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort3) {
1043   // Still unsafe. 3 * 256 + 4 = 772, which is < 1024.
1044   FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,3,4)\r\n",
1045                                             FtpSocketDataProvider::PRE_QUIT);
1046   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1047 }
1048 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvUnsafePort4)1049 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort4) {
1050   // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
1051   FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,8,1)\r\n",
1052                                             FtpSocketDataProvider::PRE_QUIT);
1053   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1054 }
1055 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvInvalidPort1)1056 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvInvalidPort1) {
1057   // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
1058   FtpSocketDataProviderEvilPasv ctrl_socket(
1059       "227 Portscan (127,0,0,1,256,100)\r\n", FtpSocketDataProvider::PRE_QUIT);
1060   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1061 }
1062 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvInvalidPort2)1063 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvInvalidPort2) {
1064   // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
1065   FtpSocketDataProviderEvilPasv ctrl_socket(
1066       "227 Portscan (127,0,0,1,100,256)\r\n", FtpSocketDataProvider::PRE_QUIT);
1067   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1068 }
1069 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvInvalidPort3)1070 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvInvalidPort3) {
1071   // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
1072   FtpSocketDataProviderEvilPasv ctrl_socket(
1073       "227 Portscan (127,0,0,1,-100,100)\r\n", FtpSocketDataProvider::PRE_QUIT);
1074   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1075 }
1076 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvInvalidPort4)1077 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvInvalidPort4) {
1078   // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
1079   FtpSocketDataProviderEvilPasv ctrl_socket(
1080       "227 Portscan (127,0,0,1,100,-100)\r\n", FtpSocketDataProvider::PRE_QUIT);
1081   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1082 }
1083 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilPasvUnsafeHost)1084 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafeHost) {
1085   FtpSocketDataProviderEvilPasv ctrl_socket(
1086       "227 Portscan (10,1,2,3,123,123)\r\n", FtpSocketDataProvider::PRE_RETR);
1087   ctrl_socket.set_use_epsv(GetFamily() != AF_INET);
1088   std::string mock_data("mock-data");
1089   MockRead data_reads[] = {
1090     MockRead(mock_data.c_str()),
1091   };
1092   StaticSocketDataProvider data_socket1;
1093   StaticSocketDataProvider data_socket2(data_reads, base::span<MockWrite>());
1094   mock_socket_factory_->AddSocketDataProvider(&ctrl_socket);
1095   mock_socket_factory_->AddSocketDataProvider(&data_socket1);
1096   mock_socket_factory_->AddSocketDataProvider(&data_socket2);
1097   FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1098 
1099   // Start the transaction.
1100   ASSERT_EQ(
1101       ERR_IO_PENDING,
1102       transaction_->Start(&request_info, callback_.callback(),
1103                           NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS));
1104   ASSERT_THAT(callback_.WaitForResult(), IsOk());
1105 
1106   // The transaction fires the callback when we can start reading data. That
1107   // means that the data socket should be open.
1108   MockTCPClientSocket* data_socket =
1109       static_cast<MockTCPClientSocket*>(transaction_->data_socket_.get());
1110   ASSERT_TRUE(data_socket);
1111   ASSERT_TRUE(data_socket->IsConnected());
1112 
1113   // Even if the PASV response specified some other address, we connect
1114   // to the address we used for control connection (which could be 127.0.0.1
1115   // or ::1 depending on whether we use IPv6).
1116   for (auto it = data_socket->addresses().begin();
1117        it != data_socket->addresses().end(); ++it) {
1118     EXPECT_NE("10.1.2.3", it->ToStringWithoutPort());
1119   }
1120 }
1121 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvReallyBadFormat1)1122 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat1) {
1123   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1124   if (GetFamily() == AF_INET)
1125     return;
1126 
1127   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||22)\r\n",
1128                                             FtpSocketDataProvider::PRE_QUIT);
1129   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1130 }
1131 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvReallyBadFormat2)1132 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat2) {
1133   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1134   if (GetFamily() == AF_INET)
1135     return;
1136 
1137   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (||\r\n",
1138                                             FtpSocketDataProvider::PRE_QUIT);
1139   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1140 }
1141 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvReallyBadFormat3)1142 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat3) {
1143   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1144   if (GetFamily() == AF_INET)
1145     return;
1146 
1147   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan\r\n",
1148                                             FtpSocketDataProvider::PRE_QUIT);
1149   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1150 }
1151 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvReallyBadFormat4)1152 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat4) {
1153   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1154   if (GetFamily() == AF_INET)
1155     return;
1156 
1157   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (||||)\r\n",
1158                                             FtpSocketDataProvider::PRE_QUIT);
1159   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1160 }
1161 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvReallyBadFormat5)1162 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat5) {
1163   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1164   if (GetFamily() == AF_INET)
1165     return;
1166 
1167   // Breaking the string in the next line prevents MSVC warning C4125.
1168   const char response[] = "227 Portscan (\0\0\031" "773\0)\r\n";
1169   FtpSocketDataProviderEvilEpsv ctrl_socket(response, sizeof(response)-1,
1170                                             FtpSocketDataProvider::PRE_QUIT);
1171   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1172 }
1173 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvUnsafePort1)1174 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort1) {
1175   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1176   if (GetFamily() == AF_INET)
1177     return;
1178 
1179   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||22|)\r\n",
1180                                             FtpSocketDataProvider::PRE_QUIT);
1181   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1182 }
1183 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvUnsafePort2)1184 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort2) {
1185   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1186   if (GetFamily() == AF_INET)
1187     return;
1188 
1189   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||258|)\r\n",
1190                                             FtpSocketDataProvider::PRE_QUIT);
1191   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1192 }
1193 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvUnsafePort3)1194 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort3) {
1195   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1196   if (GetFamily() == AF_INET)
1197     return;
1198 
1199   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||772|)\r\n",
1200                                             FtpSocketDataProvider::PRE_QUIT);
1201   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1202 }
1203 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvUnsafePort4)1204 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort4) {
1205   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1206   if (GetFamily() == AF_INET)
1207     return;
1208 
1209   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||2049|)\r\n",
1210                                             FtpSocketDataProvider::PRE_QUIT);
1211   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1212 }
1213 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvInvalidPort)1214 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvInvalidPort) {
1215   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1216   if (GetFamily() == AF_INET)
1217     return;
1218 
1219   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||4294973296|)\r\n",
1220                                             FtpSocketDataProvider::PRE_QUIT);
1221   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1222 }
1223 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvWeirdSep)1224 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvWeirdSep) {
1225   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1226   if (GetFamily() == AF_INET)
1227     return;
1228 
1229   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan ($$$31744$)\r\n",
1230                                             FtpSocketDataProvider::PRE_RETR);
1231   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1232 }
1233 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvWeirdSepUnsafePort)1234 TEST_P(FtpNetworkTransactionTest,
1235        DownloadTransactionEvilEpsvWeirdSepUnsafePort) {
1236   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1237   if (GetFamily() == AF_INET)
1238     return;
1239 
1240   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan ($$$317$)\r\n",
1241                                             FtpSocketDataProvider::PRE_QUIT);
1242   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1243 }
1244 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilEpsvIllegalHost)1245 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvIllegalHost) {
1246   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1247   if (GetFamily() == AF_INET)
1248     return;
1249 
1250   FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|2|::1|31744|)\r\n",
1251                                             FtpSocketDataProvider::PRE_QUIT);
1252   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1253 }
1254 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilLoginBadUsername)1255 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilLoginBadUsername) {
1256   FtpSocketDataProviderEvilLogin ctrl_socket("hello%0Aworld", "test");
1257   ExecuteTransaction(&ctrl_socket, "ftp://hello%0Aworld:test@host/file", OK);
1258 }
1259 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilLoginBadPassword)1260 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilLoginBadPassword) {
1261   FtpSocketDataProviderEvilLogin ctrl_socket("test", "hello%0Dworld");
1262   ExecuteTransaction(&ctrl_socket, "ftp://test:hello%0Dworld@host/file", OK);
1263 }
1264 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionSpaceInLogin)1265 TEST_P(FtpNetworkTransactionTest, DownloadTransactionSpaceInLogin) {
1266   FtpSocketDataProviderEvilLogin ctrl_socket("hello world", "test");
1267   ExecuteTransaction(&ctrl_socket, "ftp://hello%20world:test@host/file", OK);
1268 }
1269 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionSpaceInPassword)1270 TEST_P(FtpNetworkTransactionTest, DownloadTransactionSpaceInPassword) {
1271   FtpSocketDataProviderEvilLogin ctrl_socket("test", "hello world");
1272   ExecuteTransaction(&ctrl_socket, "ftp://test:hello%20world@host/file", OK);
1273 }
1274 
TEST_P(FtpNetworkTransactionTest,FailOnInvalidUrls)1275 TEST_P(FtpNetworkTransactionTest, FailOnInvalidUrls) {
1276   const char* const kBadUrls[]{
1277       // Make sure FtpNetworkTransaction doesn't request paths like
1278       // "/foo/../bar".  Doing so wouldn't be a security issue, client side, but
1279       // just doesn't seem like a good idea.
1280       "ftp://host/foo%2f..%2fbar%5c",
1281 
1282       // LF
1283       "ftp://host/foo%10.txt",
1284       // CR
1285       "ftp://host/foo%13.txt",
1286 
1287       "ftp://host/foo%00.txt",
1288   };
1289 
1290   for (const char* bad_url : kBadUrls) {
1291     SCOPED_TRACE(bad_url);
1292 
1293     SetUpTransaction();
1294     FtpRequestInfo request_info = GetRequestInfo(bad_url);
1295     ASSERT_EQ(
1296         ERR_INVALID_URL,
1297         transaction_->Start(&request_info, callback_.callback(),
1298                             NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS));
1299   }
1300 }
1301 
TEST_P(FtpNetworkTransactionTest,EvilRestartUser)1302 TEST_P(FtpNetworkTransactionTest, EvilRestartUser) {
1303   FtpSocketDataProvider ctrl_socket1;
1304   ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
1305                              FtpSocketDataProvider::PRE_QUIT,
1306                              "530 Login authentication failed\r\n");
1307   mock_socket_factory_->AddSocketDataProvider(&ctrl_socket1);
1308 
1309   FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1310 
1311   ASSERT_EQ(
1312       ERR_IO_PENDING,
1313       transaction_->Start(&request_info, callback_.callback(),
1314                           NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS));
1315   ASSERT_THAT(callback_.WaitForResult(), IsError(ERR_FTP_FAILED));
1316 
1317   MockRead ctrl_reads[] = {
1318     MockRead("220 host TestFTPd\r\n"),
1319     MockRead("221 Goodbye!\r\n"),
1320     MockRead(SYNCHRONOUS, OK),
1321   };
1322   MockWrite ctrl_writes[] = {
1323     MockWrite("QUIT\r\n"),
1324   };
1325   StaticSocketDataProvider ctrl_socket2(ctrl_reads, ctrl_writes);
1326   mock_socket_factory_->AddSocketDataProvider(&ctrl_socket2);
1327   ASSERT_EQ(ERR_IO_PENDING,
1328             transaction_->RestartWithAuth(
1329                 AuthCredentials(base::ASCIIToUTF16("foo\nownz0red"),
1330                                 base::ASCIIToUTF16("innocent")),
1331                 callback_.callback()));
1332   EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_MALFORMED_IDENTITY));
1333 }
1334 
TEST_P(FtpNetworkTransactionTest,EvilRestartPassword)1335 TEST_P(FtpNetworkTransactionTest, EvilRestartPassword) {
1336   FtpSocketDataProvider ctrl_socket1;
1337   ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
1338                              FtpSocketDataProvider::PRE_QUIT,
1339                              "530 Login authentication failed\r\n");
1340   mock_socket_factory_->AddSocketDataProvider(&ctrl_socket1);
1341 
1342   FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1343 
1344   ASSERT_EQ(
1345       ERR_IO_PENDING,
1346       transaction_->Start(&request_info, callback_.callback(),
1347                           NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS));
1348   ASSERT_THAT(callback_.WaitForResult(), IsError(ERR_FTP_FAILED));
1349 
1350   MockRead ctrl_reads[] = {
1351     MockRead("220 host TestFTPd\r\n"),
1352     MockRead("331 User okay, send password\r\n"),
1353     MockRead("221 Goodbye!\r\n"),
1354     MockRead(SYNCHRONOUS, OK),
1355   };
1356   MockWrite ctrl_writes[] = {
1357     MockWrite("USER innocent\r\n"),
1358     MockWrite("QUIT\r\n"),
1359   };
1360   StaticSocketDataProvider ctrl_socket2(ctrl_reads, ctrl_writes);
1361   mock_socket_factory_->AddSocketDataProvider(&ctrl_socket2);
1362   ASSERT_EQ(ERR_IO_PENDING,
1363             transaction_->RestartWithAuth(
1364                 AuthCredentials(base::ASCIIToUTF16("innocent"),
1365                                 base::ASCIIToUTF16("foo\nownz0red")),
1366                 callback_.callback()));
1367   EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_MALFORMED_IDENTITY));
1368 }
1369 
TEST_P(FtpNetworkTransactionTest,Escaping)1370 TEST_P(FtpNetworkTransactionTest, Escaping) {
1371   const struct TestCase {
1372     const char* url;
1373     const char* expected_path;
1374   } kTestCases[] = {
1375       {"ftp://host/%20%21%22%23%24%25%79%80%81", "/ !\"#$%y\200\201"},
1376       // This is no allowed to be unescaped by UnescapeURLComponent, since it's
1377       // a lock icon. But it has no special meaning or security concern in the
1378       // context of making FTP requests.
1379       {"ftp://host/%F0%9F%94%92", "/\xF0\x9F\x94\x92"},
1380       // Invalid UTF-8 character, which again has no special meaning over FTP.
1381       {"ftp://host/%81", "/\x81"},
1382   };
1383 
1384   for (const auto& test_case : kTestCases) {
1385     SCOPED_TRACE(test_case.url);
1386 
1387     SetUpTransaction();
1388     FtpSocketDataProviderFileDownload ctrl_socket;
1389     ctrl_socket.set_file_path(test_case.expected_path);
1390     ExecuteTransaction(&ctrl_socket, test_case.url, OK);
1391   }
1392 }
1393 
1394 // Test for http://crbug.com/23794.
TEST_P(FtpNetworkTransactionTest,DownloadTransactionEvilSize)1395 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilSize) {
1396   // Try to overflow int64_t in the response.
1397   FtpSocketDataProviderEvilSize ctrl_socket(
1398       "213 99999999999999999999999999999999\r\n",
1399       FtpSocketDataProvider::PRE_QUIT);
1400   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1401 }
1402 
1403 // Test for http://crbug.com/36360.
TEST_P(FtpNetworkTransactionTest,DownloadTransactionBigSize)1404 TEST_P(FtpNetworkTransactionTest, DownloadTransactionBigSize) {
1405   // Pass a valid, but large file size. The transaction should not fail.
1406   FtpSocketDataProviderEvilSize ctrl_socket(
1407       "213 3204427776\r\n",
1408       FtpSocketDataProvider::PRE_CWD);
1409   ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1410   EXPECT_EQ(3204427776LL,
1411             transaction_->GetResponseInfo()->expected_content_size);
1412 }
1413 
1414 // Regression test for http://crbug.com/25023.
TEST_P(FtpNetworkTransactionTest,CloseConnection)1415 TEST_P(FtpNetworkTransactionTest, CloseConnection) {
1416   FtpSocketDataProvider ctrl_socket;
1417   ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_USER,
1418                             FtpSocketDataProvider::PRE_QUIT, "");
1419   ExecuteTransaction(&ctrl_socket, "ftp://host", ERR_EMPTY_RESPONSE);
1420 }
1421 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailUser)1422 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailUser) {
1423   FtpSocketDataProviderDirectoryListing ctrl_socket;
1424   // Use unallocated 599 FTP error code to make sure it falls into the generic
1425   // ERR_FTP_FAILED bucket.
1426   TransactionFailHelper(&ctrl_socket,
1427                         "ftp://host",
1428                         FtpSocketDataProvider::PRE_USER,
1429                         FtpSocketDataProvider::PRE_QUIT,
1430                         "599 fail\r\n",
1431                         ERR_FTP_FAILED);
1432 }
1433 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailPass)1434 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailPass) {
1435   FtpSocketDataProviderDirectoryListing ctrl_socket;
1436   TransactionFailHelper(&ctrl_socket,
1437                         "ftp://host",
1438                         FtpSocketDataProvider::PRE_PASSWD,
1439                         FtpSocketDataProvider::PRE_QUIT,
1440                         "530 Login authentication failed\r\n",
1441                         ERR_FTP_FAILED);
1442 }
1443 
1444 // Regression test for http://crbug.com/38707.
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailPass503)1445 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailPass503) {
1446   FtpSocketDataProviderDirectoryListing ctrl_socket;
1447   TransactionFailHelper(&ctrl_socket,
1448                         "ftp://host",
1449                         FtpSocketDataProvider::PRE_PASSWD,
1450                         FtpSocketDataProvider::PRE_QUIT,
1451                         "503 Bad sequence of commands\r\n",
1452                         ERR_FTP_BAD_COMMAND_SEQUENCE);
1453 }
1454 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailSyst)1455 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailSyst) {
1456   FtpSocketDataProviderDirectoryListing ctrl_socket;
1457   // Use unallocated 599 FTP error code to make sure it falls into the generic
1458   // ERR_FTP_FAILED bucket.
1459   TransactionFailHelper(&ctrl_socket,
1460                         "ftp://host",
1461                         FtpSocketDataProvider::PRE_SYST,
1462                         FtpSocketDataProvider::PRE_PWD,
1463                         "599 fail\r\n",
1464                         OK);
1465 }
1466 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailPwd)1467 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailPwd) {
1468   FtpSocketDataProviderDirectoryListing ctrl_socket;
1469   // Use unallocated 599 FTP error code to make sure it falls into the generic
1470   // ERR_FTP_FAILED bucket.
1471   TransactionFailHelper(&ctrl_socket,
1472                         "ftp://host",
1473                         FtpSocketDataProvider::PRE_PWD,
1474                         FtpSocketDataProvider::PRE_QUIT,
1475                         "599 fail\r\n",
1476                         ERR_FTP_FAILED);
1477 }
1478 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailType)1479 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailType) {
1480   FtpSocketDataProviderDirectoryListing ctrl_socket;
1481   // Use unallocated 599 FTP error code to make sure it falls into the generic
1482   // ERR_FTP_FAILED bucket.
1483   TransactionFailHelper(&ctrl_socket,
1484                         "ftp://host",
1485                         FtpSocketDataProvider::PRE_TYPE,
1486                         FtpSocketDataProvider::PRE_QUIT,
1487                         "599 fail\r\n",
1488                         ERR_FTP_FAILED);
1489 }
1490 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailEpsv)1491 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailEpsv) {
1492   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1493   if (GetFamily() == AF_INET)
1494     return;
1495 
1496   FtpSocketDataProviderDirectoryListing ctrl_socket;
1497   // Use unallocated 599 FTP error code to make sure it falls into the generic
1498   // ERR_FTP_FAILED bucket.
1499   TransactionFailHelper(
1500       &ctrl_socket, "ftp://host", FtpSocketDataProvider::PRE_LIST_EPSV,
1501       FtpSocketDataProvider::PRE_NOPASV, "599 fail\r\n", ERR_FTP_FAILED);
1502 }
1503 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailCwd)1504 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailCwd) {
1505   FtpSocketDataProviderDirectoryListing ctrl_socket;
1506   // Use unallocated 599 FTP error code to make sure it falls into the generic
1507   // ERR_FTP_FAILED bucket.
1508   TransactionFailHelper(&ctrl_socket,
1509                         "ftp://host",
1510                         FtpSocketDataProvider::PRE_CWD,
1511                         FtpSocketDataProvider::PRE_QUIT,
1512                         "599 fail\r\n",
1513                         ERR_FTP_FAILED);
1514 }
1515 
TEST_P(FtpNetworkTransactionTest,DirectoryTransactionFailList)1516 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailList) {
1517   FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
1518   // Use unallocated 599 FTP error code to make sure it falls into the generic
1519   // ERR_FTP_FAILED bucket.
1520   TransactionFailHelper(&ctrl_socket,
1521                         "ftp://host/dir",
1522                         FtpSocketDataProvider::PRE_LIST,
1523                         FtpSocketDataProvider::PRE_QUIT,
1524                         "599 fail\r\n",
1525                         ERR_FTP_FAILED);
1526 }
1527 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionFailUser)1528 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailUser) {
1529   FtpSocketDataProviderFileDownload ctrl_socket;
1530   // Use unallocated 599 FTP error code to make sure it falls into the generic
1531   // ERR_FTP_FAILED bucket.
1532   TransactionFailHelper(&ctrl_socket,
1533                         "ftp://host/file",
1534                         FtpSocketDataProvider::PRE_USER,
1535                         FtpSocketDataProvider::PRE_QUIT,
1536                         "599 fail\r\n",
1537                         ERR_FTP_FAILED);
1538 }
1539 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionFailPass)1540 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailPass) {
1541   FtpSocketDataProviderFileDownload ctrl_socket;
1542   TransactionFailHelper(&ctrl_socket,
1543                         "ftp://host/file",
1544                         FtpSocketDataProvider::PRE_PASSWD,
1545                         FtpSocketDataProvider::PRE_QUIT,
1546                         "530 Login authentication failed\r\n",
1547                         ERR_FTP_FAILED);
1548 }
1549 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionFailSyst)1550 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailSyst) {
1551   FtpSocketDataProviderFileDownload ctrl_socket;
1552   // Use unallocated 599 FTP error code to make sure it falls into the generic
1553   // ERR_FTP_FAILED bucket.
1554   TransactionFailHelper(&ctrl_socket,
1555                         "ftp://host/file",
1556                         FtpSocketDataProvider::PRE_SYST,
1557                         FtpSocketDataProvider::PRE_PWD,
1558                         "599 fail\r\n",
1559                         OK);
1560 }
1561 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionFailPwd)1562 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailPwd) {
1563   FtpSocketDataProviderFileDownload ctrl_socket;
1564   // Use unallocated 599 FTP error code to make sure it falls into the generic
1565   // ERR_FTP_FAILED bucket.
1566   TransactionFailHelper(&ctrl_socket,
1567                         "ftp://host/file",
1568                         FtpSocketDataProvider::PRE_PWD,
1569                         FtpSocketDataProvider::PRE_QUIT,
1570                         "599 fail\r\n",
1571                         ERR_FTP_FAILED);
1572 }
1573 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionFailType)1574 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailType) {
1575   FtpSocketDataProviderFileDownload ctrl_socket;
1576   // Use unallocated 599 FTP error code to make sure it falls into the generic
1577   // ERR_FTP_FAILED bucket.
1578   TransactionFailHelper(&ctrl_socket,
1579                         "ftp://host/file",
1580                         FtpSocketDataProvider::PRE_TYPE,
1581                         FtpSocketDataProvider::PRE_QUIT,
1582                         "599 fail\r\n",
1583                         ERR_FTP_FAILED);
1584 }
1585 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionFailEpsv)1586 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailEpsv) {
1587   // This test makes no sense for IPv4 connections (we don't use EPSV there).
1588   if (GetFamily() == AF_INET)
1589     return;
1590 
1591   FtpSocketDataProviderFileDownload ctrl_socket;
1592   // Use unallocated 599 FTP error code to make sure it falls into the generic
1593   // ERR_FTP_FAILED bucket.
1594   TransactionFailHelper(
1595       &ctrl_socket, "ftp://host/file", FtpSocketDataProvider::PRE_RETR_EPSV,
1596       FtpSocketDataProvider::PRE_NOPASV, "599 fail\r\n", ERR_FTP_FAILED);
1597 }
1598 
TEST_P(FtpNetworkTransactionTest,DownloadTransactionFailRetr)1599 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailRetr) {
1600   FtpSocketDataProviderFileDownload ctrl_socket;
1601   // Use unallocated 599 FTP error code to make sure it falls into the generic
1602   // ERR_FTP_FAILED bucket.
1603   TransactionFailHelper(&ctrl_socket,
1604                         "ftp://host/file",
1605                         FtpSocketDataProvider::PRE_RETR,
1606                         FtpSocketDataProvider::PRE_QUIT,
1607                         "599 fail\r\n",
1608                         ERR_FTP_FAILED);
1609 }
1610 
TEST_P(FtpNetworkTransactionTest,FileNotFound)1611 TEST_P(FtpNetworkTransactionTest, FileNotFound) {
1612   FtpSocketDataProviderFileNotFound ctrl_socket;
1613   ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_FTP_FAILED);
1614 }
1615 
1616 // Test for http://crbug.com/38845.
TEST_P(FtpNetworkTransactionTest,ZeroLengthDirInPWD)1617 TEST_P(FtpNetworkTransactionTest, ZeroLengthDirInPWD) {
1618   FtpSocketDataProviderFileDownload ctrl_socket;
1619   TransactionFailHelper(&ctrl_socket,
1620                         "ftp://host/file",
1621                         FtpSocketDataProvider::PRE_PWD,
1622                         FtpSocketDataProvider::PRE_TYPE,
1623                         "257 \"\"\r\n",
1624                         OK);
1625 }
1626 
TEST_P(FtpNetworkTransactionTest,UnexpectedInitiatedResponseForDirectory)1627 TEST_P(FtpNetworkTransactionTest, UnexpectedInitiatedResponseForDirectory) {
1628   // The states for a directory listing where an initiated response will cause
1629   // an error.  Includes all commands sent on the directory listing path, except
1630   // CWD, SIZE, LIST, and QUIT commands.
1631   FtpSocketDataProvider::State kFailingStates[] = {
1632       FtpSocketDataProvider::PRE_USER, FtpSocketDataProvider::PRE_PASSWD,
1633       FtpSocketDataProvider::PRE_SYST, FtpSocketDataProvider::PRE_PWD,
1634       FtpSocketDataProvider::PRE_TYPE,
1635       GetFamily() != AF_INET ? FtpSocketDataProvider::PRE_LIST_EPSV
1636                              : FtpSocketDataProvider::PRE_LIST_PASV,
1637       FtpSocketDataProvider::PRE_CWD,
1638   };
1639 
1640   for (FtpSocketDataProvider::State state : kFailingStates) {
1641     SetUpTransaction();
1642     FtpSocketDataProviderDirectoryListing ctrl_socket;
1643     ctrl_socket.InjectFailure(state, FtpSocketDataProvider::PRE_QUIT,
1644                               "157 Foo\r\n");
1645     ExecuteTransaction(&ctrl_socket, "ftp://host/", ERR_INVALID_RESPONSE);
1646   }
1647 }
1648 
TEST_P(FtpNetworkTransactionTest,UnexpectedInitiatedResponseForFile)1649 TEST_P(FtpNetworkTransactionTest, UnexpectedInitiatedResponseForFile) {
1650   // The states for a download where an initiated response will cause an error.
1651   // Includes all commands sent on the file download path, except CWD, SIZE, and
1652   // QUIT commands.
1653   const FtpSocketDataProvider::State kFailingStates[] = {
1654       FtpSocketDataProvider::PRE_USER, FtpSocketDataProvider::PRE_PASSWD,
1655       FtpSocketDataProvider::PRE_SYST, FtpSocketDataProvider::PRE_PWD,
1656       FtpSocketDataProvider::PRE_TYPE,
1657       GetFamily() != AF_INET ? FtpSocketDataProvider::PRE_RETR_EPSV
1658                              : FtpSocketDataProvider::PRE_RETR_PASV,
1659       FtpSocketDataProvider::PRE_CWD};
1660 
1661   for (FtpSocketDataProvider::State state : kFailingStates) {
1662     LOG(ERROR) << "??: " << state;
1663     SetUpTransaction();
1664     FtpSocketDataProviderFileDownload ctrl_socket;
1665     ctrl_socket.InjectFailure(state, FtpSocketDataProvider::PRE_QUIT,
1666                               "157 Foo\r\n");
1667     ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1668   }
1669 }
1670 
1671 // Make sure that receiving extra unexpected responses correctly results in
1672 // sending a QUIT message, without triggering a DCHECK.
TEST_P(FtpNetworkTransactionTest,ExtraResponses)1673 TEST_P(FtpNetworkTransactionTest, ExtraResponses) {
1674   FtpSocketDataProviderDirectoryListing ctrl_socket;
1675   ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_TYPE,
1676                             FtpSocketDataProvider::PRE_QUIT,
1677                             "157 Foo\r\n"
1678                             "157 Bar\r\n"
1679                             "157 Trombones\r\n");
1680   ExecuteTransaction(&ctrl_socket, "ftp://host/", ERR_INVALID_RESPONSE);
1681 }
1682 
1683 // Make sure that receiving extra unexpected responses to a QUIT message
1684 // correctly results in ending the transaction with an error, without triggering
1685 // a DCHECK.
TEST_P(FtpNetworkTransactionTest,ExtraQuitResponses)1686 TEST_P(FtpNetworkTransactionTest, ExtraQuitResponses) {
1687   FtpSocketDataProviderDirectoryListing ctrl_socket;
1688   ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_QUIT,
1689                             FtpSocketDataProvider::QUIT,
1690                             "221 Foo\r\n"
1691                             "221 Bar\r\n"
1692                             "221 Trombones\r\n");
1693   ExecuteTransaction(&ctrl_socket, "ftp://host/", ERR_INVALID_RESPONSE);
1694 }
1695 
1696 // Test case for https://crbug.com/633841 - similar to the ExtraQuitResponses
1697 // test case, but with an empty response.
TEST_P(FtpNetworkTransactionTest,EmptyQuitResponse)1698 TEST_P(FtpNetworkTransactionTest, EmptyQuitResponse) {
1699   FtpSocketDataProviderDirectoryListing ctrl_socket;
1700   ctrl_socket.InjectFailure(FtpSocketDataProvider::PRE_QUIT,
1701                             FtpSocketDataProvider::QUIT, "");
1702   ExecuteTransaction(&ctrl_socket, "ftp://host/", OK);
1703 }
1704 
TEST_P(FtpNetworkTransactionTest,InvalidRemoteDirectory)1705 TEST_P(FtpNetworkTransactionTest, InvalidRemoteDirectory) {
1706   FtpSocketDataProviderFileDownload ctrl_socket;
1707   TransactionFailHelper(
1708       &ctrl_socket, "ftp://host/file", FtpSocketDataProvider::PRE_PWD,
1709       FtpSocketDataProvider::PRE_QUIT,
1710       "257 \"foo\rbar\" is your current location\r\n", ERR_INVALID_RESPONSE);
1711 }
1712 
TEST_P(FtpNetworkTransactionTest,InvalidRemoteDirectory2)1713 TEST_P(FtpNetworkTransactionTest, InvalidRemoteDirectory2) {
1714   FtpSocketDataProviderFileDownload ctrl_socket;
1715   TransactionFailHelper(
1716       &ctrl_socket, "ftp://host/file", FtpSocketDataProvider::PRE_PWD,
1717       FtpSocketDataProvider::PRE_QUIT,
1718       "257 \"foo\nbar\" is your current location\r\n", ERR_INVALID_RESPONSE);
1719 }
1720 
1721 INSTANTIATE_TEST_SUITE_P(Ftp,
1722                          FtpNetworkTransactionTest,
1723                          ::testing::Values(AF_INET, AF_INET6));
1724 
1725 }  // namespace net
1726