Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: net/ftp/ftp_network_transaction.cc

Issue 2538773002: Fix yet another silly DCHECK in the FTP code. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | net/ftp/ftp_network_transaction_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/ftp/ftp_network_transaction.h" 5 #include "net/ftp/ftp_network_transaction.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
(...skipping 18 matching lines...) Expand all
29 #include "url/url_constants.h" 29 #include "url/url_constants.h"
30 30
31 namespace net { 31 namespace net {
32 32
33 namespace { 33 namespace {
34 34
35 const char kCRLF[] = "\r\n"; 35 const char kCRLF[] = "\r\n";
36 36
37 const int kCtrlBufLen = 1024; 37 const int kCtrlBufLen = 1024;
38 38
39 // Returns true if |input| can be safely used as a part of FTP command. 39 // Returns true if |input| can be safely used as a part of an FTP command.
40 bool IsValidFTPCommandString(const std::string& input) { 40 bool IsValidFTPCommandSubstring(const std::string& input) {
41 // RFC 959 only allows ASCII strings, but at least Firefox can send non-ASCII 41 // RFC 959 only allows ASCII strings, but at least Firefox can send non-ASCII
42 // characters in the command if the request path contains them. To be 42 // characters in the command if the request path contains them. To be
43 // compatible, we do the same and allow non-ASCII characters in a command. 43 // compatible, we do the same and allow non-ASCII characters in a command.
44 44
45 // Protect agains newline injection attack. 45 // Protect agains newline injection attack.
46 if (input.find_first_of("\r\n") != std::string::npos) 46 if (input.find_first_of("\r\n") != std::string::npos)
47 return false; 47 return false;
48 48
49 return true; 49 return true;
50 } 50 }
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 const std::string& command_for_log, 455 const std::string& command_for_log,
456 Command cmd) { 456 Command cmd) {
457 // If we send a new command when we still have unprocessed responses 457 // If we send a new command when we still have unprocessed responses
458 // for previous commands, the response receiving code will have no way to know 458 // for previous commands, the response receiving code will have no way to know
459 // which responses are for which command. 459 // which responses are for which command.
460 DCHECK(!ctrl_response_buffer_->ResponseAvailable()); 460 DCHECK(!ctrl_response_buffer_->ResponseAvailable());
461 461
462 DCHECK(!write_command_buf_.get()); 462 DCHECK(!write_command_buf_.get());
463 DCHECK(!write_buf_.get()); 463 DCHECK(!write_buf_.get());
464 464
465 if (!IsValidFTPCommandString(command)) { 465 if (!IsValidFTPCommandSubstring(command)) {
466 // Callers should validate the command themselves and return a more specific 466 // Callers should validate the command themselves and return a more specific
467 // error code. 467 // error code.
468 NOTREACHED(); 468 NOTREACHED();
469 return Stop(ERR_UNEXPECTED); 469 return Stop(ERR_UNEXPECTED);
470 } 470 }
471 471
472 command_sent_ = cmd; 472 command_sent_ = cmd;
473 473
474 write_command_buf_ = new IOBufferWithSize(command.length() + 2); 474 write_command_buf_ = new IOBufferWithSize(command.length() + 2);
475 write_buf_ = new DrainableIOBuffer(write_command_buf_.get(), 475 write_buf_ = new DrainableIOBuffer(write_command_buf_.get(),
(...skipping 22 matching lines...) Expand all
498 path.append(gurl_path); 498 path.append(gurl_path);
499 } 499 }
500 // Make sure that if the path is expected to be a file, it won't end 500 // Make sure that if the path is expected to be a file, it won't end
501 // with a trailing slash. 501 // with a trailing slash.
502 if (!is_directory && path.length() > 1 && path.back() == '/') 502 if (!is_directory && path.length() > 1 && path.back() == '/')
503 path.erase(path.length() - 1); 503 path.erase(path.length() - 1);
504 UnescapeRule::Type unescape_rules = 504 UnescapeRule::Type unescape_rules =
505 UnescapeRule::SPACES | 505 UnescapeRule::SPACES |
506 UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS; 506 UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS;
507 // This may unescape to non-ASCII characters, but we allow that. See the 507 // This may unescape to non-ASCII characters, but we allow that. See the
508 // comment for IsValidFTPCommandString. 508 // comment for IsValidFTPCommandSubstring.
509 path = UnescapeURLComponent(path, unescape_rules); 509 path = UnescapeURLComponent(path, unescape_rules);
510 510
511 if (system_type_ == SYSTEM_TYPE_VMS) { 511 if (system_type_ == SYSTEM_TYPE_VMS) {
512 if (is_directory) 512 if (is_directory)
513 path = FtpUtil::UnixDirectoryPathToVMS(path); 513 path = FtpUtil::UnixDirectoryPathToVMS(path);
514 else 514 else
515 path = FtpUtil::UnixFilePathToVMS(path); 515 path = FtpUtil::UnixFilePathToVMS(path);
516 } 516 }
517 517
518 DCHECK(IsValidFTPCommandString(path)); 518 DCHECK(IsValidFTPCommandSubstring(path));
519 return path; 519 return path;
520 } 520 }
521 521
522 void FtpNetworkTransaction::DetectTypecode() { 522 void FtpNetworkTransaction::DetectTypecode() {
523 if (!request_->url.has_path()) 523 if (!request_->url.has_path())
524 return; 524 return;
525 std::string gurl_path(request_->url.path()); 525 std::string gurl_path(request_->url.path());
526 526
527 // Extract the typecode, see RFC 1738 section 3.2.2. FTP url-path. 527 // Extract the typecode, see RFC 1738 section 3.2.2. FTP url-path.
528 std::string::size_type pos = gurl_path.rfind(';'); 528 std::string::size_type pos = gurl_path.rfind(';');
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 } 749 }
750 return OK; 750 return OK;
751 } 751 }
752 752
753 // FTP Commands and responses 753 // FTP Commands and responses
754 754
755 // USER Command. 755 // USER Command.
756 int FtpNetworkTransaction::DoCtrlWriteUSER() { 756 int FtpNetworkTransaction::DoCtrlWriteUSER() {
757 std::string command = "USER " + base::UTF16ToUTF8(credentials_.username()); 757 std::string command = "USER " + base::UTF16ToUTF8(credentials_.username());
758 758
759 if (!IsValidFTPCommandString(command)) 759 if (!IsValidFTPCommandSubstring(command))
760 return Stop(ERR_MALFORMED_IDENTITY); 760 return Stop(ERR_MALFORMED_IDENTITY);
761 761
762 next_state_ = STATE_CTRL_READ; 762 next_state_ = STATE_CTRL_READ;
763 return SendFtpCommand(command, "USER ***", COMMAND_USER); 763 return SendFtpCommand(command, "USER ***", COMMAND_USER);
764 } 764 }
765 765
766 int FtpNetworkTransaction::ProcessResponseUSER( 766 int FtpNetworkTransaction::ProcessResponseUSER(
767 const FtpCtrlResponse& response) { 767 const FtpCtrlResponse& response) {
768 switch (GetErrorClass(response.status_code)) { 768 switch (GetErrorClass(response.status_code)) {
769 case ERROR_CLASS_INITIATED: 769 case ERROR_CLASS_INITIATED:
770 return Stop(ERR_INVALID_RESPONSE); 770 return Stop(ERR_INVALID_RESPONSE);
771 case ERROR_CLASS_OK: 771 case ERROR_CLASS_OK:
772 next_state_ = STATE_CTRL_WRITE_SYST; 772 next_state_ = STATE_CTRL_WRITE_SYST;
773 break; 773 break;
774 case ERROR_CLASS_INFO_NEEDED: 774 case ERROR_CLASS_INFO_NEEDED:
775 next_state_ = STATE_CTRL_WRITE_PASS; 775 next_state_ = STATE_CTRL_WRITE_PASS;
776 break; 776 break;
777 case ERROR_CLASS_TRANSIENT_ERROR: 777 case ERROR_CLASS_TRANSIENT_ERROR:
778 case ERROR_CLASS_PERMANENT_ERROR: 778 case ERROR_CLASS_PERMANENT_ERROR:
779 response_.needs_auth = true; 779 response_.needs_auth = true;
780 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 780 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
781 } 781 }
782 return OK; 782 return OK;
783 } 783 }
784 784
785 // PASS command. 785 // PASS command.
786 int FtpNetworkTransaction::DoCtrlWritePASS() { 786 int FtpNetworkTransaction::DoCtrlWritePASS() {
787 std::string command = "PASS " + base::UTF16ToUTF8(credentials_.password()); 787 std::string command = "PASS " + base::UTF16ToUTF8(credentials_.password());
788 788
789 if (!IsValidFTPCommandString(command)) 789 if (!IsValidFTPCommandSubstring(command))
790 return Stop(ERR_MALFORMED_IDENTITY); 790 return Stop(ERR_MALFORMED_IDENTITY);
791 791
792 next_state_ = STATE_CTRL_READ; 792 next_state_ = STATE_CTRL_READ;
793 return SendFtpCommand(command, "PASS ***", COMMAND_PASS); 793 return SendFtpCommand(command, "PASS ***", COMMAND_PASS);
794 } 794 }
795 795
796 int FtpNetworkTransaction::ProcessResponsePASS( 796 int FtpNetworkTransaction::ProcessResponsePASS(
797 const FtpCtrlResponse& response) { 797 const FtpCtrlResponse& response) {
798 switch (GetErrorClass(response.status_code)) { 798 switch (GetErrorClass(response.status_code)) {
799 case ERROR_CLASS_INITIATED: 799 case ERROR_CLASS_INITIATED:
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 line = line.substr(quote_pos + 1); 889 line = line.substr(quote_pos + 1);
890 quote_pos = line.find('"'); 890 quote_pos = line.find('"');
891 if (quote_pos == std::string::npos) 891 if (quote_pos == std::string::npos)
892 return Stop(ERR_INVALID_RESPONSE); 892 return Stop(ERR_INVALID_RESPONSE);
893 line = line.substr(0, quote_pos); 893 line = line.substr(0, quote_pos);
894 } 894 }
895 if (system_type_ == SYSTEM_TYPE_VMS) 895 if (system_type_ == SYSTEM_TYPE_VMS)
896 line = FtpUtil::VMSPathToUnix(line); 896 line = FtpUtil::VMSPathToUnix(line);
897 if (!line.empty() && line.back() == '/') 897 if (!line.empty() && line.back() == '/')
898 line.erase(line.length() - 1); 898 line.erase(line.length() - 1);
899 // Fail if the "path" contains characters not allowed in commands.
900 // This does mean that files with CRs or LFs in their names aren't
901 // handled, but that's probably for the best.
902 if (!IsValidFTPCommandSubstring(line))
903 return Stop(ERR_INVALID_RESPONSE);
899 current_remote_directory_ = line; 904 current_remote_directory_ = line;
900 next_state_ = STATE_CTRL_WRITE_TYPE; 905 next_state_ = STATE_CTRL_WRITE_TYPE;
901 break; 906 break;
902 } 907 }
903 case ERROR_CLASS_INFO_NEEDED: 908 case ERROR_CLASS_INFO_NEEDED:
904 return Stop(ERR_INVALID_RESPONSE); 909 return Stop(ERR_INVALID_RESPONSE);
905 case ERROR_CLASS_TRANSIENT_ERROR: 910 case ERROR_CLASS_TRANSIENT_ERROR:
906 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 911 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
907 case ERROR_CLASS_PERMANENT_ERROR: 912 case ERROR_CLASS_PERMANENT_ERROR:
908 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 913 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
1356 if (!had_error_type[type]) { 1361 if (!had_error_type[type]) {
1357 had_error_type[type] = true; 1362 had_error_type[type] = true;
1358 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened", 1363 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened",
1359 type, NUM_OF_NET_ERROR_TYPES); 1364 type, NUM_OF_NET_ERROR_TYPES);
1360 } 1365 }
1361 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount", 1366 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount",
1362 type, NUM_OF_NET_ERROR_TYPES); 1367 type, NUM_OF_NET_ERROR_TYPES);
1363 } 1368 }
1364 1369
1365 } // namespace net 1370 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/ftp/ftp_network_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698