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

Side by Side Diff: third_party/WebKit/Source/core/loader/BaseFetchContext.cpp

Issue 2823213002: Implement CanRequest in BaseFetchContext (Closed)
Patch Set: rebase, tests 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 "core/loader/BaseFetchContext.h" 5 #include "core/loader/BaseFetchContext.h"
6 6
7 #include "core/frame/csp/ContentSecurityPolicy.h" 7 #include "core/dom/ExecutionContext.h"
8 #include "core/frame/ContentSettingsClient.h"
9 #include "core/frame/Settings.h"
8 #include "core/inspector/ConsoleMessage.h" 10 #include "core/inspector/ConsoleMessage.h"
11 #include "core/loader/SubresourceFilter.h"
12 #include "core/loader/private/FrameClientHintsPreferencesContext.h"
13 #include "platform/exported/WrappedResourceRequest.h"
14 #include "platform/loader/fetch/FetchInitiatorTypeNames.h"
15 #include "platform/loader/fetch/Resource.h"
16 #include "platform/loader/fetch/ResourceLoadPriority.h"
17 #include "platform/loader/fetch/ResourceLoadingLog.h"
18 #include "platform/weborigin/SchemeRegistry.h"
9 #include "platform/weborigin/SecurityPolicy.h" 19 #include "platform/weborigin/SecurityPolicy.h"
10 20
11 namespace blink { 21 namespace blink {
12 22
13 BaseFetchContext::BaseFetchContext(ExecutionContext* context) 23 BaseFetchContext::BaseFetchContext(ExecutionContext* context)
14 : execution_context_(context) {} 24 : execution_context_(context) {}
15 25
16 void BaseFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request, 26 void BaseFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request,
17 FetchResourceType type) { 27 FetchResourceType type) {
18 bool is_main_resource = type == kFetchMainResource; 28 bool is_main_resource = type == kFetchMainResource;
(...skipping 17 matching lines...) Expand all
36 if (execution_context_) { 46 if (execution_context_) {
37 request.SetExternalRequestStateFromRequestorAddressSpace( 47 request.SetExternalRequestStateFromRequestorAddressSpace(
38 execution_context_->GetSecurityContext().AddressSpace()); 48 execution_context_->GetSecurityContext().AddressSpace());
39 } 49 }
40 } 50 }
41 51
42 SecurityOrigin* BaseFetchContext::GetSecurityOrigin() const { 52 SecurityOrigin* BaseFetchContext::GetSecurityOrigin() const {
43 return execution_context_ ? execution_context_->GetSecurityOrigin() : nullptr; 53 return execution_context_ ? execution_context_->GetSecurityOrigin() : nullptr;
44 } 54 }
45 55
56 ResourceRequestBlockedReason BaseFetchContext::CanRequest(
57 Resource::Type type,
58 const ResourceRequest& resource_request,
59 const KURL& url,
60 const ResourceLoaderOptions& options,
61 SecurityViolationReportingPolicy reporting_policy,
62 FetchParameters::OriginRestriction origin_restriction) const {
63 ResourceRequestBlockedReason blocked_reason = CanRequestInternal(
64 type, resource_request, url, options, reporting_policy,
65 origin_restriction, resource_request.GetRedirectStatus());
66 if (blocked_reason != ResourceRequestBlockedReason::kNone &&
67 reporting_policy == SecurityViolationReportingPolicy::kReport) {
68 DispatchDidBlockRequest(resource_request, options.initiator_info,
69 blocked_reason);
70 }
71 return blocked_reason;
72 }
73
74 ResourceRequestBlockedReason BaseFetchContext::CanFollowRedirect(
75 Resource::Type type,
76 const ResourceRequest& resource_request,
77 const KURL& url,
78 const ResourceLoaderOptions& options,
79 SecurityViolationReportingPolicy reporting_policy,
80 FetchParameters::OriginRestriction origin_restriction) const {
81 // CanRequestInternal checks enforced CSP, so check report-only here to ensure
82 // that violations are sent.
83 CheckCSPForRequest(resource_request, url, options, reporting_policy,
84 RedirectStatus::kFollowedRedirect,
85 ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly);
86 return CanRequest(type, resource_request, url, options, reporting_policy,
87 origin_restriction);
88 }
89
90 ResourceRequestBlockedReason BaseFetchContext::AllowResponse(
91 Resource::Type type,
92 const ResourceRequest& resource_request,
93 const KURL& url,
94 const ResourceLoaderOptions& options) const {
95 // CanRequestInternal only checks enforced policies: check report-only here
96 // to ensure violations are sent.
97 CheckCSPForRequest(resource_request, url, options,
98 SecurityViolationReportingPolicy::kReport,
99 RedirectStatus::kFollowedRedirect,
100 ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly);
101 ResourceRequestBlockedReason blocked_reason =
102 CanRequestInternal(type, resource_request, url, options,
103 SecurityViolationReportingPolicy::kReport,
104 FetchParameters::kUseDefaultOriginRestrictionForType,
105 RedirectStatus::kFollowedRedirect);
106 if (blocked_reason != ResourceRequestBlockedReason::kNone) {
107 DispatchDidBlockRequest(resource_request, options.initiator_info,
108 blocked_reason);
109 }
110 return blocked_reason;
111 }
112
46 void BaseFetchContext::PrintAccessDeniedMessage(const KURL& url) const { 113 void BaseFetchContext::PrintAccessDeniedMessage(const KURL& url) const {
47 if (url.IsNull()) 114 if (url.IsNull())
48 return; 115 return;
49 116
50 DCHECK(execution_context_); 117 DCHECK(execution_context_);
51 String message; 118 String message;
52 if (execution_context_->Url().IsNull()) { 119 if (execution_context_->Url().IsNull()) {
53 message = "Unsafe attempt to load URL " + url.ElidedString() + '.'; 120 message = "Unsafe attempt to load URL " + url.ElidedString() + '.';
54 } else if (url.IsLocalFile() || execution_context_->Url().IsLocalFile()) { 121 } else if (url.IsLocalFile() || execution_context_->Url().IsLocalFile()) {
55 message = "Unsafe attempt to load URL " + url.ElidedString() + 122 message = "Unsafe attempt to load URL " + url.ElidedString() +
(...skipping 15 matching lines...) Expand all
71 ResourceRequest& request) { 138 ResourceRequest& request) {
72 if (!execution_context_) 139 if (!execution_context_)
73 return; 140 return;
74 141
75 const ContentSecurityPolicy* csp = 142 const ContentSecurityPolicy* csp =
76 execution_context_->GetContentSecurityPolicy(); 143 execution_context_->GetContentSecurityPolicy();
77 if (csp->ShouldSendCSPHeader(type)) 144 if (csp->ShouldSendCSPHeader(type))
78 request.AddHTTPHeaderField("CSP", "active"); 145 request.AddHTTPHeaderField("CSP", "active");
79 } 146 }
80 147
148 ResourceRequestBlockedReason BaseFetchContext::CheckCSPForRequest(
149 const ResourceRequest& resource_request,
150 const KURL& url,
151 const ResourceLoaderOptions& options,
152 SecurityViolationReportingPolicy reporting_policy,
153 ResourceRequest::RedirectStatus redirect_status,
154 ContentSecurityPolicy::CheckHeaderType check_header_type) const {
155 if (ShouldBypassMainWorldCSP() || options.content_security_policy_option ==
156 kDoNotCheckContentSecurityPolicy) {
157 return ResourceRequestBlockedReason::kNone;
158 }
159
160 if (execution_context_) {
161 DCHECK(execution_context_->GetContentSecurityPolicy());
162 if (!execution_context_->GetContentSecurityPolicy()->AllowRequest(
163 resource_request.GetRequestContext(), url,
164 options.content_security_policy_nonce, options.integrity_metadata,
165 options.parser_disposition, redirect_status, reporting_policy,
166 check_header_type))
167 return ResourceRequestBlockedReason::CSP;
168 }
169 return ResourceRequestBlockedReason::kNone;
170 }
171
172 ResourceRequestBlockedReason BaseFetchContext::CanRequestInternal(
173 Resource::Type type,
174 const ResourceRequest& resource_request,
175 const KURL& url,
176 const ResourceLoaderOptions& options,
177 SecurityViolationReportingPolicy reporting_policy,
178 FetchParameters::OriginRestriction origin_restriction,
179 ResourceRequest::RedirectStatus redirect_status) const {
180 if (ShouldBlockRequestByInspector(resource_request))
181 return ResourceRequestBlockedReason::kInspector;
182
183 SecurityOrigin* security_origin = options.security_origin.Get();
184 if (!security_origin && execution_context_)
185 security_origin = execution_context_->GetSecurityOrigin();
186
187 if (origin_restriction != FetchParameters::kNoOriginRestriction &&
188 security_origin && !security_origin->CanDisplay(url)) {
189 if (reporting_policy == SecurityViolationReportingPolicy::kReport)
190 ReportLocalLoadFailed(url);
Nate Chapin 2017/04/21 18:33:07 Maybe add a TODO to make ReportLocalLoadFiled live
kinuko 2017/04/24 06:05:27 Yeah looks like. Done.
191 RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::requestResource URL was not "
192 "allowed by SecurityOrigin::CanDisplay";
193 return ResourceRequestBlockedReason::kOther;
194 }
195
196 // Some types of resources can be loaded only from the same origin. Other
197 // types of resources, like Images, Scripts, and CSS, can be loaded from
198 // any URL.
199 switch (type) {
200 case Resource::kMainResource:
201 case Resource::kImage:
202 case Resource::kCSSStyleSheet:
203 case Resource::kScript:
204 case Resource::kFont:
205 case Resource::kRaw:
206 case Resource::kLinkPrefetch:
207 case Resource::kTextTrack:
208 case Resource::kImportResource:
209 case Resource::kMedia:
210 case Resource::kManifest:
211 case Resource::kMock:
212 // By default these types of resources can be loaded from any origin.
213 // FIXME: Are we sure about Resource::kFont?
214 if (origin_restriction == FetchParameters::kRestrictToSameOrigin &&
215 !security_origin->CanRequest(url)) {
216 PrintAccessDeniedMessage(url);
217 return ResourceRequestBlockedReason::kOrigin;
218 }
219 break;
220 case Resource::kXSLStyleSheet:
221 DCHECK(RuntimeEnabledFeatures::xsltEnabled());
222 case Resource::kSVGDocument:
223 if (!security_origin->CanRequest(url)) {
224 PrintAccessDeniedMessage(url);
225 return ResourceRequestBlockedReason::kOrigin;
226 }
227 break;
228 }
229
230 // We check the 'report-only' headers before upgrading the request (in
231 // populateResourceRequest). We check the enforced headers here to ensure we
232 // block things we ought to block.
233 if (CheckCSPForRequest(
234 resource_request, url, options, reporting_policy, redirect_status,
235 ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) ==
236 ResourceRequestBlockedReason::CSP) {
237 return ResourceRequestBlockedReason::CSP;
238 }
239
240 if (type == Resource::kScript || type == Resource::kImportResource) {
241 if (GetContentSettingsClient() &&
242 !GetContentSettingsClient()->AllowScriptFromSource(
243 !GetSettings() || GetSettings()->GetScriptEnabled(), url)) {
244 GetContentSettingsClient()->DidNotAllowScript();
245 // TODO(estark): Use a different ResourceRequestBlockedReason here, since
246 // this check has nothing to do with CSP. https://crbug.com/600795
247 return ResourceRequestBlockedReason::CSP;
248 }
249 }
250
251 // SVG Images have unique security rules that prevent all subresource requests
252 // except for data urls.
253 if (type != Resource::kMainResource && IsSVGImageChromeClient() &&
254 !url.ProtocolIsData())
255 return ResourceRequestBlockedReason::kOrigin;
256
257 // Measure the number of legacy URL schemes ('ftp://') and the number of
258 // embedded-credential ('http://user:password@...') resources embedded as
259 // subresources.
260 if (resource_request.GetFrameType() != WebURLRequest::kFrameTypeTopLevel) {
261 if (GetMainResourceSecurityContext() &&
262 SchemeRegistry::ShouldTreatURLSchemeAsLegacy(url.Protocol()) &&
263 !SchemeRegistry::ShouldTreatURLSchemeAsLegacy(
264 GetMainResourceSecurityContext()
265 ->GetSecurityOrigin()
266 ->Protocol())) {
267 CountDeprecation(UseCounter::kLegacyProtocolEmbeddedAsSubresource);
268
269 // TODO(mkwst): Enabled by default in M59. Drop the runtime-enabled check
270 // in M60: https://www.chromestatus.com/feature/5709390967472128
271 if (RuntimeEnabledFeatures::blockLegacySubresourcesEnabled())
272 return ResourceRequestBlockedReason::kOrigin;
273 }
274
275 if ((!url.User().IsEmpty() || !url.Pass().IsEmpty()) &&
276 resource_request.GetRequestContext() !=
277 WebURLRequest::kRequestContextXMLHttpRequest) {
278 CountDeprecation(
279 UseCounter::kRequestedSubresourceWithEmbeddedCredentials);
280 // TODO(mkwst): Remove the runtime-enabled check in M59:
281 // https://www.chromestatus.com/feature/5669008342777856
282 if (RuntimeEnabledFeatures::blockCredentialedSubresourcesEnabled())
283 return ResourceRequestBlockedReason::kOrigin;
284 }
285 }
286
287 // Check for mixed content. We do this second-to-last so that when folks block
288 // mixed content with a CSP policy, they don't get a warning. They'll still
289 // get a warning in the console about CSP blocking the load.
290 if (ShouldBlockFetchByMixedContentCheck(resource_request, url,
291 reporting_policy))
292 return ResourceRequestBlockedReason::kMixedContent;
293
294 if (url.WhitespaceRemoved()) {
295 CountDeprecation(UseCounter::kCanRequestURLHTTPContainingNewline);
296 if (url.ProtocolIsInHTTPFamily()) {
297 if (RuntimeEnabledFeatures::restrictCanRequestURLCharacterSetEnabled())
298 return ResourceRequestBlockedReason::kOther;
299 } else {
300 CountUsage(UseCounter::kCanRequestURLNonHTTPContainingNewline);
301 }
302 }
303
304 // Let the client have the final say into whether or not the load should
305 // proceed.
306 if (GetSubresourceFilter() && type != Resource::kMainResource &&
307 type != Resource::kImportResource) {
308 if (!GetSubresourceFilter()->AllowLoad(
309 url, resource_request.GetRequestContext(), reporting_policy)) {
310 return ResourceRequestBlockedReason::kSubresourceFilter;
311 }
312 }
313
314 return ResourceRequestBlockedReason::kNone;
315 }
316
81 DEFINE_TRACE(BaseFetchContext) { 317 DEFINE_TRACE(BaseFetchContext) {
82 visitor->Trace(execution_context_); 318 visitor->Trace(execution_context_);
83 FetchContext::Trace(visitor); 319 FetchContext::Trace(visitor);
84 } 320 }
85 321
86 } // namespace blink 322 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698