1// Copyright (c) 2011 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/memory/ref_counted.h"
10#include "base/string_util.h"
11#include "base/utf_string_conversions.h"
12#include "net/base/host_port_pair.h"
13#include "net/base/io_buffer.h"
14#include "net/base/mock_host_resolver.h"
15#include "net/base/net_util.h"
16#include "net/base/sys_addrinfo.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) {
61    if (InjectFault())
62      return MockWriteResult(true, 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(true, 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() {
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(true, data.length());
151    }
152    return MockWriteResult(true, 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) {
185    if (InjectFault())
186      return MockWriteResult(true, 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) {
211    if (InjectFault())
212      return MockWriteResult(true, 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) {
237    if (InjectFault())
238      return MockWriteResult(true, 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) {
257    if (InjectFault())
258      return MockWriteResult(true, 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) {
294    if (InjectFault())
295      return MockWriteResult(true, 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) {
333    if (InjectFault())
334      return MockWriteResult(true, 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) {
356    if (InjectFault())
357      return MockWriteResult(true, 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) {
382    if (InjectFault())
383      return MockWriteResult(true, 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) {
410    if (InjectFault())
411      return MockWriteResult(true, 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) {
435    if (InjectFault())
436      return MockWriteResult(true, 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 FtpSocketDataProviderVMSFileDownload : public FtpSocketDataProvider {
454 public:
455  FtpSocketDataProviderVMSFileDownload() {
456  }
457
458  virtual MockWriteResult OnWrite(const std::string& data) {
459    if (InjectFault())
460      return MockWriteResult(true, data.length());
461    switch (state()) {
462      case PRE_SYST:
463        return Verify("SYST\r\n", data, PRE_PWD, "215 VMS\r\n");
464      case PRE_PWD:
465        return Verify("PWD\r\n", data, PRE_TYPE,
466                      "257 \"ANONYMOUS_ROOT:[000000]\"\r\n");
467      case PRE_EPSV:
468        return Verify("EPSV\r\n", data, PRE_PASV,
469                      "500 EPSV command unknown\r\n");
470      case PRE_PASV:
471        return Verify("PASV\r\n", data, PRE_SIZE,
472                      "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
473      case PRE_SIZE:
474        return Verify("SIZE ANONYMOUS_ROOT:[000000]file\r\n", data, PRE_CWD,
475                      "213 18\r\n");
476      case PRE_CWD:
477        return Verify("CWD ANONYMOUS_ROOT:[file]\r\n", data, PRE_RETR,
478                      "550 Not a directory\r\n");
479      case PRE_RETR:
480        return Verify("RETR ANONYMOUS_ROOT:[000000]file\r\n", data, PRE_QUIT,
481                      "200 OK\r\n");
482      default:
483        return FtpSocketDataProvider::OnWrite(data);
484    }
485  }
486
487 private:
488  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderVMSFileDownload);
489};
490
491class FtpSocketDataProviderEscaping : public FtpSocketDataProviderFileDownload {
492 public:
493  FtpSocketDataProviderEscaping() {
494  }
495
496  virtual MockWriteResult OnWrite(const std::string& data) {
497    if (InjectFault())
498      return MockWriteResult(true, data.length());
499    switch (state()) {
500      case PRE_SIZE:
501        return Verify("SIZE / !\"#$%y\200\201\r\n", data, PRE_CWD,
502                      "213 18\r\n");
503      case PRE_CWD:
504        return Verify("CWD / !\"#$%y\200\201\r\n", data, PRE_RETR,
505                      "550 Not a directory\r\n");
506      case PRE_RETR:
507        return Verify("RETR / !\"#$%y\200\201\r\n", data, PRE_QUIT,
508                      "200 OK\r\n");
509      default:
510        return FtpSocketDataProviderFileDownload::OnWrite(data);
511    }
512  }
513
514 private:
515  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEscaping);
516};
517
518class FtpSocketDataProviderFileDownloadTransferStarting
519    : public FtpSocketDataProviderFileDownload {
520 public:
521  FtpSocketDataProviderFileDownloadTransferStarting() {
522  }
523
524  virtual MockWriteResult OnWrite(const std::string& data) {
525    if (InjectFault())
526      return MockWriteResult(true, data.length());
527    switch (state()) {
528      case PRE_RETR:
529        return Verify("RETR /file\r\n", data, PRE_QUIT,
530                      "125-Data connection already open.\r\n"
531                      "125  Transfer starting.\r\n"
532                      "226 Transfer complete.\r\n");
533      default:
534        return FtpSocketDataProviderFileDownload::OnWrite(data);
535    }
536  }
537
538 private:
539  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadTransferStarting);
540};
541
542class FtpSocketDataProviderDirectoryListingTransferStarting
543    : public FtpSocketDataProviderDirectoryListing {
544 public:
545  FtpSocketDataProviderDirectoryListingTransferStarting() {
546  }
547
548  virtual MockWriteResult OnWrite(const std::string& data) {
549    if (InjectFault())
550      return MockWriteResult(true, data.length());
551    switch (state()) {
552      case PRE_LIST:
553        return Verify("LIST\r\n", data, PRE_QUIT,
554                      "125-Data connection already open.\r\n"
555                      "125  Transfer starting.\r\n"
556                      "226 Transfer complete.\r\n");
557      default:
558        return FtpSocketDataProviderDirectoryListing::OnWrite(data);
559    }
560  }
561
562 private:
563  DISALLOW_COPY_AND_ASSIGN(
564      FtpSocketDataProviderDirectoryListingTransferStarting);
565};
566
567class FtpSocketDataProviderFileDownloadInvalidResponse
568    : public FtpSocketDataProviderFileDownload {
569 public:
570  FtpSocketDataProviderFileDownloadInvalidResponse() {
571  }
572
573  virtual MockWriteResult OnWrite(const std::string& data) {
574    if (InjectFault())
575      return MockWriteResult(true, data.length());
576    switch (state()) {
577      case PRE_SIZE:
578        // Use unallocated 599 FTP error code to make sure it falls into the
579        // generic ERR_FTP_FAILED bucket.
580        return Verify("SIZE /file\r\n", data, PRE_QUIT,
581                      "599 Evil Response\r\n"
582                      "599 More Evil\r\n");
583      default:
584        return FtpSocketDataProviderFileDownload::OnWrite(data);
585    }
586  }
587
588 private:
589  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadInvalidResponse);
590};
591
592class FtpSocketDataProviderEvilEpsv : public FtpSocketDataProviderFileDownload {
593 public:
594  FtpSocketDataProviderEvilEpsv(const char* epsv_response,
595                                State expected_state)
596      : epsv_response_(epsv_response),
597        epsv_response_length_(std::strlen(epsv_response)),
598        expected_state_(expected_state) {}
599
600  FtpSocketDataProviderEvilEpsv(const char* epsv_response,
601                               size_t epsv_response_length,
602                               State expected_state)
603      : epsv_response_(epsv_response),
604        epsv_response_length_(epsv_response_length),
605        expected_state_(expected_state) {}
606
607  virtual MockWriteResult OnWrite(const std::string& data) {
608    if (InjectFault())
609      return MockWriteResult(true, data.length());
610    switch (state()) {
611      case PRE_EPSV:
612        return Verify("EPSV\r\n", data, expected_state_,
613                      epsv_response_, epsv_response_length_);
614      default:
615        return FtpSocketDataProviderFileDownload::OnWrite(data);
616    }
617  }
618
619 private:
620  const char* epsv_response_;
621  const size_t epsv_response_length_;
622  const State expected_state_;
623
624  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilEpsv);
625};
626
627class FtpSocketDataProviderEvilPasv
628    : public FtpSocketDataProviderFileDownloadWithPasvFallback {
629 public:
630  explicit FtpSocketDataProviderEvilPasv(const char* pasv_response,
631                                         State expected_state)
632      : pasv_response_(pasv_response),
633        expected_state_(expected_state) {
634  }
635
636  virtual MockWriteResult OnWrite(const std::string& data) {
637    if (InjectFault())
638      return MockWriteResult(true, data.length());
639    switch (state()) {
640      case PRE_PASV:
641        return Verify("PASV\r\n", data, expected_state_, pasv_response_);
642      default:
643        return FtpSocketDataProviderFileDownloadWithPasvFallback::OnWrite(data);
644    }
645  }
646
647 private:
648  const char* pasv_response_;
649  const State expected_state_;
650
651  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilPasv);
652};
653
654class FtpSocketDataProviderEvilSize : public FtpSocketDataProviderFileDownload {
655 public:
656  FtpSocketDataProviderEvilSize(const char* size_response, State expected_state)
657      : size_response_(size_response),
658        expected_state_(expected_state) {
659  }
660
661  virtual MockWriteResult OnWrite(const std::string& data) {
662    if (InjectFault())
663      return MockWriteResult(true, data.length());
664    switch (state()) {
665      case PRE_SIZE:
666        return Verify("SIZE /file\r\n", data, expected_state_, size_response_);
667      default:
668        return FtpSocketDataProviderFileDownload::OnWrite(data);
669    }
670  }
671
672 private:
673  const char* size_response_;
674  const State expected_state_;
675
676  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilSize);
677};
678
679class FtpSocketDataProviderEvilLogin
680    : public FtpSocketDataProviderFileDownload {
681 public:
682  FtpSocketDataProviderEvilLogin(const char* expected_user,
683                                const char* expected_password)
684      : expected_user_(expected_user),
685        expected_password_(expected_password) {
686  }
687
688  virtual MockWriteResult OnWrite(const std::string& data) {
689    if (InjectFault())
690      return MockWriteResult(true, data.length());
691    switch (state()) {
692      case PRE_USER:
693        return Verify(std::string("USER ") + expected_user_ + "\r\n", data,
694                      PRE_PASSWD, "331 Password needed\r\n");
695      case PRE_PASSWD:
696        return Verify(std::string("PASS ") + expected_password_ + "\r\n", data,
697                      PRE_SYST, "230 Welcome\r\n");
698      default:
699        return FtpSocketDataProviderFileDownload::OnWrite(data);
700    }
701  }
702
703 private:
704  const char* expected_user_;
705  const char* expected_password_;
706
707  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilLogin);
708};
709
710class FtpSocketDataProviderCloseConnection : public FtpSocketDataProvider {
711 public:
712  FtpSocketDataProviderCloseConnection() {
713  }
714
715  virtual MockWriteResult OnWrite(const std::string& data) {
716    if (InjectFault())
717      return MockWriteResult(true, data.length());
718    switch (state()) {
719      case PRE_USER:
720        return Verify("USER anonymous\r\n", data,
721                      PRE_QUIT, "");
722      default:
723        return FtpSocketDataProvider::OnWrite(data);
724    }
725  }
726
727 private:
728  DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderCloseConnection);
729};
730
731class FtpNetworkTransactionTest : public PlatformTest {
732 public:
733  FtpNetworkTransactionTest()
734      : host_resolver_(new MockHostResolver),
735        session_(new FtpNetworkSession(host_resolver_.get())),
736        transaction_(session_.get(), &mock_socket_factory_) {
737  }
738
739 protected:
740  FtpRequestInfo GetRequestInfo(const std::string& url) {
741    FtpRequestInfo info;
742    info.url = GURL(url);
743    return info;
744  }
745
746  void ExecuteTransaction(FtpSocketDataProvider* ctrl_socket,
747                          const char* request,
748                          int expected_result) {
749    std::string mock_data("mock-data");
750    MockRead data_reads[] = {
751      // Usually FTP servers close the data connection after the entire data has
752      // been received.
753      MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
754      MockRead(mock_data.c_str()),
755    };
756    StaticSocketDataProvider data_socket(data_reads, arraysize(data_reads),
757                                         NULL, 0);
758    mock_socket_factory_.AddSocketDataProvider(ctrl_socket);
759    mock_socket_factory_.AddSocketDataProvider(&data_socket);
760    FtpRequestInfo request_info = GetRequestInfo(request);
761    EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
762    ASSERT_EQ(ERR_IO_PENDING,
763              transaction_.Start(&request_info, &callback_, BoundNetLog()));
764    EXPECT_NE(LOAD_STATE_IDLE, transaction_.GetLoadState());
765    ASSERT_EQ(expected_result, callback_.WaitForResult());
766    if (expected_result == OK) {
767      scoped_refptr<IOBuffer> io_buffer(new IOBuffer(kBufferSize));
768      memset(io_buffer->data(), 0, kBufferSize);
769      ASSERT_EQ(ERR_IO_PENDING,
770                transaction_.Read(io_buffer.get(), kBufferSize, &callback_));
771      ASSERT_EQ(static_cast<int>(mock_data.length()),
772                callback_.WaitForResult());
773      EXPECT_EQ(mock_data, std::string(io_buffer->data(), mock_data.length()));
774
775      // Do another Read to detect that the data socket is now closed.
776      int rv = transaction_.Read(io_buffer.get(), kBufferSize, &callback_);
777      if (rv == ERR_IO_PENDING) {
778        EXPECT_EQ(0, callback_.WaitForResult());
779      } else {
780        EXPECT_EQ(0, rv);
781      }
782    }
783    EXPECT_EQ(FtpSocketDataProvider::QUIT, ctrl_socket->state());
784    EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
785  }
786
787  void TransactionFailHelper(FtpSocketDataProvider* ctrl_socket,
788                             const char* request,
789                             FtpSocketDataProvider::State state,
790                             FtpSocketDataProvider::State next_state,
791                             const char* response,
792                             int expected_result) {
793    ctrl_socket->InjectFailure(state, next_state, response);
794    ExecuteTransaction(ctrl_socket, request, expected_result);
795  }
796
797  scoped_ptr<MockHostResolver> host_resolver_;
798  scoped_refptr<FtpNetworkSession> session_;
799  MockClientSocketFactory mock_socket_factory_;
800  FtpNetworkTransaction transaction_;
801  TestCompletionCallback callback_;
802};
803
804TEST_F(FtpNetworkTransactionTest, FailedLookup) {
805  FtpRequestInfo request_info = GetRequestInfo("ftp://badhost");
806  host_resolver_->rules()->AddSimulatedFailure("badhost");
807  EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
808  ASSERT_EQ(ERR_IO_PENDING,
809            transaction_.Start(&request_info, &callback_, BoundNetLog()));
810  ASSERT_EQ(ERR_NAME_NOT_RESOLVED, callback_.WaitForResult());
811  EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
812}
813
814// Check that when determining the host, the square brackets decorating IPv6
815// literals in URLs are stripped.
816TEST_F(FtpNetworkTransactionTest, StripBracketsFromIPv6Literals) {
817  host_resolver_->rules()->AddSimulatedFailure("[::1]");
818
819  // We start a transaction that is expected to fail with ERR_INVALID_RESPONSE.
820  // The important part of this test is to make sure that we don't fail with
821  // ERR_NAME_NOT_RESOLVED, since that would mean the decorated hostname
822  // was used.
823  FtpSocketDataProviderEvilSize ctrl_socket(
824      "213 99999999999999999999999999999999\r\n",
825      FtpSocketDataProvider::PRE_QUIT);
826  ExecuteTransaction(&ctrl_socket, "ftp://[::1]/file", ERR_INVALID_RESPONSE);
827}
828
829TEST_F(FtpNetworkTransactionTest, DirectoryTransaction) {
830  FtpSocketDataProviderDirectoryListing ctrl_socket;
831  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
832
833  EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
834  EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
835  EXPECT_EQ("192.0.2.33",
836            transaction_.GetResponseInfo()->socket_address.host());
837  EXPECT_EQ(0, transaction_.GetResponseInfo()->socket_address.port());
838}
839
840TEST_F(FtpNetworkTransactionTest, DirectoryTransactionWithPasvFallback) {
841  FtpSocketDataProviderDirectoryListingWithPasvFallback ctrl_socket;
842  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
843
844  EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
845  EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
846}
847
848TEST_F(FtpNetworkTransactionTest, DirectoryTransactionWithTypecode) {
849  FtpSocketDataProviderDirectoryListing ctrl_socket;
850  ExecuteTransaction(&ctrl_socket, "ftp://host;type=d", OK);
851
852  EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
853  EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
854}
855
856TEST_F(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcome) {
857  FtpSocketDataProviderDirectoryListing ctrl_socket;
858  ctrl_socket.set_multiline_welcome(true);
859  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
860}
861
862TEST_F(FtpNetworkTransactionTest, DirectoryTransactionShortReads2) {
863  FtpSocketDataProviderDirectoryListing ctrl_socket;
864  ctrl_socket.set_short_read_limit(2);
865  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
866}
867
868TEST_F(FtpNetworkTransactionTest, DirectoryTransactionShortReads5) {
869  FtpSocketDataProviderDirectoryListing ctrl_socket;
870  ctrl_socket.set_short_read_limit(5);
871  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
872}
873
874TEST_F(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcomeShort) {
875  FtpSocketDataProviderDirectoryListing ctrl_socket;
876  // The client will not consume all three 230 lines. That's good, we want to
877  // test that scenario.
878  ctrl_socket.allow_unconsumed_reads(true);
879  ctrl_socket.set_multiline_welcome(true);
880  ctrl_socket.set_short_read_limit(5);
881  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
882}
883
884// Regression test for http://crbug.com/60555.
885TEST_F(FtpNetworkTransactionTest, DirectoryTransactionZeroSize) {
886  FtpSocketDataProviderDirectoryListingZeroSize ctrl_socket;
887  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
888}
889
890TEST_F(FtpNetworkTransactionTest, DirectoryTransactionVMS) {
891  FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
892  ExecuteTransaction(&ctrl_socket, "ftp://host/dir", OK);
893}
894
895TEST_F(FtpNetworkTransactionTest, DirectoryTransactionVMSRootDirectory) {
896  FtpSocketDataProviderVMSDirectoryListingRootDirectory ctrl_socket;
897  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
898}
899
900TEST_F(FtpNetworkTransactionTest, DirectoryTransactionTransferStarting) {
901  FtpSocketDataProviderDirectoryListingTransferStarting ctrl_socket;
902  ExecuteTransaction(&ctrl_socket, "ftp://host", OK);
903}
904
905TEST_F(FtpNetworkTransactionTest, DownloadTransaction) {
906  FtpSocketDataProviderFileDownload ctrl_socket;
907  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
908
909  // We pass an artificial value of 18 as a response to the SIZE command.
910  EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
911  EXPECT_EQ("192.0.2.33",
912            transaction_.GetResponseInfo()->socket_address.host());
913  EXPECT_EQ(0, transaction_.GetResponseInfo()->socket_address.port());
914}
915
916TEST_F(FtpNetworkTransactionTest, DownloadTransactionWithPasvFallback) {
917  FtpSocketDataProviderFileDownloadWithPasvFallback ctrl_socket;
918  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
919
920  // We pass an artificial value of 18 as a response to the SIZE command.
921  EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
922}
923
924TEST_F(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeA) {
925  FtpSocketDataProviderFileDownloadWithFileTypecode ctrl_socket;
926  ctrl_socket.set_data_type('A');
927  ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=a", OK);
928
929  // We pass an artificial value of 18 as a response to the SIZE command.
930  EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
931}
932
933TEST_F(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeI) {
934  FtpSocketDataProviderFileDownloadWithFileTypecode ctrl_socket;
935  ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=i", OK);
936
937  // We pass an artificial value of 18 as a response to the SIZE command.
938  EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
939}
940
941TEST_F(FtpNetworkTransactionTest, DownloadTransactionMultilineWelcome) {
942  FtpSocketDataProviderFileDownload ctrl_socket;
943  ctrl_socket.set_multiline_welcome(true);
944  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
945}
946
947TEST_F(FtpNetworkTransactionTest, DownloadTransactionShortReads2) {
948  FtpSocketDataProviderFileDownload ctrl_socket;
949  ctrl_socket.set_short_read_limit(2);
950  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
951}
952
953TEST_F(FtpNetworkTransactionTest, DownloadTransactionShortReads5) {
954  FtpSocketDataProviderFileDownload ctrl_socket;
955  ctrl_socket.set_short_read_limit(5);
956  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
957}
958
959TEST_F(FtpNetworkTransactionTest, DownloadTransactionZeroSize) {
960  FtpSocketDataProviderFileDownloadZeroSize ctrl_socket;
961  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
962}
963
964TEST_F(FtpNetworkTransactionTest, DownloadTransactionVMS) {
965  FtpSocketDataProviderVMSFileDownload ctrl_socket;
966  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
967}
968
969TEST_F(FtpNetworkTransactionTest, DownloadTransactionTransferStarting) {
970  FtpSocketDataProviderFileDownloadTransferStarting ctrl_socket;
971  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
972}
973
974TEST_F(FtpNetworkTransactionTest, DownloadTransactionInvalidResponse) {
975  FtpSocketDataProviderFileDownloadInvalidResponse ctrl_socket;
976  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
977}
978
979TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvReallyBadFormat) {
980  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,\r\n",
981                                           FtpSocketDataProvider::PRE_QUIT);
982  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
983}
984
985TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort1) {
986  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,0,22)\r\n",
987                                           FtpSocketDataProvider::PRE_QUIT);
988  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
989}
990
991TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort2) {
992  // Still unsafe. 1 * 256 + 2 = 258, which is < 1024.
993  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,1,2)\r\n",
994                                           FtpSocketDataProvider::PRE_QUIT);
995  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
996}
997
998TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort3) {
999  // Still unsafe. 3 * 256 + 4 = 772, which is < 1024.
1000  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,3,4)\r\n",
1001                                           FtpSocketDataProvider::PRE_QUIT);
1002  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1003}
1004
1005TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafePort4) {
1006  // Unsafe. 8 * 256 + 1 = 2049, which is used by nfs.
1007  FtpSocketDataProviderEvilPasv ctrl_socket("227 Portscan (127,0,0,1,8,1)\r\n",
1008                                           FtpSocketDataProvider::PRE_QUIT);
1009  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1010}
1011
1012TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilPasvUnsafeHost) {
1013  FtpSocketDataProviderEvilPasv ctrl_socket(
1014      "227 Portscan (10,1,2,3,4,123,456)\r\n", FtpSocketDataProvider::PRE_SIZE);
1015  std::string mock_data("mock-data");
1016  MockRead data_reads[] = {
1017    MockRead(mock_data.c_str()),
1018  };
1019  StaticSocketDataProvider data_socket1(data_reads, arraysize(data_reads),
1020                                        NULL, 0);
1021  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket);
1022  mock_socket_factory_.AddSocketDataProvider(&data_socket1);
1023  FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1024
1025  // Start the transaction.
1026  ASSERT_EQ(ERR_IO_PENDING,
1027            transaction_.Start(&request_info, &callback_, BoundNetLog()));
1028  ASSERT_EQ(OK, callback_.WaitForResult());
1029
1030  // The transaction fires the callback when we can start reading data. That
1031  // means that the data socket should be open.
1032  MockTCPClientSocket* data_socket =
1033      mock_socket_factory_.GetMockTCPClientSocket(1);
1034  ASSERT_TRUE(data_socket);
1035  ASSERT_TRUE(data_socket->IsConnected());
1036
1037  // Even if the PASV response specified some other address, we connect
1038  // to the address we used for control connection (which could be 127.0.0.1
1039  // or ::1 depending on whether we use IPv6).
1040  const struct addrinfo* addrinfo = data_socket->addresses().head();
1041  while (addrinfo) {
1042    EXPECT_NE("1.2.3.4", NetAddressToString(addrinfo));
1043    addrinfo = addrinfo->ai_next;
1044  }
1045}
1046
1047TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat1) {
1048  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||22)\r\n",
1049                                            FtpSocketDataProvider::PRE_QUIT);
1050  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1051}
1052
1053TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat2) {
1054  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (||\r\n",
1055                                            FtpSocketDataProvider::PRE_QUIT);
1056  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1057}
1058
1059TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat3) {
1060  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan\r\n",
1061                                            FtpSocketDataProvider::PRE_QUIT);
1062  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1063}
1064
1065TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat4) {
1066  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (||||)\r\n",
1067                                            FtpSocketDataProvider::PRE_QUIT);
1068  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1069}
1070
1071TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvReallyBadFormat5) {
1072  const char response[] = "227 Portscan (\0\0\031773\0)\r\n";
1073  FtpSocketDataProviderEvilEpsv ctrl_socket(response, sizeof(response)-1,
1074                                            FtpSocketDataProvider::PRE_QUIT);
1075  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1076}
1077
1078TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort1) {
1079  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||22|)\r\n",
1080                                            FtpSocketDataProvider::PRE_QUIT);
1081  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1082}
1083
1084TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort2) {
1085  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||258|)\r\n",
1086                                            FtpSocketDataProvider::PRE_QUIT);
1087  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1088}
1089
1090TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort3) {
1091  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||772|)\r\n",
1092                                            FtpSocketDataProvider::PRE_QUIT);
1093  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1094}
1095
1096TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort4) {
1097  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||2049|)\r\n",
1098                                            FtpSocketDataProvider::PRE_QUIT);
1099  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1100}
1101
1102TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvWeirdSep) {
1103  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan ($$$31744$)\r\n",
1104                                            FtpSocketDataProvider::PRE_SIZE);
1105  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1106}
1107
1108TEST_F(FtpNetworkTransactionTest,
1109       DownloadTransactionEvilEpsvWeirdSepUnsafePort) {
1110  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan ($$$317$)\r\n",
1111                                            FtpSocketDataProvider::PRE_QUIT);
1112  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_UNSAFE_PORT);
1113}
1114
1115TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvIllegalHost) {
1116  FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|2|::1|31744|)\r\n",
1117                                            FtpSocketDataProvider::PRE_QUIT);
1118  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1119}
1120
1121TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilLoginBadUsername) {
1122  FtpSocketDataProviderEvilLogin ctrl_socket("hello%0Aworld", "test");
1123  ExecuteTransaction(&ctrl_socket, "ftp://hello%0Aworld:test@host/file", OK);
1124}
1125
1126TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilLoginBadPassword) {
1127  FtpSocketDataProviderEvilLogin ctrl_socket("test", "hello%0Dworld");
1128  ExecuteTransaction(&ctrl_socket, "ftp://test:hello%0Dworld@host/file", OK);
1129}
1130
1131TEST_F(FtpNetworkTransactionTest, DownloadTransactionSpaceInLogin) {
1132  FtpSocketDataProviderEvilLogin ctrl_socket("hello world", "test");
1133  ExecuteTransaction(&ctrl_socket, "ftp://hello%20world:test@host/file", OK);
1134}
1135
1136TEST_F(FtpNetworkTransactionTest, DownloadTransactionSpaceInPassword) {
1137  FtpSocketDataProviderEvilLogin ctrl_socket("test", "hello world");
1138  ExecuteTransaction(&ctrl_socket, "ftp://test:hello%20world@host/file", OK);
1139}
1140
1141TEST_F(FtpNetworkTransactionTest, EvilRestartUser) {
1142  FtpSocketDataProvider ctrl_socket1;
1143  ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
1144                             FtpSocketDataProvider::PRE_QUIT,
1145                             "530 Login authentication failed\r\n");
1146  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket1);
1147
1148  FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1149
1150  ASSERT_EQ(ERR_IO_PENDING,
1151            transaction_.Start(&request_info, &callback_, BoundNetLog()));
1152  ASSERT_EQ(ERR_FTP_FAILED, callback_.WaitForResult());
1153
1154  MockRead ctrl_reads[] = {
1155    MockRead("220 host TestFTPd\r\n"),
1156    MockRead("221 Goodbye!\r\n"),
1157    MockRead(false, OK),
1158  };
1159  MockWrite ctrl_writes[] = {
1160    MockWrite("QUIT\r\n"),
1161  };
1162  StaticSocketDataProvider ctrl_socket2(ctrl_reads, arraysize(ctrl_reads),
1163                                        ctrl_writes, arraysize(ctrl_writes));
1164  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket2);
1165  ASSERT_EQ(ERR_IO_PENDING,
1166            transaction_.RestartWithAuth(ASCIIToUTF16("foo\nownz0red"),
1167                                         ASCIIToUTF16("innocent"),
1168                                         &callback_));
1169  EXPECT_EQ(ERR_MALFORMED_IDENTITY, callback_.WaitForResult());
1170}
1171
1172TEST_F(FtpNetworkTransactionTest, EvilRestartPassword) {
1173  FtpSocketDataProvider ctrl_socket1;
1174  ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
1175                             FtpSocketDataProvider::PRE_QUIT,
1176                             "530 Login authentication failed\r\n");
1177  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket1);
1178
1179  FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1180
1181  ASSERT_EQ(ERR_IO_PENDING,
1182            transaction_.Start(&request_info, &callback_, BoundNetLog()));
1183  ASSERT_EQ(ERR_FTP_FAILED, callback_.WaitForResult());
1184
1185  MockRead ctrl_reads[] = {
1186    MockRead("220 host TestFTPd\r\n"),
1187    MockRead("331 User okay, send password\r\n"),
1188    MockRead("221 Goodbye!\r\n"),
1189    MockRead(false, OK),
1190  };
1191  MockWrite ctrl_writes[] = {
1192    MockWrite("USER innocent\r\n"),
1193    MockWrite("QUIT\r\n"),
1194  };
1195  StaticSocketDataProvider ctrl_socket2(ctrl_reads, arraysize(ctrl_reads),
1196                                        ctrl_writes, arraysize(ctrl_writes));
1197  mock_socket_factory_.AddSocketDataProvider(&ctrl_socket2);
1198  ASSERT_EQ(ERR_IO_PENDING,
1199            transaction_.RestartWithAuth(ASCIIToUTF16("innocent"),
1200                                         ASCIIToUTF16("foo\nownz0red"),
1201                                         &callback_));
1202  EXPECT_EQ(ERR_MALFORMED_IDENTITY, callback_.WaitForResult());
1203}
1204
1205TEST_F(FtpNetworkTransactionTest, Escaping) {
1206  FtpSocketDataProviderEscaping ctrl_socket;
1207  ExecuteTransaction(&ctrl_socket, "ftp://host/%20%21%22%23%24%25%79%80%81",
1208                     OK);
1209}
1210
1211// Test for http://crbug.com/23794.
1212TEST_F(FtpNetworkTransactionTest, DownloadTransactionEvilSize) {
1213  // Try to overflow int64 in the response.
1214  FtpSocketDataProviderEvilSize ctrl_socket(
1215      "213 99999999999999999999999999999999\r\n",
1216      FtpSocketDataProvider::PRE_QUIT);
1217  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_INVALID_RESPONSE);
1218}
1219
1220// Test for http://crbug.com/36360.
1221TEST_F(FtpNetworkTransactionTest, DownloadTransactionBigSize) {
1222  // Pass a valid, but large file size. The transaction should not fail.
1223  FtpSocketDataProviderEvilSize ctrl_socket(
1224      "213 3204427776\r\n",
1225      FtpSocketDataProvider::PRE_CWD);
1226  ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK);
1227  EXPECT_EQ(3204427776LL,
1228            transaction_.GetResponseInfo()->expected_content_size);
1229}
1230
1231// Regression test for http://crbug.com/25023.
1232TEST_F(FtpNetworkTransactionTest, CloseConnection) {
1233  FtpSocketDataProviderCloseConnection ctrl_socket;
1234  ExecuteTransaction(&ctrl_socket, "ftp://host", ERR_EMPTY_RESPONSE);
1235}
1236
1237TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailUser) {
1238  FtpSocketDataProviderDirectoryListing ctrl_socket;
1239  // Use unallocated 599 FTP error code to make sure it falls into the generic
1240  // ERR_FTP_FAILED bucket.
1241  TransactionFailHelper(&ctrl_socket,
1242                        "ftp://host",
1243                        FtpSocketDataProvider::PRE_USER,
1244                        FtpSocketDataProvider::PRE_QUIT,
1245                        "599 fail\r\n",
1246                        ERR_FTP_FAILED);
1247}
1248
1249TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPass) {
1250  FtpSocketDataProviderDirectoryListing ctrl_socket;
1251  TransactionFailHelper(&ctrl_socket,
1252                        "ftp://host",
1253                        FtpSocketDataProvider::PRE_PASSWD,
1254                        FtpSocketDataProvider::PRE_QUIT,
1255                        "530 Login authentication failed\r\n",
1256                        ERR_FTP_FAILED);
1257}
1258
1259// Regression test for http://crbug.com/38707.
1260TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPass503) {
1261  FtpSocketDataProviderDirectoryListing ctrl_socket;
1262  TransactionFailHelper(&ctrl_socket,
1263                        "ftp://host",
1264                        FtpSocketDataProvider::PRE_PASSWD,
1265                        FtpSocketDataProvider::PRE_QUIT,
1266                        "503 Bad sequence of commands\r\n",
1267                        ERR_FTP_BAD_COMMAND_SEQUENCE);
1268}
1269
1270TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailSyst) {
1271  FtpSocketDataProviderDirectoryListing ctrl_socket;
1272  // Use unallocated 599 FTP error code to make sure it falls into the generic
1273  // ERR_FTP_FAILED bucket.
1274  TransactionFailHelper(&ctrl_socket,
1275                        "ftp://host",
1276                        FtpSocketDataProvider::PRE_SYST,
1277                        FtpSocketDataProvider::PRE_PWD,
1278                        "599 fail\r\n",
1279                        OK);
1280}
1281
1282TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPwd) {
1283  FtpSocketDataProviderDirectoryListing ctrl_socket;
1284  // Use unallocated 599 FTP error code to make sure it falls into the generic
1285  // ERR_FTP_FAILED bucket.
1286  TransactionFailHelper(&ctrl_socket,
1287                        "ftp://host",
1288                        FtpSocketDataProvider::PRE_PWD,
1289                        FtpSocketDataProvider::PRE_QUIT,
1290                        "599 fail\r\n",
1291                        ERR_FTP_FAILED);
1292}
1293
1294TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailType) {
1295  FtpSocketDataProviderDirectoryListing ctrl_socket;
1296  // Use unallocated 599 FTP error code to make sure it falls into the generic
1297  // ERR_FTP_FAILED bucket.
1298  TransactionFailHelper(&ctrl_socket,
1299                        "ftp://host",
1300                        FtpSocketDataProvider::PRE_TYPE,
1301                        FtpSocketDataProvider::PRE_QUIT,
1302                        "599 fail\r\n",
1303                        ERR_FTP_FAILED);
1304}
1305
1306TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailEpsv) {
1307  FtpSocketDataProviderDirectoryListing ctrl_socket;
1308  // Use unallocated 599 FTP error code to make sure it falls into the generic
1309  // ERR_FTP_FAILED bucket.
1310  TransactionFailHelper(&ctrl_socket,
1311                        "ftp://host",
1312                        FtpSocketDataProvider::PRE_EPSV,
1313                        FtpSocketDataProvider::PRE_NOPASV,
1314                        "599 fail\r\n",
1315                        ERR_FTP_FAILED);
1316}
1317
1318TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailCwd) {
1319  FtpSocketDataProviderDirectoryListing ctrl_socket;
1320  // Use unallocated 599 FTP error code to make sure it falls into the generic
1321  // ERR_FTP_FAILED bucket.
1322  TransactionFailHelper(&ctrl_socket,
1323                        "ftp://host",
1324                        FtpSocketDataProvider::PRE_CWD,
1325                        FtpSocketDataProvider::PRE_QUIT,
1326                        "599 fail\r\n",
1327                        ERR_FTP_FAILED);
1328}
1329
1330TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) {
1331  FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
1332  // Use unallocated 599 FTP error code to make sure it falls into the generic
1333  // ERR_FTP_FAILED bucket.
1334  TransactionFailHelper(&ctrl_socket,
1335                        "ftp://host/dir",
1336                        FtpSocketDataProvider::PRE_LIST,
1337                        FtpSocketDataProvider::PRE_QUIT,
1338                        "599 fail\r\n",
1339                        ERR_FTP_FAILED);
1340}
1341
1342TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailUser) {
1343  FtpSocketDataProviderFileDownload ctrl_socket;
1344  // Use unallocated 599 FTP error code to make sure it falls into the generic
1345  // ERR_FTP_FAILED bucket.
1346  TransactionFailHelper(&ctrl_socket,
1347                        "ftp://host/file",
1348                        FtpSocketDataProvider::PRE_USER,
1349                        FtpSocketDataProvider::PRE_QUIT,
1350                        "599 fail\r\n",
1351                        ERR_FTP_FAILED);
1352}
1353
1354TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPass) {
1355  FtpSocketDataProviderFileDownload ctrl_socket;
1356  TransactionFailHelper(&ctrl_socket,
1357                        "ftp://host/file",
1358                        FtpSocketDataProvider::PRE_PASSWD,
1359                        FtpSocketDataProvider::PRE_QUIT,
1360                        "530 Login authentication failed\r\n",
1361                        ERR_FTP_FAILED);
1362}
1363
1364TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailSyst) {
1365  FtpSocketDataProviderFileDownload ctrl_socket;
1366  // Use unallocated 599 FTP error code to make sure it falls into the generic
1367  // ERR_FTP_FAILED bucket.
1368  TransactionFailHelper(&ctrl_socket,
1369                        "ftp://host/file",
1370                        FtpSocketDataProvider::PRE_SYST,
1371                        FtpSocketDataProvider::PRE_PWD,
1372                        "599 fail\r\n",
1373                        OK);
1374}
1375
1376TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPwd) {
1377  FtpSocketDataProviderFileDownload ctrl_socket;
1378  // Use unallocated 599 FTP error code to make sure it falls into the generic
1379  // ERR_FTP_FAILED bucket.
1380  TransactionFailHelper(&ctrl_socket,
1381                        "ftp://host/file",
1382                        FtpSocketDataProvider::PRE_PWD,
1383                        FtpSocketDataProvider::PRE_QUIT,
1384                        "599 fail\r\n",
1385                        ERR_FTP_FAILED);
1386}
1387
1388TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailType) {
1389  FtpSocketDataProviderFileDownload ctrl_socket;
1390  // Use unallocated 599 FTP error code to make sure it falls into the generic
1391  // ERR_FTP_FAILED bucket.
1392  TransactionFailHelper(&ctrl_socket,
1393                        "ftp://host/file",
1394                        FtpSocketDataProvider::PRE_TYPE,
1395                        FtpSocketDataProvider::PRE_QUIT,
1396                        "599 fail\r\n",
1397                        ERR_FTP_FAILED);
1398}
1399
1400TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailEpsv) {
1401  FtpSocketDataProviderFileDownload ctrl_socket;
1402  // Use unallocated 599 FTP error code to make sure it falls into the generic
1403  // ERR_FTP_FAILED bucket.
1404  TransactionFailHelper(&ctrl_socket,
1405                        "ftp://host/file",
1406                        FtpSocketDataProvider::PRE_EPSV,
1407                        FtpSocketDataProvider::PRE_NOPASV,
1408                        "599 fail\r\n",
1409                        ERR_FTP_FAILED);
1410}
1411
1412TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailRetr) {
1413  FtpSocketDataProviderFileDownload ctrl_socket;
1414  // Use unallocated 599 FTP error code to make sure it falls into the generic
1415  // ERR_FTP_FAILED bucket.
1416  TransactionFailHelper(&ctrl_socket,
1417                        "ftp://host/file",
1418                        FtpSocketDataProvider::PRE_RETR,
1419                        FtpSocketDataProvider::PRE_QUIT,
1420                        "599 fail\r\n",
1421                        ERR_FTP_FAILED);
1422}
1423
1424TEST_F(FtpNetworkTransactionTest, FileNotFound) {
1425  FtpSocketDataProviderFileNotFound ctrl_socket;
1426  ExecuteTransaction(&ctrl_socket, "ftp://host/file", ERR_FTP_FAILED);
1427}
1428
1429// Test for http://crbug.com/38845.
1430TEST_F(FtpNetworkTransactionTest, ZeroLengthDirInPWD) {
1431  FtpSocketDataProviderFileDownload ctrl_socket;
1432  TransactionFailHelper(&ctrl_socket,
1433                        "ftp://host/file",
1434                        FtpSocketDataProvider::PRE_PWD,
1435                        FtpSocketDataProvider::PRE_TYPE,
1436                        "257 \"\"\r\n",
1437                        OK);
1438}
1439
1440}  // namespace net
1441