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

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

Issue 550223002: CSP: Separate side-effects of parsing from the parsing code. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: 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
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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698