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

Side by Side Diff: net/http/http_stream_parser.cc

Issue 9757002: Allow multiple identical Location and Content-Disposition headers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Fix comments, update strings Created 8 years, 9 months 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 | Annotate | Revision Log
« no previous file with comments | « net/http/http_network_transaction_spdy3_unittest.cc ('k') | no next file » | 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/http/http_stream_parser.h" 5 #include "net/http/http_stream_parser.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "net/base/address_list.h" 10 #include "net/base/address_list.h"
(...skipping 19 matching lines...) Expand all
30 const char* header_line = null_separated_headers; 30 const char* header_line = null_separated_headers;
31 std::string cr_separated_headers; 31 std::string cr_separated_headers;
32 while (header_line[0] != 0) { 32 while (header_line[0] != 0) {
33 cr_separated_headers += header_line; 33 cr_separated_headers += header_line;
34 cr_separated_headers += "\n"; 34 cr_separated_headers += "\n";
35 header_line += strlen(header_line) + 1; 35 header_line += strlen(header_line) + 1;
36 } 36 }
37 return cr_separated_headers; 37 return cr_separated_headers;
38 } 38 }
39 39
40 // Return true if |headers| contain multiple |field_name| fields. If 40 // Return true if |headers| contain multiple |field_name| fields.
41 // |count_same_value| is false, returns false if all copies of the field have
42 // the same value.
43 bool HeadersContainMultipleCopiesOfField( 41 bool HeadersContainMultipleCopiesOfField(
44 const net::HttpResponseHeaders& headers, 42 const net::HttpResponseHeaders& headers,
45 const std::string& field_name, 43 const std::string& field_name) {
46 bool count_same_value) {
47 void* it = NULL; 44 void* it = NULL;
48 std::string field_value; 45 std::string field_value;
49 if (!headers.EnumerateHeader(&it, field_name, &field_value)) 46 if (!headers.EnumerateHeader(&it, field_name, &field_value))
50 return false; 47 return false;
51 // There's at least one |field_name| header. Check if there are any more 48 // There's at least one |field_name| header. Check if there are any more
52 // such headers, and if so, return true if they have different values or 49 // such headers, and if so, return true if they have different values or
53 // |count_same_value| is true. 50 // |count_same_value| is true.
54 std::string field_value2; 51 std::string field_value2;
55 while (headers.EnumerateHeader(&it, field_name, &field_value2)) { 52 while (headers.EnumerateHeader(&it, field_name, &field_value2)) {
56 if (count_same_value || field_value != field_value2) 53 if (field_value != field_value2)
57 return true; 54 return true;
58 } 55 }
59 return false; 56 return false;
60 } 57 }
61 58
62 } // namespace 59 } // namespace
63 60
64 namespace net { 61 namespace net {
65 62
66 // Similar to DrainableIOBuffer(), but this version comes with its own 63 // Similar to DrainableIOBuffer(), but this version comes with its own
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset)); 767 read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset));
771 } else { 768 } else {
772 // Enough data was read -- there is no status line. 769 // Enough data was read -- there is no status line.
773 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); 770 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK"));
774 } 771 }
775 772
776 // Check for multiple Content-Length headers with no Transfer-Encoding header. 773 // Check for multiple Content-Length headers with no Transfer-Encoding header.
777 // If they exist, and have distinct values, it's a potential response 774 // If they exist, and have distinct values, it's a potential response
778 // smuggling attack. 775 // smuggling attack.
779 if (!headers->HasHeader("Transfer-Encoding")) { 776 if (!headers->HasHeader("Transfer-Encoding")) {
780 if (HeadersContainMultipleCopiesOfField(*headers, 777 if (HeadersContainMultipleCopiesOfField(*headers, "Content-Length"))
781 "Content-Length",
782 false)) {
783 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; 778 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH;
784 }
785 } 779 }
786 780
787 // Check for multiple Content-Disposition or Location headers. If they exist, 781 // Check for multiple Content-Disposition or Location headers. If they exist,
788 // it's also a potential response smuggling attack. 782 // it's also a potential response smuggling attack.
789 if (HeadersContainMultipleCopiesOfField(*headers, 783 if (HeadersContainMultipleCopiesOfField(*headers, "Content-Disposition"))
790 "Content-Disposition",
791 true)) {
792 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION; 784 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION;
793 } 785 if (HeadersContainMultipleCopiesOfField(*headers, "Location"))
794 if (HeadersContainMultipleCopiesOfField(*headers, "Location", true))
795 return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION; 786 return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION;
796 787
797 response_->headers = headers; 788 response_->headers = headers;
798 response_->vary_data.Init(*request_, *response_->headers); 789 response_->vary_data.Init(*request_, *response_->headers);
799 DVLOG(1) << __FUNCTION__ << "()" 790 DVLOG(1) << __FUNCTION__ << "()"
800 << " content_length = \"" 791 << " content_length = \""
801 << response_->headers->GetContentLength() << "\n\"" 792 << response_->headers->GetContentLength() << "\n\""
802 << " headers = \"" << GetResponseHeaderLines(*response_->headers) 793 << " headers = \"" << GetResponseHeaderLines(*response_->headers)
803 << "\""; 794 << "\"";
804 return OK; 795 return OK;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 request_body->IsInMemory() && 924 request_body->IsInMemory() &&
934 request_body->size() > 0) { 925 request_body->size() > 0) {
935 size_t merged_size = request_headers.size() + request_body->size(); 926 size_t merged_size = request_headers.size() + request_body->size();
936 if (merged_size <= kMaxMergedHeaderAndBodySize) 927 if (merged_size <= kMaxMergedHeaderAndBodySize)
937 return true; 928 return true;
938 } 929 }
939 return false; 930 return false;
940 } 931 }
941 932
942 } // namespace net 933 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_network_transaction_spdy3_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698