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