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

Side by Side Diff: Source/core/frame/csp/ContentSecurityPolicy.cpp

Issue 553423002: CSP: Use a specified frame for reporting 'frame-ancestors' violations. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Feedback, tests, and rebase. Created 6 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/frame/csp/ContentSecurityPolicy.h ('k') | Source/core/loader/DocumentLoader.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/core/frame/csp/ContentSecurityPolicy.h ('k') | Source/core/loader/DocumentLoader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698