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 |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "core/frame/csp/ContentSecurityPolicy.h" | 26 #include "core/frame/csp/ContentSecurityPolicy.h" |
27 | 27 |
28 #include <memory> | 28 #include <memory> |
29 #include "bindings/core/v8/ScriptController.h" | 29 #include "bindings/core/v8/ScriptController.h" |
30 #include "bindings/core/v8/SourceLocation.h" | |
31 #include "core/dom/DOMStringList.h" | 30 #include "core/dom/DOMStringList.h" |
32 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
33 #include "core/dom/Element.h" | 32 #include "core/dom/Element.h" |
34 #include "core/dom/SandboxFlags.h" | 33 #include "core/dom/SandboxFlags.h" |
35 #include "core/dom/TaskRunnerHelper.h" | 34 #include "core/dom/TaskRunnerHelper.h" |
36 #include "core/events/EventQueue.h" | 35 #include "core/events/EventQueue.h" |
37 #include "core/events/SecurityPolicyViolationEvent.h" | 36 #include "core/events/SecurityPolicyViolationEvent.h" |
38 #include "core/frame/FrameClient.h" | 37 #include "core/frame/FrameClient.h" |
39 #include "core/frame/LocalDOMWindow.h" | 38 #include "core/frame/LocalDOMWindow.h" |
40 #include "core/frame/LocalFrame.h" | 39 #include "core/frame/LocalFrame.h" |
(...skipping 992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 static void gatherSecurityPolicyViolationEventData( | 1032 static void gatherSecurityPolicyViolationEventData( |
1034 SecurityPolicyViolationEventInit& init, | 1033 SecurityPolicyViolationEventInit& init, |
1035 ExecutionContext* context, | 1034 ExecutionContext* context, |
1036 const String& directiveText, | 1035 const String& directiveText, |
1037 const ContentSecurityPolicy::DirectiveType& effectiveType, | 1036 const ContentSecurityPolicy::DirectiveType& effectiveType, |
1038 const KURL& blockedURL, | 1037 const KURL& blockedURL, |
1039 const String& header, | 1038 const String& header, |
1040 RedirectStatus redirectStatus, | 1039 RedirectStatus redirectStatus, |
1041 ContentSecurityPolicyHeaderType headerType, | 1040 ContentSecurityPolicyHeaderType headerType, |
1042 ContentSecurityPolicy::ViolationType violationType, | 1041 ContentSecurityPolicy::ViolationType violationType, |
1043 int contextLine, | 1042 std::unique_ptr<SourceLocation> sourceLocation, |
1044 const String& scriptSource) { | 1043 const String& scriptSource) { |
1045 if (effectiveType == ContentSecurityPolicy::DirectiveType::FrameAncestors) { | 1044 if (effectiveType == ContentSecurityPolicy::DirectiveType::FrameAncestors) { |
1046 // If this load was blocked via 'frame-ancestors', then the URL of | 1045 // If this load was blocked via 'frame-ancestors', then the URL of |
1047 // |document| has not yet been initialized. In this case, we'll set both | 1046 // |document| has not yet been initialized. In this case, we'll set both |
1048 // 'documentURI' and 'blockedURI' to the blocked document's URL. | 1047 // 'documentURI' and 'blockedURI' to the blocked document's URL. |
1049 String strippedURL = stripURLForUseInReport( | 1048 String strippedURL = stripURLForUseInReport( |
1050 context, blockedURL, RedirectStatus::NoRedirect, | 1049 context, blockedURL, RedirectStatus::NoRedirect, |
1051 ContentSecurityPolicy::DirectiveType::DefaultSrc); | 1050 ContentSecurityPolicy::DirectiveType::DefaultSrc); |
1052 init.setDocumentURI(strippedURL); | 1051 init.setDocumentURI(strippedURL); |
1053 init.setBlockedURI(strippedURL); | 1052 init.setBlockedURI(strippedURL); |
(...skipping 17 matching lines...) Expand all Loading... |
1071 } | 1070 } |
1072 | 1071 |
1073 String effectiveDirective = | 1072 String effectiveDirective = |
1074 ContentSecurityPolicy::getDirectiveName(effectiveType); | 1073 ContentSecurityPolicy::getDirectiveName(effectiveType); |
1075 init.setViolatedDirective(effectiveDirective); | 1074 init.setViolatedDirective(effectiveDirective); |
1076 init.setEffectiveDirective(effectiveDirective); | 1075 init.setEffectiveDirective(effectiveDirective); |
1077 init.setOriginalPolicy(header); | 1076 init.setOriginalPolicy(header); |
1078 init.setDisposition(headerType == ContentSecurityPolicyHeaderTypeEnforce | 1077 init.setDisposition(headerType == ContentSecurityPolicyHeaderTypeEnforce |
1079 ? "enforce" | 1078 ? "enforce" |
1080 : "report"); | 1079 : "report"); |
1081 init.setSourceFile(String()); | |
1082 init.setLineNumber(contextLine); | |
1083 init.setColumnNumber(0); | |
1084 init.setStatusCode(0); | 1080 init.setStatusCode(0); |
1085 | 1081 |
1086 // TODO(mkwst): We only have referrer and status code information for | 1082 // TODO(mkwst): We only have referrer and status code information for |
1087 // Documents. It would be nice to get them for Workers as well. | 1083 // Documents. It would be nice to get them for Workers as well. |
1088 if (context->isDocument()) { | 1084 if (context->isDocument()) { |
1089 Document* document = toDocument(context); | 1085 Document* document = toDocument(context); |
1090 DCHECK(document); | 1086 DCHECK(document); |
1091 init.setReferrer(document->referrer()); | 1087 init.setReferrer(document->referrer()); |
1092 if (!SecurityOrigin::isSecure(context->url()) && document->loader()) | 1088 if (!SecurityOrigin::isSecure(context->url()) && document->loader()) |
1093 init.setStatusCode(document->loader()->response().httpStatusCode()); | 1089 init.setStatusCode(document->loader()->response().httpStatusCode()); |
1094 } | 1090 } |
1095 | 1091 |
1096 std::unique_ptr<SourceLocation> location = SourceLocation::capture(context); | 1092 // If no source location is provided, use the source location of the context. |
1097 if (location->lineNumber()) { | 1093 if (!sourceLocation) |
1098 KURL source = KURL(ParsedURLString, location->url()); | 1094 sourceLocation = SourceLocation::capture(context); |
| 1095 if (sourceLocation->lineNumber()) { |
| 1096 KURL source = KURL(ParsedURLString, sourceLocation->url()); |
1099 init.setSourceFile( | 1097 init.setSourceFile( |
1100 stripURLForUseInReport(context, source, redirectStatus, effectiveType)); | 1098 stripURLForUseInReport(context, source, redirectStatus, effectiveType)); |
1101 init.setLineNumber(location->lineNumber()); | 1099 init.setLineNumber(sourceLocation->lineNumber()); |
1102 init.setColumnNumber(location->columnNumber()); | 1100 init.setColumnNumber(sourceLocation->columnNumber()); |
| 1101 } else { |
| 1102 init.setSourceFile(String()); |
| 1103 init.setLineNumber(0); |
| 1104 init.setColumnNumber(0); |
1103 } | 1105 } |
1104 | 1106 |
1105 if (!scriptSource.isEmpty()) | 1107 if (!scriptSource.isEmpty()) |
1106 init.setSample(scriptSource.stripWhiteSpace().left(40)); | 1108 init.setSample(scriptSource.stripWhiteSpace().left(40)); |
1107 } | 1109 } |
1108 | 1110 |
1109 void ContentSecurityPolicy::reportViolation( | 1111 void ContentSecurityPolicy::reportViolation( |
1110 const String& directiveText, | 1112 const String& directiveText, |
1111 const DirectiveType& effectiveType, | 1113 const DirectiveType& effectiveType, |
1112 const String& consoleMessage, | 1114 const String& consoleMessage, |
1113 const KURL& blockedURL, | 1115 const KURL& blockedURL, |
1114 const Vector<String>& reportEndpoints, | 1116 const Vector<String>& reportEndpoints, |
1115 const String& header, | 1117 const String& header, |
1116 ContentSecurityPolicyHeaderType headerType, | 1118 ContentSecurityPolicyHeaderType headerType, |
1117 ViolationType violationType, | 1119 ViolationType violationType, |
| 1120 std::unique_ptr<SourceLocation> sourceLocation, |
1118 LocalFrame* contextFrame, | 1121 LocalFrame* contextFrame, |
1119 RedirectStatus redirectStatus, | 1122 RedirectStatus redirectStatus, |
1120 int contextLine, | |
1121 Element* element, | 1123 Element* element, |
1122 const String& source) { | 1124 const String& source) { |
1123 ASSERT(violationType == URLViolation || blockedURL.isEmpty()); | 1125 ASSERT(violationType == URLViolation || blockedURL.isEmpty()); |
1124 | 1126 |
1125 // TODO(lukasza): Support sending reports from OOPIFs - | 1127 // TODO(lukasza): Support sending reports from OOPIFs - |
1126 // https://crbug.com/611232 (or move CSP child-src and frame-src checks to the | 1128 // https://crbug.com/611232 (or move CSP child-src and frame-src checks to the |
1127 // browser process - see https://crbug.com/376522). | 1129 // browser process - see https://crbug.com/376522). |
1128 if (!m_executionContext && !contextFrame) { | 1130 if (!m_executionContext && !contextFrame) { |
1129 DCHECK(effectiveType == DirectiveType::ChildSrc || | 1131 DCHECK(effectiveType == DirectiveType::ChildSrc || |
1130 effectiveType == DirectiveType::FrameSrc || | 1132 effectiveType == DirectiveType::FrameSrc || |
1131 effectiveType == DirectiveType::PluginTypes); | 1133 effectiveType == DirectiveType::PluginTypes); |
1132 return; | 1134 return; |
1133 } | 1135 } |
1134 | 1136 |
1135 DCHECK((m_executionContext && !contextFrame) || | 1137 DCHECK((m_executionContext && !contextFrame) || |
1136 ((effectiveType == DirectiveType::FrameAncestors) && contextFrame)); | 1138 ((effectiveType == DirectiveType::FrameAncestors) && contextFrame)); |
1137 | 1139 |
1138 SecurityPolicyViolationEventInit violationData; | 1140 SecurityPolicyViolationEventInit violationData; |
1139 | 1141 |
1140 // If we're processing 'frame-ancestors', use |contextFrame|'s execution | 1142 // If we're processing 'frame-ancestors', use |contextFrame|'s execution |
1141 // context to gather data. Otherwise, use the policy's execution context. | 1143 // context to gather data. Otherwise, use the policy's execution context. |
1142 ExecutionContext* relevantContext = | 1144 ExecutionContext* relevantContext = |
1143 contextFrame ? contextFrame->document() : m_executionContext; | 1145 contextFrame ? contextFrame->document() : m_executionContext; |
1144 DCHECK(relevantContext); | 1146 DCHECK(relevantContext); |
1145 gatherSecurityPolicyViolationEventData( | 1147 gatherSecurityPolicyViolationEventData( |
1146 violationData, relevantContext, directiveText, effectiveType, blockedURL, | 1148 violationData, relevantContext, directiveText, effectiveType, blockedURL, |
1147 header, redirectStatus, headerType, violationType, contextLine, source); | 1149 header, redirectStatus, headerType, violationType, |
| 1150 std::move(sourceLocation), source); |
1148 | 1151 |
1149 // TODO(mkwst): Obviously, we shouldn't hit this check, as extension-loaded | 1152 // TODO(mkwst): Obviously, we shouldn't hit this check, as extension-loaded |
1150 // resources should be allowed regardless. We apparently do, however, so | 1153 // resources should be allowed regardless. We apparently do, however, so |
1151 // we should at least stop spamming reporting endpoints. See | 1154 // we should at least stop spamming reporting endpoints. See |
1152 // https://crbug.com/524356 for detail. | 1155 // https://crbug.com/524356 for detail. |
1153 if (!violationData.sourceFile().isEmpty() && | 1156 if (!violationData.sourceFile().isEmpty() && |
1154 shouldBypassContentSecurityPolicy( | 1157 shouldBypassContentSecurityPolicy( |
1155 KURL(ParsedURLString, violationData.sourceFile()))) { | 1158 KURL(ParsedURLString, violationData.sourceFile()))) { |
1156 return; | 1159 return; |
1157 } | 1160 } |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1643 if (SecurityOrigin::shouldUseInnerURL(url)) { | 1646 if (SecurityOrigin::shouldUseInnerURL(url)) { |
1644 return SchemeRegistry::schemeShouldBypassContentSecurityPolicy( | 1647 return SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
1645 SecurityOrigin::extractInnerURL(url).protocol(), area); | 1648 SecurityOrigin::extractInnerURL(url).protocol(), area); |
1646 } else { | 1649 } else { |
1647 return SchemeRegistry::schemeShouldBypassContentSecurityPolicy( | 1650 return SchemeRegistry::schemeShouldBypassContentSecurityPolicy( |
1648 url.protocol(), area); | 1651 url.protocol(), area); |
1649 } | 1652 } |
1650 } | 1653 } |
1651 | 1654 |
1652 } // namespace blink | 1655 } // namespace blink |
OLD | NEW |