Roll src/third_party/WebKit 8121bc6:918aba1 (svn 188871:188878)
[chromium-blink-merge.git] / net / ftp / ftp_network_transaction_unittest.cc
blob4ee812dff413c43eedbcc068b23d883023c3bbc8
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.
5 #include "net/ftp/ftp_network_transaction.h"
7 #include "build/build_config.h"
9 #include "base/compiler_specific.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/strings/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"
25 namespace {
27 // Size we use for IOBuffers used to receive data from the test data socket.
28 const int kBufferSize = 128;
30 } // namespace
32 namespace net {
34 class 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
58 FtpSocketDataProvider()
59 : failure_injection_state_(NONE),
60 multiline_welcome_(false),
61 use_epsv_(true),
62 data_type_('I') {
63 Init();
66 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:
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);
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);
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;
130 State state() const {
131 return state_;
134 void Reset() override {
135 DynamicSocketDataProvider::Reset();
136 Init();
139 void set_multiline_welcome(bool multiline) { multiline_welcome_ = multiline; }
141 bool use_epsv() const { return use_epsv_; }
142 void set_use_epsv(bool use_epsv) { use_epsv_ = use_epsv; }
144 void set_data_type(char data_type) { data_type_ = data_type; }
146 protected:
147 void Init() {
148 state_ = PRE_USER;
149 SimulateRead("220 host TestFTPd\r\n");
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;
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());
173 return MockWriteResult(ASYNC, ERR_UNEXPECTED);
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));
185 private:
186 State state_;
187 State failure_injection_state_;
188 State failure_injection_next_state_;
189 const char* fault_response_;
191 // If true, we will send multiple 230 lines as response after PASS.
192 bool multiline_welcome_;
194 // If true, we will use EPSV command.
195 bool use_epsv_;
197 // Data type to be used for TYPE command.
198 char data_type_;
200 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProvider);
203 class FtpSocketDataProviderDirectoryListing : public FtpSocketDataProvider {
204 public:
205 FtpSocketDataProviderDirectoryListing() {
208 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);
225 private:
226 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderDirectoryListing);
229 class FtpSocketDataProviderDirectoryListingWithPasvFallback
230 : public FtpSocketDataProviderDirectoryListing {
231 public:
232 FtpSocketDataProviderDirectoryListingWithPasvFallback() {
235 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);
250 private:
251 DISALLOW_COPY_AND_ASSIGN(
252 FtpSocketDataProviderDirectoryListingWithPasvFallback);
255 class FtpSocketDataProviderDirectoryListingZeroSize
256 : public FtpSocketDataProviderDirectoryListing {
257 public:
258 FtpSocketDataProviderDirectoryListingZeroSize() {
261 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);
272 private:
273 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderDirectoryListingZeroSize);
276 class FtpSocketDataProviderVMSDirectoryListing : public FtpSocketDataProvider {
277 public:
278 FtpSocketDataProviderVMSDirectoryListing() {
281 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);
305 private:
306 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderVMSDirectoryListing);
309 class FtpSocketDataProviderVMSDirectoryListingRootDirectory
310 : public FtpSocketDataProvider {
311 public:
312 FtpSocketDataProviderVMSDirectoryListingRootDirectory() {
315 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);
340 private:
341 DISALLOW_COPY_AND_ASSIGN(
342 FtpSocketDataProviderVMSDirectoryListingRootDirectory);
345 class FtpSocketDataProviderFileDownloadWithFileTypecode
346 : public FtpSocketDataProvider {
347 public:
348 FtpSocketDataProviderFileDownloadWithFileTypecode() {
351 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);
365 private:
366 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadWithFileTypecode);
369 class FtpSocketDataProviderFileDownload : public FtpSocketDataProvider {
370 public:
371 FtpSocketDataProviderFileDownload() {
374 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);
392 private:
393 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownload);
396 class FtpSocketDataProviderFileNotFound : public FtpSocketDataProvider {
397 public:
398 FtpSocketDataProviderFileNotFound() {
401 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);
421 private:
422 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileNotFound);
425 class FtpSocketDataProviderFileDownloadWithPasvFallback
426 : public FtpSocketDataProviderFileDownload {
427 public:
428 FtpSocketDataProviderFileDownloadWithPasvFallback() {
431 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);
446 private:
447 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadWithPasvFallback);
450 class FtpSocketDataProviderFileDownloadZeroSize
451 : public FtpSocketDataProviderFileDownload {
452 public:
453 FtpSocketDataProviderFileDownloadZeroSize() {
456 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);
472 private:
473 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadZeroSize);
476 class FtpSocketDataProviderFileDownloadCWD451
477 : public FtpSocketDataProviderFileDownload {
478 public:
479 FtpSocketDataProviderFileDownloadCWD451() {
482 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);
495 private:
496 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadCWD451);
499 class FtpSocketDataProviderVMSFileDownload : public FtpSocketDataProvider {
500 public:
501 FtpSocketDataProviderVMSFileDownload() {
504 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);
530 private:
531 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderVMSFileDownload);
534 class FtpSocketDataProviderEscaping : public FtpSocketDataProviderFileDownload {
535 public:
536 FtpSocketDataProviderEscaping() {
539 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);
558 private:
559 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEscaping);
562 class FtpSocketDataProviderFileDownloadTransferStarting
563 : public FtpSocketDataProviderFileDownload {
564 public:
565 FtpSocketDataProviderFileDownloadTransferStarting() {
568 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);
582 private:
583 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadTransferStarting);
586 class FtpSocketDataProviderDirectoryListingTransferStarting
587 : public FtpSocketDataProviderDirectoryListing {
588 public:
589 FtpSocketDataProviderDirectoryListingTransferStarting() {
592 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);
606 private:
607 DISALLOW_COPY_AND_ASSIGN(
608 FtpSocketDataProviderDirectoryListingTransferStarting);
611 class FtpSocketDataProviderFileDownloadInvalidResponse
612 : public FtpSocketDataProviderFileDownload {
613 public:
614 FtpSocketDataProviderFileDownloadInvalidResponse() {
617 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);
632 private:
633 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadInvalidResponse);
636 class 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) {}
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) {}
651 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);
663 private:
664 const char* epsv_response_;
665 const size_t epsv_response_length_;
666 const State expected_state_;
668 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilEpsv);
671 class 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) {
679 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);
690 private:
691 const char* pasv_response_;
692 const State expected_state_;
694 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilPasv);
697 class FtpSocketDataProviderEvilSize : public FtpSocketDataProviderFileDownload {
698 public:
699 FtpSocketDataProviderEvilSize(const char* size_response, State expected_state)
700 : size_response_(size_response),
701 expected_state_(expected_state) {
704 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);
715 private:
716 const char* size_response_;
717 const State expected_state_;
719 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilSize);
722 class 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) {
731 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);
746 private:
747 const char* expected_user_;
748 const char* expected_password_;
750 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderEvilLogin);
753 class FtpSocketDataProviderCloseConnection : public FtpSocketDataProvider {
754 public:
755 FtpSocketDataProviderCloseConnection() {
758 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);
770 private:
771 DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderCloseConnection);
774 class 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();
791 host_resolver_->set_rules(rules.get());
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();
801 FtpRequestInfo GetRequestInfo(const std::string& url) {
802 FtpRequestInfo info;
803 info.url = GURL(url);
804 return info;
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));
814 mock_socket_factory_.AddSocketDataProvider(ctrl_socket);
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()),
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);
834 mock_socket_factory_.AddSocketDataProvider(data_sockets[i]);
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()));
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);
863 EXPECT_EQ(FtpSocketDataProvider::QUIT, ctrl_socket->state());
864 EXPECT_EQ(LOAD_STATE_IDLE, transaction_.GetLoadState());
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);
877 scoped_ptr<MockHostResolver> host_resolver_;
878 scoped_refptr<FtpNetworkSession> session_;
879 MockClientSocketFactory mock_socket_factory_;
880 FtpNetworkTransaction transaction_;
881 TestCompletionCallback callback_;
884 TEST_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());
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());
899 // Check that when determining the host, the square brackets decorating IPv6
900 // literals in URLs are stripped.
901 TEST_P(FtpNetworkTransactionTest, StripBracketsFromIPv6Literals) {
902 // This test only makes sense for IPv6 connections.
903 if (GetFamily() != AF_INET6)
904 return;
906 host_resolver_->rules()->AddSimulatedFailure("[::1]");
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);
918 TEST_P(FtpNetworkTransactionTest, DirectoryTransaction) {
919 FtpSocketDataProviderDirectoryListing ctrl_socket;
920 ExecuteTransaction(&ctrl_socket, "ftp://host", 1, OK);
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());
929 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithPasvFallback) {
930 FtpSocketDataProviderDirectoryListingWithPasvFallback ctrl_socket;
931 ExecuteTransaction(&ctrl_socket, "ftp://host", 1, OK);
933 EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
934 EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
937 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithTypecode) {
938 FtpSocketDataProviderDirectoryListing ctrl_socket;
939 ExecuteTransaction(&ctrl_socket, "ftp://host;type=d", 1, OK);
941 EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
942 EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
945 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionMultilineWelcome) {
946 FtpSocketDataProviderDirectoryListing ctrl_socket;
947 ctrl_socket.set_multiline_welcome(true);
948 ExecuteTransaction(&ctrl_socket, "ftp://host", 1, OK);
951 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionShortReads2) {
952 FtpSocketDataProviderDirectoryListing ctrl_socket;
953 ctrl_socket.set_short_read_limit(2);
954 ExecuteTransaction(&ctrl_socket, "ftp://host", 1, OK);
957 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionShortReads5) {
958 FtpSocketDataProviderDirectoryListing ctrl_socket;
959 ctrl_socket.set_short_read_limit(5);
960 ExecuteTransaction(&ctrl_socket, "ftp://host", 1, OK);
963 TEST_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);
973 // Regression test for http://crbug.com/60555.
974 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionZeroSize) {
975 FtpSocketDataProviderDirectoryListingZeroSize ctrl_socket;
976 ExecuteTransaction(&ctrl_socket, "ftp://host", 0, OK);
979 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionVMS) {
980 FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
981 ExecuteTransaction(&ctrl_socket, "ftp://host/dir", 1, OK);
984 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionVMSRootDirectory) {
985 FtpSocketDataProviderVMSDirectoryListingRootDirectory ctrl_socket;
986 ExecuteTransaction(&ctrl_socket, "ftp://host", 1, OK);
989 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionTransferStarting) {
990 FtpSocketDataProviderDirectoryListingTransferStarting ctrl_socket;
991 ExecuteTransaction(&ctrl_socket, "ftp://host", 1, OK);
994 TEST_P(FtpNetworkTransactionTest, DownloadTransaction) {
995 FtpSocketDataProviderFileDownload ctrl_socket;
996 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
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());
1005 TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithPasvFallback) {
1006 FtpSocketDataProviderFileDownloadWithPasvFallback ctrl_socket;
1007 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1009 // We pass an artificial value of 18 as a response to the SIZE command.
1010 EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
1013 TEST_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);
1018 // We pass an artificial value of 18 as a response to the SIZE command.
1019 EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
1022 TEST_P(FtpNetworkTransactionTest, DownloadTransactionWithTypecodeI) {
1023 FtpSocketDataProviderFileDownloadWithFileTypecode ctrl_socket;
1024 ExecuteTransaction(&ctrl_socket, "ftp://host/file;type=i", 0, OK);
1026 // We pass an artificial value of 18 as a response to the SIZE command.
1027 EXPECT_EQ(18, transaction_.GetResponseInfo()->expected_content_size);
1030 TEST_P(FtpNetworkTransactionTest, DownloadTransactionMultilineWelcome) {
1031 FtpSocketDataProviderFileDownload ctrl_socket;
1032 ctrl_socket.set_multiline_welcome(true);
1033 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1036 TEST_P(FtpNetworkTransactionTest, DownloadTransactionShortReads2) {
1037 FtpSocketDataProviderFileDownload ctrl_socket;
1038 ctrl_socket.set_short_read_limit(2);
1039 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1042 TEST_P(FtpNetworkTransactionTest, DownloadTransactionShortReads5) {
1043 FtpSocketDataProviderFileDownload ctrl_socket;
1044 ctrl_socket.set_short_read_limit(5);
1045 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1048 TEST_P(FtpNetworkTransactionTest, DownloadTransactionZeroSize) {
1049 FtpSocketDataProviderFileDownloadZeroSize ctrl_socket;
1050 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1053 TEST_P(FtpNetworkTransactionTest, DownloadTransactionCWD451) {
1054 FtpSocketDataProviderFileDownloadCWD451 ctrl_socket;
1055 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1058 TEST_P(FtpNetworkTransactionTest, DownloadTransactionVMS) {
1059 FtpSocketDataProviderVMSFileDownload ctrl_socket;
1060 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1063 TEST_P(FtpNetworkTransactionTest, DownloadTransactionTransferStarting) {
1064 FtpSocketDataProviderFileDownloadTransferStarting ctrl_socket;
1065 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1068 TEST_P(FtpNetworkTransactionTest, DownloadTransactionInvalidResponse) {
1069 FtpSocketDataProviderFileDownloadInvalidResponse ctrl_socket;
1070 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_INVALID_RESPONSE);
1073 TEST_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);
1079 TEST_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);
1085 TEST_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);
1092 TEST_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);
1099 TEST_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);
1106 TEST_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()),
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");
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());
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());
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());
1144 TEST_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;
1149 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||22)\r\n",
1150 FtpSocketDataProvider::PRE_QUIT);
1151 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_INVALID_RESPONSE);
1154 TEST_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;
1159 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (||\r\n",
1160 FtpSocketDataProvider::PRE_QUIT);
1161 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_INVALID_RESPONSE);
1164 TEST_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;
1169 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan\r\n",
1170 FtpSocketDataProvider::PRE_QUIT);
1171 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_INVALID_RESPONSE);
1174 TEST_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;
1179 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (||||)\r\n",
1180 FtpSocketDataProvider::PRE_QUIT);
1181 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_INVALID_RESPONSE);
1184 TEST_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;
1189 // Breaking the string in the next line prevents MSVC warning C4125.
1190 const char response[] = "227 Portscan (\0\0\031" "773\0)\r\n";
1191 FtpSocketDataProviderEvilEpsv ctrl_socket(response, sizeof(response)-1,
1192 FtpSocketDataProvider::PRE_QUIT);
1193 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_INVALID_RESPONSE);
1196 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort1) {
1197 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1198 if (GetFamily() == AF_INET)
1199 return;
1201 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||22|)\r\n",
1202 FtpSocketDataProvider::PRE_QUIT);
1203 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_UNSAFE_PORT);
1206 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort2) {
1207 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1208 if (GetFamily() == AF_INET)
1209 return;
1211 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||258|)\r\n",
1212 FtpSocketDataProvider::PRE_QUIT);
1213 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_UNSAFE_PORT);
1216 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort3) {
1217 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1218 if (GetFamily() == AF_INET)
1219 return;
1221 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||772|)\r\n",
1222 FtpSocketDataProvider::PRE_QUIT);
1223 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_UNSAFE_PORT);
1226 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvUnsafePort4) {
1227 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1228 if (GetFamily() == AF_INET)
1229 return;
1231 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|||2049|)\r\n",
1232 FtpSocketDataProvider::PRE_QUIT);
1233 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_UNSAFE_PORT);
1236 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvWeirdSep) {
1237 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1238 if (GetFamily() == AF_INET)
1239 return;
1241 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan ($$$31744$)\r\n",
1242 FtpSocketDataProvider::PRE_SIZE);
1243 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1246 TEST_P(FtpNetworkTransactionTest,
1247 DownloadTransactionEvilEpsvWeirdSepUnsafePort) {
1248 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1249 if (GetFamily() == AF_INET)
1250 return;
1252 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan ($$$317$)\r\n",
1253 FtpSocketDataProvider::PRE_QUIT);
1254 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_UNSAFE_PORT);
1257 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilEpsvIllegalHost) {
1258 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1259 if (GetFamily() == AF_INET)
1260 return;
1262 FtpSocketDataProviderEvilEpsv ctrl_socket("227 Portscan (|2|::1|31744|)\r\n",
1263 FtpSocketDataProvider::PRE_QUIT);
1264 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_INVALID_RESPONSE);
1267 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilLoginBadUsername) {
1268 FtpSocketDataProviderEvilLogin ctrl_socket("hello%0Aworld", "test");
1269 ExecuteTransaction(&ctrl_socket, "ftp://hello%0Aworld:test@host/file", 1, OK);
1272 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilLoginBadPassword) {
1273 FtpSocketDataProviderEvilLogin ctrl_socket("test", "hello%0Dworld");
1274 ExecuteTransaction(&ctrl_socket, "ftp://test:hello%0Dworld@host/file", 1, OK);
1277 TEST_P(FtpNetworkTransactionTest, DownloadTransactionSpaceInLogin) {
1278 FtpSocketDataProviderEvilLogin ctrl_socket("hello world", "test");
1279 ExecuteTransaction(&ctrl_socket, "ftp://hello%20world:test@host/file", 1, OK);
1282 TEST_P(FtpNetworkTransactionTest, DownloadTransactionSpaceInPassword) {
1283 FtpSocketDataProviderEvilLogin ctrl_socket("test", "hello world");
1284 ExecuteTransaction(&ctrl_socket, "ftp://test:hello%20world@host/file", 1, OK);
1287 TEST_P(FtpNetworkTransactionTest, EvilRestartUser) {
1288 FtpSocketDataProvider ctrl_socket1;
1289 ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
1290 FtpSocketDataProvider::PRE_QUIT,
1291 "530 Login authentication failed\r\n");
1292 mock_socket_factory_.AddSocketDataProvider(&ctrl_socket1);
1294 FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1296 ASSERT_EQ(ERR_IO_PENDING,
1297 transaction_.Start(&request_info, callback_.callback(),
1298 BoundNetLog()));
1299 ASSERT_EQ(ERR_FTP_FAILED, callback_.WaitForResult());
1301 MockRead ctrl_reads[] = {
1302 MockRead("220 host TestFTPd\r\n"),
1303 MockRead("221 Goodbye!\r\n"),
1304 MockRead(SYNCHRONOUS, OK),
1306 MockWrite ctrl_writes[] = {
1307 MockWrite("QUIT\r\n"),
1309 StaticSocketDataProvider ctrl_socket2(ctrl_reads, arraysize(ctrl_reads),
1310 ctrl_writes, arraysize(ctrl_writes));
1311 mock_socket_factory_.AddSocketDataProvider(&ctrl_socket2);
1312 ASSERT_EQ(ERR_IO_PENDING,
1313 transaction_.RestartWithAuth(
1314 AuthCredentials(
1315 base::ASCIIToUTF16("foo\nownz0red"),
1316 base::ASCIIToUTF16("innocent")),
1317 callback_.callback()));
1318 EXPECT_EQ(ERR_MALFORMED_IDENTITY, callback_.WaitForResult());
1321 TEST_P(FtpNetworkTransactionTest, EvilRestartPassword) {
1322 FtpSocketDataProvider ctrl_socket1;
1323 ctrl_socket1.InjectFailure(FtpSocketDataProvider::PRE_PASSWD,
1324 FtpSocketDataProvider::PRE_QUIT,
1325 "530 Login authentication failed\r\n");
1326 mock_socket_factory_.AddSocketDataProvider(&ctrl_socket1);
1328 FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
1330 ASSERT_EQ(ERR_IO_PENDING,
1331 transaction_.Start(&request_info, callback_.callback(),
1332 BoundNetLog()));
1333 ASSERT_EQ(ERR_FTP_FAILED, callback_.WaitForResult());
1335 MockRead ctrl_reads[] = {
1336 MockRead("220 host TestFTPd\r\n"),
1337 MockRead("331 User okay, send password\r\n"),
1338 MockRead("221 Goodbye!\r\n"),
1339 MockRead(SYNCHRONOUS, OK),
1341 MockWrite ctrl_writes[] = {
1342 MockWrite("USER innocent\r\n"),
1343 MockWrite("QUIT\r\n"),
1345 StaticSocketDataProvider ctrl_socket2(ctrl_reads, arraysize(ctrl_reads),
1346 ctrl_writes, arraysize(ctrl_writes));
1347 mock_socket_factory_.AddSocketDataProvider(&ctrl_socket2);
1348 ASSERT_EQ(ERR_IO_PENDING,
1349 transaction_.RestartWithAuth(
1350 AuthCredentials(base::ASCIIToUTF16("innocent"),
1351 base::ASCIIToUTF16("foo\nownz0red")),
1352 callback_.callback()));
1353 EXPECT_EQ(ERR_MALFORMED_IDENTITY, callback_.WaitForResult());
1356 TEST_P(FtpNetworkTransactionTest, Escaping) {
1357 FtpSocketDataProviderEscaping ctrl_socket;
1358 ExecuteTransaction(&ctrl_socket, "ftp://host/%20%21%22%23%24%25%79%80%81",
1359 1, OK);
1362 // Test for http://crbug.com/23794.
1363 TEST_P(FtpNetworkTransactionTest, DownloadTransactionEvilSize) {
1364 // Try to overflow int64 in the response.
1365 FtpSocketDataProviderEvilSize ctrl_socket(
1366 "213 99999999999999999999999999999999\r\n",
1367 FtpSocketDataProvider::PRE_QUIT);
1368 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, ERR_INVALID_RESPONSE);
1371 // Test for http://crbug.com/36360.
1372 TEST_P(FtpNetworkTransactionTest, DownloadTransactionBigSize) {
1373 // Pass a valid, but large file size. The transaction should not fail.
1374 FtpSocketDataProviderEvilSize ctrl_socket(
1375 "213 3204427776\r\n",
1376 FtpSocketDataProvider::PRE_CWD);
1377 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 1, OK);
1378 EXPECT_EQ(3204427776LL,
1379 transaction_.GetResponseInfo()->expected_content_size);
1382 // Regression test for http://crbug.com/25023.
1383 TEST_P(FtpNetworkTransactionTest, CloseConnection) {
1384 FtpSocketDataProviderCloseConnection ctrl_socket;
1385 ExecuteTransaction(&ctrl_socket, "ftp://host", 1, ERR_EMPTY_RESPONSE);
1388 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailUser) {
1389 FtpSocketDataProviderDirectoryListing 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",
1394 FtpSocketDataProvider::PRE_USER,
1395 FtpSocketDataProvider::PRE_QUIT,
1396 "599 fail\r\n",
1397 ERR_FTP_FAILED);
1400 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailPass) {
1401 FtpSocketDataProviderDirectoryListing ctrl_socket;
1402 TransactionFailHelper(&ctrl_socket,
1403 "ftp://host",
1404 FtpSocketDataProvider::PRE_PASSWD,
1405 FtpSocketDataProvider::PRE_QUIT,
1406 "530 Login authentication failed\r\n",
1407 ERR_FTP_FAILED);
1410 // Regression test for http://crbug.com/38707.
1411 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailPass503) {
1412 FtpSocketDataProviderDirectoryListing ctrl_socket;
1413 TransactionFailHelper(&ctrl_socket,
1414 "ftp://host",
1415 FtpSocketDataProvider::PRE_PASSWD,
1416 FtpSocketDataProvider::PRE_QUIT,
1417 "503 Bad sequence of commands\r\n",
1418 ERR_FTP_BAD_COMMAND_SEQUENCE);
1421 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailSyst) {
1422 FtpSocketDataProviderDirectoryListing ctrl_socket;
1423 // Use unallocated 599 FTP error code to make sure it falls into the generic
1424 // ERR_FTP_FAILED bucket.
1425 TransactionFailHelper(&ctrl_socket,
1426 "ftp://host",
1427 FtpSocketDataProvider::PRE_SYST,
1428 FtpSocketDataProvider::PRE_PWD,
1429 "599 fail\r\n",
1430 OK);
1433 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailPwd) {
1434 FtpSocketDataProviderDirectoryListing ctrl_socket;
1435 // Use unallocated 599 FTP error code to make sure it falls into the generic
1436 // ERR_FTP_FAILED bucket.
1437 TransactionFailHelper(&ctrl_socket,
1438 "ftp://host",
1439 FtpSocketDataProvider::PRE_PWD,
1440 FtpSocketDataProvider::PRE_QUIT,
1441 "599 fail\r\n",
1442 ERR_FTP_FAILED);
1445 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailType) {
1446 FtpSocketDataProviderDirectoryListing ctrl_socket;
1447 // Use unallocated 599 FTP error code to make sure it falls into the generic
1448 // ERR_FTP_FAILED bucket.
1449 TransactionFailHelper(&ctrl_socket,
1450 "ftp://host",
1451 FtpSocketDataProvider::PRE_TYPE,
1452 FtpSocketDataProvider::PRE_QUIT,
1453 "599 fail\r\n",
1454 ERR_FTP_FAILED);
1457 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailEpsv) {
1458 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1459 if (GetFamily() == AF_INET)
1460 return;
1462 FtpSocketDataProviderDirectoryListing ctrl_socket;
1463 // Use unallocated 599 FTP error code to make sure it falls into the generic
1464 // ERR_FTP_FAILED bucket.
1465 TransactionFailHelper(&ctrl_socket,
1466 "ftp://host",
1467 FtpSocketDataProvider::PRE_EPSV,
1468 FtpSocketDataProvider::PRE_NOPASV,
1469 "599 fail\r\n",
1470 ERR_FTP_FAILED);
1473 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailCwd) {
1474 FtpSocketDataProviderDirectoryListing ctrl_socket;
1475 // Use unallocated 599 FTP error code to make sure it falls into the generic
1476 // ERR_FTP_FAILED bucket.
1477 TransactionFailHelper(&ctrl_socket,
1478 "ftp://host",
1479 FtpSocketDataProvider::PRE_CWD,
1480 FtpSocketDataProvider::PRE_QUIT,
1481 "599 fail\r\n",
1482 ERR_FTP_FAILED);
1485 TEST_P(FtpNetworkTransactionTest, DirectoryTransactionFailList) {
1486 FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
1487 // Use unallocated 599 FTP error code to make sure it falls into the generic
1488 // ERR_FTP_FAILED bucket.
1489 TransactionFailHelper(&ctrl_socket,
1490 "ftp://host/dir",
1491 FtpSocketDataProvider::PRE_LIST,
1492 FtpSocketDataProvider::PRE_QUIT,
1493 "599 fail\r\n",
1494 ERR_FTP_FAILED);
1497 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailUser) {
1498 FtpSocketDataProviderFileDownload ctrl_socket;
1499 // Use unallocated 599 FTP error code to make sure it falls into the generic
1500 // ERR_FTP_FAILED bucket.
1501 TransactionFailHelper(&ctrl_socket,
1502 "ftp://host/file",
1503 FtpSocketDataProvider::PRE_USER,
1504 FtpSocketDataProvider::PRE_QUIT,
1505 "599 fail\r\n",
1506 ERR_FTP_FAILED);
1509 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailPass) {
1510 FtpSocketDataProviderFileDownload ctrl_socket;
1511 TransactionFailHelper(&ctrl_socket,
1512 "ftp://host/file",
1513 FtpSocketDataProvider::PRE_PASSWD,
1514 FtpSocketDataProvider::PRE_QUIT,
1515 "530 Login authentication failed\r\n",
1516 ERR_FTP_FAILED);
1519 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailSyst) {
1520 FtpSocketDataProviderFileDownload ctrl_socket;
1521 // Use unallocated 599 FTP error code to make sure it falls into the generic
1522 // ERR_FTP_FAILED bucket.
1523 TransactionFailHelper(&ctrl_socket,
1524 "ftp://host/file",
1525 FtpSocketDataProvider::PRE_SYST,
1526 FtpSocketDataProvider::PRE_PWD,
1527 "599 fail\r\n",
1528 OK);
1531 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailPwd) {
1532 FtpSocketDataProviderFileDownload ctrl_socket;
1533 // Use unallocated 599 FTP error code to make sure it falls into the generic
1534 // ERR_FTP_FAILED bucket.
1535 TransactionFailHelper(&ctrl_socket,
1536 "ftp://host/file",
1537 FtpSocketDataProvider::PRE_PWD,
1538 FtpSocketDataProvider::PRE_QUIT,
1539 "599 fail\r\n",
1540 ERR_FTP_FAILED);
1543 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailType) {
1544 FtpSocketDataProviderFileDownload ctrl_socket;
1545 // Use unallocated 599 FTP error code to make sure it falls into the generic
1546 // ERR_FTP_FAILED bucket.
1547 TransactionFailHelper(&ctrl_socket,
1548 "ftp://host/file",
1549 FtpSocketDataProvider::PRE_TYPE,
1550 FtpSocketDataProvider::PRE_QUIT,
1551 "599 fail\r\n",
1552 ERR_FTP_FAILED);
1555 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailEpsv) {
1556 // This test makes no sense for IPv4 connections (we don't use EPSV there).
1557 if (GetFamily() == AF_INET)
1558 return;
1560 FtpSocketDataProviderFileDownload ctrl_socket;
1561 // Use unallocated 599 FTP error code to make sure it falls into the generic
1562 // ERR_FTP_FAILED bucket.
1563 TransactionFailHelper(&ctrl_socket,
1564 "ftp://host/file",
1565 FtpSocketDataProvider::PRE_EPSV,
1566 FtpSocketDataProvider::PRE_NOPASV,
1567 "599 fail\r\n",
1568 ERR_FTP_FAILED);
1571 TEST_P(FtpNetworkTransactionTest, DownloadTransactionFailRetr) {
1572 FtpSocketDataProviderFileDownload ctrl_socket;
1573 // Use unallocated 599 FTP error code to make sure it falls into the generic
1574 // ERR_FTP_FAILED bucket.
1575 TransactionFailHelper(&ctrl_socket,
1576 "ftp://host/file",
1577 FtpSocketDataProvider::PRE_RETR,
1578 FtpSocketDataProvider::PRE_QUIT,
1579 "599 fail\r\n",
1580 ERR_FTP_FAILED);
1583 TEST_P(FtpNetworkTransactionTest, FileNotFound) {
1584 FtpSocketDataProviderFileNotFound ctrl_socket;
1585 ExecuteTransaction(&ctrl_socket, "ftp://host/file", 2, ERR_FTP_FAILED);
1588 // Test for http://crbug.com/38845.
1589 TEST_P(FtpNetworkTransactionTest, ZeroLengthDirInPWD) {
1590 FtpSocketDataProviderFileDownload ctrl_socket;
1591 TransactionFailHelper(&ctrl_socket,
1592 "ftp://host/file",
1593 FtpSocketDataProvider::PRE_PWD,
1594 FtpSocketDataProvider::PRE_TYPE,
1595 "257 \"\"\r\n",
1596 OK);
1599 INSTANTIATE_TEST_CASE_P(FTP,
1600 FtpNetworkTransactionTest,
1601 ::testing::Values(AF_INET, AF_INET6));
1603 } // namespace net