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

Side by Side Diff: Source/platform/weborigin/SecurityOrigin.cpp

Issue 1109633002: Basic experimental suborigin CSP directive and SecurityOrigin mods (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 8 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2007 Apple 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 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 11 matching lines...) Expand all
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "config.h" 29 #include "config.h"
30 #include "platform/weborigin/SecurityOrigin.h" 30 #include "platform/weborigin/SecurityOrigin.h"
31 31
32 #include "platform/RuntimeEnabledFeatures.h"
32 #include "platform/weborigin/KURL.h" 33 #include "platform/weborigin/KURL.h"
33 #include "platform/weborigin/KnownPorts.h" 34 #include "platform/weborigin/KnownPorts.h"
34 #include "platform/weborigin/SchemeRegistry.h" 35 #include "platform/weborigin/SchemeRegistry.h"
35 #include "platform/weborigin/SecurityOriginCache.h" 36 #include "platform/weborigin/SecurityOriginCache.h"
36 #include "platform/weborigin/SecurityPolicy.h" 37 #include "platform/weborigin/SecurityPolicy.h"
37 #include "url/url_canon_ip.h" 38 #include "url/url_canon_ip.h"
38 #include "wtf/HexNumber.h" 39 #include "wtf/HexNumber.h"
39 #include "wtf/MainThread.h" 40 #include "wtf/MainThread.h"
41 #include "wtf/NotFound.h"
40 #include "wtf/StdLibExtras.h" 42 #include "wtf/StdLibExtras.h"
41 #include "wtf/text/StringBuilder.h" 43 #include "wtf/text/StringBuilder.h"
42 44
43 namespace blink { 45 namespace blink {
44 46
45 const int InvalidPort = 0; 47 const int InvalidPort = 0;
46 const int MaxAllowedPort = 65535; 48 const int MaxAllowedPort = 65535;
47 49
48 static SecurityOriginCache* s_originCache = 0; 50 static SecurityOriginCache* s_originCache = 0;
49 51
50 static bool schemeRequiresAuthority(const KURL& url) 52 static bool schemeRequiresAuthority(const KURL& url)
51 { 53 {
52 // We expect URLs with these schemes to have authority components. If the 54 // We expect URLs with these schemes to have authority components. If the
53 // URL lacks an authority component, we get concerned and mark the origin 55 // URL lacks an authority component, we get concerned and mark the origin
54 // as unique. 56 // as unique.
55 return url.protocolIsInHTTPFamily() || url.protocolIs("ftp"); 57 return url.protocolIsInHTTPFamily() || url.protocolIs("ftp");
56 } 58 }
57 59
58 static SecurityOrigin* cachedOrigin(const KURL& url) 60 static SecurityOrigin* cachedOrigin(const KURL& url)
59 { 61 {
60 if (s_originCache) 62 if (s_originCache)
61 return s_originCache->cachedOrigin(url); 63 return s_originCache->cachedOrigin(url);
62 return 0; 64 return 0;
63 } 65 }
64 66
67 static bool sameSuborigin(const SecurityOrigin* origin1, const SecurityOrigin* o rigin2)
68 {
69 // If either origin has a suborigin set, both must have the same suborigin.
70 return origin1->suboriginName() == origin2->suboriginName();
71 }
72
65 bool SecurityOrigin::shouldUseInnerURL(const KURL& url) 73 bool SecurityOrigin::shouldUseInnerURL(const KURL& url)
66 { 74 {
67 // FIXME: Blob URLs don't have inner URLs. Their form is "blob:<inner-origin >/<UUID>", so treating the part after "blob:" as a URL is incorrect. 75 // FIXME: Blob URLs don't have inner URLs. Their form is "blob:<inner-origin >/<UUID>", so treating the part after "blob:" as a URL is incorrect.
68 if (url.protocolIs("blob")) 76 if (url.protocolIs("blob"))
69 return true; 77 return true;
70 if (url.protocolIs("filesystem")) 78 if (url.protocolIs("filesystem"))
71 return true; 79 return true;
72 return false; 80 return false;
73 } 81 }
74 82
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 SecurityOrigin::SecurityOrigin(const KURL& url) 127 SecurityOrigin::SecurityOrigin(const KURL& url)
120 : m_protocol(url.protocol().isNull() ? "" : url.protocol().lower()) 128 : m_protocol(url.protocol().isNull() ? "" : url.protocol().lower())
121 , m_host(url.host().isNull() ? "" : url.host().lower()) 129 , m_host(url.host().isNull() ? "" : url.host().lower())
122 , m_port(url.port()) 130 , m_port(url.port())
123 , m_isUnique(false) 131 , m_isUnique(false)
124 , m_universalAccess(false) 132 , m_universalAccess(false)
125 , m_domainWasSetInDOM(false) 133 , m_domainWasSetInDOM(false)
126 , m_enforceFilePathSeparation(false) 134 , m_enforceFilePathSeparation(false)
127 , m_needsDatabaseIdentifierQuirkForFiles(false) 135 , m_needsDatabaseIdentifierQuirkForFiles(false)
128 { 136 {
137 // Suborigins are serialized into the host, so extract it if necessary.
138 String suboriginName;
139 if (deserializeSuboriginAndHost(m_host, suboriginName, m_host))
140 addSuborigin(suboriginName);
141
129 // document.domain starts as m_host, but can be set by the DOM. 142 // document.domain starts as m_host, but can be set by the DOM.
130 m_domain = m_host; 143 m_domain = m_host;
131 144
132 if (isDefaultPortForProtocol(m_port, m_protocol)) 145 if (isDefaultPortForProtocol(m_port, m_protocol))
133 m_port = InvalidPort; 146 m_port = InvalidPort;
134 147
135 // By default, only local SecurityOrigins can load local resources. 148 // By default, only local SecurityOrigins can load local resources.
136 m_canLoadLocalResources = isLocal(); 149 m_canLoadLocalResources = isLocal();
137 150
138 if (m_canLoadLocalResources) 151 if (m_canLoadLocalResources)
139 m_filePath = url.path(); // In case enforceFilePathSeparation() is calle d. 152 m_filePath = url.path(); // In case enforceFilePathSeparation() is calle d.
140 } 153 }
141 154
142 SecurityOrigin::SecurityOrigin() 155 SecurityOrigin::SecurityOrigin()
143 : m_protocol("") 156 : m_protocol("")
144 , m_host("") 157 , m_host("")
145 , m_domain("") 158 , m_domain("")
159 , m_suboriginName(WTF::String())
146 , m_port(InvalidPort) 160 , m_port(InvalidPort)
147 , m_isUnique(true) 161 , m_isUnique(true)
148 , m_universalAccess(false) 162 , m_universalAccess(false)
149 , m_domainWasSetInDOM(false) 163 , m_domainWasSetInDOM(false)
150 , m_canLoadLocalResources(false) 164 , m_canLoadLocalResources(false)
151 , m_enforceFilePathSeparation(false) 165 , m_enforceFilePathSeparation(false)
152 , m_needsDatabaseIdentifierQuirkForFiles(false) 166 , m_needsDatabaseIdentifierQuirkForFiles(false)
153 { 167 {
154 } 168 }
155 169
156 SecurityOrigin::SecurityOrigin(const SecurityOrigin* other) 170 SecurityOrigin::SecurityOrigin(const SecurityOrigin* other)
157 : m_protocol(other->m_protocol.isolatedCopy()) 171 : m_protocol(other->m_protocol.isolatedCopy())
158 , m_host(other->m_host.isolatedCopy()) 172 , m_host(other->m_host.isolatedCopy())
159 , m_domain(other->m_domain.isolatedCopy()) 173 , m_domain(other->m_domain.isolatedCopy())
160 , m_filePath(other->m_filePath.isolatedCopy()) 174 , m_filePath(other->m_filePath.isolatedCopy())
175 , m_suboriginName(other->m_suboriginName)
161 , m_port(other->m_port) 176 , m_port(other->m_port)
162 , m_isUnique(other->m_isUnique) 177 , m_isUnique(other->m_isUnique)
163 , m_universalAccess(other->m_universalAccess) 178 , m_universalAccess(other->m_universalAccess)
164 , m_domainWasSetInDOM(other->m_domainWasSetInDOM) 179 , m_domainWasSetInDOM(other->m_domainWasSetInDOM)
165 , m_canLoadLocalResources(other->m_canLoadLocalResources) 180 , m_canLoadLocalResources(other->m_canLoadLocalResources)
166 , m_enforceFilePathSeparation(other->m_enforceFilePathSeparation) 181 , m_enforceFilePathSeparation(other->m_enforceFilePathSeparation)
167 , m_needsDatabaseIdentifierQuirkForFiles(other->m_needsDatabaseIdentifierQui rkForFiles) 182 , m_needsDatabaseIdentifierQuirkForFiles(other->m_needsDatabaseIdentifierQui rkForFiles)
168 { 183 {
169 } 184 }
170 185
(...skipping 22 matching lines...) Expand all
193 return adoptRef(new SecurityOrigin(url)); 208 return adoptRef(new SecurityOrigin(url));
194 } 209 }
195 210
196 PassRefPtr<SecurityOrigin> SecurityOrigin::createUnique() 211 PassRefPtr<SecurityOrigin> SecurityOrigin::createUnique()
197 { 212 {
198 RefPtr<SecurityOrigin> origin = adoptRef(new SecurityOrigin()); 213 RefPtr<SecurityOrigin> origin = adoptRef(new SecurityOrigin());
199 ASSERT(origin->isUnique()); 214 ASSERT(origin->isUnique());
200 return origin.release(); 215 return origin.release();
201 } 216 }
202 217
218 void SecurityOrigin::addSuborigin(const String& suborigin)
219 {
220 ASSERT(RuntimeEnabledFeatures::suboriginsEnabled());
221 // Changing suborigins midstream is bad. Very bad. It should not happen.
222 // This is, in fact, one of the very basic invariants that makes suborigins
223 // an effective security tool.
224 RELEASE_ASSERT(m_suboriginName.isNull() || m_suboriginName == suborigin);
225 m_suboriginName = suborigin;
226 }
227
203 PassRefPtr<SecurityOrigin> SecurityOrigin::isolatedCopy() const 228 PassRefPtr<SecurityOrigin> SecurityOrigin::isolatedCopy() const
204 { 229 {
205 return adoptRef(new SecurityOrigin(this)); 230 return adoptRef(new SecurityOrigin(this));
206 } 231 }
207 232
208 void SecurityOrigin::setDomainFromDOM(const String& newDomain) 233 void SecurityOrigin::setDomainFromDOM(const String& newDomain)
209 { 234 {
210 m_domainWasSetInDOM = true; 235 m_domainWasSetInDOM = true;
211 m_domain = newDomain.lower(); 236 m_domain = newDomain.lower();
212 } 237 }
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 String SecurityOrigin::toRawString() const 491 String SecurityOrigin::toRawString() const
467 { 492 {
468 if (m_protocol == "file") 493 if (m_protocol == "file")
469 return "file://"; 494 return "file://";
470 495
471 StringBuilder result; 496 StringBuilder result;
472 buildRawString(result); 497 buildRawString(result);
473 return result.toString(); 498 return result.toString();
474 } 499 }
475 500
501 // Returns true if and only if a suborigin component was found. If false, no
502 // guarantees about the return value |suboriginName| are made.
503 bool SecurityOrigin::deserializeSuboriginAndHost(const String& oldHost, String& suboriginName, String& newHost)
504 {
505 if (!RuntimeEnabledFeatures::suboriginsEnabled())
506 return false;
507
508 size_t suboriginEnd = oldHost.find('_');
jochen (gone - plz use gerrit) 2015/04/27 19:35:10 underscore looks odd but is ok i guess
jww 2015/05/30 01:11:07 Yeah, I'm happy to discuss what we should use as a
509 // Suborigins cannot be empty
510 if (suboriginEnd == 0 || suboriginEnd == WTF::kNotFound)
511 return false;
512
513 suboriginName = oldHost.substring(0, suboriginEnd);
514 newHost = oldHost.substring(suboriginEnd + 1);
515
516 return true;
517 }
518
519
476 AtomicString SecurityOrigin::toRawAtomicString() const 520 AtomicString SecurityOrigin::toRawAtomicString() const
477 { 521 {
478 if (m_protocol == "file") 522 if (m_protocol == "file")
479 return AtomicString("file://", AtomicString::ConstructFromLiteral); 523 return AtomicString("file://", AtomicString::ConstructFromLiteral);
480 524
481 StringBuilder result; 525 StringBuilder result;
482 buildRawString(result); 526 buildRawString(result);
483 return result.toAtomicString(); 527 return result.toAtomicString();
484 } 528 }
485 529
486 inline void SecurityOrigin::buildRawString(StringBuilder& builder) const 530 void SecurityOrigin::buildRawString(StringBuilder& builder) const
487 { 531 {
488 builder.reserveCapacity(m_protocol.length() + m_host.length() + 10);
489 builder.append(m_protocol); 532 builder.append(m_protocol);
490 builder.appendLiteral("://"); 533 builder.appendLiteral("://");
534 if (hasSuborigin()) {
535 builder.append(m_suboriginName);
536 builder.appendLiteral("_");
537 }
491 builder.append(m_host); 538 builder.append(m_host);
492 539
493 if (m_port) { 540 if (m_port) {
494 builder.append(':'); 541 builder.append(':');
495 builder.appendNumber(m_port); 542 builder.appendNumber(m_port);
496 } 543 }
497 } 544 }
498 545
499 PassRefPtr<SecurityOrigin> SecurityOrigin::createFromString(const String& origin String) 546 PassRefPtr<SecurityOrigin> SecurityOrigin::createFromString(const String& origin String)
500 { 547 {
501 return SecurityOrigin::create(KURL(KURL(), originString)); 548 return SecurityOrigin::create(KURL(KURL(), originString));
502 } 549 }
503 550
504 PassRefPtr<SecurityOrigin> SecurityOrigin::create(const String& protocol, const String& host, int port) 551 PassRefPtr<SecurityOrigin> SecurityOrigin::create(const String& protocol, const String& host, int port)
505 { 552 {
506 if (port < 0 || port > MaxAllowedPort) 553 if (port < 0 || port > MaxAllowedPort)
507 return createUnique(); 554 return createUnique();
508 String decodedHost = decodeURLEscapeSequences(host); 555 String decodedHost = decodeURLEscapeSequences(host);
509 return create(KURL(KURL(), protocol + "://" + host + ":" + String::number(po rt) + "/")); 556 return create(KURL(KURL(), protocol + "://" + host + ":" + String::number(po rt) + "/"));
510 } 557 }
511 558
512 bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin* other) const 559 bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin* other) const
513 { 560 {
561 if (!sameSuborigin(this, other))
562 return false;
563
514 if (m_host != other->m_host) 564 if (m_host != other->m_host)
515 return false; 565 return false;
516 566
517 if (m_protocol != other->m_protocol) 567 if (m_protocol != other->m_protocol)
518 return false; 568 return false;
519 569
520 if (m_port != other->m_port) 570 if (m_port != other->m_port)
521 return false; 571 return false;
522 572
523 if (isLocal() && !passesFileCheck(other)) 573 if (isLocal() && !passesFileCheck(other))
(...skipping 10 matching lines...) Expand all
534 } 584 }
535 585
536 void SecurityOrigin::transferPrivilegesFrom(const SecurityOrigin& origin) 586 void SecurityOrigin::transferPrivilegesFrom(const SecurityOrigin& origin)
537 { 587 {
538 m_universalAccess = origin.m_universalAccess; 588 m_universalAccess = origin.m_universalAccess;
539 m_canLoadLocalResources = origin.m_canLoadLocalResources; 589 m_canLoadLocalResources = origin.m_canLoadLocalResources;
540 m_enforceFilePathSeparation = origin.m_enforceFilePathSeparation; 590 m_enforceFilePathSeparation = origin.m_enforceFilePathSeparation;
541 } 591 }
542 592
543 } // namespace blink 593 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698