OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google, Inc. All rights reserved. | 2 * Copyright (C) 2011 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 | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) | 331 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) |
332 return true; | 332 return true; |
333 | 333 |
334 for (size_t i = 0; i < policies.size(); ++i) { | 334 for (size_t i = 0; i < policies.size(); ++i) { |
335 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus)) | 335 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus)) |
336 return false; | 336 return false; |
337 } | 337 } |
338 return true; | 338 return true; |
339 } | 339 } |
340 | 340 |
341 template<bool (CSPDirectiveList::*allowed)(LocalFrame*, ContentSecurityPolicy::R
eportingStatus) const> | 341 template<bool (CSPDirectiveList::*allowed)(LocalFrame*, const KURL&, ContentSecu
rityPolicy::ReportingStatus) const> |
342 bool isAllowedByAllWithFrame(const CSPDirectiveListVector& policies, LocalFrame*
frame, ContentSecurityPolicy::ReportingStatus reportingStatus) | 342 bool isAllowedByAllWithFrame(const CSPDirectiveListVector& policies, LocalFrame*
frame, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) |
343 { | 343 { |
344 for (size_t i = 0; i < policies.size(); ++i) { | 344 for (size_t i = 0; i < policies.size(); ++i) { |
345 if (!(policies[i].get()->*allowed)(frame, reportingStatus)) | 345 if (!(policies[i].get()->*allowed)(frame, url, reportingStatus)) |
346 return false; | 346 return false; |
347 } | 347 } |
348 return true; | 348 return true; |
349 } | 349 } |
350 | 350 |
351 template<bool (CSPDirectiveList::*allowed)(const CSPHashValue&) const> | 351 template<bool (CSPDirectiveList::*allowed)(const CSPHashValue&) const> |
352 bool checkDigest(const String& source, uint8_t hashAlgorithmsUsed, const CSPDire
ctiveListVector& policies) | 352 bool checkDigest(const String& source, uint8_t hashAlgorithmsUsed, const CSPDire
ctiveListVector& policies) |
353 { | 353 { |
354 // Any additions or subtractions from this struct should also modify the | 354 // Any additions or subtractions from this struct should also modify the |
355 // respective entries in the kSupportedPrefixes array in | 355 // respective entries in the kSupportedPrefixes array in |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 bool ContentSecurityPolicy::allowFormAction(const KURL& url, ContentSecurityPoli
cy::ReportingStatus reportingStatus) const | 502 bool ContentSecurityPolicy::allowFormAction(const KURL& url, ContentSecurityPoli
cy::ReportingStatus reportingStatus) const |
503 { | 503 { |
504 return isAllowedByAllWithURL<&CSPDirectiveList::allowFormAction>(m_policies,
url, reportingStatus); | 504 return isAllowedByAllWithURL<&CSPDirectiveList::allowFormAction>(m_policies,
url, reportingStatus); |
505 } | 505 } |
506 | 506 |
507 bool ContentSecurityPolicy::allowBaseURI(const KURL& url, ContentSecurityPolicy:
:ReportingStatus reportingStatus) const | 507 bool ContentSecurityPolicy::allowBaseURI(const KURL& url, ContentSecurityPolicy:
:ReportingStatus reportingStatus) const |
508 { | 508 { |
509 return isAllowedByAllWithURL<&CSPDirectiveList::allowBaseURI>(m_policies, ur
l, reportingStatus); | 509 return isAllowedByAllWithURL<&CSPDirectiveList::allowBaseURI>(m_policies, ur
l, reportingStatus); |
510 } | 510 } |
511 | 511 |
512 bool ContentSecurityPolicy::allowAncestors(LocalFrame* frame, ContentSecurityPol
icy::ReportingStatus reportingStatus) const | 512 bool ContentSecurityPolicy::allowAncestors(LocalFrame* frame, const KURL& url, C
ontentSecurityPolicy::ReportingStatus reportingStatus) const |
513 { | 513 { |
514 return isAllowedByAllWithFrame<&CSPDirectiveList::allowAncestors>(m_policies
, frame, reportingStatus); | 514 return isAllowedByAllWithFrame<&CSPDirectiveList::allowAncestors>(m_policies
, frame, url, reportingStatus); |
515 } | 515 } |
516 | 516 |
517 bool ContentSecurityPolicy::allowChildContextFromSource(const KURL& url, Content
SecurityPolicy::ReportingStatus reportingStatus) const | 517 bool ContentSecurityPolicy::allowChildContextFromSource(const KURL& url, Content
SecurityPolicy::ReportingStatus reportingStatus) const |
518 { | 518 { |
519 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>
(m_policies, url, reportingStatus); | 519 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>
(m_policies, url, reportingStatus); |
520 } | 520 } |
521 | 521 |
522 bool ContentSecurityPolicy::allowWorkerContextFromSource(const KURL& url, Conten
tSecurityPolicy::ReportingStatus reportingStatus) const | 522 bool ContentSecurityPolicy::allowWorkerContextFromSource(const KURL& url, Conten
tSecurityPolicy::ReportingStatus reportingStatus) const |
523 { | 523 { |
524 // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure t
he impact of this backwards-incompatible change. | 524 // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure t
he impact of this backwards-incompatible change. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 { | 596 { |
597 if (!url.isValid()) | 597 if (!url.isValid()) |
598 return String(); | 598 return String(); |
599 if (!url.isHierarchical() || url.protocolIs("file")) | 599 if (!url.isHierarchical() || url.protocolIs("file")) |
600 return url.protocol(); | 600 return url.protocol(); |
601 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); | 601 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); |
602 } | 602 } |
603 | 603 |
604 static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventI
nit& init, Document* document, const String& directiveText, const String& effect
iveDirective, const KURL& blockedURL, const String& header) | 604 static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventI
nit& init, Document* document, const String& directiveText, const String& effect
iveDirective, const KURL& blockedURL, const String& header) |
605 { | 605 { |
606 init.documentURI = document->url().string(); | 606 if (equalIgnoringCase(effectiveDirective, ContentSecurityPolicy::FrameAncest
ors)) { |
| 607 // If this load was blocked via 'frame-ancestors', then the URL of |docu
ment| has not yet |
| 608 // been initialized. In this case, we'll set both 'documentURI' and 'blo
ckedURI' to the |
| 609 // blocked document's URL. |
| 610 init.documentURI = blockedURL.string(); |
| 611 init.blockedURI = blockedURL.string(); |
| 612 } else { |
| 613 init.documentURI = document->url().string(); |
| 614 init.blockedURI = stripURLForUseInReport(document, blockedURL); |
| 615 } |
607 init.referrer = document->referrer(); | 616 init.referrer = document->referrer(); |
608 init.blockedURI = stripURLForUseInReport(document, blockedURL); | |
609 init.violatedDirective = directiveText; | 617 init.violatedDirective = directiveText; |
610 init.effectiveDirective = effectiveDirective; | 618 init.effectiveDirective = effectiveDirective; |
611 init.originalPolicy = header; | 619 init.originalPolicy = header; |
612 init.sourceFile = String(); | 620 init.sourceFile = String(); |
613 init.lineNumber = 0; | 621 init.lineNumber = 0; |
614 init.columnNumber = 0; | 622 init.columnNumber = 0; |
615 init.statusCode = 0; | 623 init.statusCode = 0; |
616 | 624 |
617 if (!SecurityOrigin::isSecure(document->url()) && document->loader()) | 625 if (!SecurityOrigin::isSecure(document->url()) && document->loader()) |
618 init.statusCode = document->loader()->response().httpStatusCode(); | 626 init.statusCode = document->loader()->response().httpStatusCode(); |
619 | 627 |
620 RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(1, false); | 628 RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(1, false); |
621 if (!stack) | 629 if (!stack) |
622 return; | 630 return; |
623 | 631 |
624 const ScriptCallFrame& callFrame = stack->at(0); | 632 const ScriptCallFrame& callFrame = stack->at(0); |
625 | 633 |
626 if (callFrame.lineNumber()) { | 634 if (callFrame.lineNumber()) { |
627 KURL source = KURL(ParsedURLString, callFrame.sourceURL()); | 635 KURL source = KURL(ParsedURLString, callFrame.sourceURL()); |
628 init.sourceFile = stripURLForUseInReport(document, source); | 636 init.sourceFile = stripURLForUseInReport(document, source); |
629 init.lineNumber = callFrame.lineNumber(); | 637 init.lineNumber = callFrame.lineNumber(); |
630 init.columnNumber = callFrame.columnNumber(); | 638 init.columnNumber = callFrame.columnNumber(); |
631 } | 639 } |
632 } | 640 } |
633 | 641 |
634 void ContentSecurityPolicy::reportViolation(const String& directiveText, const S
tring& effectiveDirective, const String& consoleMessage, const KURL& blockedURL,
const Vector<String>& reportEndpoints, const String& header) | 642 void ContentSecurityPolicy::reportViolation(const String& directiveText, const S
tring& effectiveDirective, const String& consoleMessage, const KURL& blockedURL,
const Vector<String>& reportEndpoints, const String& header, LocalFrame* contex
tFrame) |
635 { | 643 { |
636 // FIXME: Support sending 'frame-ancestor' reports (which occur before we're
bound to an execution context) | 644 ASSERT((m_executionContext && !contextFrame) || (equalIgnoringCase(effective
Directive, ContentSecurityPolicy::FrameAncestors) && contextFrame)); |
637 if (!m_executionContext) | |
638 return; | |
639 | 645 |
640 // FIXME: Support sending reports from worker. | 646 // FIXME: Support sending reports from worker. |
641 Document* document = this->document(); | 647 Document* document = contextFrame ? contextFrame->document() : this->documen
t(); |
642 if (!document) | 648 if (!document) |
643 return; | 649 return; |
644 | 650 |
645 LocalFrame* frame = document->frame(); | 651 LocalFrame* frame = document->frame(); |
646 if (!frame) | 652 if (!frame) |
647 return; | 653 return; |
648 | 654 |
649 SecurityPolicyViolationEventInit violationData; | 655 SecurityPolicyViolationEventInit violationData; |
650 gatherSecurityPolicyViolationEventData(violationData, document, directiveTex
t, effectiveDirective, blockedURL, header); | 656 gatherSecurityPolicyViolationEventData(violationData, document, directiveTex
t, effectiveDirective, blockedURL, header); |
651 | 657 |
(...skipping 30 matching lines...) Expand all Loading... |
682 | 688 |
683 RefPtr<JSONObject> reportObject = JSONObject::create(); | 689 RefPtr<JSONObject> reportObject = JSONObject::create(); |
684 reportObject->setObject("csp-report", cspReport.release()); | 690 reportObject->setObject("csp-report", cspReport.release()); |
685 String stringifiedReport = reportObject->toJSONString(); | 691 String stringifiedReport = reportObject->toJSONString(); |
686 | 692 |
687 if (!shouldSendViolationReport(stringifiedReport)) | 693 if (!shouldSendViolationReport(stringifiedReport)) |
688 return; | 694 return; |
689 | 695 |
690 RefPtr<FormData> report = FormData::create(stringifiedReport.utf8()); | 696 RefPtr<FormData> report = FormData::create(stringifiedReport.utf8()); |
691 | 697 |
692 for (size_t i = 0; i < reportEndpoints.size(); ++i) | 698 for (size_t i = 0; i < reportEndpoints.size(); ++i) { |
| 699 // If we have a context frame we're dealing with 'frame-ancestors' and w
e don't have our |
| 700 // own execution context. Use the frame's document to complete the endpo
int URL, overriding |
| 701 // its URL with the blocked document's URL. |
| 702 ASSERT(!contextFrame || !m_executionContext); |
| 703 ASSERT(!contextFrame || equalIgnoringCase(effectiveDirective, FrameAnces
tors)); |
| 704 KURL endpoint = contextFrame ? frame->document()->completeURLWithOverrid
e(reportEndpoints[i], blockedURL) : completeURL(reportEndpoints[i]); |
693 PingLoader::sendViolationReport(frame, completeURL(reportEndpoints[i]),
report, PingLoader::ContentSecurityPolicyViolationReport); | 705 PingLoader::sendViolationReport(frame, completeURL(reportEndpoints[i]),
report, PingLoader::ContentSecurityPolicyViolationReport); |
| 706 } |
694 | 707 |
695 didSendViolationReport(stringifiedReport); | 708 didSendViolationReport(stringifiedReport); |
696 } | 709 } |
697 | 710 |
698 void ContentSecurityPolicy::reportInvalidReferrer(const String& invalidValue) | 711 void ContentSecurityPolicy::reportInvalidReferrer(const String& invalidValue) |
699 { | 712 { |
700 logToConsole("The 'referrer' Content Security Policy directive has the inval
id value \"" + invalidValue + "\". Valid values are \"always\", \"default\", \"n
ever\", and \"origin\"."); | 713 logToConsole("The 'referrer' Content Security Policy directive has the inval
id value \"" + invalidValue + "\". Valid values are \"always\", \"default\", \"n
ever\", and \"origin\"."); |
701 } | 714 } |
702 | 715 |
703 void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) | 716 void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) | 813 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) |
801 { | 814 { |
802 logToConsole("The Content Security Policy '" + policy + "' was delivered in
report-only mode, but does not specify a 'report-uri'; the policy will have no e
ffect. Please either add a 'report-uri' directive, or deliver the policy via the
'Content-Security-Policy' header."); | 815 logToConsole("The Content Security Policy '" + policy + "' was delivered in
report-only mode, but does not specify a 'report-uri'; the policy will have no e
ffect. Please either add a 'report-uri' directive, or deliver the policy via the
'Content-Security-Policy' header."); |
803 } | 816 } |
804 | 817 |
805 void ContentSecurityPolicy::logToConsole(const String& message, MessageLevel lev
el) | 818 void ContentSecurityPolicy::logToConsole(const String& message, MessageLevel lev
el) |
806 { | 819 { |
807 logToConsole(ConsoleMessage::create(SecurityMessageSource, level, message)); | 820 logToConsole(ConsoleMessage::create(SecurityMessageSource, level, message)); |
808 } | 821 } |
809 | 822 |
810 void ContentSecurityPolicy::logToConsole(PassRefPtrWillBeRawPtr<ConsoleMessage>
consoleMessage) | 823 void ContentSecurityPolicy::logToConsole(PassRefPtrWillBeRawPtr<ConsoleMessage>
consoleMessage, LocalFrame* frame) |
811 { | 824 { |
812 if (m_executionContext) | 825 if (frame) |
| 826 frame->document()->addConsoleMessage(consoleMessage); |
| 827 else if (m_executionContext) |
813 m_executionContext->addConsoleMessage(consoleMessage); | 828 m_executionContext->addConsoleMessage(consoleMessage); |
814 else | 829 else |
815 m_consoleMessages.append(consoleMessage); | 830 m_consoleMessages.append(consoleMessage); |
816 } | 831 } |
817 | 832 |
818 void ContentSecurityPolicy::reportBlockedScriptExecutionToInspector(const String
& directiveText) const | 833 void ContentSecurityPolicy::reportBlockedScriptExecutionToInspector(const String
& directiveText) const |
819 { | 834 { |
820 m_executionContext->reportBlockedScriptExecutionToInspector(directiveText); | 835 m_executionContext->reportBlockedScriptExecutionToInspector(directiveText); |
821 } | 836 } |
822 | 837 |
(...skipping 30 matching lines...) Expand all Loading... |
853 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. | 868 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. |
854 return !m_violationReportsSent.contains(report.impl()->hash()); | 869 return !m_violationReportsSent.contains(report.impl()->hash()); |
855 } | 870 } |
856 | 871 |
857 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 872 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
858 { | 873 { |
859 m_violationReportsSent.add(report.impl()->hash()); | 874 m_violationReportsSent.add(report.impl()->hash()); |
860 } | 875 } |
861 | 876 |
862 } // namespace blink | 877 } // namespace blink |
OLD | NEW |