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

Side by Side Diff: third_party/WebKit/Source/core/frame/csp/CSPSource.cpp

Issue 2708873002: Stop CSP from matching independent scheme/port upgrades (Closed)
Patch Set: rebase-update Created 3 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "core/frame/csp/CSPSource.h" 5 #include "core/frame/csp/CSPSource.h"
6 6
7 #include "core/frame/UseCounter.h" 7 #include "core/frame/UseCounter.h"
8 #include "core/frame/csp/ContentSecurityPolicy.h" 8 #include "core/frame/csp/ContentSecurityPolicy.h"
9 #include "platform/weborigin/KURL.h" 9 #include "platform/weborigin/KURL.h"
10 #include "platform/weborigin/KnownPorts.h" 10 #include "platform/weborigin/KnownPorts.h"
(...skipping 12 matching lines...) Expand all
23 : m_policy(policy), 23 : m_policy(policy),
24 m_scheme(scheme.lower()), 24 m_scheme(scheme.lower()),
25 m_host(host), 25 m_host(host),
26 m_port(port), 26 m_port(port),
27 m_path(path), 27 m_path(path),
28 m_hostWildcard(hostWildcard), 28 m_hostWildcard(hostWildcard),
29 m_portWildcard(portWildcard) {} 29 m_portWildcard(portWildcard) {}
30 30
31 bool CSPSource::matches(const KURL& url, 31 bool CSPSource::matches(const KURL& url,
32 ResourceRequest::RedirectStatus redirectStatus) const { 32 ResourceRequest::RedirectStatus redirectStatus) const {
33 bool schemesMatch = m_scheme.isEmpty() ? m_policy->protocolMatchesSelf(url) 33 SchemeMatchingResult schemesMatch = schemeMatches(url.protocol());
34 : schemeMatches(url.protocol()); 34 if (schemesMatch == SchemeMatchingResult::NotMatching)
35 if (!schemesMatch)
36 return false; 35 return false;
37 if (isSchemeOnly()) 36 if (isSchemeOnly())
38 return true; 37 return true;
39 bool pathsMatch = (redirectStatus == RedirectStatus::FollowedRedirect) || 38 bool pathsMatch = (redirectStatus == RedirectStatus::FollowedRedirect) ||
40 pathMatches(url.path()); 39 pathMatches(url.path());
41 return hostMatches(url.host()) && portMatches(url.port(), url.protocol()) && 40 PortMatchingResult portsMatch = portMatches(url.port(), url.protocol());
42 pathsMatch; 41
42 // if either the scheme or the port would require an upgrade (e.g. from http
43 // to https) then check that both of them can upgrade to ensure that we don't
44 // run into situations where we only upgrade the port but not the scheme or
45 // viceversa
46 if ((requiresUpgrade(schemesMatch) || (requiresUpgrade(portsMatch))) &&
47 (!canUpgrade(schemesMatch) || !canUpgrade(portsMatch))) {
48 return false;
49 }
50
51 return hostMatches(url.host()) && portsMatch != PortMatchingResult::NotMatchin g && pathsMatch;
43 } 52 }
44 53
45 bool CSPSource::schemeMatches(const String& protocol) const { 54 CSPSource::SchemeMatchingResult CSPSource::schemeMatches(
55 const String& protocol) const {
46 DCHECK_EQ(protocol, protocol.lower()); 56 DCHECK_EQ(protocol, protocol.lower());
47 if (m_scheme == "http") 57 const String& scheme =
48 return protocol == "http" || protocol == "https"; 58 (m_scheme.isEmpty() ? m_policy->getSelfProtocol() : m_scheme);
49 if (m_scheme == "ws") 59
50 return protocol == "ws" || protocol == "wss"; 60 if (scheme == protocol)
51 return protocol == m_scheme; 61 return SchemeMatchingResult::MatchingExact;
62
63 if ((scheme == "http" && protocol == "https") ||
64 (scheme == "http" && protocol == "https-so") ||
65 (scheme == "ws" && protocol == "wss")) {
66 return SchemeMatchingResult::MatchingUpgrade;
67 }
68
69 if ((scheme == "http" && protocol == "http-so") ||
70 (scheme == "https" && protocol == "https-so")) {
71 return SchemeMatchingResult::MatchingExact;
72 }
73
74 return SchemeMatchingResult::NotMatching;
52 } 75 }
53 76
54 bool CSPSource::hostMatches(const String& host) const { 77 bool CSPSource::hostMatches(const String& host) const {
55 Document* document = m_policy->document(); 78 Document* document = m_policy->document();
56 bool match; 79 bool match;
57 80
58 bool equalHosts = m_host == host; 81 bool equalHosts = m_host == host;
59 if (m_hostWildcard == HasWildcard) { 82 if (m_hostWildcard == HasWildcard) {
60 if (m_host.isEmpty()) { 83 if (m_host.isEmpty()) {
61 // host-part = "*" 84 // host-part = "*"
(...skipping 23 matching lines...) Expand all
85 return true; 108 return true;
86 109
87 String path = decodeURLEscapeSequences(urlPath); 110 String path = decodeURLEscapeSequences(urlPath);
88 111
89 if (m_path.endsWith("/")) 112 if (m_path.endsWith("/"))
90 return path.startsWith(m_path); 113 return path.startsWith(m_path);
91 114
92 return path == m_path; 115 return path == m_path;
93 } 116 }
94 117
95 bool CSPSource::portMatches(int port, const String& protocol) const { 118 CSPSource::PortMatchingResult CSPSource::portMatches(
119 int port,
120 const String& protocol) const {
96 if (m_portWildcard == HasWildcard) 121 if (m_portWildcard == HasWildcard)
97 return true; 122 return PortMatchingResult::MatchingWildcard;
98 123
99 if (port == m_port) 124 if (port == m_port) {
100 return true; 125 if (port == 0)
126 return PortMatchingResult::MatchingWildcard;
127 return PortMatchingResult::MatchingExact;
128 }
101 129
102 if (m_port == 80 && 130 bool isSchemeHttp; // needed for detecting an upgrade when the port is 0
131 isSchemeHttp = m_scheme.isEmpty() ? m_policy->protocolEqualsSelf("http")
132 : equalIgnoringCase("http", m_scheme);
133
134 if ((m_port == 80 || (m_port == 0 && isSchemeHttp)) &&
103 (port == 443 || (port == 0 && defaultPortForProtocol(protocol) == 443))) 135 (port == 443 || (port == 0 && defaultPortForProtocol(protocol) == 443)))
104 return true; 136 return PortMatchingResult::MatchingUpgrade;
105 137
106 if (!port) 138 if (!port) {
107 return isDefaultPortForProtocol(m_port, protocol); 139 if (isDefaultPortForProtocol(m_port, protocol))
140 return PortMatchingResult::MatchingExact;
108 141
109 if (!m_port) 142 return PortMatchingResult::NotMatching;
110 return isDefaultPortForProtocol(port, protocol); 143 }
111 144
112 return false; 145 if (!m_port) {
146 if (isDefaultPortForProtocol(port, protocol))
147 return PortMatchingResult::MatchingExact;
148
149 return PortMatchingResult::NotMatching;
150 }
151
152 return PortMatchingResult::NotMatching;
113 } 153 }
114 154
115 bool CSPSource::subsumes(CSPSource* other) const { 155 bool CSPSource::subsumes(CSPSource* other) const {
116 if (!schemeMatches(other->m_scheme)) 156 if (schemeMatches(other->m_scheme) == SchemeMatchingResult::NotMatching)
117 return false; 157 return false;
118 158
119 if (other->isSchemeOnly() || isSchemeOnly()) 159 if (other->isSchemeOnly() || isSchemeOnly())
120 return isSchemeOnly(); 160 return isSchemeOnly();
121 161
122 if ((m_hostWildcard == NoWildcard && other->m_hostWildcard == HasWildcard) || 162 if ((m_hostWildcard == NoWildcard && other->m_hostWildcard == HasWildcard) ||
123 (m_portWildcard == NoWildcard && other->m_portWildcard == HasWildcard)) { 163 (m_portWildcard == NoWildcard && other->m_portWildcard == HasWildcard)) {
124 return false; 164 return false;
125 } 165 }
126 166
127 bool hostSubsumes = (m_host == other->m_host || hostMatches(other->m_host)); 167 bool hostSubsumes = (m_host == other->m_host || hostMatches(other->m_host));
128 bool portSubsumes = (m_portWildcard == HasWildcard) || 168 bool portSubsumes = (m_portWildcard == HasWildcard) ||
129 portMatches(other->m_port, other->m_scheme); 169 portMatches(other->m_port, other->m_scheme) != PortMatchingResult::NotMatc hing;
130 bool pathSubsumes = pathMatches(other->m_path); 170 bool pathSubsumes = pathMatches(other->m_path);
131 return hostSubsumes && portSubsumes && pathSubsumes; 171 return hostSubsumes && portSubsumes && pathSubsumes;
132 } 172 }
133 173
134 bool CSPSource::isSimilar(CSPSource* other) const { 174 bool CSPSource::isSimilar(CSPSource* other) const {
135 bool schemesMatch = 175 bool schemesMatch =
136 schemeMatches(other->m_scheme) || other->schemeMatches(m_scheme); 176 schemeMatches(other->m_scheme) != SchemeMatchingResult::NotMatching
177 || other->schemeMatches(m_scheme) != SchemeMatchingResult::NotMatching;
137 if (!schemesMatch || isSchemeOnly() || other->isSchemeOnly()) 178 if (!schemesMatch || isSchemeOnly() || other->isSchemeOnly())
138 return schemesMatch; 179 return schemesMatch;
139 bool hostsMatch = (m_host == other->m_host) || hostMatches(other->m_host) || 180 bool hostsMatch = (m_host == other->m_host) || hostMatches(other->m_host) ||
140 other->hostMatches(m_host); 181 other->hostMatches(m_host);
141 bool portsMatch = (other->m_portWildcard == HasWildcard) || 182 bool portsMatch = (other->m_portWildcard == HasWildcard) ||
142 portMatches(other->m_port, other->m_scheme) || 183 portMatches(other->m_port, other->m_scheme) != PortMatchingResult::NotMatc hing ||
143 other->portMatches(m_port, m_scheme); 184 other->portMatches(m_port, m_scheme) != PortMatchingResult::NotMatching;
144 bool pathsMatch = pathMatches(other->m_path) || other->pathMatches(m_path); 185 bool pathsMatch = pathMatches(other->m_path) || other->pathMatches(m_path);
145 if (hostsMatch && portsMatch && pathsMatch) 186 if (hostsMatch && portsMatch && pathsMatch)
146 return true; 187 return true;
147 188
148 return false; 189 return false;
149 } 190 }
150 191
151 CSPSource* CSPSource::intersect(CSPSource* other) const { 192 CSPSource* CSPSource::intersect(CSPSource* other) const {
152 if (!isSimilar(other)) 193 if (!isSimilar(other))
153 return nullptr; 194 return nullptr;
154 195
155 String scheme = other->schemeMatches(m_scheme) ? m_scheme : other->m_scheme; 196 String scheme = other->schemeMatches(m_scheme) != SchemeMatchingResult::NotMat ching ? m_scheme : other->m_scheme;
156 if (isSchemeOnly() || other->isSchemeOnly()) { 197 if (isSchemeOnly() || other->isSchemeOnly()) {
157 const CSPSource* stricter = isSchemeOnly() ? other : this; 198 const CSPSource* stricter = isSchemeOnly() ? other : this;
158 return new CSPSource(m_policy, scheme, stricter->m_host, stricter->m_port, 199 return new CSPSource(m_policy, scheme, stricter->m_host, stricter->m_port,
159 stricter->m_path, stricter->m_hostWildcard, 200 stricter->m_path, stricter->m_hostWildcard,
160 stricter->m_portWildcard); 201 stricter->m_portWildcard);
161 } 202 }
162 203
163 String host = m_hostWildcard == NoWildcard ? m_host : other->m_host; 204 String host = m_hostWildcard == NoWildcard ? m_host : other->m_host;
164 // Since sources are similar and paths match, pick the longer one. 205 // Since sources are similar and paths match, pick the longer one.
165 String path = 206 String path =
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 static_cast<WebWildcardDisposition>(m_portWildcard); 258 static_cast<WebWildcardDisposition>(m_portWildcard);
218 sourceExpression.path = m_path; 259 sourceExpression.path = m_path;
219 return sourceExpression; 260 return sourceExpression;
220 } 261 }
221 262
222 DEFINE_TRACE(CSPSource) { 263 DEFINE_TRACE(CSPSource) {
223 visitor->trace(m_policy); 264 visitor->trace(m_policy);
224 } 265 }
225 266
226 } // namespace blink 267 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/frame/csp/CSPSource.h ('k') | third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698