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