caps/src/nsPrincipal.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 sw=2 et tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "nsPrincipal.h"
michael@0 8
michael@0 9 #include "mozIThirdPartyUtil.h"
michael@0 10 #include "nscore.h"
michael@0 11 #include "nsScriptSecurityManager.h"
michael@0 12 #include "nsString.h"
michael@0 13 #include "nsReadableUtils.h"
michael@0 14 #include "pratom.h"
michael@0 15 #include "nsIURI.h"
michael@0 16 #include "nsJSPrincipals.h"
michael@0 17 #include "nsIObjectInputStream.h"
michael@0 18 #include "nsIObjectOutputStream.h"
michael@0 19 #include "nsIClassInfoImpl.h"
michael@0 20 #include "nsError.h"
michael@0 21 #include "nsIContentSecurityPolicy.h"
michael@0 22 #include "nsCxPusher.h"
michael@0 23 #include "jswrapper.h"
michael@0 24
michael@0 25 #include "mozilla/Preferences.h"
michael@0 26 #include "mozilla/HashFunctions.h"
michael@0 27
michael@0 28 #include "nsIAppsService.h"
michael@0 29 #include "mozIApplication.h"
michael@0 30
michael@0 31 using namespace mozilla;
michael@0 32
michael@0 33 static bool gCodeBasePrincipalSupport = false;
michael@0 34 static bool gIsObservingCodeBasePrincipalSupport = false;
michael@0 35
michael@0 36 static bool URIIsImmutable(nsIURI* aURI)
michael@0 37 {
michael@0 38 nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI));
michael@0 39 bool isMutable;
michael@0 40 return
michael@0 41 mutableObj &&
michael@0 42 NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) &&
michael@0 43 !isMutable;
michael@0 44 }
michael@0 45
michael@0 46 // Static member variables
michael@0 47 const char nsBasePrincipal::sInvalid[] = "Invalid";
michael@0 48
michael@0 49 NS_IMETHODIMP_(MozExternalRefCountType)
michael@0 50 nsBasePrincipal::AddRef()
michael@0 51 {
michael@0 52 NS_PRECONDITION(int32_t(refcount) >= 0, "illegal refcnt");
michael@0 53 // XXXcaa does this need to be threadsafe? See bug 143559.
michael@0 54 nsrefcnt count = ++refcount;
michael@0 55 NS_LOG_ADDREF(this, count, "nsBasePrincipal", sizeof(*this));
michael@0 56 return count;
michael@0 57 }
michael@0 58
michael@0 59 NS_IMETHODIMP_(MozExternalRefCountType)
michael@0 60 nsBasePrincipal::Release()
michael@0 61 {
michael@0 62 NS_PRECONDITION(0 != refcount, "dup release");
michael@0 63 nsrefcnt count = --refcount;
michael@0 64 NS_LOG_RELEASE(this, count, "nsBasePrincipal");
michael@0 65 if (count == 0) {
michael@0 66 delete this;
michael@0 67 }
michael@0 68
michael@0 69 return count;
michael@0 70 }
michael@0 71
michael@0 72 nsBasePrincipal::nsBasePrincipal()
michael@0 73 {
michael@0 74 if (!gIsObservingCodeBasePrincipalSupport) {
michael@0 75 nsresult rv =
michael@0 76 Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
michael@0 77 "signed.applets.codebase_principal_support",
michael@0 78 false);
michael@0 79 gIsObservingCodeBasePrincipalSupport = NS_SUCCEEDED(rv);
michael@0 80 NS_WARN_IF_FALSE(gIsObservingCodeBasePrincipalSupport,
michael@0 81 "Installing gCodeBasePrincipalSupport failed!");
michael@0 82 }
michael@0 83 }
michael@0 84
michael@0 85 nsBasePrincipal::~nsBasePrincipal(void)
michael@0 86 {
michael@0 87 }
michael@0 88
michael@0 89 NS_IMETHODIMP
michael@0 90 nsBasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
michael@0 91 {
michael@0 92 NS_IF_ADDREF(*aCsp = mCSP);
michael@0 93 return NS_OK;
michael@0 94 }
michael@0 95
michael@0 96 NS_IMETHODIMP
michael@0 97 nsBasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
michael@0 98 {
michael@0 99 // If CSP was already set, it should not be destroyed! Instead, it should
michael@0 100 // get set anew when a new principal is created.
michael@0 101 if (mCSP)
michael@0 102 return NS_ERROR_ALREADY_INITIALIZED;
michael@0 103
michael@0 104 mCSP = aCsp;
michael@0 105 return NS_OK;
michael@0 106 }
michael@0 107
michael@0 108 #ifdef DEBUG
michael@0 109 void nsPrincipal::dumpImpl()
michael@0 110 {
michael@0 111 nsAutoCString str;
michael@0 112 GetScriptLocation(str);
michael@0 113 fprintf(stderr, "nsPrincipal (%p) = %s\n", static_cast<void*>(this), str.get());
michael@0 114 }
michael@0 115 #endif
michael@0 116
michael@0 117 NS_IMPL_CLASSINFO(nsPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
michael@0 118 NS_PRINCIPAL_CID)
michael@0 119 NS_IMPL_QUERY_INTERFACE_CI(nsPrincipal,
michael@0 120 nsIPrincipal,
michael@0 121 nsISerializable)
michael@0 122 NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal,
michael@0 123 nsIPrincipal,
michael@0 124 nsISerializable)
michael@0 125 NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal)
michael@0 126 NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal)
michael@0 127
michael@0 128 nsPrincipal::nsPrincipal()
michael@0 129 : mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
michael@0 130 , mInMozBrowser(false)
michael@0 131 , mCodebaseImmutable(false)
michael@0 132 , mDomainImmutable(false)
michael@0 133 , mInitialized(false)
michael@0 134 { }
michael@0 135
michael@0 136 nsPrincipal::~nsPrincipal()
michael@0 137 { }
michael@0 138
michael@0 139 nsresult
michael@0 140 nsPrincipal::Init(nsIURI *aCodebase,
michael@0 141 uint32_t aAppId,
michael@0 142 bool aInMozBrowser)
michael@0 143 {
michael@0 144 NS_ENSURE_STATE(!mInitialized);
michael@0 145 NS_ENSURE_ARG(aCodebase);
michael@0 146
michael@0 147 mInitialized = true;
michael@0 148
michael@0 149 mCodebase = NS_TryToMakeImmutable(aCodebase);
michael@0 150 mCodebaseImmutable = URIIsImmutable(mCodebase);
michael@0 151
michael@0 152 mAppId = aAppId;
michael@0 153 mInMozBrowser = aInMozBrowser;
michael@0 154
michael@0 155 return NS_OK;
michael@0 156 }
michael@0 157
michael@0 158 void
michael@0 159 nsPrincipal::GetScriptLocation(nsACString &aStr)
michael@0 160 {
michael@0 161 mCodebase->GetSpec(aStr);
michael@0 162 }
michael@0 163
michael@0 164 /* static */ nsresult
michael@0 165 nsPrincipal::GetOriginForURI(nsIURI* aURI, char **aOrigin)
michael@0 166 {
michael@0 167 if (!aURI) {
michael@0 168 return NS_ERROR_FAILURE;
michael@0 169 }
michael@0 170
michael@0 171 *aOrigin = nullptr;
michael@0 172
michael@0 173 nsCOMPtr<nsIURI> origin = NS_GetInnermostURI(aURI);
michael@0 174 if (!origin) {
michael@0 175 return NS_ERROR_FAILURE;
michael@0 176 }
michael@0 177
michael@0 178 nsAutoCString hostPort;
michael@0 179
michael@0 180 // chrome: URLs don't have a meaningful origin, so make
michael@0 181 // sure we just get the full spec for them.
michael@0 182 // XXX this should be removed in favor of the solution in
michael@0 183 // bug 160042.
michael@0 184 bool isChrome;
michael@0 185 nsresult rv = origin->SchemeIs("chrome", &isChrome);
michael@0 186 if (NS_SUCCEEDED(rv) && !isChrome) {
michael@0 187 rv = origin->GetAsciiHost(hostPort);
michael@0 188 // Some implementations return an empty string, treat it as no support
michael@0 189 // for asciiHost by that implementation.
michael@0 190 if (hostPort.IsEmpty()) {
michael@0 191 rv = NS_ERROR_FAILURE;
michael@0 192 }
michael@0 193 }
michael@0 194
michael@0 195 int32_t port;
michael@0 196 if (NS_SUCCEEDED(rv) && !isChrome) {
michael@0 197 rv = origin->GetPort(&port);
michael@0 198 }
michael@0 199
michael@0 200 if (NS_SUCCEEDED(rv) && !isChrome) {
michael@0 201 if (port != -1) {
michael@0 202 hostPort.AppendLiteral(":");
michael@0 203 hostPort.AppendInt(port, 10);
michael@0 204 }
michael@0 205
michael@0 206 nsAutoCString scheme;
michael@0 207 rv = origin->GetScheme(scheme);
michael@0 208 NS_ENSURE_SUCCESS(rv, rv);
michael@0 209
michael@0 210 *aOrigin = ToNewCString(scheme + NS_LITERAL_CSTRING("://") + hostPort);
michael@0 211 }
michael@0 212 else {
michael@0 213 // Some URIs (e.g., nsSimpleURI) don't support asciiHost. Just
michael@0 214 // get the full spec.
michael@0 215 nsAutoCString spec;
michael@0 216 // XXX nsMozIconURI and nsJARURI don't implement this correctly, they
michael@0 217 // both fall back to GetSpec. That needs to be fixed.
michael@0 218 rv = origin->GetAsciiSpec(spec);
michael@0 219 NS_ENSURE_SUCCESS(rv, rv);
michael@0 220
michael@0 221 *aOrigin = ToNewCString(spec);
michael@0 222 }
michael@0 223
michael@0 224 return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
michael@0 225 }
michael@0 226
michael@0 227 NS_IMETHODIMP
michael@0 228 nsPrincipal::GetOrigin(char **aOrigin)
michael@0 229 {
michael@0 230 return GetOriginForURI(mCodebase, aOrigin);
michael@0 231 }
michael@0 232
michael@0 233 NS_IMETHODIMP
michael@0 234 nsPrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult)
michael@0 235 {
michael@0 236 *aResult = false;
michael@0 237
michael@0 238 if (!aOther) {
michael@0 239 NS_WARNING("Need a principal to compare this to!");
michael@0 240 return NS_OK;
michael@0 241 }
michael@0 242
michael@0 243 if (aOther == this) {
michael@0 244 *aResult = true;
michael@0 245 return NS_OK;
michael@0 246 }
michael@0 247
michael@0 248 if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) {
michael@0 249 return NS_OK;
michael@0 250 }
michael@0 251
michael@0 252 // If either the subject or the object has changed its principal by
michael@0 253 // explicitly setting document.domain then the other must also have
michael@0 254 // done so in order to be considered the same origin. This prevents
michael@0 255 // DNS spoofing based on document.domain (154930)
michael@0 256
michael@0 257 nsCOMPtr<nsIURI> thisURI;
michael@0 258 this->GetDomain(getter_AddRefs(thisURI));
michael@0 259 bool thisSetDomain = !!thisURI;
michael@0 260 if (!thisURI) {
michael@0 261 this->GetURI(getter_AddRefs(thisURI));
michael@0 262 }
michael@0 263
michael@0 264 nsCOMPtr<nsIURI> otherURI;
michael@0 265 aOther->GetDomain(getter_AddRefs(otherURI));
michael@0 266 bool otherSetDomain = !!otherURI;
michael@0 267 if (!otherURI) {
michael@0 268 aOther->GetURI(getter_AddRefs(otherURI));
michael@0 269 }
michael@0 270
michael@0 271 *aResult = thisSetDomain == otherSetDomain &&
michael@0 272 nsScriptSecurityManager::SecurityCompareURIs(thisURI, otherURI);
michael@0 273 return NS_OK;
michael@0 274 }
michael@0 275
michael@0 276 NS_IMETHODIMP
michael@0 277 nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
michael@0 278 {
michael@0 279 *aResult = false;
michael@0 280
michael@0 281 if (!aOther) {
michael@0 282 NS_WARNING("Need a principal to compare this to!");
michael@0 283 return NS_OK;
michael@0 284 }
michael@0 285
michael@0 286 if (aOther == this) {
michael@0 287 *aResult = true;
michael@0 288 return NS_OK;
michael@0 289 }
michael@0 290
michael@0 291 if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) {
michael@0 292 return NS_OK;
michael@0 293 }
michael@0 294
michael@0 295 nsCOMPtr<nsIURI> otherURI;
michael@0 296 nsresult rv = aOther->GetURI(getter_AddRefs(otherURI));
michael@0 297 if (NS_FAILED(rv)) {
michael@0 298 return rv;
michael@0 299 }
michael@0 300
michael@0 301 NS_ASSERTION(mCodebase,
michael@0 302 "shouldn't be calling this on principals from preferences");
michael@0 303
michael@0 304 // Compare codebases.
michael@0 305 *aResult = nsScriptSecurityManager::SecurityCompareURIs(mCodebase,
michael@0 306 otherURI);
michael@0 307 return NS_OK;
michael@0 308 }
michael@0 309
michael@0 310 NS_IMETHODIMP
michael@0 311 nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
michael@0 312 {
michael@0 313 return Equals(aOther, aResult);
michael@0 314 }
michael@0 315
michael@0 316 NS_IMETHODIMP
michael@0 317 nsPrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult)
michael@0 318 {
michael@0 319 return EqualsConsideringDomain(aOther, aResult);
michael@0 320 }
michael@0 321
michael@0 322 NS_IMETHODIMP
michael@0 323 nsPrincipal::GetURI(nsIURI** aURI)
michael@0 324 {
michael@0 325 if (mCodebaseImmutable) {
michael@0 326 NS_ADDREF(*aURI = mCodebase);
michael@0 327 return NS_OK;
michael@0 328 }
michael@0 329
michael@0 330 if (!mCodebase) {
michael@0 331 *aURI = nullptr;
michael@0 332 return NS_OK;
michael@0 333 }
michael@0 334
michael@0 335 return NS_EnsureSafeToReturn(mCodebase, aURI);
michael@0 336 }
michael@0 337
michael@0 338 NS_IMETHODIMP
michael@0 339 nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
michael@0 340 {
michael@0 341 if (aAllowIfInheritsPrincipal) {
michael@0 342 // If the caller specified to allow loads of URIs that inherit
michael@0 343 // our principal, allow the load if this URI inherits its principal
michael@0 344 if (nsPrincipal::IsPrincipalInherited(aURI)) {
michael@0 345 return NS_OK;
michael@0 346 }
michael@0 347 }
michael@0 348
michael@0 349 if (nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
michael@0 350 return NS_OK;
michael@0 351 }
michael@0 352
michael@0 353 // If strict file origin policy is in effect, local files will always fail
michael@0 354 // SecurityCompareURIs unless they are identical. Explicitly check file origin
michael@0 355 // policy, in that case.
michael@0 356 if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
michael@0 357 NS_URIIsLocalFile(aURI) &&
michael@0 358 NS_RelaxStrictFileOriginPolicy(aURI, mCodebase)) {
michael@0 359 return NS_OK;
michael@0 360 }
michael@0 361
michael@0 362 if (aReport) {
michael@0 363 nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
michael@0 364 }
michael@0 365 return NS_ERROR_DOM_BAD_URI;
michael@0 366 }
michael@0 367
michael@0 368 void
michael@0 369 nsPrincipal::SetURI(nsIURI* aURI)
michael@0 370 {
michael@0 371 mCodebase = NS_TryToMakeImmutable(aURI);
michael@0 372 mCodebaseImmutable = URIIsImmutable(mCodebase);
michael@0 373 }
michael@0 374
michael@0 375 NS_IMETHODIMP
michael@0 376 nsPrincipal::GetHashValue(uint32_t* aValue)
michael@0 377 {
michael@0 378 NS_PRECONDITION(mCodebase, "Need a codebase");
michael@0 379
michael@0 380 *aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this);
michael@0 381 return NS_OK;
michael@0 382 }
michael@0 383
michael@0 384 NS_IMETHODIMP
michael@0 385 nsPrincipal::GetDomain(nsIURI** aDomain)
michael@0 386 {
michael@0 387 if (!mDomain) {
michael@0 388 *aDomain = nullptr;
michael@0 389 return NS_OK;
michael@0 390 }
michael@0 391
michael@0 392 if (mDomainImmutable) {
michael@0 393 NS_ADDREF(*aDomain = mDomain);
michael@0 394 return NS_OK;
michael@0 395 }
michael@0 396
michael@0 397 return NS_EnsureSafeToReturn(mDomain, aDomain);
michael@0 398 }
michael@0 399
michael@0 400 NS_IMETHODIMP
michael@0 401 nsPrincipal::SetDomain(nsIURI* aDomain)
michael@0 402 {
michael@0 403 mDomain = NS_TryToMakeImmutable(aDomain);
michael@0 404 mDomainImmutable = URIIsImmutable(mDomain);
michael@0 405
michael@0 406 // Recompute all wrappers between compartments using this principal and other
michael@0 407 // non-chrome compartments.
michael@0 408 AutoSafeJSContext cx;
michael@0 409 JSPrincipals *principals = nsJSPrincipals::get(static_cast<nsIPrincipal*>(this));
michael@0 410 bool success = js::RecomputeWrappers(cx, js::ContentCompartmentsOnly(),
michael@0 411 js::CompartmentsWithPrincipals(principals));
michael@0 412 NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
michael@0 413 success = js::RecomputeWrappers(cx, js::CompartmentsWithPrincipals(principals),
michael@0 414 js::ContentCompartmentsOnly());
michael@0 415 NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
michael@0 416
michael@0 417 return NS_OK;
michael@0 418 }
michael@0 419
michael@0 420 NS_IMETHODIMP
michael@0 421 nsPrincipal::GetJarPrefix(nsACString& aJarPrefix)
michael@0 422 {
michael@0 423 MOZ_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
michael@0 424
michael@0 425 mozilla::GetJarPrefix(mAppId, mInMozBrowser, aJarPrefix);
michael@0 426 return NS_OK;
michael@0 427 }
michael@0 428
michael@0 429 NS_IMETHODIMP
michael@0 430 nsPrincipal::GetAppStatus(uint16_t* aAppStatus)
michael@0 431 {
michael@0 432 *aAppStatus = GetAppStatus();
michael@0 433 return NS_OK;
michael@0 434 }
michael@0 435
michael@0 436 NS_IMETHODIMP
michael@0 437 nsPrincipal::GetAppId(uint32_t* aAppId)
michael@0 438 {
michael@0 439 if (mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
michael@0 440 MOZ_ASSERT(false);
michael@0 441 *aAppId = nsIScriptSecurityManager::NO_APP_ID;
michael@0 442 return NS_OK;
michael@0 443 }
michael@0 444
michael@0 445 *aAppId = mAppId;
michael@0 446 return NS_OK;
michael@0 447 }
michael@0 448
michael@0 449 NS_IMETHODIMP
michael@0 450 nsPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
michael@0 451 {
michael@0 452 *aIsInBrowserElement = mInMozBrowser;
michael@0 453 return NS_OK;
michael@0 454 }
michael@0 455
michael@0 456 NS_IMETHODIMP
michael@0 457 nsPrincipal::GetUnknownAppId(bool* aUnknownAppId)
michael@0 458 {
michael@0 459 *aUnknownAppId = mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID;
michael@0 460 return NS_OK;
michael@0 461 }
michael@0 462
michael@0 463 NS_IMETHODIMP
michael@0 464 nsPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
michael@0 465 {
michael@0 466 *aIsNullPrincipal = false;
michael@0 467 return NS_OK;
michael@0 468 }
michael@0 469
michael@0 470 NS_IMETHODIMP
michael@0 471 nsPrincipal::GetBaseDomain(nsACString& aBaseDomain)
michael@0 472 {
michael@0 473 // For a file URI, we return the file path.
michael@0 474 if (NS_URIIsLocalFile(mCodebase)) {
michael@0 475 nsCOMPtr<nsIURL> url = do_QueryInterface(mCodebase);
michael@0 476
michael@0 477 if (url) {
michael@0 478 return url->GetFilePath(aBaseDomain);
michael@0 479 }
michael@0 480 }
michael@0 481
michael@0 482 // For everything else, we ask the TLD service via
michael@0 483 // the ThirdPartyUtil.
michael@0 484 nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
michael@0 485 do_GetService(THIRDPARTYUTIL_CONTRACTID);
michael@0 486 if (thirdPartyUtil) {
michael@0 487 return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain);
michael@0 488 }
michael@0 489
michael@0 490 return NS_OK;
michael@0 491 }
michael@0 492
michael@0 493 NS_IMETHODIMP
michael@0 494 nsPrincipal::Read(nsIObjectInputStream* aStream)
michael@0 495 {
michael@0 496 nsCOMPtr<nsISupports> supports;
michael@0 497 nsCOMPtr<nsIURI> codebase;
michael@0 498 nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
michael@0 499 if (NS_FAILED(rv)) {
michael@0 500 return rv;
michael@0 501 }
michael@0 502
michael@0 503 codebase = do_QueryInterface(supports);
michael@0 504
michael@0 505 nsCOMPtr<nsIURI> domain;
michael@0 506 rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
michael@0 507 if (NS_FAILED(rv)) {
michael@0 508 return rv;
michael@0 509 }
michael@0 510
michael@0 511 domain = do_QueryInterface(supports);
michael@0 512
michael@0 513 uint32_t appId;
michael@0 514 rv = aStream->Read32(&appId);
michael@0 515 NS_ENSURE_SUCCESS(rv, rv);
michael@0 516
michael@0 517 bool inMozBrowser;
michael@0 518 rv = aStream->ReadBoolean(&inMozBrowser);
michael@0 519 NS_ENSURE_SUCCESS(rv, rv);
michael@0 520
michael@0 521 rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
michael@0 522 NS_ENSURE_SUCCESS(rv, rv);
michael@0 523
michael@0 524 // This may be null.
michael@0 525 nsCOMPtr<nsIContentSecurityPolicy> csp = do_QueryInterface(supports, &rv);
michael@0 526
michael@0 527 rv = Init(codebase, appId, inMozBrowser);
michael@0 528 NS_ENSURE_SUCCESS(rv, rv);
michael@0 529
michael@0 530 rv = SetCsp(csp);
michael@0 531 NS_ENSURE_SUCCESS(rv, rv);
michael@0 532
michael@0 533 // need to link in the CSP context here (link in a reference to this
michael@0 534 // nsIPrincipal and to the URI of the protected resource).
michael@0 535 if (csp) {
michael@0 536 csp->SetRequestContext(codebase, nullptr, this, nullptr);
michael@0 537 }
michael@0 538
michael@0 539 SetDomain(domain);
michael@0 540
michael@0 541 return NS_OK;
michael@0 542 }
michael@0 543
michael@0 544 NS_IMETHODIMP
michael@0 545 nsPrincipal::Write(nsIObjectOutputStream* aStream)
michael@0 546 {
michael@0 547 NS_ENSURE_STATE(mCodebase);
michael@0 548
michael@0 549 nsresult rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI),
michael@0 550 true);
michael@0 551 if (NS_FAILED(rv)) {
michael@0 552 return rv;
michael@0 553 }
michael@0 554
michael@0 555 rv = NS_WriteOptionalCompoundObject(aStream, mDomain, NS_GET_IID(nsIURI),
michael@0 556 true);
michael@0 557 if (NS_FAILED(rv)) {
michael@0 558 return rv;
michael@0 559 }
michael@0 560
michael@0 561 aStream->Write32(mAppId);
michael@0 562 aStream->WriteBoolean(mInMozBrowser);
michael@0 563
michael@0 564 rv = NS_WriteOptionalCompoundObject(aStream, mCSP,
michael@0 565 NS_GET_IID(nsIContentSecurityPolicy),
michael@0 566 true);
michael@0 567 if (NS_FAILED(rv)) {
michael@0 568 return rv;
michael@0 569 }
michael@0 570
michael@0 571 // mCodebaseImmutable and mDomainImmutable will be recomputed based
michael@0 572 // on the deserialized URIs in Read().
michael@0 573
michael@0 574 return NS_OK;
michael@0 575 }
michael@0 576
michael@0 577 uint16_t
michael@0 578 nsPrincipal::GetAppStatus()
michael@0 579 {
michael@0 580 NS_WARN_IF_FALSE(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
michael@0 581 "Asking for app status on a principal with an unknown app id");
michael@0 582 // Installed apps have a valid app id (not NO_APP_ID or UNKNOWN_APP_ID)
michael@0 583 // and they are not inside a mozbrowser.
michael@0 584 if (mAppId == nsIScriptSecurityManager::NO_APP_ID ||
michael@0 585 mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID || mInMozBrowser) {
michael@0 586 return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
michael@0 587 }
michael@0 588
michael@0 589 nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
michael@0 590 NS_ENSURE_TRUE(appsService, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
michael@0 591
michael@0 592 nsCOMPtr<mozIApplication> app;
michael@0 593 appsService->GetAppByLocalId(mAppId, getter_AddRefs(app));
michael@0 594 NS_ENSURE_TRUE(app, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
michael@0 595
michael@0 596 uint16_t status = nsIPrincipal::APP_STATUS_INSTALLED;
michael@0 597 NS_ENSURE_SUCCESS(app->GetAppStatus(&status),
michael@0 598 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
michael@0 599
michael@0 600 nsAutoCString origin;
michael@0 601 NS_ENSURE_SUCCESS(GetOrigin(getter_Copies(origin)),
michael@0 602 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
michael@0 603 nsString appOrigin;
michael@0 604 NS_ENSURE_SUCCESS(app->GetOrigin(appOrigin),
michael@0 605 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
michael@0 606
michael@0 607 // We go from string -> nsIURI -> origin to be sure we
michael@0 608 // compare two punny-encoded origins.
michael@0 609 nsCOMPtr<nsIURI> appURI;
michael@0 610 NS_ENSURE_SUCCESS(NS_NewURI(getter_AddRefs(appURI), appOrigin),
michael@0 611 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
michael@0 612
michael@0 613 nsAutoCString appOriginPunned;
michael@0 614 NS_ENSURE_SUCCESS(GetOriginForURI(appURI, getter_Copies(appOriginPunned)),
michael@0 615 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
michael@0 616
michael@0 617 if (!appOriginPunned.Equals(origin)) {
michael@0 618 return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
michael@0 619 }
michael@0 620
michael@0 621 return status;
michael@0 622 }
michael@0 623
michael@0 624 /************************************************************************************************************************/
michael@0 625
michael@0 626 static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]";
michael@0 627
michael@0 628 NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
michael@0 629 NS_EXPANDEDPRINCIPAL_CID)
michael@0 630 NS_IMPL_QUERY_INTERFACE_CI(nsExpandedPrincipal,
michael@0 631 nsIPrincipal,
michael@0 632 nsIExpandedPrincipal)
michael@0 633 NS_IMPL_CI_INTERFACE_GETTER(nsExpandedPrincipal,
michael@0 634 nsIPrincipal,
michael@0 635 nsIExpandedPrincipal)
michael@0 636 NS_IMPL_ADDREF_INHERITED(nsExpandedPrincipal, nsBasePrincipal)
michael@0 637 NS_IMPL_RELEASE_INHERITED(nsExpandedPrincipal, nsBasePrincipal)
michael@0 638
michael@0 639 nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr <nsIPrincipal> > &aWhiteList)
michael@0 640 {
michael@0 641 mPrincipals.AppendElements(aWhiteList);
michael@0 642 }
michael@0 643
michael@0 644 nsExpandedPrincipal::~nsExpandedPrincipal()
michael@0 645 { }
michael@0 646
michael@0 647 NS_IMETHODIMP
michael@0 648 nsExpandedPrincipal::GetDomain(nsIURI** aDomain)
michael@0 649 {
michael@0 650 *aDomain = nullptr;
michael@0 651 return NS_OK;
michael@0 652 }
michael@0 653
michael@0 654 NS_IMETHODIMP
michael@0 655 nsExpandedPrincipal::SetDomain(nsIURI* aDomain)
michael@0 656 {
michael@0 657 return NS_OK;
michael@0 658 }
michael@0 659
michael@0 660 NS_IMETHODIMP
michael@0 661 nsExpandedPrincipal::GetOrigin(char** aOrigin)
michael@0 662 {
michael@0 663 *aOrigin = ToNewCString(NS_LITERAL_CSTRING(EXPANDED_PRINCIPAL_SPEC));
michael@0 664 return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
michael@0 665 }
michael@0 666
michael@0 667 typedef nsresult (NS_STDCALL nsIPrincipal::*nsIPrincipalMemFn)(nsIPrincipal* aOther,
michael@0 668 bool* aResult);
michael@0 669 #define CALL_MEMBER_FUNCTION(THIS,MEM_FN) ((THIS)->*(MEM_FN))
michael@0 670
michael@0 671 // nsExpandedPrincipal::Equals and nsExpandedPrincipal::EqualsConsideringDomain
michael@0 672 // shares the same logic. The difference only that Equals requires 'this'
michael@0 673 // and 'aOther' to Subsume each other while EqualsConsideringDomain requires
michael@0 674 // bidirectional SubsumesConsideringDomain.
michael@0 675 static nsresult
michael@0 676 Equals(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
michael@0 677 bool* aResult)
michael@0 678 {
michael@0 679 // If (and only if) 'aThis' and 'aOther' both Subsume/SubsumesConsideringDomain
michael@0 680 // each other, then they are Equal.
michael@0 681 *aResult = false;
michael@0 682 // Calling the corresponding subsume function on this (aFn).
michael@0 683 nsresult rv = CALL_MEMBER_FUNCTION(aThis, aFn)(aOther, aResult);
michael@0 684 NS_ENSURE_SUCCESS(rv, rv);
michael@0 685 if (!*aResult)
michael@0 686 return NS_OK;
michael@0 687
michael@0 688 // Calling the corresponding subsume function on aOther (aFn).
michael@0 689 rv = CALL_MEMBER_FUNCTION(aOther, aFn)(aThis, aResult);
michael@0 690 NS_ENSURE_SUCCESS(rv, rv);
michael@0 691 return NS_OK;
michael@0 692 }
michael@0 693
michael@0 694 NS_IMETHODIMP
michael@0 695 nsExpandedPrincipal::Equals(nsIPrincipal* aOther, bool* aResult)
michael@0 696 {
michael@0 697 return ::Equals(this, &nsIPrincipal::Subsumes, aOther, aResult);
michael@0 698 }
michael@0 699
michael@0 700 NS_IMETHODIMP
michael@0 701 nsExpandedPrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult)
michael@0 702 {
michael@0 703 return ::Equals(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult);
michael@0 704 }
michael@0 705
michael@0 706 // nsExpandedPrincipal::Subsumes and nsExpandedPrincipal::SubsumesConsideringDomain
michael@0 707 // shares the same logic. The difference only that Subsumes calls are replaced
michael@0 708 //with SubsumesConsideringDomain calls in the second case.
michael@0 709 static nsresult
michael@0 710 Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
michael@0 711 bool* aResult)
michael@0 712 {
michael@0 713 nsresult rv;
michael@0 714 nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aOther);
michael@0 715 if (expanded) {
michael@0 716 // If aOther is an ExpandedPrincipal too, check if all of its
michael@0 717 // principals are subsumed.
michael@0 718 nsTArray< nsCOMPtr<nsIPrincipal> >* otherList;
michael@0 719 expanded->GetWhiteList(&otherList);
michael@0 720 for (uint32_t i = 0; i < otherList->Length(); ++i){
michael@0 721 rv = CALL_MEMBER_FUNCTION(aThis, aFn)((*otherList)[i], aResult);
michael@0 722 NS_ENSURE_SUCCESS(rv, rv);
michael@0 723 if (!*aResult) {
michael@0 724 // If we don't subsume at least one principal of aOther, return false.
michael@0 725 return NS_OK;
michael@0 726 }
michael@0 727 }
michael@0 728 } else {
michael@0 729 // For a regular aOther, one of our principals must subsume it.
michael@0 730 nsTArray< nsCOMPtr<nsIPrincipal> >* list;
michael@0 731 aThis->GetWhiteList(&list);
michael@0 732 for (uint32_t i = 0; i < list->Length(); ++i){
michael@0 733 rv = CALL_MEMBER_FUNCTION((*list)[i], aFn)(aOther, aResult);
michael@0 734 NS_ENSURE_SUCCESS(rv, rv);
michael@0 735 if (*aResult) {
michael@0 736 // If one of our principal subsumes it, return true.
michael@0 737 return NS_OK;
michael@0 738 }
michael@0 739 }
michael@0 740 }
michael@0 741 return NS_OK;
michael@0 742 }
michael@0 743
michael@0 744 #undef CALL_MEMBER_FUNCTION
michael@0 745
michael@0 746 NS_IMETHODIMP
michael@0 747 nsExpandedPrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult)
michael@0 748 {
michael@0 749 return ::Subsumes(this, &nsIPrincipal::Subsumes, aOther, aResult);
michael@0 750 }
michael@0 751
michael@0 752 NS_IMETHODIMP
michael@0 753 nsExpandedPrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult)
michael@0 754 {
michael@0 755 return ::Subsumes(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult);
michael@0 756 }
michael@0 757
michael@0 758 NS_IMETHODIMP
michael@0 759 nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal)
michael@0 760 {
michael@0 761 nsresult rv;
michael@0 762 for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
michael@0 763 rv = mPrincipals[i]->CheckMayLoad(uri, aReport, aAllowIfInheritsPrincipal);
michael@0 764 if (NS_SUCCEEDED(rv))
michael@0 765 return rv;
michael@0 766 }
michael@0 767
michael@0 768 return NS_ERROR_DOM_BAD_URI;
michael@0 769 }
michael@0 770
michael@0 771 NS_IMETHODIMP
michael@0 772 nsExpandedPrincipal::GetHashValue(uint32_t* result)
michael@0 773 {
michael@0 774 MOZ_CRASH("extended principal should never be used as key in a hash map");
michael@0 775 }
michael@0 776
michael@0 777 NS_IMETHODIMP
michael@0 778 nsExpandedPrincipal::GetURI(nsIURI** aURI)
michael@0 779 {
michael@0 780 *aURI = nullptr;
michael@0 781 return NS_OK;
michael@0 782 }
michael@0 783
michael@0 784 NS_IMETHODIMP
michael@0 785 nsExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList)
michael@0 786 {
michael@0 787 *aWhiteList = &mPrincipals;
michael@0 788 return NS_OK;
michael@0 789 }
michael@0 790
michael@0 791 NS_IMETHODIMP
michael@0 792 nsExpandedPrincipal::GetJarPrefix(nsACString& aJarPrefix)
michael@0 793 {
michael@0 794 aJarPrefix.Truncate();
michael@0 795 return NS_OK;
michael@0 796 }
michael@0 797
michael@0 798 NS_IMETHODIMP
michael@0 799 nsExpandedPrincipal::GetAppStatus(uint16_t* aAppStatus)
michael@0 800 {
michael@0 801 *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
michael@0 802 return NS_OK;
michael@0 803 }
michael@0 804
michael@0 805 NS_IMETHODIMP
michael@0 806 nsExpandedPrincipal::GetAppId(uint32_t* aAppId)
michael@0 807 {
michael@0 808 *aAppId = nsIScriptSecurityManager::NO_APP_ID;
michael@0 809 return NS_OK;
michael@0 810 }
michael@0 811
michael@0 812 NS_IMETHODIMP
michael@0 813 nsExpandedPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
michael@0 814 {
michael@0 815 *aIsInBrowserElement = false;
michael@0 816 return NS_OK;
michael@0 817 }
michael@0 818
michael@0 819 NS_IMETHODIMP
michael@0 820 nsExpandedPrincipal::GetUnknownAppId(bool* aUnknownAppId)
michael@0 821 {
michael@0 822 *aUnknownAppId = false;
michael@0 823 return NS_OK;
michael@0 824 }
michael@0 825
michael@0 826 NS_IMETHODIMP
michael@0 827 nsExpandedPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
michael@0 828 {
michael@0 829 *aIsNullPrincipal = false;
michael@0 830 return NS_OK;
michael@0 831 }
michael@0 832
michael@0 833 NS_IMETHODIMP
michael@0 834 nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
michael@0 835 {
michael@0 836 return NS_ERROR_NOT_AVAILABLE;
michael@0 837 }
michael@0 838
michael@0 839 void
michael@0 840 nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
michael@0 841 {
michael@0 842 // Is that a good idea to list it's principals?
michael@0 843 aStr.Assign(EXPANDED_PRINCIPAL_SPEC);
michael@0 844 }
michael@0 845
michael@0 846 #ifdef DEBUG
michael@0 847 void nsExpandedPrincipal::dumpImpl()
michael@0 848 {
michael@0 849 fprintf(stderr, "nsExpandedPrincipal (%p)\n", static_cast<void*>(this));
michael@0 850 }
michael@0 851 #endif
michael@0 852
michael@0 853 //////////////////////////////////////////
michael@0 854 // Methods implementing nsISerializable //
michael@0 855 //////////////////////////////////////////
michael@0 856
michael@0 857 NS_IMETHODIMP
michael@0 858 nsExpandedPrincipal::Read(nsIObjectInputStream* aStream)
michael@0 859 {
michael@0 860 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 861 }
michael@0 862
michael@0 863 NS_IMETHODIMP
michael@0 864 nsExpandedPrincipal::Write(nsIObjectOutputStream* aStream)
michael@0 865 {
michael@0 866 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 867 }

mercurial