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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
129 if (a != b) | 129 if (a != b) |
130 return ReferrerPolicyNever; | 130 return ReferrerPolicyNever; |
131 return a; | 131 return a; |
132 } | 132 } |
133 | 133 |
134 ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContext* executionContext) | 134 ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContext* executionContext) |
135 : m_executionContext(executionContext) | 135 : m_executionContext(executionContext) |
136 , m_overrideInlineStyleAllowed(false) | 136 , m_overrideInlineStyleAllowed(false) |
137 , m_scriptHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) | 137 , m_scriptHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) |
138 , m_styleHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) | 138 , m_styleHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) |
139 , m_sandboxMask(0) | |
140 , m_setReferrerPolicy(false) | |
141 , m_referrerPolicy(ReferrerPolicyDefault) | |
139 { | 142 { |
143 } | |
144 | |
145 void ContentSecurityPolicy::applyPolicySideEffectsToExecutionContext() | |
146 { | |
147 // Ensure that 'self' processes correctly. | |
140 m_selfSource = adoptPtr(new CSPSource(this, securityOrigin()->protocol(), se curityOrigin()->host(), securityOrigin()->port(), String(), false, false)); | 148 m_selfSource = adoptPtr(new CSPSource(this, securityOrigin()->protocol(), se curityOrigin()->host(), securityOrigin()->port(), String(), false, false)); |
149 | |
150 // If we're in a Document, set the referrer policy and sandbox flags. | |
151 if (Document* document = this->document()) { | |
152 document->enforceSandboxFlags(m_sandboxMask); | |
153 document->setReferrerPolicy(m_referrerPolicy); | |
jochen (gone - plz use gerrit)
2014/09/09 08:08:33
should this only be done if didSetReferrerPolicy()
Mike West
2014/09/09 09:12:02
Yes!
| |
154 } | |
155 | |
156 // We disable 'eval()' even in the case of report-only policies, and rely on the check in the | |
157 // V8Initializer::codeGenerationCheckCallbackInMainThread callback to determ ine whether the | |
158 // call should execute or not. | |
159 if (!m_disableEvalErrorMessage.isNull()) | |
160 executionContext()->disableEval(m_disableEvalErrorMessage); | |
141 } | 161 } |
142 | 162 |
143 ContentSecurityPolicy::~ContentSecurityPolicy() | 163 ContentSecurityPolicy::~ContentSecurityPolicy() |
144 { | 164 { |
145 } | 165 } |
146 | 166 |
147 Document* ContentSecurityPolicy::document() const | 167 Document* ContentSecurityPolicy::document() const |
148 { | 168 { |
149 return m_executionContext->isDocument() ? toDocument(m_executionContext) : 0 ; | 169 return m_executionContext->isDocument() ? toDocument(m_executionContext) : 0 ; |
150 } | 170 } |
151 | 171 |
152 void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other) | 172 void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other) |
153 { | 173 { |
154 ASSERT(m_policies.isEmpty()); | 174 ASSERT(m_policies.isEmpty()); |
155 for (CSPDirectiveListVector::const_iterator iter = other->m_policies.begin() ; iter != other->m_policies.end(); ++iter) | 175 for (CSPDirectiveListVector::const_iterator iter = other->m_policies.begin() ; iter != other->m_policies.end(); ++iter) |
156 addPolicyFromHeaderValue((*iter)->header(), (*iter)->headerType(), (*ite r)->headerSource()); | 176 addPolicyFromHeaderValue((*iter)->header(), (*iter)->headerType(), (*ite r)->headerSource()); |
177 | |
178 // FIXME: This ought to be a step distinct from copyStateFrom(). https://crb ug.com/411889 | |
179 applyPolicySideEffectsToExecutionContext(); | |
157 } | 180 } |
158 | 181 |
159 void ContentSecurityPolicy::didReceiveHeaders(const ContentSecurityPolicyRespons eHeaders& headers) | 182 void ContentSecurityPolicy::didReceiveHeaders(const ContentSecurityPolicyRespons eHeaders& headers) |
160 { | 183 { |
161 if (!headers.contentSecurityPolicy().isEmpty()) | 184 if (!headers.contentSecurityPolicy().isEmpty()) |
162 didReceiveHeader(headers.contentSecurityPolicy(), ContentSecurityPolicyH eaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); | 185 didReceiveHeader(headers.contentSecurityPolicy(), ContentSecurityPolicyH eaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP, false); |
163 if (!headers.contentSecurityPolicyReportOnly().isEmpty()) | 186 if (!headers.contentSecurityPolicyReportOnly().isEmpty()) |
164 didReceiveHeader(headers.contentSecurityPolicyReportOnly(), ContentSecur ityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); | 187 didReceiveHeader(headers.contentSecurityPolicyReportOnly(), ContentSecur ityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP, false); |
188 | |
189 // FIXME: This ought to be a step distinct from didReceiveHeaders(). https:/ /crbug.com/411889 | |
190 applyPolicySideEffectsToExecutionContext(); | |
165 } | 191 } |
166 | 192 |
167 void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecuri tyPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) | 193 void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecuri tyPolicyHeaderType type, ContentSecurityPolicyHeaderSource source, bool shouldAp plySideEffects) |
168 { | 194 { |
169 addPolicyFromHeaderValue(header, type, source); | 195 addPolicyFromHeaderValue(header, type, source); |
196 | |
197 // FIXME: This ought to be a step distinct from didReceiveHeader(). https:// crbug.com/411889 | |
198 if (shouldApplySideEffects) | |
199 applyPolicySideEffectsToExecutionContext(); | |
170 } | 200 } |
171 | 201 |
172 void ContentSecurityPolicy::addPolicyFromHeaderValue(const String& header, Conte ntSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) | 202 void ContentSecurityPolicy::addPolicyFromHeaderValue(const String& header, Conte ntSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) |
173 { | 203 { |
174 Document* document = this->document(); | 204 Document* document = this->document(); |
175 if (document) { | 205 if (document) { |
176 UseCounter::count(*document, getUseCounterType(type)); | 206 UseCounter::count(*document, getUseCounterType(type)); |
177 | 207 |
178 // CSP 1.1 defines report-only in a <meta> element as invalid. Measure f or now, disable in experimental mode. | 208 // CSP 1.1 defines report-only in a <meta> element as invalid. Measure f or now, disable in experimental mode. |
179 if (source == ContentSecurityPolicyHeaderSourceMeta && type == ContentSe curityPolicyHeaderTypeReport) { | 209 if (source == ContentSecurityPolicyHeaderSourceMeta && type == ContentSe curityPolicyHeaderTypeReport) { |
180 UseCounter::count(*document, UseCounter::ContentSecurityPolicyReport OnlyInMeta); | 210 UseCounter::count(*document, UseCounter::ContentSecurityPolicyReport OnlyInMeta); |
181 if (experimentalFeaturesEnabled()) { | 211 if (experimentalFeaturesEnabled()) { |
182 reportReportOnlyInMeta(header); | 212 reportReportOnlyInMeta(header); |
183 return; | 213 return; |
184 } | 214 } |
185 } | 215 } |
186 } | 216 } |
187 | 217 |
188 | |
189 Vector<UChar> characters; | 218 Vector<UChar> characters; |
190 header.appendTo(characters); | 219 header.appendTo(characters); |
191 | 220 |
192 const UChar* begin = characters.data(); | 221 const UChar* begin = characters.data(); |
193 const UChar* end = begin + characters.size(); | 222 const UChar* end = begin + characters.size(); |
194 | 223 |
195 // RFC2616, section 4.2 specifies that headers appearing multiple times can | 224 // RFC2616, section 4.2 specifies that headers appearing multiple times can |
196 // be combined with a comma. Walk the header string, and parse each comma | 225 // be combined with a comma. Walk the header string, and parse each comma |
197 // separated chunk as a separate header. | 226 // separated chunk as a separate header. |
198 const UChar* position = begin; | 227 const UChar* position = begin; |
199 while (position < end) { | 228 while (position < end) { |
200 skipUntil<UChar>(position, end, ','); | 229 skipUntil<UChar>(position, end, ','); |
201 | 230 |
202 // header1,header2 OR header1 | 231 // header1,header2 OR header1 |
203 // ^ ^ | 232 // ^ ^ |
204 OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin, position, type, source); | 233 OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin, position, type, source); |
205 | 234 |
206 // We disable 'eval()' even in the case of report-only policies, and rel y on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread cal lback to determine whether the call should execute or not. | 235 if (type != ContentSecurityPolicyHeaderTypeReport && policy->didSetRefer rerPolicy()) { |
207 if (!policy->allowEval(0, SuppressReport)) | 236 // FIXME: We need a 'ReferrerPolicyUnset' enum to avoid confusing co de like this. |
208 m_executionContext->disableEval(policy->evalDisabledErrorMessage()); | 237 if (m_setReferrerPolicy) { |
238 m_referrerPolicy = mergeReferrerPolicies(m_referrerPolicy, polic y->referrerPolicy()); | |
239 } else { | |
240 m_referrerPolicy = policy->referrerPolicy(); | |
241 } | |
242 } | |
243 | |
244 if (!policy->allowEval(0, SuppressReport) && m_disableEvalErrorMessage.i sNull()) | |
245 m_disableEvalErrorMessage = policy->evalDisabledErrorMessage(); | |
209 | 246 |
210 m_policies.append(policy.release()); | 247 m_policies.append(policy.release()); |
211 | 248 |
212 // Skip the comma, and begin the next header from the current position. | 249 // Skip the comma, and begin the next header from the current position. |
213 ASSERT(position == end || *position == ','); | 250 ASSERT(position == end || *position == ','); |
214 skipExactly<UChar>(position, end, ','); | 251 skipExactly<UChar>(position, end, ','); |
215 begin = position; | 252 begin = position; |
216 } | 253 } |
217 | |
218 if (document && type != ContentSecurityPolicyHeaderTypeReport && didSetRefer rerPolicy()) | |
219 document->setReferrerPolicy(referrerPolicy()); | |
220 } | 254 } |
221 | 255 |
222 void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) | 256 void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) |
223 { | 257 { |
224 m_overrideInlineStyleAllowed = value; | 258 m_overrideInlineStyleAllowed = value; |
225 } | 259 } |
226 | 260 |
227 const String& ContentSecurityPolicy::deprecatedHeader() const | 261 const String& ContentSecurityPolicy::deprecatedHeader() const |
228 { | 262 { |
229 return m_policies.isEmpty() ? emptyString() : m_policies[0]->header(); | 263 return m_policies.isEmpty() ? emptyString() : m_policies[0]->header(); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
539 const KURL ContentSecurityPolicy::url() const | 573 const KURL ContentSecurityPolicy::url() const |
540 { | 574 { |
541 return m_executionContext->contextURL(); | 575 return m_executionContext->contextURL(); |
542 } | 576 } |
543 | 577 |
544 KURL ContentSecurityPolicy::completeURL(const String& url) const | 578 KURL ContentSecurityPolicy::completeURL(const String& url) const |
545 { | 579 { |
546 return m_executionContext->contextCompleteURL(url); | 580 return m_executionContext->contextCompleteURL(url); |
547 } | 581 } |
548 | 582 |
549 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) const | 583 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) |
550 { | 584 { |
551 if (Document* document = this->document()) | 585 m_sandboxMask |= mask; |
552 document->enforceSandboxFlags(mask); | |
553 } | 586 } |
554 | 587 |
555 static String stripURLForUseInReport(Document* document, const KURL& url) | 588 static String stripURLForUseInReport(Document* document, const KURL& url) |
556 { | 589 { |
557 if (!url.isValid()) | 590 if (!url.isValid()) |
558 return String(); | 591 return String(); |
559 if (!url.isHierarchical() || url.protocolIs("file")) | 592 if (!url.isHierarchical() || url.protocolIs("file")) |
560 return url.protocol(); | 593 return url.protocol(); |
561 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef errer() : SecurityOrigin::create(url)->toString(); | 594 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef errer() : SecurityOrigin::create(url)->toString(); |
562 } | 595 } |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
801 // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report. | 834 // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report. |
802 return !m_violationReportsSent.contains(report.impl()->hash()); | 835 return !m_violationReportsSent.contains(report.impl()->hash()); |
803 } | 836 } |
804 | 837 |
805 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 838 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
806 { | 839 { |
807 m_violationReportsSent.add(report.impl()->hash()); | 840 m_violationReportsSent.add(report.impl()->hash()); |
808 } | 841 } |
809 | 842 |
810 } // namespace blink | 843 } // namespace blink |
OLD | NEW |