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