| 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_macros.h" |
| 10 #include "base/profiler/scoped_tracker.h" | 11 #include "base/profiler/scoped_tracker.h" |
| 11 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 12 #include "base/values.h" | 13 #include "base/values.h" |
| 13 #include "net/base/io_buffer.h" | 14 #include "net/base/io_buffer.h" |
| 14 #include "net/base/ip_endpoint.h" | 15 #include "net/base/ip_endpoint.h" |
| 15 #include "net/base/upload_data_stream.h" | 16 #include "net/base/upload_data_stream.h" |
| 16 #include "net/http/http_chunked_decoder.h" | 17 #include "net/http/http_chunked_decoder.h" |
| 17 #include "net/http/http_request_headers.h" | 18 #include "net/http/http_request_headers.h" |
| 18 #include "net/http/http_request_info.h" | 19 #include "net/http/http_request_info.h" |
| 19 #include "net/http/http_response_headers.h" | 20 #include "net/http/http_response_headers.h" |
| 20 #include "net/http/http_util.h" | 21 #include "net/http/http_util.h" |
| 21 #include "net/socket/client_socket_handle.h" | 22 #include "net/socket/client_socket_handle.h" |
| 22 #include "net/socket/ssl_client_socket.h" | 23 #include "net/socket/ssl_client_socket.h" |
| 23 | 24 |
| 24 namespace net { | 25 namespace net { |
| 25 | 26 |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 29 enum HttpHeaderParserEvent { |
| 30 HEADER_PARSER_INVOKED = 0, |
| 31 HEADER_HTTP_09_RESPONSE = 1, |
| 32 HEADER_ALLOWED_TRUNCATED_HEADERS = 2, |
| 33 HEADER_SKIPPED_WS_PREFIX = 3, |
| 34 HEADER_SKIPPED_NON_WS_PREFIX = 4, |
| 35 NUM_HEADER_EVENTS |
| 36 }; |
| 37 |
| 38 void RecordHeaderParserEvent(HttpHeaderParserEvent header_event) { |
| 39 UMA_HISTOGRAM_ENUMERATION("Net.HttpHeaderParserEvent", header_event, |
| 40 NUM_HEADER_EVENTS); |
| 41 } |
| 42 |
| 28 const uint64 kMaxMergedHeaderAndBodySize = 1400; | 43 const uint64 kMaxMergedHeaderAndBodySize = 1400; |
| 29 const size_t kRequestBodyBufferSize = 1 << 14; // 16KB | 44 const size_t kRequestBodyBufferSize = 1 << 14; // 16KB |
| 30 | 45 |
| 31 std::string GetResponseHeaderLines(const HttpResponseHeaders& headers) { | 46 std::string GetResponseHeaderLines(const HttpResponseHeaders& headers) { |
| 32 std::string raw_headers = headers.raw_headers(); | 47 std::string raw_headers = headers.raw_headers(); |
| 33 const char* null_separated_headers = raw_headers.c_str(); | 48 const char* null_separated_headers = raw_headers.c_str(); |
| 34 const char* header_line = null_separated_headers; | 49 const char* header_line = null_separated_headers; |
| 35 std::string cr_separated_headers; | 50 std::string cr_separated_headers; |
| 36 while (header_line[0] != 0) { | 51 while (header_line[0] != 0) { |
| 37 cr_separated_headers += header_line; | 52 cr_separated_headers += header_line; |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 } else if (request_->url.SchemeIsSecure()) { | 836 } else if (request_->url.SchemeIsSecure()) { |
| 822 // The connection was closed in the middle of the headers. For HTTPS we | 837 // The connection was closed in the middle of the headers. For HTTPS we |
| 823 // don't parse partial headers. Return a different error code so that we | 838 // don't parse partial headers. Return a different error code so that we |
| 824 // know that we shouldn't attempt to retry the request. | 839 // know that we shouldn't attempt to retry the request. |
| 825 io_state_ = STATE_DONE; | 840 io_state_ = STATE_DONE; |
| 826 return ERR_RESPONSE_HEADERS_TRUNCATED; | 841 return ERR_RESPONSE_HEADERS_TRUNCATED; |
| 827 } | 842 } |
| 828 // Parse things as well as we can and let the caller decide what to do. | 843 // Parse things as well as we can and let the caller decide what to do. |
| 829 int end_offset; | 844 int end_offset; |
| 830 if (response_header_start_offset_ >= 0) { | 845 if (response_header_start_offset_ >= 0) { |
| 846 // The response looks to be a truncated set of HTTP headers. |
| 831 io_state_ = STATE_READ_BODY_COMPLETE; | 847 io_state_ = STATE_READ_BODY_COMPLETE; |
| 832 end_offset = read_buf_->offset(); | 848 end_offset = read_buf_->offset(); |
| 849 RecordHeaderParserEvent(HEADER_ALLOWED_TRUNCATED_HEADERS); |
| 833 } else { | 850 } else { |
| 834 // Now waiting for the body to be read. | 851 // The response is apparently using HTTP/0.9. Treat the entire response |
| 852 // the body. |
| 835 end_offset = 0; | 853 end_offset = 0; |
| 836 } | 854 } |
| 837 int rv = DoParseResponseHeaders(end_offset); | 855 int rv = ParseResponseHeaders(end_offset); |
| 838 if (rv < 0) | 856 if (rv < 0) |
| 839 return rv; | 857 return rv; |
| 840 return result; | 858 return result; |
| 841 } | 859 } |
| 842 | 860 |
| 843 read_buf_->set_offset(read_buf_->offset() + result); | 861 read_buf_->set_offset(read_buf_->offset() + result); |
| 844 DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); | 862 DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); |
| 845 DCHECK_GE(result, 0); | 863 DCHECK_GE(result, 0); |
| 846 | 864 |
| 847 int end_of_header_offset = ParseResponseHeaders(); | 865 int end_of_header_offset = FindAndParseResponseHeaders(); |
| 848 | 866 |
| 849 // Note: -1 is special, it indicates we haven't found the end of headers. | 867 // Note: -1 is special, it indicates we haven't found the end of headers. |
| 850 // Anything less than -1 is a net::Error, so we bail out. | 868 // Anything less than -1 is a net::Error, so we bail out. |
| 851 if (end_of_header_offset < -1) | 869 if (end_of_header_offset < -1) |
| 852 return end_of_header_offset; | 870 return end_of_header_offset; |
| 853 | 871 |
| 854 if (end_of_header_offset == -1) { | 872 if (end_of_header_offset == -1) { |
| 855 io_state_ = STATE_READ_HEADERS; | 873 io_state_ = STATE_READ_HEADERS; |
| 856 // Prevent growing the headers buffer indefinitely. | 874 // Prevent growing the headers buffer indefinitely. |
| 857 if (read_buf_->offset() >= kMaxHeaderBufSize) { | 875 if (read_buf_->offset() >= kMaxHeaderBufSize) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 888 return OK; | 906 return OK; |
| 889 } | 907 } |
| 890 | 908 |
| 891 // Note where the headers stop. | 909 // Note where the headers stop. |
| 892 read_buf_unused_offset_ = end_of_header_offset; | 910 read_buf_unused_offset_ = end_of_header_offset; |
| 893 // Now waiting for the body to be read. | 911 // Now waiting for the body to be read. |
| 894 } | 912 } |
| 895 return result; | 913 return result; |
| 896 } | 914 } |
| 897 | 915 |
| 898 int HttpStreamParser::ParseResponseHeaders() { | 916 int HttpStreamParser::FindAndParseResponseHeaders() { |
| 899 int end_offset = -1; | 917 int end_offset = -1; |
| 900 DCHECK_EQ(0, read_buf_unused_offset_); | 918 DCHECK_EQ(0, read_buf_unused_offset_); |
| 901 | 919 |
| 902 // Look for the start of the status line, if it hasn't been found yet. | 920 // Look for the start of the status line, if it hasn't been found yet. |
| 903 if (response_header_start_offset_ < 0) { | 921 if (response_header_start_offset_ < 0) { |
| 904 response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( | 922 response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( |
| 905 read_buf_->StartOfBuffer(), read_buf_->offset()); | 923 read_buf_->StartOfBuffer(), read_buf_->offset()); |
| 906 } | 924 } |
| 907 | 925 |
| 908 if (response_header_start_offset_ >= 0) { | 926 if (response_header_start_offset_ >= 0) { |
| 909 end_offset = HttpUtil::LocateEndOfHeaders(read_buf_->StartOfBuffer(), | 927 end_offset = HttpUtil::LocateEndOfHeaders(read_buf_->StartOfBuffer(), |
| 910 read_buf_->offset(), | 928 read_buf_->offset(), |
| 911 response_header_start_offset_); | 929 response_header_start_offset_); |
| 912 } else if (read_buf_->offset() >= 8) { | 930 } else if (read_buf_->offset() >= 8) { |
| 913 // Enough data to decide that this is an HTTP/0.9 response. | 931 // Enough data to decide that this is an HTTP/0.9 response. |
| 914 // 8 bytes = (4 bytes of junk) + "http".length() | 932 // 8 bytes = (4 bytes of junk) + "http".length() |
| 915 end_offset = 0; | 933 end_offset = 0; |
| 916 } | 934 } |
| 917 | 935 |
| 918 if (end_offset == -1) | 936 if (end_offset == -1) |
| 919 return -1; | 937 return -1; |
| 920 | 938 |
| 921 int rv = DoParseResponseHeaders(end_offset); | 939 int rv = ParseResponseHeaders(end_offset); |
| 922 if (rv < 0) | 940 if (rv < 0) |
| 923 return rv; | 941 return rv; |
| 924 return end_offset; | 942 return end_offset; |
| 925 } | 943 } |
| 926 | 944 |
| 927 int HttpStreamParser::DoParseResponseHeaders(int end_offset) { | 945 int HttpStreamParser::ParseResponseHeaders(int end_offset) { |
| 928 scoped_refptr<HttpResponseHeaders> headers; | 946 scoped_refptr<HttpResponseHeaders> headers; |
| 929 DCHECK_EQ(0, read_buf_unused_offset_); | 947 DCHECK_EQ(0, read_buf_unused_offset_); |
| 930 | 948 |
| 949 RecordHeaderParserEvent(HEADER_PARSER_INVOKED); |
| 950 |
| 951 if (response_header_start_offset_ > 0) { |
| 952 bool has_non_whitespace_in_prefix = false; |
| 953 for (int i = 0; i < response_header_start_offset_; ++i) { |
| 954 if (!strchr(" \t\r\n", read_buf_->StartOfBuffer()[i])) { |
| 955 has_non_whitespace_in_prefix = true; |
| 956 break; |
| 957 } |
| 958 } |
| 959 if (has_non_whitespace_in_prefix) { |
| 960 RecordHeaderParserEvent(HEADER_SKIPPED_NON_WS_PREFIX); |
| 961 } else { |
| 962 RecordHeaderParserEvent(HEADER_SKIPPED_WS_PREFIX); |
| 963 } |
| 964 } |
| 965 |
| 931 if (response_header_start_offset_ >= 0) { | 966 if (response_header_start_offset_ >= 0) { |
| 932 received_bytes_ += end_offset; | 967 received_bytes_ += end_offset; |
| 933 headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( | 968 headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( |
| 934 read_buf_->StartOfBuffer(), end_offset)); | 969 read_buf_->StartOfBuffer(), end_offset)); |
| 935 } else { | 970 } else { |
| 936 // Enough data was read -- there is no status line. | 971 // Enough data was read -- there is no status line. |
| 937 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); | 972 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); |
| 973 RecordHeaderParserEvent(HEADER_HTTP_09_RESPONSE); |
| 938 } | 974 } |
| 939 | 975 |
| 940 // Check for multiple Content-Length headers with no Transfer-Encoding header. | 976 // Check for multiple Content-Length headers with no Transfer-Encoding header. |
| 941 // If they exist, and have distinct values, it's a potential response | 977 // If they exist, and have distinct values, it's a potential response |
| 942 // smuggling attack. | 978 // smuggling attack. |
| 943 if (!headers->HasHeader("Transfer-Encoding")) { | 979 if (!headers->HasHeader("Transfer-Encoding")) { |
| 944 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Content-Length")) | 980 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Content-Length")) |
| 945 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; | 981 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; |
| 946 } | 982 } |
| 947 | 983 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1093 request_body->IsInMemory() && | 1129 request_body->IsInMemory() && |
| 1094 request_body->size() > 0) { | 1130 request_body->size() > 0) { |
| 1095 uint64 merged_size = request_headers.size() + request_body->size(); | 1131 uint64 merged_size = request_headers.size() + request_body->size(); |
| 1096 if (merged_size <= kMaxMergedHeaderAndBodySize) | 1132 if (merged_size <= kMaxMergedHeaderAndBodySize) |
| 1097 return true; | 1133 return true; |
| 1098 } | 1134 } |
| 1099 return false; | 1135 return false; |
| 1100 } | 1136 } |
| 1101 | 1137 |
| 1102 } // namespace net | 1138 } // namespace net |
| OLD | NEW |