| 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_referrerPolicy(ReferrerPolicyDefault) |
| 139 { | 141 { |
| 142 } |
| 143 |
| 144 void ContentSecurityPolicy::applyPolicySideEffectsToExecutionContext() |
| 145 { |
| 146 // Ensure that 'self' processes correctly. |
| 140 m_selfSource = adoptPtr(new CSPSource(this, securityOrigin()->protocol(), se
curityOrigin()->host(), securityOrigin()->port(), String(), false, false)); | 147 m_selfSource = adoptPtr(new CSPSource(this, securityOrigin()->protocol(), se
curityOrigin()->host(), securityOrigin()->port(), String(), false, false)); |
| 148 |
| 149 // If we're in a Document, set the referrer policy and sandbox flags. |
| 150 if (Document* document = this->document()) { |
| 151 document->enforceSandboxFlags(m_sandboxMask); |
| 152 if (didSetReferrerPolicy()) |
| 153 document->setReferrerPolicy(m_referrerPolicy); |
| 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, DoNotApplySideEffectsTo
ExecutionContext); |
| 163 if (!headers.contentSecurityPolicyReportOnly().isEmpty()) | 186 if (!headers.contentSecurityPolicyReportOnly().isEmpty()) |
| 164 didReceiveHeader(headers.contentSecurityPolicyReportOnly(), ContentSecur
ityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); | 187 didReceiveHeader(headers.contentSecurityPolicyReportOnly(), ContentSecur
ityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP, DoNotApplySide
EffectsToExecutionContext); |
| 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, SideEffectDis
position sideEffectDisposition) |
| 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 (sideEffectDisposition == ApplySideEffectsToExecutionContext) |
| 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 m_referrerPolicy = didSetReferrerPolicy() ? mergeReferrerPolicies(m_
referrerPolicy, policy->referrerPolicy()) : policy->referrerPolicy(); |
| 238 } |
| 239 |
| 240 if (!policy->allowEval(0, SuppressReport) && m_disableEvalErrorMessage.i
sNull()) |
| 241 m_disableEvalErrorMessage = policy->evalDisabledErrorMessage(); |
| 209 | 242 |
| 210 m_policies.append(policy.release()); | 243 m_policies.append(policy.release()); |
| 211 | 244 |
| 212 // Skip the comma, and begin the next header from the current position. | 245 // Skip the comma, and begin the next header from the current position. |
| 213 ASSERT(position == end || *position == ','); | 246 ASSERT(position == end || *position == ','); |
| 214 skipExactly<UChar>(position, end, ','); | 247 skipExactly<UChar>(position, end, ','); |
| 215 begin = position; | 248 begin = position; |
| 216 } | 249 } |
| 217 | |
| 218 if (document && type != ContentSecurityPolicyHeaderTypeReport && didSetRefer
rerPolicy()) | |
| 219 document->setReferrerPolicy(referrerPolicy()); | |
| 220 } | 250 } |
| 221 | 251 |
| 222 void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) | 252 void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) |
| 223 { | 253 { |
| 224 m_overrideInlineStyleAllowed = value; | 254 m_overrideInlineStyleAllowed = value; |
| 225 } | 255 } |
| 226 | 256 |
| 227 const String& ContentSecurityPolicy::deprecatedHeader() const | 257 const String& ContentSecurityPolicy::deprecatedHeader() const |
| 228 { | 258 { |
| 229 return m_policies.isEmpty() ? emptyString() : m_policies[0]->header(); | 259 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 | 569 const KURL ContentSecurityPolicy::url() const |
| 540 { | 570 { |
| 541 return m_executionContext->contextURL(); | 571 return m_executionContext->contextURL(); |
| 542 } | 572 } |
| 543 | 573 |
| 544 KURL ContentSecurityPolicy::completeURL(const String& url) const | 574 KURL ContentSecurityPolicy::completeURL(const String& url) const |
| 545 { | 575 { |
| 546 return m_executionContext->contextCompleteURL(url); | 576 return m_executionContext->contextCompleteURL(url); |
| 547 } | 577 } |
| 548 | 578 |
| 549 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) const | 579 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) |
| 550 { | 580 { |
| 551 if (Document* document = this->document()) | 581 m_sandboxMask |= mask; |
| 552 document->enforceSandboxFlags(mask); | |
| 553 } | 582 } |
| 554 | 583 |
| 555 static String stripURLForUseInReport(Document* document, const KURL& url) | 584 static String stripURLForUseInReport(Document* document, const KURL& url) |
| 556 { | 585 { |
| 557 if (!url.isValid()) | 586 if (!url.isValid()) |
| 558 return String(); | 587 return String(); |
| 559 if (!url.isHierarchical() || url.protocolIs("file")) | 588 if (!url.isHierarchical() || url.protocolIs("file")) |
| 560 return url.protocol(); | 589 return url.protocol(); |
| 561 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); | 590 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); |
| 562 } | 591 } |
| (...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. | 830 // 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()); | 831 return !m_violationReportsSent.contains(report.impl()->hash()); |
| 803 } | 832 } |
| 804 | 833 |
| 805 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 834 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
| 806 { | 835 { |
| 807 m_violationReportsSent.add(report.impl()->hash()); | 836 m_violationReportsSent.add(report.impl()->hash()); |
| 808 } | 837 } |
| 809 | 838 |
| 810 } // namespace blink | 839 } // namespace blink |
| OLD | NEW |