ftp_network_transaction_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "build/build_config.h"
8
9#include "base/compiler_specific.h"
10#include "base/memory/ref_counted.h"
11#include "base/string_util.h"
12#include "base/utf_string_conversions.h"
13#include "net/base/host_port_pair.h"
14#include "net/base/io_buffer.h"
15#include "net/base/mock_host_resolver.h"
16#include "net/base/net_util.h"
17#include "net/base/test_completion_callback.h"
18#include "net/ftp/ftp_network_session.h"
19#include "net/ftp/ftp_request_info.h"
20#include "net/socket/socket_test_util.h"
21#include "testing/gtest/include/gtest/gtest.h"
22#include "testing/platform_test.h"
23
24namespace {
25
26// Size we use for IOBuffers used to receive data from the test data socket.
27const int kBufferSize = 128;
28
29}  // namespace
30
31namespace net {
32
33class FtpSocketDataProvider : public DynamicSocketDataProvider {
34 public:
35  enum State {
36    NONE,
37    PRE_USER,
38    PRE_PASSWD,
39    PRE_SYST,
40    PRE_PWD,
41    PRE_TYPE,
42    PRE_SIZE,
43    PRE_EPSV,
44    PRE_PASV,
45    PRE_LIST,
46    PRE_RETR,
47    PRE_CWD,
48    PRE_QUIT,
49    PRE_NOPASV,
50    QUIT
51  };
52
53  FtpSocketDataProvider()
54      : failure_injection_state_(NONE),
55        multiline_welcome_(false),
56        data_type_('I') {
57    Init();
58  }
59
60  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
61    if (InjectFault())
62      return MockWriteResult(ASYNC, data.length());
63    switch (state()) {
64      case PRE_USER:
65        return Verify("USER anonymous\r\n", data, PRE_PASSWD,
66                      "331 Password needed\r\n");
67      case PRE_PASSWD:
68        {
69          const char* response_one = "230 Welcome\r\n";
70          const char* response_multi = "230- One\r\n230- Two\r\n230 Three\r\n";
71          return Verify("PASS chrome@example.com\r\n", data, PRE_SYST,
72                        multiline_welcome_ ? response_multi : response_one);
73        }
74      case PRE_SYST:
75        return Verify("SYST\r\n", data, PRE_PWD, "215 UNIX\r\n");
76      case PRE_PWD:
77        return Verify("PWD\r\n", data, PRE_TYPE,
78                      "257 \"/\" is your current location\r\n");
79      case PRE_TYPE:
80        return Verify(std::string("TYPE ") + data_type_ + "\r\n", data,
81                      PRE_EPSV, "200 TYPE set successfully\r\n");
82      case PRE_EPSV:
83        return Verify("EPSV\r\n", data, PRE_SIZE,
84                      "227 Entering Extended Passive Mode (|||31744|)\r\n");
85      case PRE_NOPASV:
86        // Use unallocated 599 FTP error code to make sure it falls into the
87        // generic ERR_FTP_FAILED bucket.
88        return Verify("PASV\r\n", data, PRE_QUIT,
89                      "599 fail\r\n");
90      case PRE_QUIT:
91        return Verify("QUIT\r\n", data, QUIT, "221 Goodbye.\r\n");
92      default:
93        NOTREACHED() << "State not handled " << state();
94        return MockWriteResult(ASYNC, ERR_UNEXPECTED);
95    }
96  }
97
98  void InjectFailure(State state, State next_state, const char* response) {
99    DCHECK_EQ(NONE, failure_injection_state_);
100    DCHECK_NE(NONE, state);
101    DCHECK_NE(NONE, next_state);
102    DCHECK_NE(state, next_state);
103    failure_injection_state_ = state;
104    failure_injection_next_state_ = next_state;
105    fault_response_ = response;
106  }
107
108  State state() const {
109    return state_;
110  }
111
112  virtual void Reset() OVERRIDE {
113    DynamicSocketDataProvider::Reset();
114    Init();
115  }
116
117  void set_multiline_welcome(bool multiline) {
118    multiline_welcome_ = multiline;
119  }
120
121  void set_data_type(char data_type) {
122    data_type_ = data_type;
123  }
124
125 protected:
126  void Init() {
127    state_ = PRE_USER;
128    SimulateRead("220 host TestFTPd\r\n");
129  }
130
131  // If protocol fault injection has been requested, adjusts state and mocked
132  // read and returns true.
133  bool InjectFault() {
134    if (state_ != failure_injection_state_)
135      return false;
136    SimulateRead(fault_response_);
137    state_ = failure_injection_next_state_;
138    return true;
139  }
140
141  MockWriteResult Verify(const std::string& expected,
142                         const std::string& data,
143                         State next_state,
144                         const char* next_read,
145                         const size_t next_read_length) {
146    EXPECT_EQ(expected, data);
147    if (expected == data) {
148      state_ = next_state;
149      SimulateRead(next_read, next_read_length);
150      return MockWriteResult(ASYNC, data.length());
151    }
152    return MockWriteResult(ASYNC, ERR_UNEXPECTED);
153  }
154
155  MockWriteResult Verify(const std::string& expected,
156                         const std::string& data,
157                         State next_state,
158                         const char* next_read) {
159    return Verify(expected, data, next_state,
160                  next_read, std::strlen(next_read));
161  }
162
163
164 private:
165  State state_;
166  State failure_injection_state_;
167  State failure_injection_next_state_;
168  const char* fault_response_;
169
170  // If true, we will send multiple 230 lines as response after PASS.
171  bool multiline_welcome_;
172
173  // Data type to be used for TYPE command.
174  char data_type_;
175
176  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProvider);
177};
178
179class FtpSocketDataProviderDirectoryListing : public FtpSocketDataProvider {
180 public:
181  FtpSocketDataProviderDirectoryListing() {
182  }
183
184  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
185    if (InjectFault())
186      return MockWriteResult(ASYNC, data.length());
187    switch (state()) {
188      case PRE_SIZE:
189        return Verify("SIZE /\r\n", data, PRE_CWD,
190                      "550 I can only retrieve regular files\r\n");
191      case PRE_CWD:
192        return Verify("CWD /\r\n", data, PRE_LIST, "200 OK\r\n");
193      case PRE_LIST:
194        return Verify("LIST\r\n", data, PRE_QUIT, "200 OK\r\n");
195      default:
196        return FtpSocketDataProvider::OnWrite(data);
197    }
198  }
199
200 private:
201  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderDirectoryListing);
202};
203
204class FtpSocketDataProviderDirectoryListingWithPasvFallback
205    : public FtpSocketDataProviderDirectoryListing {
206 public:
207  FtpSocketDataProviderDirectoryListingWithPasvFallback() {
208  }
209
210  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
211    if (InjectFault())
212      return MockWriteResult(ASYNC, data.length());
213    switch (state()) {
214      case PRE_EPSV:
215        return Verify("EPSV\r\n", data, PRE_PASV,
216                      "500 no EPSV for you\r\n");
217      case PRE_PASV:
218        return Verify("PASV\r\n", data, PRE_SIZE,
219                      "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
220      default:
221        return FtpSocketDataProviderDirectoryListing::OnWrite(data);
222    }
223  }
224
225 private:
226  DISALLOW_COPY_AND_ASSIGN(
227      FtpSocketDataProviderDirectoryListingWithPasvFallback);
228};
229
230class FtpSocketDataProviderDirectoryListingZeroSize
231    : public FtpSocketDataProviderDirectoryListing {
232 public:
233  FtpSocketDataProviderDirectoryListingZeroSize() {
234  }
235
236  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
237    if (InjectFault())
238      return MockWriteResult(ASYNC, data.length());
239    switch (state()) {
240      case PRE_SIZE:
241        return Verify("SIZE /\r\n", data, PRE_CWD, "213 0\r\n");
242      default:
243        return FtpSocketDataProviderDirectoryListing::OnWrite(data);
244    }
245  }
246
247 private:
248  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderDirectoryListingZeroSize);
249};
250
251class FtpSocketDataProviderVMSDirectoryListing : public FtpSocketDataProvider {
252 public:
253  FtpSocketDataProviderVMSDirectoryListing() {
254  }
255
256  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
257    if (InjectFault())
258      return MockWriteResult(ASYNC, data.length());
259    switch (state()) {
260      case PRE_SYST:
261        return Verify("SYST\r\n", data, PRE_PWD, "215 VMS\r\n");
262      case PRE_PWD:
263        return Verify("PWD\r\n", data, PRE_TYPE,
264                      "257 \"ANONYMOUS_ROOT:[000000]\"\r\n");
265      case PRE_EPSV:
266        return Verify("EPSV\r\n", data, PRE_PASV, "500 Invalid command\r\n");
267      case PRE_PASV:
268        return Verify("PASV\r\n", data, PRE_SIZE,
269                      "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
270      case PRE_SIZE:
271        return Verify("SIZE ANONYMOUS_ROOT:[000000]dir\r\n", data, PRE_CWD,
272                      "550 I can only retrieve regular files\r\n");
273      case PRE_CWD:
274        return Verify("CWD ANONYMOUS_ROOT:[dir]\r\n", data, PRE_LIST,
275                      "200 OK\r\n");
276      case PRE_LIST:
277        return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n");
278      default:
279        return FtpSocketDataProvider::OnWrite(data);
280    }
281  }
282
283 private:
284  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderVMSDirectoryListing);
285};
286
287class FtpSocketDataProviderVMSDirectoryListingRootDirectory
288    : public FtpSocketDataProvider {
289 public:
290  FtpSocketDataProviderVMSDirectoryListingRootDirectory() {
291  }
292
293  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
294    if (InjectFault())
295      return MockWriteResult(ASYNC, data.length());
296    switch (state()) {
297      case PRE_SYST:
298        return Verify("SYST\r\n", data, PRE_PWD, "215 VMS\r\n");
299      case PRE_PWD:
300        return Verify("PWD\r\n", data, PRE_TYPE,
301                      "257 \"ANONYMOUS_ROOT:[000000]\"\r\n");
302      case PRE_EPSV:
303        return Verify("EPSV\r\n", data, PRE_PASV,
304                      "500 EPSV command unknown\r\n");
305      case PRE_PASV:
306        return Verify("PASV\r\n", data, PRE_SIZE,
307                      "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
308      case PRE_SIZE:
309        return Verify("SIZE ANONYMOUS_ROOT\r\n", data, PRE_CWD,
310                      "550 I can only retrieve regular files\r\n");
311      case PRE_CWD:
312        return Verify("CWD ANONYMOUS_ROOT:[000000]\r\n", data, PRE_LIST,
313                      "200 OK\r\n");
314      case PRE_LIST:
315        return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n");
316      default:
317        return FtpSocketDataProvider::OnWrite(data);
318    }
319  }
320
321 private:
322  DISALLOW_COPY_AND_ASSIGN(
323      FtpSocketDataProviderVMSDirectoryListingRootDirectory);
324};
325
326class FtpSocketDataProviderFileDownloadWithFileTypecode
327    : public FtpSocketDataProvider {
328 public:
329  FtpSocketDataProviderFileDownloadWithFileTypecode() {
330  }
331
332  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
333    if (InjectFault())
334      return MockWriteResult(ASYNC, data.length());
335    switch (state()) {
336      case PRE_SIZE:
337        return Verify("SIZE /file\r\n", data, PRE_RETR,
338                      "213 18\r\n");
339      case PRE_RETR:
340        return Verify("RETR /file\r\n", data, PRE_QUIT, "200 OK\r\n");
341      default:
342        return FtpSocketDataProvider::OnWrite(data);
343    }
344  }
345
346 private:
347  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadWithFileTypecode);
348};
349
350class FtpSocketDataProviderFileDownload : public FtpSocketDataProvider {
351 public:
352  FtpSocketDataProviderFileDownload() {
353  }
354
355  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
356    if (InjectFault())
357      return MockWriteResult(ASYNC, data.length());
358    switch (state()) {
359      case PRE_SIZE:
360        return Verify("SIZE /file\r\n", data, PRE_CWD,
361                      "213 18\r\n");
362      case PRE_CWD:
363        return Verify("CWD /file\r\n", data, PRE_RETR,
364                      "550 Not a directory\r\n");
365      case PRE_RETR:
366        return Verify("RETR /file\r\n", data, PRE_QUIT, "200 OK\r\n");
367      default:
368        return FtpSocketDataProvider::OnWrite(data);
369    }
370  }
371
372 private:
373  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownload);
374};
375
376class FtpSocketDataProviderFileNotFound : public FtpSocketDataProvider {
377 public:
378  FtpSocketDataProviderFileNotFound() {
379  }
380
381  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
382    if (InjectFault())
383      return MockWriteResult(ASYNC, data.length());
384    switch (state()) {
385      case PRE_SIZE:
386        return Verify("SIZE /file\r\n", data, PRE_CWD,
387                      "550 File Not Found\r\n");
388      case PRE_CWD:
389        return Verify("CWD /file\r\n", data, PRE_RETR,
390                      "550 File Not Found\r\n");
391      case PRE_RETR:
392        return Verify("RETR /file\r\n", data, PRE_QUIT,
393                      "550 File Not Found\r\n");
394      default:
395        return FtpSocketDataProvider::OnWrite(data);
396    }
397  }
398
399 private:
400  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileNotFound);
401};
402
403class FtpSocketDataProviderFileDownloadWithPasvFallback
404    : public FtpSocketDataProviderFileDownload {
405 public:
406  FtpSocketDataProviderFileDownloadWithPasvFallback() {
407  }
408
409  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
410    if (InjectFault())
411      return MockWriteResult(ASYNC, data.length());
412    switch (state()) {
413      case PRE_EPSV:
414        return Verify("EPSV\r\n", data, PRE_PASV,
415                      "500 No can do\r\n");
416      case PRE_PASV:
417        return Verify("PASV\r\n", data, PRE_SIZE,
418                      "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
419      default:
420        return FtpSocketDataProviderFileDownload::OnWrite(data);
421    }
422  }
423
424 private:
425  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadWithPasvFallback);
426};
427
428class FtpSocketDataProviderFileDownloadZeroSize
429    : public FtpSocketDataProviderFileDownload {
430 public:
431  FtpSocketDataProviderFileDownloadZeroSize() {
432  }
433
434  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
435    if (InjectFault())
436      return MockWriteResult(ASYNC, data.length());
437    switch (state()) {
438      case PRE_SIZE:
439        return Verify("SIZE /file\r\n", data, PRE_CWD,
440                      "213 0\r\n");
441      case PRE_CWD:
442        return Verify("CWD /file\r\n", data, PRE_RETR,
443                      "550 not a directory\r\n");
444      default:
445        return FtpSocketDataProviderFileDownload::OnWrite(data);
446    }
447  }
448
449 private:
450  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadZeroSize);
451};
452
453class FtpSocketDataProviderFileDownloadCWD451
454    : public FtpSocketDataProviderFileDownload {
455 public:
456  FtpSocketDataProviderFileDownloadCWD451() {
457  }
458
459  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
460    if (InjectFault())
461      return MockWriteResult(ASYNC, data.length());
462    switch (state()) {
463      case PRE_CWD:
464        return Verify("CWD /file\r\n", data, PRE_RETR,
465                      "451 not a directory\r\n");
466      default:
467        return FtpSocketDataProviderFileDownload::OnWrite(data);
468    }
469  }
470
471 private:
472  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadCWD451);
473};
474
475class FtpSocketDataProviderVMSFileDownload : public FtpSocketDataProvider {
476 public:
477  FtpSocketDataProviderVMSFileDownload() {
478  }
479
480  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
481    if (InjectFault())
482      return MockWriteResult(ASYNC, data.length());
483    switch (state()) {
484      case PRE_SYST:
485        return Verify("SYST\r\n", data, PRE_PWD, "215 VMS\r\n");
486      case PRE_PWD:
487        return Verify("PWD\r\n", data, PRE_TYPE,
488                      "257 \"ANONYMOUS_ROOT:[000000]\"\r\n");
489      case PRE_EPSV:
490        return Verify("EPSV\r\n", data, PRE_PASV,
491                      "500 EPSV command unknown\r\n");
492      case PRE_PASV:
493        return Verify("PASV\r\n", data, PRE_SIZE,
494                      "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
495      case PRE_SIZE:
496        return Verify("SIZE ANONYMOUS_ROOT:[000000]file\r\n", data, PRE_CWD,
497                      "213 18\r\n");
498      case PRE_CWD:
499        return Verify("CWD ANONYMOUS_ROOT:[file]\r\n", data, PRE_RETR,
500                      "550 Not a directory\r\n");
501      case PRE_RETR:
502        return Verify("RETR ANONYMOUS_ROOT:[000000]file\r\n", data, PRE_QUIT,
503                      "200 OK\r\n");
504      default:
505        return FtpSocketDataProvider::OnWrite(data);
506    }
507  }
508
509 private:
510  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderVMSFileDownload);
511};
512
513class FtpSocketDataProviderEscaping : public FtpSocketDataProviderFileDownload {
514 public:
515  FtpSocketDataProviderEscaping() {
516  }
517
518  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
519    if (InjectFault())
520      return MockWriteResult(ASYNC, data.length());
521    switch (state()) {
522      case PRE_SIZE:
523        return Verify("SIZE / !\"#$%y\200\201\r\n", data, PRE_CWD,
524                      "213 18\r\n");
525      case PRE_CWD:
526        return Verify("CWD / !\"#$%y\200\201\r\n", data, PRE_RETR,
527                      "550 Not a directory\r\n");
528      case PRE_RETR:
529        return Verify("RETR / !\"#$%y\200\201\r\n", data, PRE_QUIT,
530                      "200 OK\r\n");
531      default:
532        return FtpSocketDataProviderFileDownload::OnWrite(data);
533    }
534  }
535
536 private:
537  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEscaping);
538};
539
540class FtpSocketDataProviderFileDownloadTransferStarting
541    : public FtpSocketDataProviderFileDownload {
542 public:
543  FtpSocketDataProviderFileDownloadTransferStarting() {
544  }
545
546  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
547    if (InjectFault())
548      return MockWriteResult(ASYNC, data.length());
549    switch (state()) {
550      case PRE_RETR:
551        return Verify("RETR /file\r\n", data, PRE_QUIT,
552                      "125-Data connection already open.\r\n"
553                      "125  Transfer starting.\r\n"
554                      "226 Transfer complete.\r\n");
555      default:
556        return FtpSocketDataProviderFileDownload::OnWrite(data);
557    }
558  }
559
560 private:
561  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadTransferStarting);
562};
563
564class FtpSocketDataProviderDirectoryListingTransferStarting
565    : public FtpSocketDataProviderDirectoryListing {
566 public:
567  FtpSocketDataProviderDirectoryListingTransferStarting() {
568  }
569
570  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
571    if (InjectFault())
572      return MockWriteResult(ASYNC, data.length());
573    switch (state()) {
574      case PRE_LIST:
575        return Verify("LIST\r\n", data, PRE_QUIT,
576                      "125-Data connection already open.\r\n"
577                      "125  Transfer starting.\r\n"
578                      "226 Transfer complete.\r\n");
579      default:
580        return FtpSocketDataProviderDirectoryListing::OnWrite(data);
581    }
582  }
583
584 private:
585  DISALLOW_COPY_AND_ASSIGN(
586      FtpSocketDataProviderDirectoryListingTransferStarting);
587};
588
589class FtpSocketDataProviderFileDownloadInvalidResponse
590    : public FtpSocketDataProviderFileDownload {
591 public:
592  FtpSocketDataProviderFileDownloadInvalidResponse() {
593  }
594
595  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
596    if (InjectFault())
597      return MockWriteResult(ASYNC, data.length());
598    switch (state()) {
599      case PRE_SIZE:
600        // Use unallocated 599 FTP error code to make sure it falls into the
601        // generic ERR_FTP_FAILED bucket.
602        return Verify("SIZE /file\r\n", data, PRE_QUIT,
603                      "599 Evil Response\r\n"
604                      "599 More Evil\r\n");
605      default:
606        return FtpSocketDataProviderFileDownload::OnWrite(data);
607    }
608  }
609
610 private:
611  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadInvalidResponse);
612};
613
614class FtpSocketDataProviderEvilEpsv : public FtpSocketDataProviderFileDownload {
615 public:
616  FtpSocketDataProviderEvilEpsv(const char* epsv_response,
617                                State expected_state)
618      : epsv_response_(epsv_response),
619        epsv_response_length_(std::strlen(epsv_response)),
620        expected_state_(expected_state) {}
621
622  FtpSocketDataProviderEvilEpsv(const char* epsv_response,
623                               size_t epsv_response_length,
624                               State expected_state)
625      : epsv_response_(epsv_response),
626        epsv_response_length_(epsv_response_length),
627        expected_state_(expected_state) {}
628
629  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
630    if (InjectFault())
631      return MockWriteResult(ASYNC, data.length());
632    switch (state()) {
633      case PRE_EPSV:
634        return Verify("EPSV\r\n", data, expected_state_,
635                      epsv_response_, epsv_response_length_);
636      default:
637        return FtpSocketDataProviderFileDownload::OnWrite(data);
638    }
639  }
640
641 private:
642  const char* epsv_response_;
643  const size_t epsv_response_length_;
644  const State expected_state_;
645
646  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilEpsv);
647};
648
649class FtpSocketDataProviderEvilPasv
650    : public FtpSocketDataProviderFileDownloadWithPasvFallback {
651 public:
652  FtpSocketDataProviderEvilPasv(const char* pasv_response, State expected_state)
653      : pasv_response_(pasv_response),
654        expected_state_(expected_state) {
655  }
656
657  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
658    if (InjectFault())
659      return MockWriteResult(ASYNC, data.length());
660    switch (state()) {
661      case PRE_PASV:
662        return Verify("PASV\r\n", data, expected_state_, pasv_response_);
663      default:
664        return FtpSocketDataProviderFileDownloadWithPasvFallback::OnWrite(data);
665    }
666  }
667
668 private:
669  const char* pasv_response_;
670  const State expected_state_;
671
672  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilPasv);
673};
674
675class FtpSocketDataProviderEvilSize : public FtpSocketDataProviderFileDownload {
676 public:
677  FtpSocketDataProviderEvilSize(const char* size_response, State expected_state)
678      : size_response_(size_response),
679        expected_state_(expected_state) {
680  }
681
682  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
683    if (InjectFault())
684      return MockWriteResult(ASYNC, data.length());
685    switch (state()) {
686      case PRE_SIZE:
687        return Verify("SIZE /file\r\n", data, expected_state_, size_response_);
688      default:
689        return FtpSocketDataProviderFileDownload::OnWrite(data);
690    }
691  }
692
693 private:
694  const char* size_response_;
695  const State expected_state_;
696
697  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilSize);
698};
699
700class FtpSocketDataProviderEvilLogin
701    : public FtpSocketDataProviderFileDownload {
702 public:
703  FtpSocketDataProviderEvilLogin(const char* expected_user,
704                                const char* expected_password)
705      : expected_user_(expected_user),
706        expected_password_(expected_password) {
707  }
708
709  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
710    if (InjectFault())
711      return MockWriteResult(ASYNC, data.length());
712    switch (state()) {
713      case PRE_USER:
714        return Verify(std::string("USER ") + expected_user_ + "\r\n", data,
715                      PRE_PASSWD, "331 Password needed\r\n");
716      case PRE_PASSWD:
717        return Verify(std::string("PASS ") + expected_password_ + "\r\n", data,
718                      PRE_SYST, "230 Welcome\r\n");
719      default:
720        return FtpSocketDataProviderFileDownload::OnWrite(data);
721    }
722  }
723
724 private:
725  const char* expected_user_;
726  const char* expected_password_;
727
728  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilLogin);
729};
730
731class FtpSocketDataProviderCloseConnection : public FtpSocketDataProvider {
732 public:
733  FtpSocketDataProviderCloseConnection() {
734  }
735
736  virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE {
737    if (InjectFault())
738      return MockWriteResult(ASYNC, data.length());
739    switch (state()) {
740      case PRE_USER:
741        return Verify("USER anonymous\r\n", data,
742                      PRE_QUIT, "");
743      default:
744        return FtpSocketDataProvider::OnWrite(data);
745    }
746  }
747
748 private:
749  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderCloseConnection);
750};
751
752class FtpNetworkTransactionTest : public PlatformTest {
753 public:
754  FtpNetworkTransactionTest()
755      : host_resolver_(new MockHostResolver),
756        session_(new FtpNetworkSession(host_resolver_.get())),
757        transaction_(session_.get(), &mock_socket_factory_) {
758  }
759
760 protected:
761  FtpRequestInfo GetRequestInfo(const std::string& url) {
762    FtpRequestInfo info;
763    info.url = GURL(url);
764    return info;
765  }
766
767  void ExecuteTransaction(FtpSocketDataProvider* ctrl_socket,
768                          const char* request,
769                          int expected_result) {
770    std::string mock_data("mock-data");
771    MockRead data_reads[] = {
772      // Usually FTP servers close the data connection after the entire data has
773      // been received.
774      MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
775      MockRead(mock_data.c_str()),
776    };
777    StaticSocketDataProvider data_socket(data_reads, arraysize(data_reads),
778                                         NULL, 0);
779    mock_socket_factory_.AddSocketDataProvider(ctrl_socket);
780    mock_socket_factory_.AddSocketDataProvider(&data_socket);
781    FtpRequestInfo request_info = GetRequestInfo(request);
782    EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
783    ASSERT_EQ(ERR_IO_PENDING,
784              transaction_.Start(&request_info, callback_.callback(),
785                                 BoundNetLog()));
786    EXPECT_NE(LOAD_STATE_IDLE, transaction_.GetLoadState());
787    ASSERT_EQ(expected_result, callback_.WaitForResult());
788    if (expected_result == OK) {
789      scoped_refptr<IOBuffer> io_buffer(new IOBuffer(kBufferSize));
790      memset(io_buffer->data(), 0, kBufferSize);
791      ASSERT_EQ(ERR_IO_PENDING,
792                transaction_.Read(io_buffer.get(), kBufferSize,
793                                  callback_.callback()));
794      ASSERT_EQ(static_cast<int>(mock_data.length()),
795                callback_.WaitForResult());
796      EXPECT_EQ(mock_data, std::string(io_buffer->data(), mock_data.length()));
797
798      // Do another Read to detect that the data socket is now closed.
799      int rv = transaction_.Read(io_buffer.get(), kBufferSize,
800                                 callback_.callback());
801      if (rv == ERR_IO_PENDING) {
802        EXPECT_EQ(0, callback_.WaitForResult());
803      } else {
804        EXPECT_EQ(0, rv);
805      }
806    }
807    EXPECT_EQ(FtpSocketDataProvider::QUIT, ctrl_socket->state());
808    EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
809  }
810
811  void TransactionFailHelper(FtpSocketDataProvider* ctrl_socket,
812                             const char* request,
813                             FtpSocketDataProvider::State state,
814                             FtpSocketDataProvider::State next_state,
815                             const char* response,
816                             int expected_result) {
817    ctrl_socket->InjectFailure(state, next_state, response);
818    ExecuteTransaction(ctrl_socket, request, expected_result);
819  }
820
821  scoped_ptr<MockHostResolver> host_resolver_;
822  scoped_refptr<FtpNetworkSession> session_;
823  MockClientSocketFactory mock_socket_factory_;
824  FtpNetworkTransaction transaction_;
825  TestCompletionCallback callback_;
826};
827
828TEST_F(FtpNetworkTransactionTest, FailedLookup) {
829  FtpRequestInfo request_info = GetRequestInfo("ftp://badhost");
830  host_resolver_->rules()->AddSimulatedFailure("badhost");
831  EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
832  ASSERT_EQ(ERR_IO_PENDING,
833            transaction_.Start(&request_info, callback_.callback(),
834                               BoundNetLog()));
835  ASSERT_EQ(ERR_NAME_NOT_RESOLVED, callback_.WaitForResult());
836  EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
837}
838
839// Check that when determining the host, the square brackets decorating IPv6
840// literals in URLs are stripped.
841TEST_F(FtpNetworkTransactionTest, StripBracketsFromIPv6Literals) {
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
854TEST_F(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("192.0.2.33",
861            transaction_.GetResponseInfo()->socket_address.host());
862  EXPECT_EQ(0, transaction_.GetResponseInfo()->socket_address.port());
863}
864
865TEST_F(FtpNetworkTransactionTest, DirectoryTransactionWithPasvFallback) {
866  FtpSocketDataProviderDirectoryListingWithPasvFallback ctrl_socket;
867  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
868
869  EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
870  EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
871}
872
873TEST_F(FtpNetworkTransactionTest, DirectoryTransactionWithTypecode) {
874  FtpSocketDataProviderDirectoryListing ctrl_socket;
875  ExecuteTransaction(&ctrl_socket, "ftp://host;type=d", OK);
876
877  EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
878  EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
879}
880
881TEST_F(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcome) {
882  FtpSocketDataProviderDirectoryListing ctrl_socket;
883  ctrl_socket.set_multiline_welcome(true);
884  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
885}
886
887TEST_F(FtpNetworkTransactionTest, DirectoryTransactionShortReads2) {
888  FtpSocketDataProviderDirectoryListing ctrl_socket;
889  ctrl_socket.set_short_read_limit(2);
890  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
891}
892
893TEST_F(FtpNetworkTransactionTest, DirectoryTransactionShortReads5) {
894  FtpSocketDataProviderDirectoryListing ctrl_socket;
895  ctrl_socket.set_short_read_limit(5);
896  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
897}
898
899TEST_F(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcomeShort) {
900  FtpSocketDataProviderDirectoryListing ctrl_socket;
901  // The client will not consume all three 230 lines. That's good, we want to
902  // test that scenario.
903  ctrl_socket.allow_unconsumed_reads(true);
904  ctrl_socket.set_multiline_welcome(true);
905  ctrl_socket.set_short_read_limit(5);
906  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
907}
908
909// Regression test for http://crbug.com/60555.
910TEST_F(FtpNetworkTransactionTest, DirectoryTransactionZeroSize) {
911  FtpSocketDataProviderDirectoryListingZeroSize ctrl_socket;
912  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
913}
914
915TEST_F(FtpNetworkTransactionTest, DirectoryTransactionVMS) {
916  FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
917  ExecuteTransaction(&ctrl_socket, "ftp://host/dir", OK);
918}
919
920TEST_F(FtpNetworkTransactionTest, DirectoryTransactionVMSRootDirectory) {
921  FtpSocketDataProviderVMSDirectoryListingRootDirectory ctrl_socket;
922  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
923}
924
925TEST_F(FtpNetworkTransactionTest, DirectoryTransactionTransferStarting) {
926  FtpSocketDataProviderDirectoryListingTransferStarting ctrl_socket;
927  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
928}
929
930TEST_F(FtpNetworkTransactionTest, DownloadTransaction) {
931  FtpSocketDataProviderFileDownload ctrl_socket;
932  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
933
934  // We pass an artificial value of 18 as a response to the SIZE command.
935  EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
936  EXPECT_EQ("192.0.2.33",
937            transaction_.GetResponseInfo()->socket_address.host());
938  EXPECT_EQ(0, transaction_.GetResponseInfo()->socket_address.port());
939}
940
941TEST_F(FtpNetworkTransactionTest, DownloadTransactionWithPasvFallback) {
942  FtpSocketDataProviderFileDownloadWithPasvFallback ctrl_socket;
943  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
944
945  // We pass an artificial value of 18 as a response to the SIZE command.
946  EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
947}
948
949TEST_F(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeA) {
950  FtpSocketDataProviderFileDownloadWithFileTypecode ctrl_socket;
951  ctrl_socket.set_data_type('A');
952  ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=a", 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
958TEST_F(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeI) {
959  FtpSocketDataProviderFileDownloadWithFileTypecode ctrl_socket;
960  ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=i", OK);
961
962  // We pass an artificial value of 18 as a response to the SIZE command.
963  EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
964}
965
966TEST_F(FtpNetworkTransactionTest, DownloadTransactionMultilineWelcome) {
967  FtpSocketDataProviderFileDownload ctrl_socket;
968  ctrl_socket.set_multiline_welcome(true);
969  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
970}
971
972TEST_F(FtpNetworkTransactionTest, DownloadTransactionShortReads2) {
973  FtpSocketDataProviderFileDownload ctrl_socket;
974  ctrl_socket.set_short_read_limit(2);
975  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
976}
977
978TEST_F(FtpNetworkTransactionTest, DownloadTransactionShortReads5) {
979  FtpSocketDataProviderFileDownload ctrl_socket;
980  ctrl_socket.set_short_read_limit(5);
981  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
982}
983
984TEST_F(FtpNetworkTransactionTest, DownloadTransactionZeroSize) {
985  FtpSocketDataProviderFileDownloadZeroSize ctrl_socket;
986  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
987}
988
989TEST_F(FtpNetworkTransactionTest, DownloadTransactionCWD451) {
990  FtpSocketDataProviderFileDownloadCWD451 ctrl_socket;
991  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
992}
993
994TEST_F(FtpNetworkTransactionTest, DownloadTransactionVMS) {
995  FtpSocketDataProviderVMSFileDownload ctrl_socket;
996  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
997}
998
999TEST_F(FtpNetworkTransactionTest, DownloadTransactionTransferStarting) {
1000  FtpSocketDataProviderFileDownloadTransferStarting ctrl_socket;
1001  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1002}
1003
1004TEST_F(FtpNetworkTransactionTest, DownloadTransactionInvalidResponse) {
1005  FtpSocketDataProviderFileDownloadInvalidResponse ctrl_socket;
1006  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1007}
1008
1009TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvReallyBadFormat) {
1010  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,\r\n",
1011                                            FtpSocketDataProvider::PRE_QUIT);
1012  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1013}
1014
1015TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort1) {
1016  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,0,22)\r\n",
1017                                            FtpSocketDataProvider::PRE_QUIT);
1018  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1019}
1020
1021TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort2) {
1022  // Still unsafe. 1 * 256 + 2 = 258, which is < 1024.
1023  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,1,2)\r\n",
1024                                            FtpSocketDataProvider::PRE_QUIT);
1025  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1026}
1027
1028TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort3) {
1029  // Still unsafe. 3 * 256 + 4 = 772, which is < 1024.
1030  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,3,4)\r\n",
1031                                            FtpSocketDataProvider::PRE_QUIT);
1032  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1033}
1034
1035TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort4) {
1036  // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
1037  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,8,1)\r\n",
1038                                            FtpSocketDataProvider::PRE_QUIT);
1039  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1040}
1041
1042TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafeHost) {
1043  FtpSocketDataProviderEvilPasv ctrl_socket(
1044      "227 Portscan (10,1,2,3,123,456)\r\n", FtpSocketDataProvider::PRE_SIZE);
1045  std::string mock_data("mock-data");
1046  MockRead data_reads[] = {
1047    MockRead(mock_data.c_str()),
1048  };
1049  StaticSocketDataProvider data_socket1(data_reads, arraysize(data_reads),
1050                                        NULL, 0);
1051  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket);
1052  mock_socket_factory_.AddSocketDataProvider(&data_socket1);
1053  FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1054
1055  // Start the transaction.
1056  ASSERT_EQ(ERR_IO_PENDING,
1057            transaction_.Start(&request_info, callback_.callback(),
1058                               BoundNetLog()));
1059  ASSERT_EQ(OK, callback_.WaitForResult());
1060
1061  // The transaction fires the callback when we can start reading data. That
1062  // means that the data socket should be open.
1063  MockTCPClientSocket* data_socket =
1064      static_cast<MockTCPClientSocket*>(transaction_.data_socket_.get());
1065  ASSERT_TRUE(data_socket);
1066  ASSERT_TRUE(data_socket->IsConnected());
1067
1068  // Even if the PASV response specified some other address, we connect
1069  // to the address we used for control connection (which could be 127.0.0.1
1070  // or ::1 depending on whether we use IPv6).
1071  for (AddressList::const_iterator it = data_socket->addresses().begin();
1072      it != data_socket->addresses().end(); ++it) {
1073    EXPECT_NE("10.1.2.3", it->ToStringWithoutPort());
1074  }
1075}
1076
1077TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat1) {
1078  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||22)\r\n",
1079                                            FtpSocketDataProvider::PRE_QUIT);
1080  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1081}
1082
1083TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat2) {
1084  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (||\r\n",
1085                                            FtpSocketDataProvider::PRE_QUIT);
1086  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1087}
1088
1089TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat3) {
1090  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan\r\n",
1091                                            FtpSocketDataProvider::PRE_QUIT);
1092  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1093}
1094
1095TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat4) {
1096  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (||||)\r\n",
1097                                            FtpSocketDataProvider::PRE_QUIT);
1098  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1099}
1100
1101TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat5) {
1102  const char response[] = "227 Portscan (\0\0\031773\0)\r\n";
1103  FtpSocketDataProviderEvilEpsv ctrl_socket(response, sizeof(response)-1,
1104                                            FtpSocketDataProvider::PRE_QUIT);
1105  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1106}
1107
1108TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort1) {
1109  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||22|)\r\n",
1110                                            FtpSocketDataProvider::PRE_QUIT);
1111  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1112}
1113
1114TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort2) {
1115  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||258|)\r\n",
1116                                            FtpSocketDataProvider::PRE_QUIT);
1117  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1118}
1119
1120TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort3) {
1121  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||772|)\r\n",
1122                                            FtpSocketDataProvider::PRE_QUIT);
1123  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1124}
1125
1126TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort4) {
1127  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||2049|)\r\n",
1128                                            FtpSocketDataProvider::PRE_QUIT);
1129  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1130}
1131
1132TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvWeirdSep) {
1133  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan ($$$31744$)\r\n",
1134                                            FtpSocketDataProvider::PRE_SIZE);
1135  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1136}
1137
1138TEST_F(FtpNetworkTransactionTest,
1139       DownloadTransactionEvilEpsvWeirdSepUnsafePort) {
1140  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan ($$$317$)\r\n",
1141                                            FtpSocketDataProvider::PRE_QUIT);
1142  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1143}
1144
1145TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvIllegalHost) {
1146  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|2|::1|31744|)\r\n",
1147                                            FtpSocketDataProvider::PRE_QUIT);
1148  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1149}
1150
1151TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilLoginBadUsername) {
1152  FtpSocketDataProviderEvilLogin ctrl_socket("hello%0Aworld", "test");
1153  ExecuteTransaction(&ctrl_socket, "ftp://hello%0Aworld:test@host/file", OK);
1154}
1155
1156TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilLoginBadPassword) {
1157  FtpSocketDataProviderEvilLogin ctrl_socket("test", "hello%0Dworld");
1158  ExecuteTransaction(&ctrl_socket, "ftp://test:hello%0Dworld@host/file", OK);
1159}
1160
1161TEST_F(FtpNetworkTransactionTest, DownloadTransactionSpaceInLogin) {
1162  FtpSocketDataProviderEvilLogin ctrl_socket("hello world", "test");
1163  ExecuteTransaction(&ctrl_socket, "ftp://hello%20world:test@host/file", OK);
1164}
1165
1166TEST_F(FtpNetworkTransactionTest, DownloadTransactionSpaceInPassword) {
1167  FtpSocketDataProviderEvilLogin ctrl_socket("test", "hello world");
1168  ExecuteTransaction(&ctrl_socket, "ftp://test:hello%20world@host/file", OK);
1169}
1170
1171TEST_F(FtpNetworkTransactionTest, EvilRestartUser) {
1172  FtpSocketDataProvider ctrl_socket1;
1173  ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
1174                             FtpSocketDataProvider::PRE_QUIT,
1175                             "530 Login authentication failed\r\n");
1176  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket1);
1177
1178  FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1179
1180  ASSERT_EQ(ERR_IO_PENDING,
1181            transaction_.Start(&request_info, callback_.callback(),
1182                               BoundNetLog()));
1183  ASSERT_EQ(ERR_FTP_FAILED, callback_.WaitForResult());
1184
1185  MockRead ctrl_reads[] = {
1186    MockRead("220 host TestFTPd\r\n"),
1187    MockRead("221 Goodbye!\r\n"),
1188    MockRead(SYNCHRONOUS, OK),
1189  };
1190  MockWrite ctrl_writes[] = {
1191    MockWrite("QUIT\r\n"),
1192  };
1193  StaticSocketDataProvider ctrl_socket2(ctrl_reads, arraysize(ctrl_reads),
1194                                        ctrl_writes, arraysize(ctrl_writes));
1195  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket2);
1196  ASSERT_EQ(ERR_IO_PENDING,
1197            transaction_.RestartWithAuth(
1198                AuthCredentials(
1199                    ASCIIToUTF16("foo\nownz0red"),
1200                    ASCIIToUTF16("innocent")),
1201                callback_.callback()));
1202  EXPECT_EQ(ERR_MALFORMED_IDENTITY, callback_.WaitForResult());
1203}
1204
1205TEST_F(FtpNetworkTransactionTest, EvilRestartPassword) {
1206  FtpSocketDataProvider ctrl_socket1;
1207  ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
1208                             FtpSocketDataProvider::PRE_QUIT,
1209                             "530 Login authentication failed\r\n");
1210  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket1);
1211
1212  FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1213
1214  ASSERT_EQ(ERR_IO_PENDING,
1215            transaction_.Start(&request_info, callback_.callback(),
1216                               BoundNetLog()));
1217  ASSERT_EQ(ERR_FTP_FAILED, callback_.WaitForResult());
1218
1219  MockRead ctrl_reads[] = {
1220    MockRead("220 host TestFTPd\r\n"),
1221    MockRead("331 User okay, send password\r\n"),
1222    MockRead("221 Goodbye!\r\n"),
1223    MockRead(SYNCHRONOUS, OK),
1224  };
1225  MockWrite ctrl_writes[] = {
1226    MockWrite("USER innocent\r\n"),
1227    MockWrite("QUIT\r\n"),
1228  };
1229  StaticSocketDataProvider ctrl_socket2(ctrl_reads, arraysize(ctrl_reads),
1230                                        ctrl_writes, arraysize(ctrl_writes));
1231  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket2);
1232  ASSERT_EQ(ERR_IO_PENDING,
1233            transaction_.RestartWithAuth(
1234                AuthCredentials(ASCIIToUTF16("innocent"),
1235                                ASCIIToUTF16("foo\nownz0red")),
1236                callback_.callback()));
1237  EXPECT_EQ(ERR_MALFORMED_IDENTITY, callback_.WaitForResult());
1238}
1239
1240TEST_F(FtpNetworkTransactionTest, Escaping) {
1241  FtpSocketDataProviderEscaping ctrl_socket;
1242  ExecuteTransaction(&ctrl_socket, "ftp://host/%20%21%22%23%24%25%79%80%81",
1243                     OK);
1244}
1245
1246// Test for http://crbug.com/23794.
1247TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilSize) {
1248  // Try to overflow int64 in the response.
1249  FtpSocketDataProviderEvilSize ctrl_socket(
1250      "213 99999999999999999999999999999999\r\n",
1251      FtpSocketDataProvider::PRE_QUIT);
1252  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1253}
1254
1255// Test for http://crbug.com/36360.
1256TEST_F(FtpNetworkTransactionTest, DownloadTransactionBigSize) {
1257  // Pass a valid, but large file size. The transaction should not fail.
1258  FtpSocketDataProviderEvilSize ctrl_socket(
1259      "213 3204427776\r\n",
1260      FtpSocketDataProvider::PRE_CWD);
1261  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1262  EXPECT_EQ(3204427776LL,
1263            transaction_.GetResponseInfo()->expected_content_size);
1264}
1265
1266// Regression test for http://crbug.com/25023.
1267TEST_F(FtpNetworkTransactionTest, CloseConnection) {
1268  FtpSocketDataProviderCloseConnection ctrl_socket;
1269  ExecuteTransaction(&ctrl_socket, "ftp://host", ERR_EMPTY_RESPONSE);
1270}
1271
1272TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailUser) {
1273  FtpSocketDataProviderDirectoryListing ctrl_socket;
1274  // Use unallocated 599 FTP error code to make sure it falls into the generic
1275  // ERR_FTP_FAILED bucket.
1276  TransactionFailHelper(&ctrl_socket,
1277                        "ftp://host",
1278                        FtpSocketDataProvider::PRE_USER,
1279                        FtpSocketDataProvider::PRE_QUIT,
1280                        "599 fail\r\n",
1281                        ERR_FTP_FAILED);
1282}
1283
1284TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPass) {
1285  FtpSocketDataProviderDirectoryListing ctrl_socket;
1286  TransactionFailHelper(&ctrl_socket,
1287                        "ftp://host",
1288                        FtpSocketDataProvider::PRE_PASSWD,
1289                        FtpSocketDataProvider::PRE_QUIT,
1290                        "530 Login authentication failed\r\n",
1291                        ERR_FTP_FAILED);
1292}
1293
1294// Regression test for http://crbug.com/38707.
1295TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPass503) {
1296  FtpSocketDataProviderDirectoryListing ctrl_socket;
1297  TransactionFailHelper(&ctrl_socket,
1298                        "ftp://host",
1299                        FtpSocketDataProvider::PRE_PASSWD,
1300                        FtpSocketDataProvider::PRE_QUIT,
1301                        "503 Bad sequence of commands\r\n",
1302                        ERR_FTP_BAD_COMMAND_SEQUENCE);
1303}
1304
1305TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailSyst) {
1306  FtpSocketDataProviderDirectoryListing ctrl_socket;
1307  // Use unallocated 599 FTP error code to make sure it falls into the generic
1308  // ERR_FTP_FAILED bucket.
1309  TransactionFailHelper(&ctrl_socket,
1310                        "ftp://host",
1311                        FtpSocketDataProvider::PRE_SYST,
1312                        FtpSocketDataProvider::PRE_PWD,
1313                        "599 fail\r\n",
1314                        OK);
1315}
1316
1317TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPwd) {
1318  FtpSocketDataProviderDirectoryListing ctrl_socket;
1319  // Use unallocated 599 FTP error code to make sure it falls into the generic
1320  // ERR_FTP_FAILED bucket.
1321  TransactionFailHelper(&ctrl_socket,
1322                        "ftp://host",
1323                        FtpSocketDataProvider::PRE_PWD,
1324                        FtpSocketDataProvider::PRE_QUIT,
1325                        "599 fail\r\n",
1326                        ERR_FTP_FAILED);
1327}
1328
1329TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailType) {
1330  FtpSocketDataProviderDirectoryListing ctrl_socket;
1331  // Use unallocated 599 FTP error code to make sure it falls into the generic
1332  // ERR_FTP_FAILED bucket.
1333  TransactionFailHelper(&ctrl_socket,
1334                        "ftp://host",
1335                        FtpSocketDataProvider::PRE_TYPE,
1336                        FtpSocketDataProvider::PRE_QUIT,
1337                        "599 fail\r\n",
1338                        ERR_FTP_FAILED);
1339}
1340
1341TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailEpsv) {
1342  FtpSocketDataProviderDirectoryListing ctrl_socket;
1343  // Use unallocated 599 FTP error code to make sure it falls into the generic
1344  // ERR_FTP_FAILED bucket.
1345  TransactionFailHelper(&ctrl_socket,
1346                        "ftp://host",
1347                        FtpSocketDataProvider::PRE_EPSV,
1348                        FtpSocketDataProvider::PRE_NOPASV,
1349                        "599 fail\r\n",
1350                        ERR_FTP_FAILED);
1351}
1352
1353TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailCwd) {
1354  FtpSocketDataProviderDirectoryListing ctrl_socket;
1355  // Use unallocated 599 FTP error code to make sure it falls into the generic
1356  // ERR_FTP_FAILED bucket.
1357  TransactionFailHelper(&ctrl_socket,
1358                        "ftp://host",
1359                        FtpSocketDataProvider::PRE_CWD,
1360                        FtpSocketDataProvider::PRE_QUIT,
1361                        "599 fail\r\n",
1362                        ERR_FTP_FAILED);
1363}
1364
1365TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) {
1366  FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
1367  // Use unallocated 599 FTP error code to make sure it falls into the generic
1368  // ERR_FTP_FAILED bucket.
1369  TransactionFailHelper(&ctrl_socket,
1370                        "ftp://host/dir",
1371                        FtpSocketDataProvider::PRE_LIST,
1372                        FtpSocketDataProvider::PRE_QUIT,
1373                        "599 fail\r\n",
1374                        ERR_FTP_FAILED);
1375}
1376
1377TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailUser) {
1378  FtpSocketDataProviderFileDownload ctrl_socket;
1379  // Use unallocated 599 FTP error code to make sure it falls into the generic
1380  // ERR_FTP_FAILED bucket.
1381  TransactionFailHelper(&ctrl_socket,
1382                        "ftp://host/file",
1383                        FtpSocketDataProvider::PRE_USER,
1384                        FtpSocketDataProvider::PRE_QUIT,
1385                        "599 fail\r\n",
1386                        ERR_FTP_FAILED);
1387}
1388
1389TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPass) {
1390  FtpSocketDataProviderFileDownload ctrl_socket;
1391  TransactionFailHelper(&ctrl_socket,
1392                        "ftp://host/file",
1393                        FtpSocketDataProvider::PRE_PASSWD,
1394                        FtpSocketDataProvider::PRE_QUIT,
1395                        "530 Login authentication failed\r\n",
1396                        ERR_FTP_FAILED);
1397}
1398
1399TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailSyst) {
1400  FtpSocketDataProviderFileDownload ctrl_socket;
1401  // Use unallocated 599 FTP error code to make sure it falls into the generic
1402  // ERR_FTP_FAILED bucket.
1403  TransactionFailHelper(&ctrl_socket,
1404                        "ftp://host/file",
1405                        FtpSocketDataProvider::PRE_SYST,
1406                        FtpSocketDataProvider::PRE_PWD,
1407                        "599 fail\r\n",
1408                        OK);
1409}
1410
1411TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPwd) {
1412  FtpSocketDataProviderFileDownload ctrl_socket;
1413  // Use unallocated 599 FTP error code to make sure it falls into the generic
1414  // ERR_FTP_FAILED bucket.
1415  TransactionFailHelper(&ctrl_socket,
1416                        "ftp://host/file",
1417                        FtpSocketDataProvider::PRE_PWD,
1418                        FtpSocketDataProvider::PRE_QUIT,
1419                        "599 fail\r\n",
1420                        ERR_FTP_FAILED);
1421}
1422
1423TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailType) {
1424  FtpSocketDataProviderFileDownload ctrl_socket;
1425  // Use unallocated 599 FTP error code to make sure it falls into the generic
1426  // ERR_FTP_FAILED bucket.
1427  TransactionFailHelper(&ctrl_socket,
1428                        "ftp://host/file",
1429                        FtpSocketDataProvider::PRE_TYPE,
1430                        FtpSocketDataProvider::PRE_QUIT,
1431                        "599 fail\r\n",
1432                        ERR_FTP_FAILED);
1433}
1434
1435TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailEpsv) {
1436  FtpSocketDataProviderFileDownload ctrl_socket;
1437  // Use unallocated 599 FTP error code to make sure it falls into the generic
1438  // ERR_FTP_FAILED bucket.
1439  TransactionFailHelper(&ctrl_socket,
1440                        "ftp://host/file",
1441                        FtpSocketDataProvider::PRE_EPSV,
1442                        FtpSocketDataProvider::PRE_NOPASV,
1443                        "599 fail\r\n",
1444                        ERR_FTP_FAILED);
1445}
1446
1447TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailRetr) {
1448  FtpSocketDataProviderFileDownload ctrl_socket;
1449  // Use unallocated 599 FTP error code to make sure it falls into the generic
1450  // ERR_FTP_FAILED bucket.
1451  TransactionFailHelper(&ctrl_socket,
1452                        "ftp://host/file",
1453                        FtpSocketDataProvider::PRE_RETR,
1454                        FtpSocketDataProvider::PRE_QUIT,
1455                        "599 fail\r\n",
1456                        ERR_FTP_FAILED);
1457}
1458
1459TEST_F(FtpNetworkTransactionTest, FileNotFound) {
1460  FtpSocketDataProviderFileNotFound ctrl_socket;
1461  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_FTP_FAILED);
1462}
1463
1464// Test for http://crbug.com/38845.
1465TEST_F(FtpNetworkTransactionTest, ZeroLengthDirInPWD) {
1466  FtpSocketDataProviderFileDownload ctrl_socket;
1467  TransactionFailHelper(&ctrl_socket,
1468                        "ftp://host/file",
1469                        FtpSocketDataProvider::PRE_PWD,
1470                        FtpSocketDataProvider::PRE_TYPE,
1471                        "257 \"\"\r\n",
1472                        OK);
1473}
1474
1475}  // namespace net
1476