OLD | NEW |
---|---|
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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 return url.protocolIsInHTTPFamily() || url.protocolIs("ftp"); | 55 return url.protocolIsInHTTPFamily() || url.protocolIs("ftp"); |
56 } | 56 } |
57 | 57 |
58 static SecurityOrigin* cachedOrigin(const KURL& url) | 58 static SecurityOrigin* cachedOrigin(const KURL& url) |
59 { | 59 { |
60 if (s_originCache) | 60 if (s_originCache) |
61 return s_originCache->cachedOrigin(url); | 61 return s_originCache->cachedOrigin(url); |
62 return 0; | 62 return 0; |
63 } | 63 } |
64 | 64 |
65 static bool sameSuborigin(const SecurityOrigin* origin1, const SecurityOrigin* o rigin2) | |
66 { | |
67 // If either origin has a suborigin set, both must have the same suborigin. | |
68 return (!origin1->hasSuborigin() && !origin2->hasSuborigin()) || (origin1->s uboriginName() == origin2->suboriginName()); | |
69 } | |
70 | |
65 bool SecurityOrigin::shouldUseInnerURL(const KURL& url) | 71 bool SecurityOrigin::shouldUseInnerURL(const KURL& url) |
66 { | 72 { |
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. | 73 // 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")) | 74 if (url.protocolIs("blob")) |
69 return true; | 75 return true; |
70 if (url.protocolIs("filesystem")) | 76 if (url.protocolIs("filesystem")) |
71 return true; | 77 return true; |
72 return false; | 78 return false; |
73 } | 79 } |
74 | 80 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
112 if (SchemeRegistry::shouldTreatURLSchemeAsNoAccess(protocol)) | 118 if (SchemeRegistry::shouldTreatURLSchemeAsNoAccess(protocol)) |
113 return true; | 119 return true; |
114 | 120 |
115 // This is the common case. | 121 // This is the common case. |
116 return false; | 122 return false; |
117 } | 123 } |
118 | 124 |
119 SecurityOrigin::SecurityOrigin(const KURL& url) | 125 SecurityOrigin::SecurityOrigin(const KURL& url) |
120 : m_protocol(url.protocol().isNull() ? "" : url.protocol().lower()) | 126 : m_protocol(url.protocol().isNull() ? "" : url.protocol().lower()) |
121 , m_host(url.host().isNull() ? "" : url.host().lower()) | 127 , m_host(url.host().isNull() ? "" : url.host().lower()) |
128 , m_suboriginName(String()) | |
abarth-chromium
2014/07/31 04:56:47
The compiler will generate this code for you.
jww
2014/10/21 23:51:06
Done.
| |
122 , m_port(url.port()) | 129 , m_port(url.port()) |
123 , m_isUnique(false) | 130 , m_isUnique(false) |
124 , m_universalAccess(false) | 131 , m_universalAccess(false) |
125 , m_domainWasSetInDOM(false) | 132 , m_domainWasSetInDOM(false) |
126 , m_enforceFilePathSeparation(false) | 133 , m_enforceFilePathSeparation(false) |
127 , m_needsDatabaseIdentifierQuirkForFiles(false) | 134 , m_needsDatabaseIdentifierQuirkForFiles(false) |
128 { | 135 { |
129 // document.domain starts as m_host, but can be set by the DOM. | 136 // document.domain starts as m_host, but can be set by the DOM. |
130 m_domain = m_host; | 137 m_domain = m_host; |
131 | 138 |
132 if (isDefaultPortForProtocol(m_port, m_protocol)) | 139 if (isDefaultPortForProtocol(m_port, m_protocol)) |
133 m_port = InvalidPort; | 140 m_port = InvalidPort; |
134 | 141 |
135 // By default, only local SecurityOrigins can load local resources. | 142 // By default, only local SecurityOrigins can load local resources. |
136 m_canLoadLocalResources = isLocal(); | 143 m_canLoadLocalResources = isLocal(); |
137 | 144 |
138 if (m_canLoadLocalResources) | 145 if (m_canLoadLocalResources) |
139 m_filePath = url.path(); // In case enforceFilePathSeparation() is calle d. | 146 m_filePath = url.path(); // In case enforceFilePathSeparation() is calle d. |
140 } | 147 } |
141 | 148 |
142 SecurityOrigin::SecurityOrigin() | 149 SecurityOrigin::SecurityOrigin() |
143 : m_protocol("") | 150 : m_protocol("") |
144 , m_host("") | 151 , m_host("") |
145 , m_domain("") | 152 , m_domain("") |
153 , m_suboriginName(String()) | |
abarth-chromium
2014/07/31 04:56:47
ditto
jww
2014/10/21 23:51:06
Done.
| |
146 , m_port(InvalidPort) | 154 , m_port(InvalidPort) |
147 , m_isUnique(true) | 155 , m_isUnique(true) |
148 , m_universalAccess(false) | 156 , m_universalAccess(false) |
149 , m_domainWasSetInDOM(false) | 157 , m_domainWasSetInDOM(false) |
150 , m_canLoadLocalResources(false) | 158 , m_canLoadLocalResources(false) |
151 , m_enforceFilePathSeparation(false) | 159 , m_enforceFilePathSeparation(false) |
152 , m_needsDatabaseIdentifierQuirkForFiles(false) | 160 , m_needsDatabaseIdentifierQuirkForFiles(false) |
153 { | 161 { |
154 } | 162 } |
155 | 163 |
156 SecurityOrigin::SecurityOrigin(const SecurityOrigin* other) | 164 SecurityOrigin::SecurityOrigin(const SecurityOrigin* other) |
157 : m_protocol(other->m_protocol.isolatedCopy()) | 165 : m_protocol(other->m_protocol.isolatedCopy()) |
158 , m_host(other->m_host.isolatedCopy()) | 166 , m_host(other->m_host.isolatedCopy()) |
159 , m_domain(other->m_domain.isolatedCopy()) | 167 , m_domain(other->m_domain.isolatedCopy()) |
160 , m_filePath(other->m_filePath.isolatedCopy()) | 168 , m_filePath(other->m_filePath.isolatedCopy()) |
169 , m_suboriginName(other->m_suboriginName) | |
161 , m_port(other->m_port) | 170 , m_port(other->m_port) |
162 , m_isUnique(other->m_isUnique) | 171 , m_isUnique(other->m_isUnique) |
163 , m_universalAccess(other->m_universalAccess) | 172 , m_universalAccess(other->m_universalAccess) |
164 , m_domainWasSetInDOM(other->m_domainWasSetInDOM) | 173 , m_domainWasSetInDOM(other->m_domainWasSetInDOM) |
165 , m_canLoadLocalResources(other->m_canLoadLocalResources) | 174 , m_canLoadLocalResources(other->m_canLoadLocalResources) |
166 , m_enforceFilePathSeparation(other->m_enforceFilePathSeparation) | 175 , m_enforceFilePathSeparation(other->m_enforceFilePathSeparation) |
167 , m_needsDatabaseIdentifierQuirkForFiles(other->m_needsDatabaseIdentifierQui rkForFiles) | 176 , m_needsDatabaseIdentifierQuirkForFiles(other->m_needsDatabaseIdentifierQui rkForFiles) |
168 { | 177 { |
169 } | 178 } |
170 | 179 |
(...skipping 22 matching lines...) Expand all Loading... | |
193 return adoptRef(new SecurityOrigin(url)); | 202 return adoptRef(new SecurityOrigin(url)); |
194 } | 203 } |
195 | 204 |
196 PassRefPtr<SecurityOrigin> SecurityOrigin::createUnique() | 205 PassRefPtr<SecurityOrigin> SecurityOrigin::createUnique() |
197 { | 206 { |
198 RefPtr<SecurityOrigin> origin = adoptRef(new SecurityOrigin()); | 207 RefPtr<SecurityOrigin> origin = adoptRef(new SecurityOrigin()); |
199 ASSERT(origin->isUnique()); | 208 ASSERT(origin->isUnique()); |
200 return origin.release(); | 209 return origin.release(); |
201 } | 210 } |
202 | 211 |
212 void SecurityOrigin::addSuborigin(const String& suborigin) | |
213 { | |
214 // Changing suborigins midstream is bad. Very bad. It should not happen. | |
215 // This is, in fact, one of the very basic invariants that makes suborigins | |
216 // an effective security tool. | |
217 RELEASE_ASSERT(m_suboriginName.isNull()); | |
218 m_suboriginName = suborigin; | |
219 } | |
220 | |
203 PassRefPtr<SecurityOrigin> SecurityOrigin::isolatedCopy() const | 221 PassRefPtr<SecurityOrigin> SecurityOrigin::isolatedCopy() const |
204 { | 222 { |
205 return adoptRef(new SecurityOrigin(this)); | 223 return adoptRef(new SecurityOrigin(this)); |
206 } | 224 } |
207 | 225 |
208 void SecurityOrigin::setDomainFromDOM(const String& newDomain) | 226 void SecurityOrigin::setDomainFromDOM(const String& newDomain) |
209 { | 227 { |
210 m_domainWasSetInDOM = true; | 228 m_domainWasSetInDOM = true; |
211 m_domain = newDomain.lower(); | 229 m_domain = newDomain.lower(); |
212 } | 230 } |
(...skipping 15 matching lines...) Expand all Loading... | |
228 { | 246 { |
229 if (m_universalAccess) | 247 if (m_universalAccess) |
230 return true; | 248 return true; |
231 | 249 |
232 if (this == other) | 250 if (this == other) |
233 return true; | 251 return true; |
234 | 252 |
235 if (isUnique() || other->isUnique()) | 253 if (isUnique() || other->isUnique()) |
236 return false; | 254 return false; |
237 | 255 |
256 if (!sameSuborigin(this, other)) | |
257 return false; | |
258 | |
238 // Here are two cases where we should permit access: | 259 // Here are two cases where we should permit access: |
239 // | 260 // |
240 // 1) Neither document has set document.domain. In this case, we insist | 261 // 1) Neither document has set document.domain. In this case, we insist |
241 // that the scheme, host, and port of the URLs match. | 262 // that the scheme, host, and port of the URLs match. |
242 // | 263 // |
243 // 2) Both documents have set document.domain. In this case, we insist | 264 // 2) Both documents have set document.domain. In this case, we insist |
244 // that the documents have set document.domain to the same value and | 265 // that the documents have set document.domain to the same value and |
245 // that the scheme of the URLs match. | 266 // that the scheme of the URLs match. |
246 // | 267 // |
247 // This matches the behavior of Firefox 2 and Internet Explorer 6. | 268 // This matches the behavior of Firefox 2 and Internet Explorer 6. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 return true; | 312 return true; |
292 | 313 |
293 if (isUnique()) | 314 if (isUnique()) |
294 return false; | 315 return false; |
295 | 316 |
296 RefPtr<SecurityOrigin> targetOrigin = SecurityOrigin::create(url); | 317 RefPtr<SecurityOrigin> targetOrigin = SecurityOrigin::create(url); |
297 | 318 |
298 if (targetOrigin->isUnique()) | 319 if (targetOrigin->isUnique()) |
299 return false; | 320 return false; |
300 | 321 |
322 if (!sameSuborigin(this, targetOrigin.get())) | |
323 return false; | |
324 | |
301 // We call isSameSchemeHostPort here instead of canAccess because we want | 325 // We call isSameSchemeHostPort here instead of canAccess because we want |
302 // to ignore document.domain effects. | 326 // to ignore document.domain effects. |
303 if (isSameSchemeHostPort(targetOrigin.get())) | 327 if (isSameSchemeHostPort(targetOrigin.get())) |
304 return true; | 328 return true; |
305 | 329 |
306 if (SecurityPolicy::isAccessWhiteListed(this, targetOrigin.get())) | 330 if (SecurityPolicy::isAccessWhiteListed(this, targetOrigin.get())) |
307 return true; | 331 return true; |
308 | 332 |
309 return false; | 333 return false; |
310 } | 334 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 ASSERT(m_protocol != "data"); | 405 ASSERT(m_protocol != "data"); |
382 return SchemeRegistry::shouldTreatURLSchemeAsSecure(m_protocol) || isLocal() || isLocalhost(); | 406 return SchemeRegistry::shouldTreatURLSchemeAsSecure(m_protocol) || isLocal() || isLocalhost(); |
383 } | 407 } |
384 | 408 |
385 SecurityOrigin::Policy SecurityOrigin::canShowNotifications() const | 409 SecurityOrigin::Policy SecurityOrigin::canShowNotifications() const |
386 { | 410 { |
387 if (m_universalAccess) | 411 if (m_universalAccess) |
388 return AlwaysAllow; | 412 return AlwaysAllow; |
389 if (isUnique()) | 413 if (isUnique()) |
390 return AlwaysDeny; | 414 return AlwaysDeny; |
415 if (hasSuborigin()) | |
416 return AlwaysDeny; | |
391 return Ask; | 417 return Ask; |
392 } | 418 } |
393 | 419 |
394 void SecurityOrigin::grantLoadLocalResources() | 420 void SecurityOrigin::grantLoadLocalResources() |
395 { | 421 { |
396 // Granting privileges to some, but not all, documents in a SecurityOrigin | 422 // Granting privileges to some, but not all, documents in a SecurityOrigin |
397 // is a security hazard because the documents without the privilege can | 423 // is a security hazard because the documents without the privilege can |
398 // obtain the privilege by injecting script into the documents that have | 424 // obtain the privilege by injecting script into the documents that have |
399 // been granted the privilege. | 425 // been granted the privilege. |
400 m_canLoadLocalResources = true; | 426 m_canLoadLocalResources = true; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 if (m_protocol == "file") | 498 if (m_protocol == "file") |
473 return AtomicString("file://", AtomicString::ConstructFromLiteral); | 499 return AtomicString("file://", AtomicString::ConstructFromLiteral); |
474 | 500 |
475 StringBuilder result; | 501 StringBuilder result; |
476 buildRawString(result); | 502 buildRawString(result); |
477 return result.toAtomicString(); | 503 return result.toAtomicString(); |
478 } | 504 } |
479 | 505 |
480 inline void SecurityOrigin::buildRawString(StringBuilder& builder) const | 506 inline void SecurityOrigin::buildRawString(StringBuilder& builder) const |
481 { | 507 { |
482 builder.reserveCapacity(m_protocol.length() + m_host.length() + 10); | 508 if (hasSuborigin()) { |
509 builder.reserveCapacity(11 + m_suboriginName.length() + m_protocol.lengt h() + m_host.length() + 10); | |
510 builder.appendLiteral("suborigin:"); | |
511 builder.append(m_suboriginName); | |
512 builder.append('+'); | |
513 } else { | |
514 builder.reserveCapacity(m_protocol.length() + m_host.length() + 10); | |
515 } | |
483 builder.append(m_protocol); | 516 builder.append(m_protocol); |
484 builder.appendLiteral("://"); | 517 builder.appendLiteral("://"); |
485 builder.append(m_host); | 518 builder.append(m_host); |
486 | 519 |
487 if (m_port) { | 520 if (m_port) { |
488 builder.append(':'); | 521 builder.append(':'); |
489 builder.appendNumber(m_port); | 522 builder.appendNumber(m_port); |
490 } | 523 } |
491 } | 524 } |
492 | 525 |
493 PassRefPtr<SecurityOrigin> SecurityOrigin::createFromString(const String& origin String) | 526 PassRefPtr<SecurityOrigin> SecurityOrigin::createFromString(const String& origin String) |
494 { | 527 { |
495 return SecurityOrigin::create(KURL(KURL(), originString)); | 528 return SecurityOrigin::create(KURL(KURL(), originString)); |
496 } | 529 } |
497 | 530 |
498 PassRefPtr<SecurityOrigin> SecurityOrigin::create(const String& protocol, const String& host, int port) | 531 PassRefPtr<SecurityOrigin> SecurityOrigin::create(const String& protocol, const String& host, int port) |
499 { | 532 { |
500 if (port < 0 || port > MaxAllowedPort) | 533 if (port < 0 || port > MaxAllowedPort) |
501 return createUnique(); | 534 return createUnique(); |
502 String decodedHost = decodeURLEscapeSequences(host); | 535 String decodedHost = decodeURLEscapeSequences(host); |
503 return create(KURL(KURL(), protocol + "://" + host + ":" + String::number(po rt) + "/")); | 536 return create(KURL(KURL(), protocol + "://" + host + ":" + String::number(po rt) + "/")); |
504 } | 537 } |
505 | 538 |
506 bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin* other) const | 539 bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin* other) const |
507 { | 540 { |
541 if (!sameSuborigin(this, other)) | |
542 return false; | |
543 | |
508 if (m_host != other->m_host) | 544 if (m_host != other->m_host) |
509 return false; | 545 return false; |
510 | 546 |
511 if (m_protocol != other->m_protocol) | 547 if (m_protocol != other->m_protocol) |
512 return false; | 548 return false; |
513 | 549 |
514 if (m_port != other->m_port) | 550 if (m_port != other->m_port) |
515 return false; | 551 return false; |
516 | 552 |
517 if (isLocal() && !passesFileCheck(other)) | 553 if (isLocal() && !passesFileCheck(other)) |
518 return false; | 554 return false; |
519 | 555 |
520 return true; | 556 return true; |
521 } | 557 } |
522 | 558 |
523 const String& SecurityOrigin::urlWithUniqueSecurityOrigin() | 559 const String& SecurityOrigin::urlWithUniqueSecurityOrigin() |
524 { | 560 { |
525 ASSERT(isMainThread()); | 561 ASSERT(isMainThread()); |
526 DEFINE_STATIC_LOCAL(const String, uniqueSecurityOriginURL, ("data:,")); | 562 DEFINE_STATIC_LOCAL(const String, uniqueSecurityOriginURL, ("data:,")); |
527 return uniqueSecurityOriginURL; | 563 return uniqueSecurityOriginURL; |
528 } | 564 } |
529 | 565 |
530 } // namespace WebCore | 566 } // namespace WebCore |
OLD | NEW |