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

Side by Side Diff: content/common/content_security_policy/csp_source.cc

Issue 2797183002: CSP: Allow secure upgrade from an explicitly insecure expression. (Closed)
Patch Set: Created 3 years, 8 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
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 <sstream> 5 #include <sstream>
6 6
7 #include "base/strings/string_util.h" 7 #include "base/strings/string_util.h"
8 #include "base/strings/utf_string_conversions.h" 8 #include "base/strings/utf_string_conversions.h"
9 #include "content/common/content_security_policy/csp_context.h" 9 #include "content/common/content_security_policy/csp_context.h"
10 #include "url/url_canon.h" 10 #include "url/url_canon.h"
11 #include "url/url_util.h" 11 #include "url/url_util.h"
12 12
13 namespace content { 13 namespace content {
14 14
15 namespace { 15 namespace {
16 16
17 bool DecodePath(const base::StringPiece& path, std::string* output) { 17 bool DecodePath(const base::StringPiece& path, std::string* output) {
18 url::RawCanonOutputT<base::char16> unescaped; 18 url::RawCanonOutputT<base::char16> unescaped;
19 url::DecodeURLEscapeSequences(path.data(), path.size(), &unescaped); 19 url::DecodeURLEscapeSequences(path.data(), path.size(), &unescaped);
20 return base::UTF16ToUTF8(unescaped.data(), unescaped.length(), output); 20 return base::UTF16ToUTF8(unescaped.data(), unescaped.length(), output);
21 } 21 }
22 22
23 int DefaultPortForScheme(const std::string& scheme) { 23 int DefaultPortForScheme(const base::StringPiece& scheme) {
24 return url::DefaultPortForScheme(scheme.data(), scheme.size()); 24 return url::DefaultPortForScheme(scheme.data(), scheme.size());
25 } 25 }
26 26
27 bool SourceAllowScheme(const CSPSource& source, 27 bool SourceAllowScheme(const CSPSource& source,
28 const GURL& url, 28 const base::StringPiece& scheme,
29 CSPContext* context) { 29 CSPContext* context) {
30 if (source.scheme.empty()) 30 const std::string& source_scheme =
31 return context->ProtocolMatchesSelf(url); 31 source.scheme.empty() ? context->GetSelfScheme() : source.scheme;
32 if (source.scheme == url::kHttpScheme) 32
33 return url.SchemeIsHTTPOrHTTPS(); 33 return (scheme == source_scheme) ||
34 if (source.scheme == url::kWsScheme) 34 (source_scheme == url::kHttpScheme &&
35 return url.SchemeIsWSOrWSS(); 35 scheme == url::kHttpSuboriginScheme) ||
36 return url.SchemeIs(source.scheme); 36 (source_scheme == url::kHttpsScheme &&
37 scheme == url::kHttpsSuboriginScheme);
37 } 38 }
38 39
39 bool SourceAllowHost(const CSPSource& source, const GURL& url) { 40 bool SourceAllowHost(const CSPSource& source, const GURL& url) {
40 if (source.is_host_wildcard) { 41 if (source.is_host_wildcard) {
41 if (source.host.empty()) 42 if (source.host.empty())
42 return true; 43 return true;
43 // TODO(arthursonzogni): Chrome used to, incorrectly, match *.x.y to x.y. 44 // TODO(arthursonzogni): Chrome used to, incorrectly, match *.x.y to x.y.
44 // The renderer version of this function count how many times it happens. 45 // The renderer version of this function count how many times it happens.
45 // It might be useful to do it outside of blink too. 46 // It might be useful to do it outside of blink too.
46 // See third_party/WebKit/Source/core/frame/csp/CSPSource.cpp 47 // See third_party/WebKit/Source/core/frame/csp/CSPSource.cpp
47 return base::EndsWith(url.host(), '.' + source.host, 48 return base::EndsWith(url.host(), '.' + source.host,
48 base::CompareCase::INSENSITIVE_ASCII); 49 base::CompareCase::INSENSITIVE_ASCII);
49 } else 50 } else
50 return url.host() == source.host; 51 return url.host() == source.host;
51 } 52 }
52 53
53 bool SourceAllowPort(const CSPSource& source, const GURL& url) { 54 bool SourceAllowPort(const CSPSource& source,
54 int url_port = url.EffectiveIntPort(); 55 const base::StringPiece& scheme,
55 56 int port) {
56 if (source.is_port_wildcard) 57 if (source.is_port_wildcard)
57 return true; 58 return true;
58 59
59 if (source.port == url::PORT_UNSPECIFIED) 60 if (source.port == url::PORT_UNSPECIFIED)
60 return DefaultPortForScheme(url.scheme()) == url_port; 61 return DefaultPortForScheme(scheme) == port;
61 62
62 if (source.port == url_port) 63 if (source.port == port)
63 return true;
64
65 if (source.port == 80 && url_port == 443)
66 return true; 64 return true;
67 65
68 return false; 66 return false;
69 } 67 }
70 68
71 bool SourceAllowPath(const CSPSource& source, 69 bool SourceAllowPath(const CSPSource& source,
72 const GURL& url, 70 const GURL& url,
73 bool is_redirect) { 71 bool is_redirect) {
74 if (is_redirect) 72 if (is_redirect)
75 return true; 73 return true;
(...skipping 10 matching lines...) Expand all
86 84
87 // If the path represents a directory. 85 // If the path represents a directory.
88 if (base::EndsWith(source.path, "/", base::CompareCase::SENSITIVE)) 86 if (base::EndsWith(source.path, "/", base::CompareCase::SENSITIVE))
89 return base::StartsWith(url_path, source.path, 87 return base::StartsWith(url_path, source.path,
90 base::CompareCase::SENSITIVE); 88 base::CompareCase::SENSITIVE);
91 89
92 // The path represents a file. 90 // The path represents a file.
93 return source.path == url_path; 91 return source.path == url_path;
94 } 92 }
95 93
94 bool AllowInternal(const CSPSource& source,
95 const GURL& url,
96 const base::StringPiece& scheme,
97 int port,
98 CSPContext* context,
99 bool is_redirect) {
100 if (source.IsSchemeOnly())
101 return SourceAllowScheme(source, scheme, context);
102
103 return SourceAllowScheme(source, scheme, context) &&
104 SourceAllowHost(source, url) &&
105 SourceAllowPort(source, scheme, port) &&
106 SourceAllowPath(source, url, is_redirect);
107 }
108
96 } // namespace 109 } // namespace
97 110
98 CSPSource::CSPSource() 111 CSPSource::CSPSource()
99 : scheme(), 112 : scheme(),
100 host(), 113 host(),
101 is_host_wildcard(false), 114 is_host_wildcard(false),
102 port(url::PORT_UNSPECIFIED), 115 port(url::PORT_UNSPECIFIED),
103 is_port_wildcard(false), 116 is_port_wildcard(false),
104 path() {} 117 path() {}
105 118
(...skipping 15 matching lines...) Expand all
121 } 134 }
122 135
123 CSPSource::CSPSource(const CSPSource& source) = default; 136 CSPSource::CSPSource(const CSPSource& source) = default;
124 CSPSource::~CSPSource() = default; 137 CSPSource::~CSPSource() = default;
125 138
126 // static 139 // static
127 bool CSPSource::Allow(const CSPSource& source, 140 bool CSPSource::Allow(const CSPSource& source,
128 const GURL& url, 141 const GURL& url,
129 CSPContext* context, 142 CSPContext* context,
130 bool is_redirect) { 143 bool is_redirect) {
131 if (source.IsSchemeOnly()) 144 base::StringPiece scheme = url.scheme_piece();
132 return SourceAllowScheme(source, url, context); 145 int port = url.EffectiveIntPort();
133 146
134 return SourceAllowScheme(source, url, context) && 147 if (AllowInternal(source, url, scheme, port, context, is_redirect))
135 SourceAllowHost(source, url) && SourceAllowPort(source, url) && 148 return true;
136 SourceAllowPath(source, url, is_redirect); 149
150 // A secure upgrade from an explicitly insecure expression is always allowed.
151 const struct {
152 std::string insecure_scheme;
153 std::string secure_scheme;
154 int insecure_port;
155 int secure_port;
156 } kUpgrade[] = {
157 {url::kHttpScheme, url::kHttpsScheme, 80, 443},
158 {url::kHttpSuboriginScheme, url::kHttpsSuboriginScheme, 80, 443},
159 {url::kWsScheme, url::kWssScheme, 80, 443},
160 };
161 for (const auto& upgrade : kUpgrade) {
162 if (scheme == upgrade.secure_scheme && port == upgrade.secure_port) {
163 return AllowInternal(source, url, upgrade.insecure_scheme,
164 upgrade.insecure_port, context, is_redirect);
165 }
166 }
167
168 return false;
137 } 169 }
138 170
139 std::string CSPSource::ToString() const { 171 std::string CSPSource::ToString() const {
140 // scheme 172 // scheme
141 if (IsSchemeOnly()) 173 if (IsSchemeOnly())
142 return scheme + ":"; 174 return scheme + ":";
143 175
144 std::stringstream text; 176 std::stringstream text;
145 if (!scheme.empty()) 177 if (!scheme.empty())
146 text << scheme << "://"; 178 text << scheme << "://";
(...skipping 30 matching lines...) Expand all
177 209
178 bool CSPSource::HasHost() const { 210 bool CSPSource::HasHost() const {
179 return !host.empty() || is_host_wildcard; 211 return !host.empty() || is_host_wildcard;
180 } 212 }
181 213
182 bool CSPSource::HasPath() const { 214 bool CSPSource::HasPath() const {
183 return !path.empty(); 215 return !path.empty();
184 } 216 }
185 217
186 } // namespace content 218 } // namespace content
OLDNEW
« no previous file with comments | « content/common/content_security_policy/csp_context.cc ('k') | content/common/content_security_policy/csp_source_list.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698