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

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

Issue 2790693002: Split CSP into pre- and post-upgrade checks (Closed)
Patch Set: revert accidental AbstractWorker change 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 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights
3 * reserved. 3 * reserved.
4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
5 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. 5 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
6 * (http://www.torchmobile.com/) 6 * (http://www.torchmobile.com/)
7 * Copyright (C) 2008 Alp Toker <alp@atoker.com> 7 * Copyright (C) 2008 Alp Toker <alp@atoker.com>
8 * Copyright (C) Research In Motion Limited 2009. All rights reserved. 8 * Copyright (C) Research In Motion Limited 2009. All rights reserved.
9 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> 9 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
10 * Copyright (C) 2011 Google Inc. All rights reserved. 10 * Copyright (C) 2011 Google Inc. All rights reserved.
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 return; 132 return;
133 } 133 }
134 if (SchemeRegistry::ShouldTreatURLSchemeAsLegacy( 134 if (SchemeRegistry::ShouldTreatURLSchemeAsLegacy(
135 document->GetSecurityOrigin()->Protocol())) { 135 document->GetSecurityOrigin()->Protocol())) {
136 return; 136 return;
137 } 137 }
138 Deprecation::CountDeprecation( 138 Deprecation::CountDeprecation(
139 document, UseCounter::kLegacyProtocolEmbeddedAsSubresource); 139 document, UseCounter::kLegacyProtocolEmbeddedAsSubresource);
140 } 140 }
141 141
142 static NavigationPolicy MaybeCheckCSP(
143 const ResourceRequest& request,
144 NavigationType type,
145 LocalFrame* frame,
146 NavigationPolicy policy,
147 bool should_check_main_world_content_security_policy,
148 bool browser_side_navigation_enabled,
149 ContentSecurityPolicy::CheckHeaderType check_header_type) {
150 // If we're loading content into |frame| (NavigationPolicyCurrentTab), check
151 // against the parent's Content Security Policy and kill the load if that
152 // check fails, unless we should bypass the main world's CSP.
153 if (policy == kNavigationPolicyCurrentTab &&
154 should_check_main_world_content_security_policy &&
155 // TODO(arthursonzogni): 'frame-src' check is disabled on the
156 // renderer side with browser-side-navigation, but is enforced on the
157 // browser side. See http://crbug.com/692595 for understanding why it
158 // can't be enforced on both sides instead.
159 !browser_side_navigation_enabled) {
160 Frame* parent_frame = frame->Tree().Parent();
161 if (parent_frame) {
162 ContentSecurityPolicy* parent_policy =
163 parent_frame->GetSecurityContext()->GetContentSecurityPolicy();
164 if (!parent_policy->AllowFrameFromSource(
165 request.Url(), request.GetRedirectStatus(),
166 SecurityViolationReportingPolicy::kReport, check_header_type)) {
167 // Fire a load event, as timing attacks would otherwise reveal that the
168 // frame was blocked. This way, it looks like every other cross-origin
169 // page load.
170 frame->GetDocument()->EnforceSandboxFlags(kSandboxOrigin);
171 frame->Owner()->DispatchLoad();
172 return kNavigationPolicyIgnore;
173 }
174 }
175 }
176
177 bool is_form_submission = type == kNavigationTypeFormSubmitted ||
178 type == kNavigationTypeFormResubmitted;
179 if (is_form_submission &&
180 // 'form-action' check in the frame that is navigating is disabled on the
181 // renderer side when PlzNavigate is enabled, but is enforced on the
182 // browser side instead.
183 // N.B. check in the frame that initiates the navigation stills occurs in
184 // blink and is not enforced on the browser-side.
185 // TODO(arthursonzogni) The 'form-action' check should be fully disabled
186 // in blink when browser side navigation is enabled, except when the form
187 // submission doesn't trigger a navigation(i.e. javascript urls). Please
188 // see https://crbug.com/701749
189 !browser_side_navigation_enabled &&
190 !frame->GetDocument()->GetContentSecurityPolicy()->AllowFormAction(
191 request.Url(), request.GetRedirectStatus(),
192 SecurityViolationReportingPolicy::kReport, check_header_type)) {
193 return kNavigationPolicyIgnore;
194 }
195
196 return policy;
197 }
198
142 ResourceRequest FrameLoader::ResourceRequestForReload( 199 ResourceRequest FrameLoader::ResourceRequestForReload(
143 FrameLoadType frame_load_type, 200 FrameLoadType frame_load_type,
144 const KURL& override_url, 201 const KURL& override_url,
145 ClientRedirectPolicy client_redirect_policy) { 202 ClientRedirectPolicy client_redirect_policy) {
146 DCHECK(IsReloadLoadType(frame_load_type)); 203 DCHECK(IsReloadLoadType(frame_load_type));
147 WebCachePolicy cache_policy = 204 WebCachePolicy cache_policy =
148 frame_load_type == kFrameLoadTypeReloadBypassingCache 205 frame_load_type == kFrameLoadTypeReloadBypassingCache
149 ? WebCachePolicy::kBypassingCache 206 ? WebCachePolicy::kBypassingCache
150 : WebCachePolicy::kValidatingCacheData; 207 : WebCachePolicy::kValidatingCacheData;
151 if (!document_loader_ || !document_loader_->GetHistoryItem()) 208 if (!document_loader_ || !document_loader_->GetHistoryItem())
(...skipping 1211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1363 NavigationType type, 1420 NavigationType type,
1364 NavigationPolicy policy, 1421 NavigationPolicy policy,
1365 FrameLoadType frame_load_type, 1422 FrameLoadType frame_load_type,
1366 bool is_client_redirect, 1423 bool is_client_redirect,
1367 HTMLFormElement* form) { 1424 HTMLFormElement* form) {
1368 // Don't ask if we are loading an empty URL. 1425 // Don't ask if we are loading an empty URL.
1369 if (request.Url().IsEmpty() || substitute_data.IsValid()) 1426 if (request.Url().IsEmpty() || substitute_data.IsValid())
1370 return kNavigationPolicyCurrentTab; 1427 return kNavigationPolicyCurrentTab;
1371 1428
1372 Settings* settings = frame_->GetSettings(); 1429 Settings* settings = frame_->GetSettings();
1373 bool browser_side_navigation_enabled = 1430 if (MaybeCheckCSP(request, type, frame_, policy,
1374 settings && settings->GetBrowserSideNavigationEnabled(); 1431 should_check_main_world_content_security_policy ==
1375 1432 kCheckContentSecurityPolicy,
1376 // If we're loading content into |m_frame| (NavigationPolicyCurrentTab), check 1433 settings && settings->GetBrowserSideNavigationEnabled(),
1377 // against the parent's Content Security Policy and kill the load if that 1434 ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) ==
1378 // check fails, unless we should bypass the main world's CSP. 1435 kNavigationPolicyIgnore) {
1379 if (policy == kNavigationPolicyCurrentTab &&
1380 should_check_main_world_content_security_policy ==
1381 kCheckContentSecurityPolicy &&
1382 // TODO(arthursonzogni): 'frame-src' check is disabled on the
1383 // renderer side with browser-side-navigation, but is enforced on the
1384 // browser side. See http://crbug.com/692595 for understanding why it
1385 // can't be enforced on both sides instead.
1386 !browser_side_navigation_enabled) {
1387 Frame* parent_frame = frame_->Tree().Parent();
1388 if (parent_frame) {
1389 ContentSecurityPolicy* parent_policy =
1390 parent_frame->GetSecurityContext()->GetContentSecurityPolicy();
1391 if (!parent_policy->AllowFrameFromSource(request.Url(),
1392 request.GetRedirectStatus())) {
1393 // Fire a load event, as timing attacks would otherwise reveal that the
1394 // frame was blocked. This way, it looks like every other cross-origin
1395 // page load.
1396 frame_->GetDocument()->EnforceSandboxFlags(kSandboxOrigin);
1397 frame_->Owner()->DispatchLoad();
1398 return kNavigationPolicyIgnore;
1399 }
1400 }
1401 }
1402
1403 bool is_form_submission = type == kNavigationTypeFormSubmitted ||
1404 type == kNavigationTypeFormResubmitted;
1405 if (is_form_submission &&
1406 // 'form-action' check in the frame that is navigating is disabled on the
1407 // renderer side when PlzNavigate is enabled, but is enforced on the
1408 // browser side instead.
1409 // N.B. check in the frame that initiates the navigation stills occurs in
1410 // blink and is not enforced on the browser-side.
1411 // TODO(arthursonzogni) The 'form-action' check should be fully disabled
1412 // in blink when browser side navigation is enabled, except when the form
1413 // submission doesn't trigger a navigation(i.e. javascript urls). Please
1414 // see https://crbug.com/701749
1415 !browser_side_navigation_enabled &&
1416 !frame_->GetDocument()->GetContentSecurityPolicy()->AllowFormAction(
1417 request.Url(), request.GetRedirectStatus())) {
1418 return kNavigationPolicyIgnore; 1436 return kNavigationPolicyIgnore;
1419 } 1437 }
1420 1438
1421 bool replaces_current_history_item = 1439 bool replaces_current_history_item =
1422 frame_load_type == kFrameLoadTypeReplaceCurrentItem; 1440 frame_load_type == kFrameLoadTypeReplaceCurrentItem;
1423 policy = Client()->DecidePolicyForNavigation( 1441 policy = Client()->DecidePolicyForNavigation(
1424 request, loader, type, policy, replaces_current_history_item, 1442 request, loader, type, policy, replaces_current_history_item,
1425 is_client_redirect, form, 1443 is_client_redirect, form,
1426 should_check_main_world_content_security_policy); 1444 should_check_main_world_content_security_policy);
1427 if (policy == kNavigationPolicyCurrentTab || 1445 if (policy == kNavigationPolicyCurrentTab ||
1428 policy == kNavigationPolicyIgnore || 1446 policy == kNavigationPolicyIgnore ||
1429 policy == kNavigationPolicyHandledByClient || 1447 policy == kNavigationPolicyHandledByClient ||
1430 policy == kNavigationPolicyHandledByClientForInitialHistory) { 1448 policy == kNavigationPolicyHandledByClientForInitialHistory) {
1431 return policy; 1449 return policy;
1432 } 1450 }
1433 1451
1434 if (!LocalDOMWindow::AllowPopUp(*frame_) && 1452 if (!LocalDOMWindow::AllowPopUp(*frame_) &&
1435 !UserGestureIndicator::UtilizeUserGesture()) 1453 !UserGestureIndicator::UtilizeUserGesture())
1436 return kNavigationPolicyIgnore; 1454 return kNavigationPolicyIgnore;
1437 Client()->LoadURLExternally(request, policy, String(), 1455 Client()->LoadURLExternally(request, policy, String(),
1438 replaces_current_history_item); 1456 replaces_current_history_item);
1439 return kNavigationPolicyIgnore; 1457 return kNavigationPolicyIgnore;
1440 } 1458 }
1441 1459
1460 NavigationPolicy FrameLoader::ShouldContinueForRedirectNavigationPolicy(
1461 const ResourceRequest& request,
1462 const SubstituteData& substitute_data,
1463 DocumentLoader* loader,
1464 ContentSecurityPolicyDisposition
1465 should_check_main_world_content_security_policy,
1466 NavigationType type,
1467 NavigationPolicy policy,
1468 FrameLoadType frame_load_type,
1469 bool is_client_redirect,
1470 HTMLFormElement* form) {
1471 Settings* settings = frame_->GetSettings();
1472 // Check report-only CSP policies, which are not checked by
1473 // ShouldContinueForNavigationPolicy.
1474 MaybeCheckCSP(request, type, frame_, policy,
1475 should_check_main_world_content_security_policy ==
1476 kCheckContentSecurityPolicy,
1477 settings && settings->GetBrowserSideNavigationEnabled(),
1478 ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly);
1479 return ShouldContinueForNavigationPolicy(
1480 request, substitute_data, loader,
1481 should_check_main_world_content_security_policy, type, policy,
1482 frame_load_type, is_client_redirect, form);
1483 }
1484
1442 NavigationPolicy FrameLoader::CheckLoadCanStart( 1485 NavigationPolicy FrameLoader::CheckLoadCanStart(
1443 FrameLoadRequest& frame_load_request, 1486 FrameLoadRequest& frame_load_request,
1444 FrameLoadType type, 1487 FrameLoadType type,
1445 NavigationPolicy navigation_policy, 1488 NavigationPolicy navigation_policy,
1446 NavigationType navigation_type) { 1489 NavigationType navigation_type) {
1447 if (frame_->GetDocument()->PageDismissalEventBeingDispatched() != 1490 if (frame_->GetDocument()->PageDismissalEventBeingDispatched() !=
1448 Document::kNoDismissal) { 1491 Document::kNoDismissal) {
1449 return kNavigationPolicyIgnore; 1492 return kNavigationPolicyIgnore;
1450 } 1493 }
1451 1494
1452 // Record the latest requiredCSP value that will be used when sending this 1495 // Record the latest requiredCSP value that will be used when sending this
1453 // request. 1496 // request.
1454 ResourceRequest& resource_request = frame_load_request.GetResourceRequest(); 1497 ResourceRequest& resource_request = frame_load_request.GetResourceRequest();
1455 RecordLatestRequiredCSP(); 1498 RecordLatestRequiredCSP();
1499 // Before modifying the request, check report-only CSP headers to give the
1500 // site owner a chance to learn about requests that need to be modified.
1501 //
1502 // TODO(estark): this doesn't work with --enable-browser-side-navigation,
1503 // wherein 'frame-src' is checked in the browser process. Figure out what to
1504 // do; maybe with browser-side navigation the upgrade should be happening in
1505 // the browser process too. See also https://crbug.com/692595
Mike West 2017/04/19 08:42:13 Ugh. Yes. This is a mess. Given infinite time, we
1506 Settings* settings = frame_->GetSettings();
1507 MaybeCheckCSP(
1508 resource_request, navigation_type, frame_, navigation_policy,
1509 frame_load_request.ShouldCheckMainWorldContentSecurityPolicy() ==
1510 kCheckContentSecurityPolicy,
1511 settings && settings->GetBrowserSideNavigationEnabled(),
1512 ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly);
1456 ModifyRequestForCSP(resource_request, nullptr); 1513 ModifyRequestForCSP(resource_request, nullptr);
1457 1514
1458 return ShouldContinueForNavigationPolicy( 1515 return ShouldContinueForNavigationPolicy(
1459 resource_request, frame_load_request.GetSubstituteData(), nullptr, 1516 resource_request, frame_load_request.GetSubstituteData(), nullptr,
1460 frame_load_request.ShouldCheckMainWorldContentSecurityPolicy(), 1517 frame_load_request.ShouldCheckMainWorldContentSecurityPolicy(),
1461 navigation_type, navigation_policy, type, 1518 navigation_type, navigation_policy, type,
1462 frame_load_request.ClientRedirect() == 1519 frame_load_request.ClientRedirect() ==
1463 ClientRedirectPolicy::kClientRedirect, 1520 ClientRedirectPolicy::kClientRedirect,
1464 frame_load_request.Form()); 1521 frame_load_request.Form());
1465 } 1522 }
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
1774 // TODO(japhet): This is needed because the browser process DCHECKs if the 1831 // TODO(japhet): This is needed because the browser process DCHECKs if the
1775 // first entry we commit in a new frame has replacement set. It's unclear 1832 // first entry we commit in a new frame has replacement set. It's unclear
1776 // whether the DCHECK is right, investigate removing this special case. 1833 // whether the DCHECK is right, investigate removing this special case.
1777 bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem && 1834 bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem &&
1778 (!Opener() || !request.Url().IsEmpty()); 1835 (!Opener() || !request.Url().IsEmpty());
1779 loader->SetReplacesCurrentHistoryItem(replace_current_item); 1836 loader->SetReplacesCurrentHistoryItem(replace_current_item);
1780 return loader; 1837 return loader;
1781 } 1838 }
1782 1839
1783 } // namespace blink 1840 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698