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