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 |