| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 else if (url.isLocalFile() || m_document->url().isLocalFile()) | 343 else if (url.isLocalFile() || m_document->url().isLocalFile()) |
| 344 message = "Unsafe attempt to load URL " + url.elidedString() + " from fr
ame with URL " + m_document->url().elidedString() + ". 'file:' URLs are treated
as unique security origins.\n"; | 344 message = "Unsafe attempt to load URL " + url.elidedString() + " from fr
ame with URL " + m_document->url().elidedString() + ". 'file:' URLs are treated
as unique security origins.\n"; |
| 345 else | 345 else |
| 346 message = "Unsafe attempt to load URL " + url.elidedString() + " from fr
ame with URL " + m_document->url().elidedString() + ". Domains, protocols and po
rts must match.\n"; | 346 message = "Unsafe attempt to load URL " + url.elidedString() + " from fr
ame with URL " + m_document->url().elidedString() + ". Domains, protocols and po
rts must match.\n"; |
| 347 | 347 |
| 348 frame()->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessag
eSource, ErrorMessageLevel, message)); | 348 frame()->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessag
eSource, ErrorMessageLevel, message)); |
| 349 } | 349 } |
| 350 | 350 |
| 351 bool FrameFetchContext::canRequest(Resource::Type type, const ResourceRequest& r
esourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forP
reload, FetchRequest::OriginRestriction originRestriction) const | 351 bool FrameFetchContext::canRequest(Resource::Type type, const ResourceRequest& r
esourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forP
reload, FetchRequest::OriginRestriction originRestriction) const |
| 352 { | 352 { |
| 353 ResourceRequestBlockedReason reason = canRequestInternal(type, resourceReque
st, url, options, forPreload, originRestriction); |
| 354 if (reason != ResourceRequestBlockedReasonNone) { |
| 355 InspectorInstrumentation::didBlockRequest(frame(), resourceRequest, ensu
reLoaderForNotifications(), options.initiatorInfo, reason); |
| 356 return false; |
| 357 } |
| 358 return true; |
| 359 } |
| 360 |
| 361 ResourceRequestBlockedReason FrameFetchContext::canRequestInternal(Resource::Typ
e type, const ResourceRequest& resourceRequest, const KURL& url, const ResourceL
oaderOptions& options, bool forPreload, FetchRequest::OriginRestriction originRe
striction) const |
| 362 { |
| 353 InstrumentingAgents* agents = InspectorInstrumentation::instrumentingAgentsF
or(frame()); | 363 InstrumentingAgents* agents = InspectorInstrumentation::instrumentingAgentsF
or(frame()); |
| 354 if (agents && agents->inspectorResourceAgent()) { | 364 if (agents && agents->inspectorResourceAgent()) { |
| 355 if (agents->inspectorResourceAgent()->shouldBlockRequest(frame(), resour
ceRequest, ensureLoaderForNotifications(), options.initiatorInfo)) | 365 if (agents->inspectorResourceAgent()->shouldBlockRequest(resourceRequest
)) |
| 356 return false; | 366 return ResourceRequestBlockedReasonInspector; |
| 357 } | 367 } |
| 358 | 368 |
| 359 SecurityOrigin* securityOrigin = options.securityOrigin.get(); | 369 SecurityOrigin* securityOrigin = options.securityOrigin.get(); |
| 360 if (!securityOrigin && m_document) | 370 if (!securityOrigin && m_document) |
| 361 securityOrigin = m_document->securityOrigin(); | 371 securityOrigin = m_document->securityOrigin(); |
| 362 | 372 |
| 363 if (originRestriction != FetchRequest::NoOriginRestriction && securityOrigin
&& !securityOrigin->canDisplay(url)) { | 373 if (originRestriction != FetchRequest::NoOriginRestriction && securityOrigin
&& !securityOrigin->canDisplay(url)) { |
| 364 if (!forPreload) | 374 if (!forPreload) |
| 365 FrameLoader::reportLocalLoadFailed(frame(), url.elidedString()); | 375 FrameLoader::reportLocalLoadFailed(frame(), url.elidedString()); |
| 366 WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource URL was not a
llowed by SecurityOrigin::canDisplay"); | 376 WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource URL was not a
llowed by SecurityOrigin::canDisplay"); |
| 367 return false; | 377 return ResourceRequestBlockedReasonOther; |
| 368 } | 378 } |
| 369 | 379 |
| 370 // Some types of resources can be loaded only from the same origin. Other | 380 // Some types of resources can be loaded only from the same origin. Other |
| 371 // types of resources, like Images, Scripts, and CSS, can be loaded from | 381 // types of resources, like Images, Scripts, and CSS, can be loaded from |
| 372 // any URL. | 382 // any URL. |
| 373 switch (type) { | 383 switch (type) { |
| 374 case Resource::MainResource: | 384 case Resource::MainResource: |
| 375 case Resource::Image: | 385 case Resource::Image: |
| 376 case Resource::CSSStyleSheet: | 386 case Resource::CSSStyleSheet: |
| 377 case Resource::Script: | 387 case Resource::Script: |
| 378 case Resource::Font: | 388 case Resource::Font: |
| 379 case Resource::Raw: | 389 case Resource::Raw: |
| 380 case Resource::LinkPrefetch: | 390 case Resource::LinkPrefetch: |
| 381 case Resource::LinkSubresource: | 391 case Resource::LinkSubresource: |
| 382 case Resource::LinkPreload: | 392 case Resource::LinkPreload: |
| 383 case Resource::TextTrack: | 393 case Resource::TextTrack: |
| 384 case Resource::ImportResource: | 394 case Resource::ImportResource: |
| 385 case Resource::Media: | 395 case Resource::Media: |
| 386 // By default these types of resources can be loaded from any origin. | 396 // By default these types of resources can be loaded from any origin. |
| 387 // FIXME: Are we sure about Resource::Font? | 397 // FIXME: Are we sure about Resource::Font? |
| 388 if (originRestriction == FetchRequest::RestrictToSameOrigin && !security
Origin->canRequest(url)) { | 398 if (originRestriction == FetchRequest::RestrictToSameOrigin && !security
Origin->canRequest(url)) { |
| 389 printAccessDeniedMessage(url); | 399 printAccessDeniedMessage(url); |
| 390 return false; | 400 return ResourceRequestBlockedReasonOrigin; |
| 391 } | 401 } |
| 392 break; | 402 break; |
| 393 case Resource::XSLStyleSheet: | 403 case Resource::XSLStyleSheet: |
| 394 ASSERT(RuntimeEnabledFeatures::xsltEnabled()); | 404 ASSERT(RuntimeEnabledFeatures::xsltEnabled()); |
| 395 case Resource::SVGDocument: | 405 case Resource::SVGDocument: |
| 396 if (!securityOrigin->canRequest(url)) { | 406 if (!securityOrigin->canRequest(url)) { |
| 397 printAccessDeniedMessage(url); | 407 printAccessDeniedMessage(url); |
| 398 return false; | 408 return ResourceRequestBlockedReasonOrigin; |
| 399 } | 409 } |
| 400 break; | 410 break; |
| 401 } | 411 } |
| 402 | 412 |
| 403 // FIXME: Convert this to check the isolated world's Content Security Policy
once webkit.org/b/104520 is solved. | 413 // FIXME: Convert this to check the isolated world's Content Security Policy
once webkit.org/b/104520 is solved. |
| 404 bool shouldBypassMainWorldCSP = frame()->script().shouldBypassMainWorldCSP()
|| options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy; | 414 bool shouldBypassMainWorldCSP = frame()->script().shouldBypassMainWorldCSP()
|| options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy; |
| 405 | 415 |
| 406 // Don't send CSP messages for preloads, we might never actually display tho
se items. | 416 // Don't send CSP messages for preloads, we might never actually display tho
se items. |
| 407 ContentSecurityPolicy::ReportingStatus cspReporting = forPreload ? | 417 ContentSecurityPolicy::ReportingStatus cspReporting = forPreload ? |
| 408 ContentSecurityPolicy::SuppressReport : ContentSecurityPolicy::SendRepor
t; | 418 ContentSecurityPolicy::SuppressReport : ContentSecurityPolicy::SendRepor
t; |
| 409 | 419 |
| 410 // As of CSP2, for requests that are the results of redirects, the match | 420 // As of CSP2, for requests that are the results of redirects, the match |
| 411 // algorithm should ignore the path component of the URL. | 421 // algorithm should ignore the path component of the URL. |
| 412 ContentSecurityPolicy::RedirectStatus redirectStatus = resourceRequest.follo
wedRedirect() ? ContentSecurityPolicy::DidRedirect : ContentSecurityPolicy::DidN
otRedirect; | 422 ContentSecurityPolicy::RedirectStatus redirectStatus = resourceRequest.follo
wedRedirect() ? ContentSecurityPolicy::DidRedirect : ContentSecurityPolicy::DidN
otRedirect; |
| 413 | 423 |
| 414 // m_document can be null, but not in any of the cases where csp is actually
used below. | 424 // m_document can be null, but not in any of the cases where csp is actually
used below. |
| 415 // ImageResourceTest.MultipartImage crashes w/o the m_document null check. | 425 // ImageResourceTest.MultipartImage crashes w/o the m_document null check. |
| 416 // I believe it's the Resource::Raw case. | 426 // I believe it's the Resource::Raw case. |
| 417 const ContentSecurityPolicy* csp = m_document ? m_document->contentSecurityP
olicy() : nullptr; | 427 const ContentSecurityPolicy* csp = m_document ? m_document->contentSecurityP
olicy() : nullptr; |
| 418 | 428 |
| 419 // FIXME: This would be cleaner if moved this switch into an allowFromSource
() | 429 // FIXME: This would be cleaner if moved this switch into an allowFromSource
() |
| 420 // helper on this object which took a Resource::Type, then this block would | 430 // helper on this object which took a Resource::Type, then this block would |
| 421 // collapse to about 10 lines for handling Raw and Script special cases. | 431 // collapse to about 10 lines for handling Raw and Script special cases. |
| 422 switch (type) { | 432 switch (type) { |
| 423 case Resource::XSLStyleSheet: | 433 case Resource::XSLStyleSheet: |
| 424 ASSERT(RuntimeEnabledFeatures::xsltEnabled()); | 434 ASSERT(RuntimeEnabledFeatures::xsltEnabled()); |
| 425 ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); | 435 ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); |
| 426 if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redire
ctStatus, cspReporting)) | 436 if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redire
ctStatus, cspReporting)) |
| 427 return false; | 437 return ResourceRequestBlockedReasonCSP; |
| 428 break; | 438 break; |
| 429 case Resource::Script: | 439 case Resource::Script: |
| 430 case Resource::ImportResource: | 440 case Resource::ImportResource: |
| 431 ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); | 441 ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); |
| 432 if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redire
ctStatus, cspReporting)) | 442 if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redire
ctStatus, cspReporting)) |
| 433 return false; | 443 return ResourceRequestBlockedReasonCSP; |
| 434 | 444 |
| 435 if (!frame()->loader().client()->allowScriptFromSource(!frame()->setting
s() || frame()->settings()->scriptEnabled(), url)) { | 445 if (!frame()->loader().client()->allowScriptFromSource(!frame()->setting
s() || frame()->settings()->scriptEnabled(), url)) { |
| 436 frame()->loader().client()->didNotAllowScript(); | 446 frame()->loader().client()->didNotAllowScript(); |
| 437 return false; | 447 return ResourceRequestBlockedReasonCSP; |
| 438 } | 448 } |
| 439 break; | 449 break; |
| 440 case Resource::CSSStyleSheet: | 450 case Resource::CSSStyleSheet: |
| 441 ASSERT(ContentSecurityPolicy::isStyleResource(resourceRequest)); | 451 ASSERT(ContentSecurityPolicy::isStyleResource(resourceRequest)); |
| 442 if (!shouldBypassMainWorldCSP && !csp->allowStyleFromSource(url, redirec
tStatus, cspReporting)) | 452 if (!shouldBypassMainWorldCSP && !csp->allowStyleFromSource(url, redirec
tStatus, cspReporting)) |
| 443 return false; | 453 return ResourceRequestBlockedReasonCSP; |
| 444 break; | 454 break; |
| 445 case Resource::SVGDocument: | 455 case Resource::SVGDocument: |
| 446 case Resource::Image: | 456 case Resource::Image: |
| 447 ASSERT(ContentSecurityPolicy::isImageResource(resourceRequest)); | 457 ASSERT(ContentSecurityPolicy::isImageResource(resourceRequest)); |
| 448 if (!shouldBypassMainWorldCSP && !csp->allowImageFromSource(url, redirec
tStatus, cspReporting)) | 458 if (!shouldBypassMainWorldCSP && !csp->allowImageFromSource(url, redirec
tStatus, cspReporting)) |
| 449 return false; | 459 return ResourceRequestBlockedReasonCSP; |
| 450 break; | 460 break; |
| 451 case Resource::Font: { | 461 case Resource::Font: { |
| 452 ASSERT(ContentSecurityPolicy::isFontResource(resourceRequest)); | 462 ASSERT(ContentSecurityPolicy::isFontResource(resourceRequest)); |
| 453 if (!shouldBypassMainWorldCSP && !csp->allowFontFromSource(url, redirect
Status, cspReporting)) | 463 if (!shouldBypassMainWorldCSP && !csp->allowFontFromSource(url, redirect
Status, cspReporting)) |
| 454 return false; | 464 return ResourceRequestBlockedReasonCSP; |
| 455 break; | 465 break; |
| 456 } | 466 } |
| 457 case Resource::MainResource: | 467 case Resource::MainResource: |
| 458 case Resource::Raw: | 468 case Resource::Raw: |
| 459 case Resource::LinkPrefetch: | 469 case Resource::LinkPrefetch: |
| 460 case Resource::LinkSubresource: | 470 case Resource::LinkSubresource: |
| 461 case Resource::LinkPreload: | 471 case Resource::LinkPreload: |
| 462 break; | 472 break; |
| 463 case Resource::Media: | 473 case Resource::Media: |
| 464 case Resource::TextTrack: | 474 case Resource::TextTrack: |
| 465 ASSERT(ContentSecurityPolicy::isMediaResource(resourceRequest)); | 475 ASSERT(ContentSecurityPolicy::isMediaResource(resourceRequest)); |
| 466 if (!shouldBypassMainWorldCSP && !csp->allowMediaFromSource(url, redirec
tStatus, cspReporting)) | 476 if (!shouldBypassMainWorldCSP && !csp->allowMediaFromSource(url, redirec
tStatus, cspReporting)) |
| 467 return false; | 477 return ResourceRequestBlockedReasonCSP; |
| 468 | 478 |
| 469 if (!frame()->loader().client()->allowMedia(url)) | 479 if (!frame()->loader().client()->allowMedia(url)) |
| 470 return false; | 480 return ResourceRequestBlockedReasonOther; |
| 471 break; | 481 break; |
| 472 } | 482 } |
| 473 | 483 |
| 474 // SVG Images have unique security rules that prevent all subresource reques
ts | 484 // SVG Images have unique security rules that prevent all subresource reques
ts |
| 475 // except for data urls. | 485 // except for data urls. |
| 476 if (type != Resource::MainResource && frame()->chromeClient().isSVGImageChro
meClient() && !url.protocolIsData()) | 486 if (type != Resource::MainResource && frame()->chromeClient().isSVGImageChro
meClient() && !url.protocolIsData()) |
| 477 return false; | 487 return ResourceRequestBlockedReasonOrigin; |
| 478 | 488 |
| 479 // FIXME: Once we use RequestContext for CSP (http://crbug.com/390497), remo
ve this extra check. | 489 // FIXME: Once we use RequestContext for CSP (http://crbug.com/390497), remo
ve this extra check. |
| 480 if (resourceRequest.requestContext() == WebURLRequest::RequestContextManifes
t) { | 490 if (resourceRequest.requestContext() == WebURLRequest::RequestContextManifes
t) { |
| 481 if (!shouldBypassMainWorldCSP && !csp->allowManifestFromSource(url, redi
rectStatus, cspReporting)) | 491 if (!shouldBypassMainWorldCSP && !csp->allowManifestFromSource(url, redi
rectStatus, cspReporting)) |
| 482 return false; | 492 return ResourceRequestBlockedReasonCSP; |
| 483 } | 493 } |
| 484 | 494 |
| 485 // Measure the number of legacy URL schemes ('ftp://') and the number of emb
edded-credential | 495 // Measure the number of legacy URL schemes ('ftp://') and the number of emb
edded-credential |
| 486 // ('http://user:password@...') resources embedded as subresources. in the h
opes that we can | 496 // ('http://user:password@...') resources embedded as subresources. in the h
opes that we can |
| 487 // block them at some point in the future. | 497 // block them at some point in the future. |
| 488 if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) { | 498 if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) { |
| 489 ASSERT(frame()->document()); | 499 ASSERT(frame()->document()); |
| 490 if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !Sch
emeRegistry::shouldTreatURLSchemeAsLegacy(frame()->document()->securityOrigin()-
>protocol())) | 500 if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !Sch
emeRegistry::shouldTreatURLSchemeAsLegacy(frame()->document()->securityOrigin()-
>protocol())) |
| 491 UseCounter::count(frame()->document(), UseCounter::LegacyProtocolEmb
eddedAsSubresource); | 501 UseCounter::count(frame()->document(), UseCounter::LegacyProtocolEmb
eddedAsSubresource); |
| 492 if (!url.user().isEmpty() || !url.pass().isEmpty()) | 502 if (!url.user().isEmpty() || !url.pass().isEmpty()) |
| 493 UseCounter::count(frame()->document(), UseCounter::RequestedSubresou
rceWithEmbeddedCredentials); | 503 UseCounter::count(frame()->document(), UseCounter::RequestedSubresou
rceWithEmbeddedCredentials); |
| 494 } | 504 } |
| 495 | 505 |
| 496 // Measure the number of pages that load resources after a redirect | 506 // Measure the number of pages that load resources after a redirect |
| 497 // when a CSP is active, to see if implementing CSP | 507 // when a CSP is active, to see if implementing CSP |
| 498 // 'unsafe-redirect' is feasible. | 508 // 'unsafe-redirect' is feasible. |
| 499 if (csp && csp->isActive() && resourceRequest.frameType() != WebURLRequest::
FrameTypeTopLevel && resourceRequest.frameType() != WebURLRequest::FrameTypeAuxi
liary && redirectStatus == ContentSecurityPolicy::DidRedirect) { | 509 if (csp && csp->isActive() && resourceRequest.frameType() != WebURLRequest::
FrameTypeTopLevel && resourceRequest.frameType() != WebURLRequest::FrameTypeAuxi
liary && redirectStatus == ContentSecurityPolicy::DidRedirect) { |
| 500 ASSERT(frame()->document()); | 510 ASSERT(frame()->document()); |
| 501 UseCounter::count(frame()->document(), UseCounter::ResourceLoadedAfterRe
directWithCSP); | 511 UseCounter::count(frame()->document(), UseCounter::ResourceLoadedAfterRe
directWithCSP); |
| 502 } | 512 } |
| 503 | 513 |
| 504 // Last of all, check for mixed content. We do this last so that when | 514 // Last of all, check for mixed content. We do this last so that when |
| 505 // folks block mixed content with a CSP policy, they don't get a warning. | 515 // folks block mixed content with a CSP policy, they don't get a warning. |
| 506 // They'll still get a warning in the console about CSP blocking the load. | 516 // They'll still get a warning in the console about CSP blocking the load. |
| 507 MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ? | 517 MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ? |
| 508 MixedContentChecker::SuppressReport : MixedContentChecker::SendReport; | 518 MixedContentChecker::SuppressReport : MixedContentChecker::SendReport; |
| 509 return !MixedContentChecker::shouldBlockFetch(MixedContentChecker::effective
FrameForFrameType(frame(), resourceRequest.frameType()), resourceRequest, url, m
ixedContentReporting); | 519 if (MixedContentChecker::shouldBlockFetch(MixedContentChecker::effectiveFram
eForFrameType(frame(), resourceRequest.frameType()), resourceRequest, url, mixed
ContentReporting)) |
| 520 return ResourceRequestBlockedReasonMixedContent; |
| 521 |
| 522 return ResourceRequestBlockedReasonNone; |
| 510 } | 523 } |
| 511 | 524 |
| 512 bool FrameFetchContext::isControlledByServiceWorker() const | 525 bool FrameFetchContext::isControlledByServiceWorker() const |
| 513 { | 526 { |
| 514 ASSERT(m_documentLoader || frame()->loader().documentLoader()); | 527 ASSERT(m_documentLoader || frame()->loader().documentLoader()); |
| 515 if (m_documentLoader) | 528 if (m_documentLoader) |
| 516 return frame()->loader().client()->isControlledByServiceWorker(*m_docume
ntLoader); | 529 return frame()->loader().client()->isControlledByServiceWorker(*m_docume
ntLoader); |
| 517 // m_documentLoader is null while loading resources from an HTML import. | 530 // m_documentLoader is null while loading resources from an HTML import. |
| 518 // In such cases whether the request is controlled by ServiceWorker or not | 531 // In such cases whether the request is controlled by ServiceWorker or not |
| 519 // is determined by the document loader of the frame. | 532 // is determined by the document loader of the frame. |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 } | 730 } |
| 718 | 731 |
| 719 DEFINE_TRACE(FrameFetchContext) | 732 DEFINE_TRACE(FrameFetchContext) |
| 720 { | 733 { |
| 721 visitor->trace(m_document); | 734 visitor->trace(m_document); |
| 722 visitor->trace(m_documentLoader); | 735 visitor->trace(m_documentLoader); |
| 723 FetchContext::trace(visitor); | 736 FetchContext::trace(visitor); |
| 724 } | 737 } |
| 725 | 738 |
| 726 } // namespace blink | 739 } // namespace blink |
| OLD | NEW |