Chromium Code Reviews| 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()); | |
|
Mike West
2014/10/23 12:59:20
Is this any different from `origin1->suboriginName
jww
2015/03/20 22:50:03
Yup. I think I was considering something tricky wi
| |
| 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 , m_enforceFilePathSeparation(false) | 157 , m_enforceFilePathSeparation(false) |
| 152 , m_needsDatabaseIdentifierQuirkForFiles(false) | 158 , m_needsDatabaseIdentifierQuirkForFiles(false) |
| 153 { | 159 { |
| 154 } | 160 } |
| 155 | 161 |
| 156 SecurityOrigin::SecurityOrigin(const SecurityOrigin* other) | 162 SecurityOrigin::SecurityOrigin(const SecurityOrigin* other) |
| 157 : m_protocol(other->m_protocol.isolatedCopy()) | 163 : m_protocol(other->m_protocol.isolatedCopy()) |
| 158 , m_host(other->m_host.isolatedCopy()) | 164 , m_host(other->m_host.isolatedCopy()) |
| 159 , m_domain(other->m_domain.isolatedCopy()) | 165 , m_domain(other->m_domain.isolatedCopy()) |
| 160 , m_filePath(other->m_filePath.isolatedCopy()) | 166 , m_filePath(other->m_filePath.isolatedCopy()) |
| 167 , m_suboriginName(other->m_suboriginName) | |
| 161 , m_port(other->m_port) | 168 , m_port(other->m_port) |
| 162 , m_isUnique(other->m_isUnique) | 169 , m_isUnique(other->m_isUnique) |
| 163 , m_universalAccess(other->m_universalAccess) | 170 , m_universalAccess(other->m_universalAccess) |
| 164 , m_domainWasSetInDOM(other->m_domainWasSetInDOM) | 171 , m_domainWasSetInDOM(other->m_domainWasSetInDOM) |
| 165 , m_canLoadLocalResources(other->m_canLoadLocalResources) | 172 , m_canLoadLocalResources(other->m_canLoadLocalResources) |
| 166 , m_enforceFilePathSeparation(other->m_enforceFilePathSeparation) | 173 , m_enforceFilePathSeparation(other->m_enforceFilePathSeparation) |
| 167 , m_needsDatabaseIdentifierQuirkForFiles(other->m_needsDatabaseIdentifierQui rkForFiles) | 174 , m_needsDatabaseIdentifierQuirkForFiles(other->m_needsDatabaseIdentifierQui rkForFiles) |
| 168 { | 175 { |
| 169 } | 176 } |
| 170 | 177 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 193 return adoptRef(new SecurityOrigin(url)); | 200 return adoptRef(new SecurityOrigin(url)); |
| 194 } | 201 } |
| 195 | 202 |
| 196 PassRefPtr<SecurityOrigin> SecurityOrigin::createUnique() | 203 PassRefPtr<SecurityOrigin> SecurityOrigin::createUnique() |
| 197 { | 204 { |
| 198 RefPtr<SecurityOrigin> origin = adoptRef(new SecurityOrigin()); | 205 RefPtr<SecurityOrigin> origin = adoptRef(new SecurityOrigin()); |
| 199 ASSERT(origin->isUnique()); | 206 ASSERT(origin->isUnique()); |
| 200 return origin.release(); | 207 return origin.release(); |
| 201 } | 208 } |
| 202 | 209 |
| 210 void SecurityOrigin::addSuborigin(const String& suborigin) | |
| 211 { | |
| 212 // Changing suborigins midstream is bad. Very bad. It should not happen. | |
| 213 // This is, in fact, one of the very basic invariants that makes suborigins | |
| 214 // an effective security tool. | |
| 215 RELEASE_ASSERT(m_suboriginName.isNull()); | |
| 216 m_suboriginName = suborigin; | |
| 217 } | |
| 218 | |
| 203 PassRefPtr<SecurityOrigin> SecurityOrigin::isolatedCopy() const | 219 PassRefPtr<SecurityOrigin> SecurityOrigin::isolatedCopy() const |
| 204 { | 220 { |
| 205 return adoptRef(new SecurityOrigin(this)); | 221 return adoptRef(new SecurityOrigin(this)); |
| 206 } | 222 } |
| 207 | 223 |
| 208 void SecurityOrigin::setDomainFromDOM(const String& newDomain) | 224 void SecurityOrigin::setDomainFromDOM(const String& newDomain) |
| 209 { | 225 { |
| 210 m_domainWasSetInDOM = true; | 226 m_domainWasSetInDOM = true; |
| 211 m_domain = newDomain.lower(); | 227 m_domain = newDomain.lower(); |
| 212 } | 228 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 228 { | 244 { |
| 229 if (m_universalAccess) | 245 if (m_universalAccess) |
| 230 return true; | 246 return true; |
| 231 | 247 |
| 232 if (this == other) | 248 if (this == other) |
| 233 return true; | 249 return true; |
| 234 | 250 |
| 235 if (isUnique() || other->isUnique()) | 251 if (isUnique() || other->isUnique()) |
| 236 return false; | 252 return false; |
| 237 | 253 |
| 254 if (!sameSuborigin(this, other)) | |
| 255 return false; | |
|
Mike West
2014/10/23 12:59:20
I assume that bypassing the `document.domain` chec
jww
2015/03/20 22:50:03
Definitely.
| |
| 256 | |
| 238 // Here are two cases where we should permit access: | 257 // Here are two cases where we should permit access: |
| 239 // | 258 // |
| 240 // 1) Neither document has set document.domain. In this case, we insist | 259 // 1) Neither document has set document.domain. In this case, we insist |
| 241 // that the scheme, host, and port of the URLs match. | 260 // that the scheme, host, and port of the URLs match. |
| 242 // | 261 // |
| 243 // 2) Both documents have set document.domain. In this case, we insist | 262 // 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 | 263 // that the documents have set document.domain to the same value and |
| 245 // that the scheme of the URLs match. | 264 // that the scheme of the URLs match. |
| 246 // | 265 // |
| 247 // This matches the behavior of Firefox 2 and Internet Explorer 6. | 266 // 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; | 310 return true; |
| 292 | 311 |
| 293 if (isUnique()) | 312 if (isUnique()) |
| 294 return false; | 313 return false; |
| 295 | 314 |
| 296 RefPtr<SecurityOrigin> targetOrigin = SecurityOrigin::create(url); | 315 RefPtr<SecurityOrigin> targetOrigin = SecurityOrigin::create(url); |
| 297 | 316 |
| 298 if (targetOrigin->isUnique()) | 317 if (targetOrigin->isUnique()) |
| 299 return false; | 318 return false; |
| 300 | 319 |
| 320 if (!sameSuborigin(this, targetOrigin.get())) | |
| 321 return false; | |
| 322 | |
| 301 // We call isSameSchemeHostPort here instead of canAccess because we want | 323 // We call isSameSchemeHostPort here instead of canAccess because we want |
| 302 // to ignore document.domain effects. | 324 // to ignore document.domain effects. |
| 303 if (isSameSchemeHostPort(targetOrigin.get())) | 325 if (isSameSchemeHostPort(targetOrigin.get())) |
| 304 return true; | 326 return true; |
| 305 | 327 |
| 306 if (SecurityPolicy::isAccessWhiteListed(this, targetOrigin.get())) | 328 if (SecurityPolicy::isAccessWhiteListed(this, targetOrigin.get())) |
| 307 return true; | 329 return true; |
| 308 | 330 |
| 309 return false; | 331 return false; |
| 310 } | 332 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 errorMessage = "Only secure origins are allowed. http://goo.gl/lq4gCo"; | 407 errorMessage = "Only secure origins are allowed. http://goo.gl/lq4gCo"; |
| 386 return false; | 408 return false; |
| 387 } | 409 } |
| 388 | 410 |
| 389 SecurityOrigin::Policy SecurityOrigin::canShowNotifications() const | 411 SecurityOrigin::Policy SecurityOrigin::canShowNotifications() const |
| 390 { | 412 { |
| 391 if (m_universalAccess) | 413 if (m_universalAccess) |
| 392 return AlwaysAllow; | 414 return AlwaysAllow; |
| 393 if (isUnique()) | 415 if (isUnique()) |
| 394 return AlwaysDeny; | 416 return AlwaysDeny; |
| 417 if (hasSuborigin()) | |
| 418 return AlwaysDeny; | |
|
Mike West
2014/10/23 12:59:20
Why?
jww
2015/03/20 22:50:03
Same rationale as above. Start with the limitation
| |
| 395 return Ask; | 419 return Ask; |
| 396 } | 420 } |
| 397 | 421 |
| 398 void SecurityOrigin::grantLoadLocalResources() | 422 void SecurityOrigin::grantLoadLocalResources() |
| 399 { | 423 { |
| 400 // Granting privileges to some, but not all, documents in a SecurityOrigin | 424 // Granting privileges to some, but not all, documents in a SecurityOrigin |
| 401 // is a security hazard because the documents without the privilege can | 425 // is a security hazard because the documents without the privilege can |
| 402 // obtain the privilege by injecting script into the documents that have | 426 // obtain the privilege by injecting script into the documents that have |
| 403 // been granted the privilege. | 427 // been granted the privilege. |
| 404 m_canLoadLocalResources = true; | 428 m_canLoadLocalResources = true; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 if (m_protocol == "file") | 500 if (m_protocol == "file") |
| 477 return AtomicString("file://", AtomicString::ConstructFromLiteral); | 501 return AtomicString("file://", AtomicString::ConstructFromLiteral); |
| 478 | 502 |
| 479 StringBuilder result; | 503 StringBuilder result; |
| 480 buildRawString(result); | 504 buildRawString(result); |
| 481 return result.toAtomicString(); | 505 return result.toAtomicString(); |
| 482 } | 506 } |
| 483 | 507 |
| 484 inline void SecurityOrigin::buildRawString(StringBuilder& builder) const | 508 inline void SecurityOrigin::buildRawString(StringBuilder& builder) const |
| 485 { | 509 { |
| 486 builder.reserveCapacity(m_protocol.length() + m_host.length() + 10); | 510 if (hasSuborigin()) { |
| 511 builder.reserveCapacity(11 + m_suboriginName.length() + m_protocol.lengt h() + m_host.length() + 10); | |
| 512 builder.appendLiteral("suborigin:"); | |
| 513 builder.append(m_suboriginName); | |
| 514 builder.append('+'); | |
|
Mike West
2014/10/23 12:59:20
Is this the scheme we ended up with on the list?
jww
2015/03/20 22:50:03
There was no consensus, but it was the compromise
| |
| 515 } else { | |
| 516 builder.reserveCapacity(m_protocol.length() + m_host.length() + 10); | |
| 517 } | |
| 487 builder.append(m_protocol); | 518 builder.append(m_protocol); |
| 488 builder.appendLiteral("://"); | 519 builder.appendLiteral("://"); |
| 489 builder.append(m_host); | 520 builder.append(m_host); |
| 490 | 521 |
| 491 if (m_port) { | 522 if (m_port) { |
| 492 builder.append(':'); | 523 builder.append(':'); |
| 493 builder.appendNumber(m_port); | 524 builder.appendNumber(m_port); |
| 494 } | 525 } |
| 495 } | 526 } |
| 496 | 527 |
| 497 PassRefPtr<SecurityOrigin> SecurityOrigin::createFromString(const String& origin String) | 528 PassRefPtr<SecurityOrigin> SecurityOrigin::createFromString(const String& origin String) |
|
Mike West
2014/10/23 12:59:20
You're not handling creation of origins with subor
jww
2015/03/20 22:50:03
You're right, I need to add to the SecurityOrigin
| |
| 498 { | 529 { |
| 499 return SecurityOrigin::create(KURL(KURL(), originString)); | 530 return SecurityOrigin::create(KURL(KURL(), originString)); |
| 500 } | 531 } |
| 501 | 532 |
| 502 PassRefPtr<SecurityOrigin> SecurityOrigin::create(const String& protocol, const String& host, int port) | 533 PassRefPtr<SecurityOrigin> SecurityOrigin::create(const String& protocol, const String& host, int port) |
| 503 { | 534 { |
| 504 if (port < 0 || port > MaxAllowedPort) | 535 if (port < 0 || port > MaxAllowedPort) |
| 505 return createUnique(); | 536 return createUnique(); |
| 506 String decodedHost = decodeURLEscapeSequences(host); | 537 String decodedHost = decodeURLEscapeSequences(host); |
| 507 return create(KURL(KURL(), protocol + "://" + host + ":" + String::number(po rt) + "/")); | 538 return create(KURL(KURL(), protocol + "://" + host + ":" + String::number(po rt) + "/")); |
| 508 } | 539 } |
| 509 | 540 |
| 510 bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin* other) const | 541 bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin* other) const |
| 511 { | 542 { |
| 543 if (!sameSuborigin(this, other)) | |
| 544 return false; | |
| 545 | |
| 512 if (m_host != other->m_host) | 546 if (m_host != other->m_host) |
| 513 return false; | 547 return false; |
| 514 | 548 |
| 515 if (m_protocol != other->m_protocol) | 549 if (m_protocol != other->m_protocol) |
| 516 return false; | 550 return false; |
| 517 | 551 |
| 518 if (m_port != other->m_port) | 552 if (m_port != other->m_port) |
| 519 return false; | 553 return false; |
| 520 | 554 |
| 521 if (isLocal() && !passesFileCheck(other)) | 555 if (isLocal() && !passesFileCheck(other)) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 532 } | 566 } |
| 533 | 567 |
| 534 void SecurityOrigin::transferPrivilegesFrom(const SecurityOrigin& origin) | 568 void SecurityOrigin::transferPrivilegesFrom(const SecurityOrigin& origin) |
| 535 { | 569 { |
| 536 m_universalAccess = origin.m_universalAccess; | 570 m_universalAccess = origin.m_universalAccess; |
| 537 m_canLoadLocalResources = origin.m_canLoadLocalResources; | 571 m_canLoadLocalResources = origin.m_canLoadLocalResources; |
| 538 m_enforceFilePathSeparation = origin.m_enforceFilePathSeparation; | 572 m_enforceFilePathSeparation = origin.m_enforceFilePathSeparation; |
| 539 } | 573 } |
| 540 | 574 |
| 541 } // namespace blink | 575 } // namespace blink |
| OLD | NEW |