| OLD | NEW |
| 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/http/http_stream_parser.h" | 5 #include "net/http/http_stream_parser.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/metrics/histogram.h" |
| 11 #include "base/pickle.h" |
| 10 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 11 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "crypto/secure_hash.h" |
| 15 #include "crypto/sha2.h" |
| 12 #include "net/base/io_buffer.h" | 16 #include "net/base/io_buffer.h" |
| 13 #include "net/base/ip_endpoint.h" | 17 #include "net/base/ip_endpoint.h" |
| 14 #include "net/base/upload_data_stream.h" | 18 #include "net/base/upload_data_stream.h" |
| 15 #include "net/http/http_chunked_decoder.h" | 19 #include "net/http/http_chunked_decoder.h" |
| 16 #include "net/http/http_request_headers.h" | 20 #include "net/http/http_request_headers.h" |
| 17 #include "net/http/http_request_info.h" | 21 #include "net/http/http_request_info.h" |
| 18 #include "net/http/http_response_headers.h" | 22 #include "net/http/http_response_headers.h" |
| 19 #include "net/http/http_util.h" | 23 #include "net/http/http_util.h" |
| 20 #include "net/socket/client_socket_handle.h" | 24 #include "net/socket/client_socket_handle.h" |
| 21 #include "net/socket/ssl_client_socket.h" | 25 #include "net/socket/ssl_client_socket.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 | 75 |
| 72 // Returns true if |error_code| is an error for which we give the server a | 76 // Returns true if |error_code| is an error for which we give the server a |
| 73 // chance to send a body containing error information, if the error was received | 77 // chance to send a body containing error information, if the error was received |
| 74 // while trying to upload a request body. | 78 // while trying to upload a request body. |
| 75 bool ShouldTryReadingOnUploadError(int error_code) { | 79 bool ShouldTryReadingOnUploadError(int error_code) { |
| 76 return (error_code == ERR_CONNECTION_RESET); | 80 return (error_code == ERR_CONNECTION_RESET); |
| 77 } | 81 } |
| 78 | 82 |
| 79 } // namespace | 83 } // namespace |
| 80 | 84 |
| 85 // To verify that retry attempts will not cause errors we hash all received |
| 86 // content. When retrying we hash the content again and verify that the |
| 87 // previous hash matches once we have received the same amount of data. |
| 88 class HttpStreamParser::HttpStreamHash { |
| 89 public: |
| 90 HttpStreamHash() |
| 91 :hash_(crypto::SecureHash::Create(crypto::SecureHash::SHA256)) { |
| 92 } |
| 93 |
| 94 // Add to hash. |
| 95 void Update(const void* input, size_t len) { |
| 96 hash_->Update(input, len); |
| 97 } |
| 98 |
| 99 // Finish hash once all content has been received. |
| 100 void Finish(void* output, size_t len) { |
| 101 hash_->Finish(output, len); |
| 102 } |
| 103 |
| 104 // Verify hash after serializing the state. Then deserialize so that we can |
| 105 // keep hashing if we decide to continue fetching the content. |
| 106 int VerifyHash() { |
| 107 int result = OK; |
| 108 uint8 hash[8]; |
| 109 Pickle pickle; |
| 110 hash_->Serialize(&pickle); |
| 111 hash_->Finish(hash, sizeof(hash)); |
| 112 DCHECK(sizeof(hash) == sizeof(previous_hash_)); |
| 113 if (memcmp(hash, previous_hash_, sizeof(previous_hash_)) != 0) { |
| 114 result = ERR_RETRY_HASH_MISMATCH; |
| 115 UMA_HISTOGRAM_COUNTS("Net.HttpRetry.VerifyHashFailure", 1); |
| 116 } else { |
| 117 PickleIterator data_iterator(pickle); |
| 118 hash_->Deserialize(&data_iterator); |
| 119 UMA_HISTOGRAM_COUNTS("Net.HttpRetry.VerifyHashSuccess", 1); |
| 120 } |
| 121 |
| 122 return result; |
| 123 } |
| 124 |
| 125 void SetPreviousHash(const void* hash, size_t len) { |
| 126 DCHECK(len == sizeof(previous_hash_)); |
| 127 memcpy(previous_hash_, hash, len); |
| 128 } |
| 129 |
| 130 private: |
| 131 // Hash of current attempt to retrieve the resource. |
| 132 scoped_ptr<crypto::SecureHash> hash_; |
| 133 |
| 134 // Hash of previous attempt to retrieve the resource. |
| 135 uint8 previous_hash_[8]; |
| 136 }; |
| 137 |
| 81 // Similar to DrainableIOBuffer(), but this version comes with its own | 138 // Similar to DrainableIOBuffer(), but this version comes with its own |
| 82 // storage. The motivation is to avoid repeated allocations of | 139 // storage. The motivation is to avoid repeated allocations of |
| 83 // DrainableIOBuffer. | 140 // DrainableIOBuffer. |
| 84 // | 141 // |
| 85 // Example: | 142 // Example: |
| 86 // | 143 // |
| 87 // scoped_refptr<SeekableIOBuffer> buf = new SeekableIOBuffer(1024); | 144 // scoped_refptr<SeekableIOBuffer> buf = new SeekableIOBuffer(1024); |
| 88 // // capacity() == 1024. size() == BytesRemaining() == BytesConsumed() == 0. | 145 // // capacity() == 1024. size() == BytesRemaining() == BytesConsumed() == 0. |
| 89 // // data() points to the beginning of the buffer. | 146 // // data() points to the beginning of the buffer. |
| 90 // | 147 // |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 const BoundNetLog& net_log) | 238 const BoundNetLog& net_log) |
| 182 : io_state_(STATE_NONE), | 239 : io_state_(STATE_NONE), |
| 183 request_(request), | 240 request_(request), |
| 184 request_headers_(NULL), | 241 request_headers_(NULL), |
| 185 request_headers_length_(0), | 242 request_headers_length_(0), |
| 186 read_buf_(read_buffer), | 243 read_buf_(read_buffer), |
| 187 read_buf_unused_offset_(0), | 244 read_buf_unused_offset_(0), |
| 188 response_header_start_offset_(-1), | 245 response_header_start_offset_(-1), |
| 189 received_bytes_(0), | 246 received_bytes_(0), |
| 190 response_body_length_(-1), | 247 response_body_length_(-1), |
| 248 read_offset_(0), |
| 249 stream_hash_(new HttpStreamHash()), |
| 191 response_body_read_(0), | 250 response_body_read_(0), |
| 192 user_read_buf_(NULL), | 251 user_read_buf_(NULL), |
| 193 user_read_buf_len_(0), | 252 user_read_buf_len_(0), |
| 194 connection_(connection), | 253 connection_(connection), |
| 195 net_log_(net_log), | 254 net_log_(net_log), |
| 196 sent_last_chunk_(false), | 255 sent_last_chunk_(false), |
| 197 upload_error_(OK), | 256 upload_error_(OK), |
| 198 weak_ptr_factory_(this) { | 257 weak_ptr_factory_(this) { |
| 199 io_callback_ = base::Bind(&HttpStreamParser::OnIOComplete, | 258 io_callback_ = base::Bind(&HttpStreamParser::OnIOComplete, |
| 200 weak_ptr_factory_.GetWeakPtr()); | 259 weak_ptr_factory_.GetWeakPtr()); |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 response_->headers = NULL; | 664 response_->headers = NULL; |
| 606 return upload_error_; | 665 return upload_error_; |
| 607 } | 666 } |
| 608 | 667 |
| 609 int HttpStreamParser::DoReadBody() { | 668 int HttpStreamParser::DoReadBody() { |
| 610 io_state_ = STATE_READ_BODY_COMPLETE; | 669 io_state_ = STATE_READ_BODY_COMPLETE; |
| 611 | 670 |
| 612 // There may be some data left over from reading the response headers. | 671 // There may be some data left over from reading the response headers. |
| 613 if (read_buf_->offset()) { | 672 if (read_buf_->offset()) { |
| 614 int available = read_buf_->offset() - read_buf_unused_offset_; | 673 int available = read_buf_->offset() - read_buf_unused_offset_; |
| 674 if (available > 0 && read_offset_) { |
| 675 int64 bytes_from_buffer = |
| 676 available < read_offset_ ? available : read_offset_; |
| 677 stream_hash_->Update((uint8*)read_buf_->StartOfBuffer() + |
| 678 read_buf_unused_offset_, bytes_from_buffer); |
| 679 read_buf_unused_offset_ += bytes_from_buffer; |
| 680 read_offset_ -= bytes_from_buffer; |
| 681 response_body_read_ += bytes_from_buffer; |
| 682 available -= bytes_from_buffer; |
| 683 |
| 684 if (read_offset_ == 0 && stream_hash_->VerifyHash() != OK) { |
| 685 io_state_ = STATE_DONE; |
| 686 return ERR_RETRY_HASH_MISMATCH; |
| 687 } |
| 688 } |
| 689 |
| 615 if (available) { | 690 if (available) { |
| 616 CHECK_GT(available, 0); | 691 CHECK_GT(available, 0); |
| 617 int bytes_from_buffer = std::min(available, user_read_buf_len_); | 692 int bytes_from_buffer = std::min(available, user_read_buf_len_); |
| 618 memcpy(user_read_buf_->data(), | 693 memcpy(user_read_buf_->data(), |
| 619 read_buf_->StartOfBuffer() + read_buf_unused_offset_, | 694 read_buf_->StartOfBuffer() + read_buf_unused_offset_, |
| 620 bytes_from_buffer); | 695 bytes_from_buffer); |
| 621 read_buf_unused_offset_ += bytes_from_buffer; | 696 read_buf_unused_offset_ += bytes_from_buffer; |
| 622 if (bytes_from_buffer == available) { | 697 if (bytes_from_buffer == available) { |
| 623 read_buf_->SetCapacity(0); | 698 read_buf_->SetCapacity(0); |
| 624 read_buf_unused_offset_ = 0; | 699 read_buf_unused_offset_ = 0; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 // Don't signal completion of the Read call yet or else it'll look like | 760 // Don't signal completion of the Read call yet or else it'll look like |
| 686 // we received end-of-file. Wait for more data. | 761 // we received end-of-file. Wait for more data. |
| 687 io_state_ = STATE_READ_BODY; | 762 io_state_ = STATE_READ_BODY; |
| 688 return OK; | 763 return OK; |
| 689 } | 764 } |
| 690 } | 765 } |
| 691 | 766 |
| 692 if (result > 0) | 767 if (result > 0) |
| 693 response_body_read_ += result; | 768 response_body_read_ += result; |
| 694 | 769 |
| 770 if (result > 0 && read_offset_) { |
| 771 if (result < read_offset_) { |
| 772 read_offset_ -= result; |
| 773 stream_hash_->Update((uint8*)user_read_buf_->data(), result); |
| 774 result = 0; |
| 775 } else { |
| 776 stream_hash_->Update((uint8*)user_read_buf_->data(), read_offset_); |
| 777 memmove(user_read_buf_->data(), |
| 778 user_read_buf_->data() + read_offset_, |
| 779 result - read_offset_); |
| 780 result -= read_offset_; |
| 781 read_offset_ = 0; |
| 782 |
| 783 if (stream_hash_->VerifyHash() != OK){ |
| 784 io_state_ = STATE_DONE; |
| 785 return ERR_RETRY_HASH_MISMATCH; |
| 786 } |
| 787 } |
| 788 |
| 789 if (result == 0) { |
| 790 io_state_ = STATE_READ_BODY; |
| 791 return OK; |
| 792 } |
| 793 } else if (result > 0) |
| 794 stream_hash_->Update((uint8*)user_read_buf_->data(), result); |
| 795 |
| 695 if (result <= 0 || IsResponseBodyComplete()) { | 796 if (result <= 0 || IsResponseBodyComplete()) { |
| 696 io_state_ = STATE_DONE; | 797 io_state_ = STATE_DONE; |
| 697 | 798 |
| 698 // Save the overflow data, which can be in two places. There may be | 799 // Save the overflow data, which can be in two places. There may be |
| 699 // some left over in |user_read_buf_|, plus there may be more | 800 // some left over in |user_read_buf_|, plus there may be more |
| 700 // in |read_buf_|. But the part left over in |user_read_buf_| must have | 801 // in |read_buf_|. But the part left over in |user_read_buf_| must have |
| 701 // come from the |read_buf_|, so there's room to put it back at the | 802 // come from the |read_buf_|, so there's room to put it back at the |
| 702 // start first. | 803 // start first. |
| 703 int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_; | 804 int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_; |
| 704 int save_amount = 0; | 805 int save_amount = 0; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 // it's also a potential response smuggling attack. | 1002 // it's also a potential response smuggling attack. |
| 902 if (HeadersContainMultipleCopiesOfField(*headers.get(), | 1003 if (HeadersContainMultipleCopiesOfField(*headers.get(), |
| 903 "Content-Disposition")) | 1004 "Content-Disposition")) |
| 904 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION; | 1005 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION; |
| 905 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Location")) | 1006 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Location")) |
| 906 return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION; | 1007 return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION; |
| 907 | 1008 |
| 908 response_->headers = headers; | 1009 response_->headers = headers; |
| 909 response_->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1; | 1010 response_->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1; |
| 910 response_->vary_data.Init(*request_, *response_->headers.get()); | 1011 response_->vary_data.Init(*request_, *response_->headers.get()); |
| 1012 if (response_->headers->response_code() != 200) |
| 1013 read_offset_ = 0; |
| 911 DVLOG(1) << __FUNCTION__ << "()" | 1014 DVLOG(1) << __FUNCTION__ << "()" |
| 912 << " content_length = \"" << response_->headers->GetContentLength() | 1015 << " content_length = \"" << response_->headers->GetContentLength() |
| 913 << "\n\"" | 1016 << "\n\"" |
| 914 << " headers = \"" | 1017 << " headers = \"" |
| 915 << GetResponseHeaderLines(*response_->headers.get()) << "\""; | 1018 << GetResponseHeaderLines(*response_->headers.get()) << "\""; |
| 916 return OK; | 1019 return OK; |
| 917 } | 1020 } |
| 918 | 1021 |
| 919 void HttpStreamParser::CalculateResponseBodySize() { | 1022 void HttpStreamParser::CalculateResponseBodySize() { |
| 920 // Figure how to determine EOF: | 1023 // Figure how to determine EOF: |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 } | 1091 } |
| 989 | 1092 |
| 990 void HttpStreamParser::SetConnectionReused() { | 1093 void HttpStreamParser::SetConnectionReused() { |
| 991 connection_->set_reuse_type(ClientSocketHandle::REUSED_IDLE); | 1094 connection_->set_reuse_type(ClientSocketHandle::REUSED_IDLE); |
| 992 } | 1095 } |
| 993 | 1096 |
| 994 bool HttpStreamParser::IsConnectionReusable() const { | 1097 bool HttpStreamParser::IsConnectionReusable() const { |
| 995 return connection_->socket() && connection_->socket()->IsConnectedAndIdle(); | 1098 return connection_->socket() && connection_->socket()->IsConnectedAndIdle(); |
| 996 } | 1099 } |
| 997 | 1100 |
| 1101 void HttpStreamParser::SetRestartInfo( |
| 1102 int64 read_offset, const void* hash, size_t hash_length) { |
| 1103 read_offset_ = read_offset; |
| 1104 stream_hash_->SetPreviousHash(hash, hash_length); |
| 1105 } |
| 1106 |
| 1107 void HttpStreamParser::GetHash(void* output, size_t hash_length) { |
| 1108 stream_hash_->Finish(output, hash_length); |
| 1109 } |
| 1110 |
| 998 void HttpStreamParser::GetSSLInfo(SSLInfo* ssl_info) { | 1111 void HttpStreamParser::GetSSLInfo(SSLInfo* ssl_info) { |
| 999 if (request_->url.SchemeIsSecure() && connection_->socket()) { | 1112 if (request_->url.SchemeIsSecure() && connection_->socket()) { |
| 1000 SSLClientSocket* ssl_socket = | 1113 SSLClientSocket* ssl_socket = |
| 1001 static_cast<SSLClientSocket*>(connection_->socket()); | 1114 static_cast<SSLClientSocket*>(connection_->socket()); |
| 1002 ssl_socket->GetSSLInfo(ssl_info); | 1115 ssl_socket->GetSSLInfo(ssl_info); |
| 1003 } | 1116 } |
| 1004 } | 1117 } |
| 1005 | 1118 |
| 1006 void HttpStreamParser::GetSSLCertRequestInfo( | 1119 void HttpStreamParser::GetSSLCertRequestInfo( |
| 1007 SSLCertRequestInfo* cert_request_info) { | 1120 SSLCertRequestInfo* cert_request_info) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1045 request_body->IsInMemory() && | 1158 request_body->IsInMemory() && |
| 1046 request_body->size() > 0) { | 1159 request_body->size() > 0) { |
| 1047 size_t merged_size = request_headers.size() + request_body->size(); | 1160 size_t merged_size = request_headers.size() + request_body->size(); |
| 1048 if (merged_size <= kMaxMergedHeaderAndBodySize) | 1161 if (merged_size <= kMaxMergedHeaderAndBodySize) |
| 1049 return true; | 1162 return true; |
| 1050 } | 1163 } |
| 1051 return false; | 1164 return false; |
| 1052 } | 1165 } |
| 1053 | 1166 |
| 1054 } // namespace net | 1167 } // namespace net |
| OLD | NEW |