Chromium Code Reviews| 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 |