BasePrincipal.cpp (45652B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 sw=2 et tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/BasePrincipal.h" 8 9 #include "nsDocShell.h" 10 11 #include "ExpandedPrincipal.h" 12 #include "nsNetUtil.h" 13 #include "nsContentUtils.h" 14 #include "nsIOService.h" 15 #include "nsIURIWithSpecialOrigin.h" 16 #include "nsScriptSecurityManager.h" 17 #include "nsServiceManagerUtils.h" 18 #include "nsAboutProtocolUtils.h" 19 #include "ThirdPartyUtil.h" 20 #include "mozilla/ContentPrincipal.h" 21 #include "mozilla/ExtensionPolicyService.h" 22 #include "mozilla/NullPrincipal.h" 23 #include "mozilla/dom/BlobURLProtocolHandler.h" 24 #include "mozilla/dom/ChromeUtils.h" 25 #include "mozilla/dom/ReferrerInfo.h" 26 #include "mozilla/dom/ToJSValue.h" 27 #include "mozilla/dom/nsMixedContentBlocker.h" 28 #include "mozilla/Components.h" 29 #include "mozilla/dom/StorageUtils.h" 30 #include "mozilla/dom/StorageUtils.h" 31 #include "mozilla/JSONStringWriteFuncs.h" 32 #include "mozilla/JSONWriter.h" 33 #include "nsIEffectiveTLDService.h" 34 #include "nsIURL.h" 35 #include "nsIURIMutator.h" 36 #include "mozilla/StaticPrefs_permissions.h" 37 #include "nsIURIMutator.h" 38 #include "nsMixedContentBlocker.h" 39 #include "prnetdb.h" 40 #include "nsIURIFixup.h" 41 #include "mozilla/dom/StorageUtils.h" 42 #include "mozilla/StorageAccess.h" 43 #include "nsPIDOMWindow.h" 44 #include "nsIURIMutator.h" 45 #include "mozilla/PermissionManager.h" 46 47 #include "nsSerializationHelper.h" 48 49 #include "js/JSON.h" 50 #include "ContentPrincipalJSONHandler.h" 51 #include "ExpandedPrincipalJSONHandler.h" 52 #include "NullPrincipalJSONHandler.h" 53 #include "PrincipalJSONHandler.h" 54 #include "SubsumedPrincipalJSONHandler.h" 55 56 namespace mozilla { 57 58 BasePrincipal::BasePrincipal(PrincipalKind aKind, 59 const nsACString& aOriginNoSuffix, 60 const OriginAttributes& aOriginAttributes) 61 : mOriginNoSuffix(NS_Atomize(aOriginNoSuffix)), 62 mOriginSuffix(aOriginAttributes.CreateSuffixAtom()), 63 mOriginAttributes(aOriginAttributes), 64 mKind(aKind), 65 mHasExplicitDomain(false) {} 66 67 BasePrincipal::BasePrincipal(BasePrincipal* aOther, 68 const OriginAttributes& aOriginAttributes) 69 : mOriginNoSuffix(aOther->mOriginNoSuffix), 70 mOriginSuffix(aOriginAttributes.CreateSuffixAtom()), 71 mOriginAttributes(aOriginAttributes), 72 mKind(aOther->mKind), 73 mHasExplicitDomain(aOther->mHasExplicitDomain.load()) {} 74 75 BasePrincipal::~BasePrincipal() = default; 76 77 NS_IMETHODIMP 78 BasePrincipal::GetOrigin(nsACString& aOrigin) { 79 nsresult rv = GetOriginNoSuffix(aOrigin); 80 NS_ENSURE_SUCCESS(rv, rv); 81 82 nsAutoCString suffix; 83 rv = GetOriginSuffix(suffix); 84 NS_ENSURE_SUCCESS(rv, rv); 85 aOrigin.Append(suffix); 86 return NS_OK; 87 } 88 89 NS_IMETHODIMP 90 BasePrincipal::GetWebExposedOriginSerialization(nsACString& aOrigin) { 91 aOrigin.Truncate(); 92 nsCOMPtr<nsIURI> prinURI; 93 nsresult rv = GetURI(getter_AddRefs(prinURI)); 94 if (NS_FAILED(rv) || !prinURI) { 95 return NS_ERROR_NOT_AVAILABLE; 96 } 97 return nsContentUtils::GetWebExposedOriginSerialization(prinURI, aOrigin); 98 } 99 100 NS_IMETHODIMP 101 BasePrincipal::GetHostPort(nsACString& aRes) { 102 aRes.Truncate(); 103 nsCOMPtr<nsIURI> prinURI; 104 nsresult rv = GetURI(getter_AddRefs(prinURI)); 105 if (NS_FAILED(rv) || !prinURI) { 106 return NS_OK; 107 } 108 return prinURI->GetHostPort(aRes); 109 } 110 111 NS_IMETHODIMP 112 BasePrincipal::GetHost(nsACString& aRes) { 113 aRes.Truncate(); 114 nsCOMPtr<nsIURI> prinURI; 115 nsresult rv = GetURI(getter_AddRefs(prinURI)); 116 if (NS_FAILED(rv) || !prinURI) { 117 return NS_OK; 118 } 119 return prinURI->GetHost(aRes); 120 } 121 122 NS_IMETHODIMP 123 BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) { 124 mOriginNoSuffix->ToUTF8String(aOrigin); 125 return NS_OK; 126 } 127 128 NS_IMETHODIMP 129 BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) { 130 nsresult rv = GetSiteOriginNoSuffix(aSiteOrigin); 131 NS_ENSURE_SUCCESS(rv, rv); 132 133 nsAutoCString suffix; 134 rv = GetOriginSuffix(suffix); 135 NS_ENSURE_SUCCESS(rv, rv); 136 aSiteOrigin.Append(suffix); 137 return NS_OK; 138 } 139 140 NS_IMETHODIMP 141 BasePrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) { 142 return GetOriginNoSuffix(aSiteOrigin); 143 } 144 145 template <typename HandlerTypesT> 146 bool ContainerPrincipalJSONHandler<HandlerTypesT>::ProcessInnerResult( 147 bool aResult) { 148 if (!aResult) { 149 NS_WARNING("Failed to parse inner object"); 150 mState = State::Error; 151 return false; 152 } 153 return true; 154 } 155 156 template <typename HandlerTypesT> 157 bool ContainerPrincipalJSONHandler<HandlerTypesT>::startObject() { 158 if (mInnerHandler.isSome()) { 159 return CallOnInner([&](auto& aInner) { return aInner.startObject(); }); 160 } 161 162 switch (mState) { 163 case State::Init: 164 mState = State::StartObject; 165 break; 166 case State::SystemPrincipal_Key: 167 mState = State::SystemPrincipal_StartObject; 168 break; 169 default: 170 NS_WARNING("Unexpected object value"); 171 mState = State::Error; 172 return false; 173 } 174 175 return true; 176 } 177 178 template <typename HandlerTypesT> 179 bool ContainerPrincipalJSONHandler<HandlerTypesT>::propertyName( 180 const JS::Latin1Char* name, size_t length) { 181 if (mInnerHandler.isSome()) { 182 return CallOnInner( 183 [&](auto& aInner) { return aInner.propertyName(name, length); }); 184 } 185 186 switch (mState) { 187 case State::StartObject: { 188 if (length != 1) { 189 NS_WARNING( 190 nsPrintfCString("Unexpected property name length: %zu", length) 191 .get()); 192 mState = State::Error; 193 return false; 194 } 195 196 char key = char(name[0]); 197 switch (key) { 198 case BasePrincipal::NullPrincipalKey: 199 mState = State::NullPrincipal_Inner; 200 mInnerHandler.emplace(VariantType<NullPrincipalJSONHandler>()); 201 break; 202 case BasePrincipal::ContentPrincipalKey: 203 mState = State::ContentPrincipal_Inner; 204 mInnerHandler.emplace(VariantType<ContentPrincipalJSONHandler>()); 205 break; 206 case BasePrincipal::SystemPrincipalKey: 207 mState = State::SystemPrincipal_Key; 208 break; 209 default: 210 if constexpr (CanContainExpandedPrincipal) { 211 if (key == BasePrincipal::ExpandedPrincipalKey) { 212 mState = State::ExpandedPrincipal_Inner; 213 mInnerHandler.emplace( 214 VariantType<ExpandedPrincipalJSONHandler>()); 215 break; 216 } 217 } 218 NS_WARNING( 219 nsPrintfCString("Unexpected property name: '%c'", key).get()); 220 mState = State::Error; 221 return false; 222 } 223 break; 224 } 225 default: 226 NS_WARNING("Unexpected property name"); 227 mState = State::Error; 228 return false; 229 } 230 231 return true; 232 } 233 234 template <typename HandlerTypesT> 235 bool ContainerPrincipalJSONHandler<HandlerTypesT>::endObject() { 236 if (mInnerHandler.isSome()) { 237 return CallOnInner([&](auto& aInner) { 238 if (!aInner.endObject()) { 239 return false; 240 } 241 if (aInner.HasAccepted()) { 242 this->mPrincipal = aInner.mPrincipal.forget(); 243 MOZ_ASSERT(this->mPrincipal); 244 mInnerHandler.reset(); 245 } 246 return true; 247 }); 248 } 249 250 switch (mState) { 251 case State::SystemPrincipal_StartObject: 252 mState = State::SystemPrincipal_EndObject; 253 break; 254 case State::SystemPrincipal_EndObject: 255 this->mPrincipal = 256 BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal()); 257 mState = State::EndObject; 258 break; 259 case State::NullPrincipal_Inner: 260 mState = State::EndObject; 261 break; 262 case State::ContentPrincipal_Inner: 263 mState = State::EndObject; 264 break; 265 default: 266 if constexpr (CanContainExpandedPrincipal) { 267 if (mState == State::ExpandedPrincipal_Inner) { 268 mState = State::EndObject; 269 break; 270 } 271 } 272 NS_WARNING("Unexpected end of object"); 273 mState = State::Error; 274 return false; 275 } 276 277 return true; 278 } 279 280 template <typename HandlerTypesT> 281 bool ContainerPrincipalJSONHandler<HandlerTypesT>::startArray() { 282 if constexpr (CanContainExpandedPrincipal) { 283 if (mInnerHandler.isSome()) { 284 return CallOnInner([&](auto& aInner) { return aInner.startArray(); }); 285 } 286 } 287 288 NS_WARNING("Unexpected array value"); 289 mState = State::Error; 290 return false; 291 } 292 293 template <typename HandlerTypesT> 294 bool ContainerPrincipalJSONHandler<HandlerTypesT>::endArray() { 295 if constexpr (CanContainExpandedPrincipal) { 296 if (mInnerHandler.isSome()) { 297 return CallOnInner([&](auto& aInner) { return aInner.endArray(); }); 298 } 299 } 300 301 NS_WARNING("Unexpected array value"); 302 mState = State::Error; 303 return false; 304 } 305 306 template <typename HandlerTypesT> 307 bool ContainerPrincipalJSONHandler<HandlerTypesT>::stringValue( 308 const JS::Latin1Char* str, size_t length) { 309 if (mInnerHandler.isSome()) { 310 return CallOnInner( 311 [&](auto& aInner) { return aInner.stringValue(str, length); }); 312 } 313 314 NS_WARNING("Unexpected string value"); 315 mState = State::Error; 316 return false; 317 } 318 319 template class ContainerPrincipalJSONHandler<PrincipalJSONHandlerTypes>; 320 template class ContainerPrincipalJSONHandler<SubsumedPrincipalJSONHandlerTypes>; 321 322 // Takes a JSON string and parses it turning it into a principal of the 323 // corresponding type 324 // 325 // Given a content principal: 326 // 327 // inner JSON object 328 // | 329 // --------------------------------------------------------- 330 // | | 331 // {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}} 332 // | | | | | 333 // | ----------------------------- | 334 // | | | | 335 // PrincipalKind | | | 336 // | ---------------------------- 337 // SerializableKeys | 338 // Value 339 // 340 already_AddRefed<BasePrincipal> BasePrincipal::FromJSON( 341 const nsACString& aJSON) { 342 PrincipalJSONHandler handler; 343 344 if (!JS::ParseJSONWithHandler( 345 reinterpret_cast<const JS::Latin1Char*>(aJSON.BeginReading()), 346 aJSON.Length(), &handler)) { 347 NS_WARNING( 348 nsPrintfCString("Unable to parse: %s", aJSON.BeginReading()).get()); 349 MOZ_ASSERT(false, 350 "Unable to parse string as JSON to deserialize as a principal"); 351 return nullptr; 352 } 353 354 return handler.Get(); 355 } 356 357 // Returns a JSON representation of the principal. 358 // Calling BasePrincipal::FromJSON will deserialize the JSON into 359 // the corresponding principal type. 360 nsresult BasePrincipal::ToJSON(nsACString& aJSON) { 361 MOZ_ASSERT(aJSON.IsEmpty(), "ToJSON only supports an empty result input"); 362 aJSON.Truncate(); 363 364 // NOTE: JSONWriter emits raw UTF-8 code units for non-ASCII range. 365 JSONStringRefWriteFunc func(aJSON); 366 JSONWriter writer(func, JSONWriter::CollectionStyle::SingleLineStyle); 367 368 nsresult rv = ToJSON(writer); 369 NS_ENSURE_SUCCESS(rv, rv); 370 371 return NS_OK; 372 } 373 374 nsresult BasePrincipal::ToJSON(JSONWriter& aWriter) { 375 static_assert(eKindMax < std::size(JSONEnumKeyStrings)); 376 377 aWriter.Start(JSONWriter::CollectionStyle::SingleLineStyle); 378 379 nsresult rv = WriteJSONProperties(aWriter); 380 NS_ENSURE_SUCCESS(rv, rv); 381 382 aWriter.End(); 383 384 return NS_OK; 385 } 386 387 nsresult BasePrincipal::WriteJSONProperties(JSONWriter& aWriter) { 388 aWriter.StartObjectProperty(JSONEnumKeyStrings[Kind()], 389 JSONWriter::CollectionStyle::SingleLineStyle); 390 391 nsresult rv = WriteJSONInnerProperties(aWriter); 392 NS_ENSURE_SUCCESS(rv, rv); 393 394 aWriter.EndObject(); 395 396 return NS_OK; 397 } 398 399 nsresult BasePrincipal::WriteJSONInnerProperties(JSONWriter& aWriter) { 400 return NS_OK; 401 } 402 403 bool BasePrincipal::FastSubsumesIgnoringFPD( 404 nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) { 405 MOZ_ASSERT(aOther); 406 407 if (Kind() == eContentPrincipal && 408 !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD( 409 mOriginAttributes, Cast(aOther)->mOriginAttributes)) { 410 return false; 411 } 412 413 return SubsumesInternal(aOther, aConsideration); 414 } 415 416 bool BasePrincipal::Subsumes(nsIPrincipal* aOther, 417 DocumentDomainConsideration aConsideration) { 418 MOZ_ASSERT(aOther); 419 MOZ_ASSERT_IF(Kind() == eContentPrincipal, mOriginSuffix); 420 421 // Expanded principals handle origin attributes for each of their 422 // sub-principals individually, null principals do only simple checks for 423 // pointer equality, and system principals are immune to origin attributes 424 // checks, so only do this check for content principals. 425 if (Kind() == eContentPrincipal && 426 mOriginSuffix != Cast(aOther)->mOriginSuffix) { 427 return false; 428 } 429 430 return SubsumesInternal(aOther, aConsideration); 431 } 432 433 NS_IMETHODIMP 434 BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) { 435 NS_ENSURE_ARG_POINTER(aOther); 436 437 *aResult = FastEquals(aOther); 438 439 return NS_OK; 440 } 441 442 NS_IMETHODIMP 443 BasePrincipal::EqualsForPermission(nsIPrincipal* aOther, bool aExactHost, 444 bool* aResult) { 445 *aResult = false; 446 NS_ENSURE_ARG_POINTER(aOther); 447 NS_ENSURE_ARG_POINTER(aResult); 448 449 auto* other = Cast(aOther); 450 if (Kind() != other->Kind()) { 451 // Principals of different kinds can't be equal. 452 return NS_OK; 453 } 454 455 if (Kind() == eSystemPrincipal) { 456 *aResult = this == other; 457 return NS_OK; 458 } 459 460 if (Kind() == eNullPrincipal) { 461 // We don't store permissions for NullPrincipals. 462 return NS_OK; 463 } 464 465 MOZ_ASSERT(Kind() == eExpandedPrincipal || Kind() == eContentPrincipal); 466 467 // Certain origin attributes should not be used to isolate permissions. 468 // Create a stripped copy of both OA sets to compare. 469 mozilla::OriginAttributes ourAttrs = mOriginAttributes; 470 PermissionManager::MaybeStripOriginAttributes(false, ourAttrs); 471 mozilla::OriginAttributes theirAttrs = aOther->OriginAttributesRef(); 472 PermissionManager::MaybeStripOriginAttributes(false, theirAttrs); 473 474 if (ourAttrs != theirAttrs) { 475 return NS_OK; 476 } 477 478 if (mOriginNoSuffix == other->mOriginNoSuffix) { 479 *aResult = true; 480 return NS_OK; 481 } 482 483 // If we are matching with an exact host, we're done now - the permissions 484 // don't match otherwise, we need to start comparing subdomains! 485 if (aExactHost) { 486 return NS_OK; 487 } 488 489 nsCOMPtr<nsIURI> ourURI; 490 nsresult rv = GetURI(getter_AddRefs(ourURI)); 491 NS_ENSURE_SUCCESS(rv, rv); 492 // Some principal types may indicate success, but still return nullptr for 493 // URI. 494 NS_ENSURE_TRUE(ourURI, NS_ERROR_FAILURE); 495 496 nsCOMPtr<nsIURI> otherURI; 497 rv = other->GetURI(getter_AddRefs(otherURI)); 498 NS_ENSURE_SUCCESS(rv, rv); 499 NS_ENSURE_TRUE(otherURI, NS_ERROR_FAILURE); 500 501 // Compare schemes 502 nsAutoCString otherScheme; 503 rv = otherURI->GetScheme(otherScheme); 504 NS_ENSURE_SUCCESS(rv, rv); 505 506 nsAutoCString ourScheme; 507 rv = ourURI->GetScheme(ourScheme); 508 NS_ENSURE_SUCCESS(rv, rv); 509 510 if (otherScheme != ourScheme) { 511 return NS_OK; 512 } 513 514 // Compare ports 515 int32_t otherPort; 516 rv = otherURI->GetPort(&otherPort); 517 NS_ENSURE_SUCCESS(rv, rv); 518 519 int32_t ourPort; 520 rv = ourURI->GetPort(&ourPort); 521 NS_ENSURE_SUCCESS(rv, rv); 522 523 if (otherPort != ourPort) { 524 return NS_OK; 525 } 526 527 // Check if the host or any subdomain of their host matches. 528 nsAutoCString otherHost; 529 rv = otherURI->GetHost(otherHost); 530 if (NS_FAILED(rv) || otherHost.IsEmpty()) { 531 return NS_OK; 532 } 533 534 nsAutoCString ourHost; 535 rv = ourURI->GetHost(ourHost); 536 if (NS_FAILED(rv) || ourHost.IsEmpty()) { 537 return NS_OK; 538 } 539 540 nsCOMPtr<nsIEffectiveTLDService> tldService = 541 mozilla::components::EffectiveTLD::Service(); 542 if (!tldService) { 543 NS_ERROR("Should have a tld service!"); 544 return NS_ERROR_FAILURE; 545 } 546 547 // This loop will not loop forever, as GetNextSubDomain will eventually fail 548 // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS. 549 while (otherHost != ourHost) { 550 rv = tldService->GetNextSubDomain(otherHost, otherHost); 551 if (NS_FAILED(rv)) { 552 if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) { 553 return NS_OK; 554 } 555 return rv; 556 } 557 } 558 559 *aResult = true; 560 return NS_OK; 561 } 562 563 NS_IMETHODIMP 564 BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) { 565 NS_ENSURE_ARG_POINTER(aOther); 566 567 *aResult = FastEqualsConsideringDomain(aOther); 568 569 return NS_OK; 570 } 571 572 NS_IMETHODIMP 573 BasePrincipal::EqualsURI(nsIURI* aOtherURI, bool* aResult) { 574 *aResult = false; 575 nsCOMPtr<nsIURI> prinURI; 576 nsresult rv = GetURI(getter_AddRefs(prinURI)); 577 if (NS_FAILED(rv) || !prinURI) { 578 return NS_OK; 579 } 580 return prinURI->EqualsExceptRef(aOtherURI, aResult); 581 } 582 583 NS_IMETHODIMP 584 BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) { 585 NS_ENSURE_ARG_POINTER(aOther); 586 587 *aResult = FastSubsumes(aOther); 588 589 return NS_OK; 590 } 591 592 NS_IMETHODIMP 593 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) { 594 NS_ENSURE_ARG_POINTER(aOther); 595 596 *aResult = FastSubsumesConsideringDomain(aOther); 597 598 return NS_OK; 599 } 600 601 NS_IMETHODIMP 602 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther, 603 bool* aResult) { 604 NS_ENSURE_ARG_POINTER(aOther); 605 606 *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther); 607 608 return NS_OK; 609 } 610 611 NS_IMETHODIMP 612 BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aAllowIfInheritsPrincipal) { 613 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0); 614 } 615 616 NS_IMETHODIMP 617 BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI, 618 bool aAllowIfInheritsPrincipal, 619 uint64_t aInnerWindowID) { 620 AssertIsOnMainThread(); 621 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true, 622 aInnerWindowID); 623 } 624 625 nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI, 626 bool aAllowIfInheritsPrincipal, 627 bool aReport, 628 uint64_t aInnerWindowID) { 629 NS_ENSURE_ARG_POINTER(aURI); 630 MOZ_ASSERT( 631 aReport || aInnerWindowID == 0, 632 "Why do we have an inner window id if we're not supposed to report?"); 633 MOZ_ASSERT(!aReport || NS_IsMainThread(), "Must be on main thread to report"); 634 635 // Check the internal method first, which allows us to quickly approve loads 636 // for the System Principal. 637 if (MayLoadInternal(aURI)) { 638 return NS_OK; 639 } 640 641 nsresult rv; 642 if (aAllowIfInheritsPrincipal) { 643 // If the caller specified to allow loads of URIs that inherit 644 // our principal, allow the load if this URI inherits its principal. 645 bool doesInheritSecurityContext; 646 rv = NS_URIChainHasFlags(aURI, 647 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, 648 &doesInheritSecurityContext); 649 if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) { 650 return NS_OK; 651 } 652 } 653 654 // Get the principal uri for the WebExtension access check or error. 655 nsCOMPtr<nsIURI> prinURI; 656 rv = GetURI(getter_AddRefs(prinURI)); 657 if (!(NS_SUCCEEDED(rv) && prinURI)) { 658 return NS_ERROR_DOM_BAD_URI; 659 } 660 661 // If the URL being loaded corresponds to a WebExtension URL, ask the policy 662 // if the path should be accessible. 663 bool isWebExtensionResource; 664 rv = NS_URIChainHasFlags(aURI, 665 nsIProtocolHandler::URI_IS_WEBEXTENSION_RESOURCE, 666 &isWebExtensionResource); 667 if (NS_SUCCEEDED(rv) && isWebExtensionResource) { 668 extensions::URLInfo urlInfo(aURI); 669 if (RefPtr<extensions::WebExtensionPolicyCore> urlPolicyCore = 670 ExtensionPolicyService::GetCoreByURL(urlInfo)) { 671 extensions::URLInfo prinUrlInfo(prinURI); 672 if (urlPolicyCore->SourceMayAccessPath(prinUrlInfo, urlInfo.FilePath())) { 673 return NS_OK; 674 } 675 } 676 } 677 678 if (aReport) { 679 // FIXME: Once bug 1900706 is complete, reporting can be updated to work 680 // off-main-thread. 681 nsScriptSecurityManager::ReportError("CheckSameOriginError", prinURI, aURI, 682 mOriginAttributes.IsPrivateBrowsing(), 683 aInnerWindowID); 684 } 685 686 return NS_ERROR_DOM_BAD_URI; 687 } 688 689 NS_IMETHODIMP 690 BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) { 691 if (IsSystemPrincipal() || (AddonPolicyCore() && AddonAllowsLoad(aURI))) { 692 *aRes = false; 693 return NS_OK; 694 } 695 696 *aRes = true; 697 // If we do not have a URI its always 3rd party. 698 nsCOMPtr<nsIURI> prinURI; 699 nsresult rv = GetURI(getter_AddRefs(prinURI)); 700 if (NS_FAILED(rv) || !prinURI) { 701 return NS_OK; 702 } 703 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance(); 704 return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes); 705 } 706 707 NS_IMETHODIMP 708 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) { 709 *aRes = true; 710 nsCOMPtr<nsIURI> prinURI; 711 nsresult rv = GetURI(getter_AddRefs(prinURI)); 712 if (NS_FAILED(rv) || !prinURI) { 713 return NS_OK; 714 } 715 return aPrin->IsThirdPartyURI(prinURI, aRes); 716 } 717 718 NS_IMETHODIMP 719 BasePrincipal::IsThirdPartyChannel(nsIChannel* aChan, bool* aRes) { 720 AssertIsOnMainThread(); 721 if (IsSystemPrincipal()) { 722 // Nothing is 3rd party to the system principal. 723 *aRes = false; 724 return NS_OK; 725 } 726 727 nsCOMPtr<nsIURI> prinURI; 728 GetURI(getter_AddRefs(prinURI)); 729 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance(); 730 return thirdPartyUtil->IsThirdPartyChannel(aChan, prinURI, aRes); 731 } 732 733 NS_IMETHODIMP 734 BasePrincipal::IsSameOrigin(nsIURI* aURI, bool* aRes) { 735 *aRes = false; 736 nsCOMPtr<nsIURI> prinURI; 737 nsresult rv = GetURI(getter_AddRefs(prinURI)); 738 if (NS_FAILED(rv) || !prinURI) { 739 // Note that expanded and system principals return here, because they have 740 // no URI. 741 return NS_OK; 742 } 743 *aRes = nsScriptSecurityManager::SecurityCompareURIs(prinURI, aURI); 744 return NS_OK; 745 } 746 747 NS_IMETHODIMP 748 BasePrincipal::IsL10nAllowed(nsIURI* aURI, bool* aRes) { 749 AssertIsOnMainThread(); // URI_DANGEROUS_TO_LOAD is not threadsafe to query. 750 *aRes = false; 751 752 if (nsContentUtils::IsErrorPage(aURI)) { 753 *aRes = true; 754 return NS_OK; 755 } 756 757 // The system principal is always allowed. 758 if (IsSystemPrincipal()) { 759 *aRes = true; 760 return NS_OK; 761 } 762 763 nsCOMPtr<nsIURI> uri; 764 nsresult rv = GetURI(getter_AddRefs(uri)); 765 NS_ENSURE_SUCCESS(rv, NS_OK); 766 767 if (!uri) { 768 return NS_OK; 769 } 770 771 bool hasFlags; 772 773 // Allow access to uris that cannot be loaded by web content. 774 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD, 775 &hasFlags); 776 NS_ENSURE_SUCCESS(rv, NS_OK); 777 if (hasFlags) { 778 *aRes = true; 779 return NS_OK; 780 } 781 782 // UI resources also get access. 783 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, 784 &hasFlags); 785 NS_ENSURE_SUCCESS(rv, NS_OK); 786 if (hasFlags) { 787 *aRes = true; 788 return NS_OK; 789 } 790 791 auto policy = AddonPolicyCore(); 792 *aRes = (policy && policy->IsPrivileged()); 793 return NS_OK; 794 } 795 796 NS_IMETHODIMP 797 BasePrincipal::GetPrefLightCacheKey(nsIURI* aURI, bool aWithCredentials, 798 const OriginAttributes& aOriginAttributes, 799 nsACString& _retval) { 800 _retval.Truncate(); 801 constexpr auto space = " "_ns; 802 803 nsCOMPtr<nsIURI> uri; 804 nsresult rv = GetURI(getter_AddRefs(uri)); 805 NS_ENSURE_SUCCESS(rv, rv); 806 807 nsAutoCString scheme, host, port; 808 if (uri) { 809 uri->GetScheme(scheme); 810 uri->GetHost(host); 811 port.AppendInt(NS_GetRealPort(uri)); 812 } 813 814 if (aWithCredentials) { 815 _retval.AssignLiteral("cred"); 816 } else { 817 _retval.AssignLiteral("nocred"); 818 } 819 820 nsAutoCString spec; 821 rv = aURI->GetSpec(spec); 822 NS_ENSURE_SUCCESS(rv, rv); 823 824 nsAutoCString originAttributesSuffix; 825 aOriginAttributes.CreateSuffix(originAttributesSuffix); 826 827 _retval.Append(space + scheme + space + host + space + port + space + spec + 828 space + originAttributesSuffix); 829 830 return NS_OK; 831 } 832 833 NS_IMETHODIMP 834 BasePrincipal::HasFirstpartyStorageAccess(mozIDOMWindow* aCheckWindow, 835 uint32_t* aRejectedReason, 836 bool* aOutAllowed) { 837 AssertIsOnMainThread(); 838 *aRejectedReason = 0; 839 *aOutAllowed = false; 840 841 if (IsSystemPrincipal()) { 842 // System principal is always considered to have first-party storage access. 843 *aOutAllowed = true; 844 return NS_OK; 845 } 846 847 nsPIDOMWindowInner* win = nsPIDOMWindowInner::From(aCheckWindow); 848 nsCOMPtr<nsIURI> uri; 849 nsresult rv = GetURI(getter_AddRefs(uri)); 850 if (NS_FAILED(rv)) { 851 return rv; 852 } 853 854 // The uri could be null if the principal is an expanded principal. 855 if (!uri) { 856 return NS_ERROR_UNEXPECTED; 857 } 858 859 *aOutAllowed = ShouldAllowAccessFor(win, uri, true, aRejectedReason); 860 return NS_OK; 861 } 862 863 NS_IMETHODIMP 864 BasePrincipal::GetIsNullPrincipal(bool* aResult) { 865 *aResult = Kind() == eNullPrincipal; 866 return NS_OK; 867 } 868 869 NS_IMETHODIMP 870 BasePrincipal::GetIsContentPrincipal(bool* aResult) { 871 *aResult = Kind() == eContentPrincipal; 872 return NS_OK; 873 } 874 875 NS_IMETHODIMP 876 BasePrincipal::GetIsExpandedPrincipal(bool* aResult) { 877 *aResult = Kind() == eExpandedPrincipal; 878 return NS_OK; 879 } 880 881 NS_IMETHODIMP 882 BasePrincipal::GetAsciiSpec(nsACString& aSpec) { 883 aSpec.Truncate(); 884 nsCOMPtr<nsIURI> prinURI; 885 nsresult rv = GetURI(getter_AddRefs(prinURI)); 886 if (NS_FAILED(rv) || !prinURI) { 887 return NS_OK; 888 } 889 return prinURI->GetAsciiSpec(aSpec); 890 } 891 892 NS_IMETHODIMP 893 BasePrincipal::GetSpec(nsACString& aSpec) { 894 aSpec.Truncate(); 895 nsCOMPtr<nsIURI> prinURI; 896 nsresult rv = GetURI(getter_AddRefs(prinURI)); 897 if (NS_FAILED(rv) || !prinURI) { 898 return NS_OK; 899 } 900 return prinURI->GetSpec(aSpec); 901 } 902 903 NS_IMETHODIMP 904 BasePrincipal::GetAsciiHost(nsACString& aHost) { 905 aHost.Truncate(); 906 nsCOMPtr<nsIURI> prinURI; 907 nsresult rv = GetURI(getter_AddRefs(prinURI)); 908 if (NS_FAILED(rv) || !prinURI) { 909 return NS_OK; 910 } 911 return prinURI->GetAsciiHost(aHost); 912 } 913 914 NS_IMETHODIMP 915 BasePrincipal::GetExposablePrePath(nsACString& aPrepath) { 916 aPrepath.Truncate(); 917 nsCOMPtr<nsIURI> prinURI; 918 nsresult rv = GetURI(getter_AddRefs(prinURI)); 919 if (NS_FAILED(rv) || !prinURI) { 920 return NS_OK; 921 } 922 923 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(prinURI); 924 return exposableURI->GetDisplayPrePath(aPrepath); 925 } 926 927 NS_IMETHODIMP 928 BasePrincipal::GetExposableSpec(nsACString& aSpec) { 929 aSpec.Truncate(); 930 nsCOMPtr<nsIURI> prinURI; 931 nsresult rv = GetURI(getter_AddRefs(prinURI)); 932 if (NS_FAILED(rv) || !prinURI) { 933 return NS_OK; 934 } 935 nsCOMPtr<nsIURI> clone; 936 rv = NS_MutateURI(prinURI) 937 .SetQuery(""_ns) 938 .SetRef(""_ns) 939 .SetUserPass(""_ns) 940 .Finalize(clone); 941 NS_ENSURE_SUCCESS(rv, rv); 942 return clone->GetAsciiSpec(aSpec); 943 } 944 945 NS_IMETHODIMP 946 BasePrincipal::GetPrePath(nsACString& aPath) { 947 aPath.Truncate(); 948 nsCOMPtr<nsIURI> prinURI; 949 nsresult rv = GetURI(getter_AddRefs(prinURI)); 950 if (NS_FAILED(rv) || !prinURI) { 951 return NS_OK; 952 } 953 return prinURI->GetPrePath(aPath); 954 } 955 956 NS_IMETHODIMP 957 BasePrincipal::GetFilePath(nsACString& aPath) { 958 aPath.Truncate(); 959 nsCOMPtr<nsIURI> prinURI; 960 nsresult rv = GetURI(getter_AddRefs(prinURI)); 961 if (NS_FAILED(rv) || !prinURI) { 962 return NS_OK; 963 } 964 return prinURI->GetFilePath(aPath); 965 } 966 967 NS_IMETHODIMP 968 BasePrincipal::GetIsSystemPrincipal(bool* aResult) { 969 *aResult = IsSystemPrincipal(); 970 return NS_OK; 971 } 972 973 NS_IMETHODIMP 974 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) { 975 *aResult = AddonPolicyCore() || ContentScriptAddonPolicyCore(); 976 return NS_OK; 977 } 978 979 NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) { 980 *aIsOnion = false; 981 nsCOMPtr<nsIURI> prinURI; 982 nsresult rv = GetURI(getter_AddRefs(prinURI)); 983 if (NS_FAILED(rv) || !prinURI) { 984 return NS_OK; 985 } 986 987 nsAutoCString host; 988 rv = prinURI->GetHost(host); 989 if (NS_FAILED(rv)) { 990 return NS_OK; 991 } 992 *aIsOnion = StringEndsWith(host, ".onion"_ns); 993 return NS_OK; 994 } 995 996 NS_IMETHODIMP BasePrincipal::GetIsIpAddress(bool* aIsIpAddress) { 997 *aIsIpAddress = false; 998 999 nsCOMPtr<nsIURI> prinURI; 1000 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1001 if (NS_FAILED(rv) || !prinURI) { 1002 return NS_OK; 1003 } 1004 1005 nsAutoCString host; 1006 rv = prinURI->GetHost(host); 1007 if (NS_FAILED(rv)) { 1008 return NS_OK; 1009 } 1010 1011 PRNetAddr prAddr; 1012 memset(&prAddr, 0, sizeof(prAddr)); 1013 1014 if (PR_StringToNetAddr(host.get(), &prAddr) == PR_SUCCESS) { 1015 *aIsIpAddress = true; 1016 } 1017 1018 return NS_OK; 1019 } 1020 1021 NS_IMETHODIMP BasePrincipal::GetIsLocalIpAddress(bool* aIsIpAddress) { 1022 *aIsIpAddress = false; 1023 1024 nsCOMPtr<nsIURI> prinURI; 1025 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1026 if (NS_FAILED(rv) || !prinURI) { 1027 return NS_OK; 1028 } 1029 1030 nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); 1031 if (NS_FAILED(rv) || !ioService) { 1032 return NS_OK; 1033 } 1034 rv = ioService->HostnameIsLocalIPAddress(prinURI, aIsIpAddress); 1035 if (NS_FAILED(rv)) { 1036 *aIsIpAddress = false; 1037 } 1038 return NS_OK; 1039 } 1040 1041 NS_IMETHODIMP 1042 BasePrincipal::GetScheme(nsACString& aScheme) { 1043 aScheme.Truncate(); 1044 1045 nsCOMPtr<nsIURI> prinURI; 1046 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1047 if (NS_FAILED(rv) || !prinURI) { 1048 return NS_OK; 1049 } 1050 1051 return prinURI->GetScheme(aScheme); 1052 } 1053 1054 NS_IMETHODIMP 1055 BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) { 1056 *aResult = false; 1057 nsCOMPtr<nsIURI> prinURI; 1058 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1059 if (NS_WARN_IF(NS_FAILED(rv)) || !prinURI) { 1060 return NS_OK; 1061 } 1062 *aResult = prinURI->SchemeIs(aScheme); 1063 return NS_OK; 1064 } 1065 1066 NS_IMETHODIMP 1067 BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) { 1068 AssertIsOnMainThread(); 1069 *aResult = false; 1070 1071 if (Kind() != eContentPrincipal) { 1072 // We don't store prefs for non-content principals. 1073 return NS_OK; 1074 } 1075 1076 nsCOMPtr<nsIURI> prinURI; 1077 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1078 if (NS_FAILED(rv) || !prinURI) { 1079 return NS_OK; 1080 } 1081 *aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref); 1082 return NS_OK; 1083 } 1084 1085 NS_IMETHODIMP 1086 BasePrincipal::IsURIInList(const nsACString& aList, bool* aResult) { 1087 *aResult = false; 1088 nsCOMPtr<nsIURI> prinURI; 1089 1090 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1091 if (NS_FAILED(rv) || !prinURI) { 1092 return NS_OK; 1093 } 1094 1095 *aResult = nsContentUtils::IsURIInList(prinURI, nsCString(aList)); 1096 return NS_OK; 1097 } 1098 1099 NS_IMETHODIMP 1100 BasePrincipal::IsContentAccessibleAboutURI(bool* aResult) { 1101 *aResult = false; 1102 1103 nsCOMPtr<nsIURI> prinURI; 1104 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1105 if (NS_FAILED(rv) || !prinURI) { 1106 return NS_OK; 1107 } 1108 1109 if (!prinURI->SchemeIs("about")) { 1110 return NS_OK; 1111 } 1112 1113 *aResult = NS_IsContentAccessibleAboutURI(prinURI); 1114 return NS_OK; 1115 } 1116 1117 NS_IMETHODIMP 1118 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) { 1119 AssertIsOnMainThread(); 1120 *aResult = false; 1121 1122 nsCOMPtr<nsIURI> uri; 1123 nsresult rv = GetURI(getter_AddRefs(uri)); 1124 if (NS_FAILED(rv) || !uri) { 1125 return NS_OK; 1126 } 1127 1128 *aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri); 1129 return NS_OK; 1130 } 1131 1132 NS_IMETHODIMP 1133 BasePrincipal::GetIsLoopbackHost(bool* aRes) { 1134 AssertIsOnMainThread(); 1135 *aRes = false; 1136 nsAutoCString host; 1137 nsresult rv = GetHost(host); 1138 // Swallow potential failure as this method is infallible. 1139 if (NS_FAILED(rv)) { 1140 return NS_OK; 1141 } 1142 1143 *aRes = nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(host); 1144 return NS_OK; 1145 } 1146 1147 NS_IMETHODIMP 1148 BasePrincipal::GetAboutModuleFlags(uint32_t* flags) { 1149 AssertIsOnMainThread(); 1150 *flags = 0; 1151 nsCOMPtr<nsIURI> prinURI; 1152 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1153 if (NS_FAILED(rv) || !prinURI) { 1154 return NS_ERROR_NOT_AVAILABLE; 1155 } 1156 if (!prinURI->SchemeIs("about")) { 1157 return NS_OK; 1158 } 1159 1160 nsCOMPtr<nsIAboutModule> aboutModule; 1161 rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule)); 1162 if (NS_FAILED(rv) || !aboutModule) { 1163 return rv; 1164 } 1165 return aboutModule->GetURIFlags(prinURI, flags); 1166 } 1167 1168 NS_IMETHODIMP 1169 BasePrincipal::GetOriginAttributes(JSContext* aCx, 1170 JS::MutableHandle<JS::Value> aVal) { 1171 if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) { 1172 return NS_ERROR_FAILURE; 1173 } 1174 return NS_OK; 1175 } 1176 1177 NS_IMETHODIMP 1178 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) { 1179 MOZ_ASSERT(mOriginSuffix); 1180 mOriginSuffix->ToUTF8String(aOriginAttributes); 1181 return NS_OK; 1182 } 1183 1184 NS_IMETHODIMP 1185 BasePrincipal::GetUserContextId(uint32_t* aUserContextId) { 1186 *aUserContextId = UserContextId(); 1187 return NS_OK; 1188 } 1189 1190 NS_IMETHODIMP 1191 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) { 1192 *aPrivateBrowsingId = PrivateBrowsingId(); 1193 return NS_OK; 1194 } 1195 1196 NS_IMETHODIMP 1197 BasePrincipal::GetIsInPrivateBrowsing(bool* aIsInPrivateBrowsing) { 1198 *aIsInPrivateBrowsing = mOriginAttributes.IsPrivateBrowsing(); 1199 return NS_OK; 1200 } 1201 1202 nsresult BasePrincipal::GetAddonPolicy( 1203 extensions::WebExtensionPolicy** aResult) { 1204 AssertIsOnMainThread(); 1205 RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy()); 1206 policy.forget(aResult); 1207 return NS_OK; 1208 } 1209 1210 nsresult BasePrincipal::GetContentScriptAddonPolicy( 1211 extensions::WebExtensionPolicy** aResult) { 1212 RefPtr<extensions::WebExtensionPolicy> policy(ContentScriptAddonPolicy()); 1213 policy.forget(aResult); 1214 return NS_OK; 1215 } 1216 1217 extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() { 1218 AssertIsOnMainThread(); 1219 RefPtr<extensions::WebExtensionPolicyCore> core = AddonPolicyCore(); 1220 return core ? core->GetMainThreadPolicy() : nullptr; 1221 } 1222 1223 RefPtr<extensions::WebExtensionPolicyCore> BasePrincipal::AddonPolicyCore() { 1224 if (Is<ContentPrincipal>()) { 1225 return As<ContentPrincipal>()->AddonPolicyCore(); 1226 } 1227 return nullptr; 1228 } 1229 1230 bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) { 1231 if (auto policy = AddonPolicyCore()) { 1232 return policy->HasPermission(aPerm); 1233 } 1234 return false; 1235 } 1236 1237 nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) { 1238 if (Is<ExpandedPrincipal>()) { 1239 return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI); 1240 } 1241 return this; 1242 } 1243 1244 bool BasePrincipal::OverridesCSP(nsIPrincipal* aDocumentPrincipal) { 1245 MOZ_ASSERT(aDocumentPrincipal); 1246 1247 // Expanded principals override CSP if and only if they subsume the document 1248 // principal. 1249 if (mKind == eExpandedPrincipal) { 1250 return FastSubsumes(aDocumentPrincipal); 1251 } 1252 // Extension principals always override the CSP of non-extension principals. 1253 // This is primarily for the sake of their stylesheets, which are usually 1254 // loaded from channels and cannot have expanded principals. 1255 return (AddonPolicyCore() && 1256 !BasePrincipal::Cast(aDocumentPrincipal)->AddonPolicyCore()); 1257 } 1258 1259 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal( 1260 nsIURI* aURI, const OriginAttributes& aAttrs, nsIURI* aInitialDomain) { 1261 MOZ_ASSERT(aURI); 1262 1263 nsAutoCString originNoSuffix; 1264 nsresult rv = 1265 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix); 1266 if (NS_FAILED(rv)) { 1267 // If the generation of the origin fails, we still want to have a valid 1268 // principal. Better to return a null principal here. 1269 return NullPrincipal::Create(aAttrs); 1270 } 1271 1272 return CreateContentPrincipal(aURI, aAttrs, originNoSuffix, aInitialDomain); 1273 } 1274 1275 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal( 1276 nsIURI* aURI, const OriginAttributes& aAttrs, 1277 const nsACString& aOriginNoSuffix, nsIURI* aInitialDomain) { 1278 MOZ_ASSERT(aURI); 1279 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty()); 1280 1281 // If the URI is supposed to inherit the security context of whoever loads it, 1282 // we shouldn't make a content principal for it. 1283 bool inheritsPrincipal; 1284 nsresult rv = NS_URIChainHasFlags( 1285 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, 1286 &inheritsPrincipal); 1287 if (NS_FAILED(rv) || inheritsPrincipal) { 1288 return NullPrincipal::Create(aAttrs); 1289 } 1290 1291 // Check whether the URI knows what its principal is supposed to be. 1292 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) 1293 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin = 1294 do_QueryInterface(aURI); 1295 if (uriWithSpecialOrigin) { 1296 nsCOMPtr<nsIURI> origin; 1297 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin)); 1298 if (NS_WARN_IF(NS_FAILED(rv))) { 1299 return nullptr; 1300 } 1301 MOZ_ASSERT(origin); 1302 OriginAttributes attrs; 1303 RefPtr<BasePrincipal> principal = 1304 CreateContentPrincipal(origin, attrs, aInitialDomain); 1305 return principal.forget(); 1306 } 1307 #endif 1308 1309 nsCOMPtr<nsIPrincipal> blobPrincipal; 1310 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal( 1311 aURI, getter_AddRefs(blobPrincipal))) { 1312 MOZ_ASSERT(blobPrincipal); 1313 MOZ_ASSERT(!aInitialDomain, 1314 "an initial domain for a blob URI makes no sense"); 1315 RefPtr<BasePrincipal> principal = Cast(blobPrincipal); 1316 return principal.forget(); 1317 } 1318 1319 // Mint a content principal. 1320 RefPtr<ContentPrincipal> principal = 1321 new ContentPrincipal(aURI, aAttrs, aOriginNoSuffix, aInitialDomain); 1322 return principal.forget(); 1323 } 1324 1325 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal( 1326 const nsACString& aOrigin) { 1327 MOZ_ASSERT(!StringBeginsWith(aOrigin, "["_ns), 1328 "CreateContentPrincipal does not support System and Expanded " 1329 "principals"); 1330 1331 MOZ_ASSERT( 1332 !StringBeginsWith(aOrigin, nsLiteralCString(NS_NULLPRINCIPAL_SCHEME ":")), 1333 "CreateContentPrincipal does not support NullPrincipal"); 1334 1335 nsAutoCString originNoSuffix; 1336 OriginAttributes attrs; 1337 if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) { 1338 return nullptr; 1339 } 1340 1341 nsCOMPtr<nsIURI> uri; 1342 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); 1343 NS_ENSURE_SUCCESS(rv, nullptr); 1344 1345 return BasePrincipal::CreateContentPrincipal(uri, attrs); 1346 } 1347 1348 already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes( 1349 const OriginAttributes& aOriginAttributes) { 1350 if (NS_WARN_IF(!IsContentPrincipal())) { 1351 return nullptr; 1352 } 1353 1354 nsAutoCString originNoSuffix; 1355 nsresult rv = GetOriginNoSuffix(originNoSuffix); 1356 NS_ENSURE_SUCCESS(rv, nullptr); 1357 1358 nsCOMPtr<nsIURI> uri; 1359 MOZ_ALWAYS_SUCCEEDS(GetURI(getter_AddRefs(uri))); 1360 1361 // XXX: This does not copy over the domain. Should it? 1362 RefPtr<ContentPrincipal> copy = 1363 new ContentPrincipal(uri, aOriginAttributes, originNoSuffix, nullptr); 1364 return copy.forget(); 1365 } 1366 1367 extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() { 1368 AssertIsOnMainThread(); 1369 RefPtr<extensions::WebExtensionPolicyCore> core = 1370 ContentScriptAddonPolicyCore(); 1371 return core ? core->GetMainThreadPolicy() : nullptr; 1372 } 1373 1374 RefPtr<extensions::WebExtensionPolicyCore> 1375 BasePrincipal::ContentScriptAddonPolicyCore() { 1376 if (!Is<ExpandedPrincipal>()) { 1377 return nullptr; 1378 } 1379 1380 auto* expanded = As<ExpandedPrincipal>(); 1381 for (const auto& prin : expanded->AllowList()) { 1382 if (RefPtr<extensions::WebExtensionPolicyCore> policy = 1383 BasePrincipal::Cast(prin)->AddonPolicyCore()) { 1384 return policy; 1385 } 1386 } 1387 1388 return nullptr; 1389 } 1390 1391 bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI, 1392 bool aExplicit /* = false */) { 1393 if (Is<ExpandedPrincipal>()) { 1394 return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit); 1395 } 1396 if (auto policy = AddonPolicyCore()) { 1397 return policy->CanAccessURI(aURI, aExplicit); 1398 } 1399 return false; 1400 } 1401 1402 NS_IMETHODIMP 1403 BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) { 1404 aKey.Truncate(); 1405 1406 nsCOMPtr<nsIURI> uri; 1407 nsresult rv = GetURI(getter_AddRefs(uri)); 1408 NS_ENSURE_SUCCESS(rv, rv); 1409 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED); 1410 1411 // The special handling of the file scheme should be consistent with 1412 // GetStorageOriginKey. 1413 1414 nsAutoCString baseDomain; 1415 rv = uri->GetAsciiHost(baseDomain); 1416 NS_ENSURE_SUCCESS(rv, rv); 1417 1418 if (baseDomain.IsEmpty() && uri->SchemeIs("file")) { 1419 nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv); 1420 NS_ENSURE_SUCCESS(rv, rv); 1421 1422 rv = url->GetDirectory(baseDomain); 1423 NS_ENSURE_SUCCESS(rv, rv); 1424 } else { 1425 nsCOMPtr<nsIEffectiveTLDService> eTLDService = 1426 mozilla::components::EffectiveTLD::Service(&rv); 1427 NS_ENSURE_SUCCESS(rv, rv); 1428 1429 nsAutoCString eTLDplusOne; 1430 rv = eTLDService->GetBaseDomain(uri, 0, eTLDplusOne); 1431 if (NS_SUCCEEDED(rv)) { 1432 baseDomain = eTLDplusOne; 1433 } else if (rv == NS_ERROR_HOST_IS_IP_ADDRESS || 1434 rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) { 1435 rv = NS_OK; 1436 } 1437 NS_ENSURE_SUCCESS(rv, rv); 1438 } 1439 1440 OriginAttributesRef().CreateSuffix(aKey); 1441 1442 nsAutoCString subdomainsDBKey; 1443 rv = dom::StorageUtils::CreateReversedDomain(baseDomain, subdomainsDBKey); 1444 NS_ENSURE_SUCCESS(rv, rv); 1445 1446 aKey.Append(':'); 1447 aKey.Append(subdomainsDBKey); 1448 1449 return NS_OK; 1450 } 1451 1452 NS_IMETHODIMP 1453 BasePrincipal::GetNextSubDomainPrincipal( 1454 nsIPrincipal** aNextSubDomainPrincipal) { 1455 nsCOMPtr<nsIURI> uri; 1456 nsresult rv = GetURI(getter_AddRefs(uri)); 1457 if (NS_FAILED(rv) || !uri) { 1458 return NS_OK; 1459 } 1460 1461 nsAutoCString host; 1462 rv = uri->GetHost(host); 1463 if (NS_FAILED(rv) || host.IsEmpty()) { 1464 return NS_OK; 1465 } 1466 1467 nsCString subDomain; 1468 nsCOMPtr<nsIEffectiveTLDService> eTLDService = 1469 mozilla::components::EffectiveTLD::Service(); 1470 if (!eTLDService) { 1471 return NS_OK; 1472 } 1473 rv = eTLDService->GetNextSubDomain(host, subDomain); 1474 1475 if (NS_FAILED(rv) || subDomain.IsEmpty()) { 1476 return NS_OK; 1477 } 1478 1479 nsCOMPtr<nsIURI> subDomainURI; 1480 rv = NS_MutateURI(uri).SetHost(subDomain).Finalize(subDomainURI); 1481 if (NS_FAILED(rv) || !subDomainURI) { 1482 return NS_OK; 1483 } 1484 // Copy the attributes over 1485 mozilla::OriginAttributes attrs = OriginAttributesRef(); 1486 1487 if (!StaticPrefs::permissions_isolateBy_userContext()) { 1488 // Disable userContext for permissions. 1489 attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID); 1490 } 1491 RefPtr<nsIPrincipal> principal = 1492 mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI, attrs); 1493 1494 if (!principal) { 1495 return NS_OK; 1496 } 1497 principal.forget(aNextSubDomainPrincipal); 1498 return NS_OK; 1499 } 1500 1501 NS_IMETHODIMP 1502 BasePrincipal::GetStorageOriginKey(nsACString& aOriginKey) { 1503 aOriginKey.Truncate(); 1504 1505 nsCOMPtr<nsIURI> uri; 1506 nsresult rv = GetURI(getter_AddRefs(uri)); 1507 NS_ENSURE_SUCCESS(rv, rv); 1508 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED); 1509 1510 // The special handling of the file scheme should be consistent with 1511 // GetLocalStorageQuotaKey. 1512 1513 nsAutoCString domainOrigin; 1514 rv = uri->GetAsciiHost(domainOrigin); 1515 NS_ENSURE_SUCCESS(rv, rv); 1516 1517 if (domainOrigin.IsEmpty()) { 1518 // For the file:/// protocol use the exact directory as domain. 1519 if (uri->SchemeIs("file")) { 1520 nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv); 1521 NS_ENSURE_SUCCESS(rv, rv); 1522 rv = url->GetDirectory(domainOrigin); 1523 NS_ENSURE_SUCCESS(rv, rv); 1524 } 1525 } 1526 1527 // Append reversed domain 1528 nsAutoCString reverseDomain; 1529 rv = dom::StorageUtils::CreateReversedDomain(domainOrigin, reverseDomain); 1530 NS_ENSURE_SUCCESS(rv, rv); 1531 1532 aOriginKey.Append(reverseDomain); 1533 1534 // Append scheme 1535 nsAutoCString scheme; 1536 rv = uri->GetScheme(scheme); 1537 NS_ENSURE_SUCCESS(rv, rv); 1538 1539 aOriginKey.Append(':'); 1540 aOriginKey.Append(scheme); 1541 1542 // Append port if any 1543 int32_t port = NS_GetRealPort(uri); 1544 if (port != -1) { 1545 aOriginKey.Append(nsPrintfCString(":%d", port)); 1546 } 1547 1548 return NS_OK; 1549 } 1550 1551 NS_IMETHODIMP 1552 BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy) { 1553 AssertIsOnMainThread(); 1554 *aIsScriptAllowedByPolicy = false; 1555 nsCOMPtr<nsIURI> prinURI; 1556 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1557 if (NS_FAILED(rv) || !prinURI) { 1558 return NS_OK; 1559 } 1560 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); 1561 if (!ssm) { 1562 return NS_ERROR_UNEXPECTED; 1563 } 1564 return ssm->PolicyAllowsScript(prinURI, aIsScriptAllowedByPolicy); 1565 } 1566 1567 bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const { 1568 MOZ_ASSERT(IsInitialized()); 1569 MOZ_ASSERT(aOther.IsInitialized()); 1570 return mPrincipal->FastEquals(aOther.mPrincipal); 1571 } 1572 1573 NS_IMETHODIMP 1574 BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy, 1575 nsIReferrerInfo** _retval) { 1576 nsCOMPtr<nsIURI> prinURI; 1577 RefPtr<dom::ReferrerInfo> info; 1578 nsresult rv = GetURI(getter_AddRefs(prinURI)); 1579 if (NS_FAILED(rv) || !prinURI) { 1580 info = new dom::ReferrerInfo(nullptr); 1581 info.forget(_retval); 1582 return NS_OK; 1583 } 1584 info = new dom::ReferrerInfo(prinURI, aReferrerPolicy); 1585 info.forget(_retval); 1586 return NS_OK; 1587 } 1588 1589 NS_IMETHODIMP 1590 BasePrincipal::GetPrecursorPrincipal(nsIPrincipal** aPrecursor) { 1591 *aPrecursor = nullptr; 1592 return NS_OK; 1593 } 1594 1595 NS_IMPL_ADDREF(BasePrincipal::Deserializer) 1596 NS_IMPL_RELEASE(BasePrincipal::Deserializer) 1597 1598 NS_INTERFACE_MAP_BEGIN(BasePrincipal::Deserializer) 1599 NS_INTERFACE_MAP_ENTRY(nsISupports) 1600 NS_INTERFACE_MAP_ENTRY(nsISerializable) 1601 if (mPrincipal) { 1602 return mPrincipal->QueryInterface(aIID, aInstancePtr); 1603 } else 1604 NS_INTERFACE_MAP_END 1605 1606 NS_IMETHODIMP 1607 BasePrincipal::Deserializer::Write(nsIObjectOutputStream* aStream) { 1608 // Read is used still for legacy principals 1609 MOZ_RELEASE_ASSERT(false, "Old style serialization is removed"); 1610 return NS_OK; 1611 } 1612 1613 /* static */ 1614 void BasePrincipal::WriteJSONProperty(JSONWriter& aWriter, 1615 const Span<const char>& aKey, 1616 const nsCString& aValue) { 1617 aWriter.StringProperty(aKey, aValue); 1618 } 1619 1620 } // namespace mozilla 1621 1622 uint32_t nsIPrincipal::GetHashValue() const { 1623 auto* bp = mozilla::BasePrincipal::Cast(this); 1624 return mozilla::HashGeneric(bp->GetOriginNoSuffixHash(), 1625 bp->GetOriginSuffixHash()); 1626 }