1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/caps/src/nsPrincipal.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,867 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 sw=2 et tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsPrincipal.h" 1.11 + 1.12 +#include "mozIThirdPartyUtil.h" 1.13 +#include "nscore.h" 1.14 +#include "nsScriptSecurityManager.h" 1.15 +#include "nsString.h" 1.16 +#include "nsReadableUtils.h" 1.17 +#include "pratom.h" 1.18 +#include "nsIURI.h" 1.19 +#include "nsJSPrincipals.h" 1.20 +#include "nsIObjectInputStream.h" 1.21 +#include "nsIObjectOutputStream.h" 1.22 +#include "nsIClassInfoImpl.h" 1.23 +#include "nsError.h" 1.24 +#include "nsIContentSecurityPolicy.h" 1.25 +#include "nsCxPusher.h" 1.26 +#include "jswrapper.h" 1.27 + 1.28 +#include "mozilla/Preferences.h" 1.29 +#include "mozilla/HashFunctions.h" 1.30 + 1.31 +#include "nsIAppsService.h" 1.32 +#include "mozIApplication.h" 1.33 + 1.34 +using namespace mozilla; 1.35 + 1.36 +static bool gCodeBasePrincipalSupport = false; 1.37 +static bool gIsObservingCodeBasePrincipalSupport = false; 1.38 + 1.39 +static bool URIIsImmutable(nsIURI* aURI) 1.40 +{ 1.41 + nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI)); 1.42 + bool isMutable; 1.43 + return 1.44 + mutableObj && 1.45 + NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) && 1.46 + !isMutable; 1.47 +} 1.48 + 1.49 +// Static member variables 1.50 +const char nsBasePrincipal::sInvalid[] = "Invalid"; 1.51 + 1.52 +NS_IMETHODIMP_(MozExternalRefCountType) 1.53 +nsBasePrincipal::AddRef() 1.54 +{ 1.55 + NS_PRECONDITION(int32_t(refcount) >= 0, "illegal refcnt"); 1.56 + // XXXcaa does this need to be threadsafe? See bug 143559. 1.57 + nsrefcnt count = ++refcount; 1.58 + NS_LOG_ADDREF(this, count, "nsBasePrincipal", sizeof(*this)); 1.59 + return count; 1.60 +} 1.61 + 1.62 +NS_IMETHODIMP_(MozExternalRefCountType) 1.63 +nsBasePrincipal::Release() 1.64 +{ 1.65 + NS_PRECONDITION(0 != refcount, "dup release"); 1.66 + nsrefcnt count = --refcount; 1.67 + NS_LOG_RELEASE(this, count, "nsBasePrincipal"); 1.68 + if (count == 0) { 1.69 + delete this; 1.70 + } 1.71 + 1.72 + return count; 1.73 +} 1.74 + 1.75 +nsBasePrincipal::nsBasePrincipal() 1.76 +{ 1.77 + if (!gIsObservingCodeBasePrincipalSupport) { 1.78 + nsresult rv = 1.79 + Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport, 1.80 + "signed.applets.codebase_principal_support", 1.81 + false); 1.82 + gIsObservingCodeBasePrincipalSupport = NS_SUCCEEDED(rv); 1.83 + NS_WARN_IF_FALSE(gIsObservingCodeBasePrincipalSupport, 1.84 + "Installing gCodeBasePrincipalSupport failed!"); 1.85 + } 1.86 +} 1.87 + 1.88 +nsBasePrincipal::~nsBasePrincipal(void) 1.89 +{ 1.90 +} 1.91 + 1.92 +NS_IMETHODIMP 1.93 +nsBasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) 1.94 +{ 1.95 + NS_IF_ADDREF(*aCsp = mCSP); 1.96 + return NS_OK; 1.97 +} 1.98 + 1.99 +NS_IMETHODIMP 1.100 +nsBasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) 1.101 +{ 1.102 + // If CSP was already set, it should not be destroyed! Instead, it should 1.103 + // get set anew when a new principal is created. 1.104 + if (mCSP) 1.105 + return NS_ERROR_ALREADY_INITIALIZED; 1.106 + 1.107 + mCSP = aCsp; 1.108 + return NS_OK; 1.109 +} 1.110 + 1.111 +#ifdef DEBUG 1.112 +void nsPrincipal::dumpImpl() 1.113 +{ 1.114 + nsAutoCString str; 1.115 + GetScriptLocation(str); 1.116 + fprintf(stderr, "nsPrincipal (%p) = %s\n", static_cast<void*>(this), str.get()); 1.117 +} 1.118 +#endif 1.119 + 1.120 +NS_IMPL_CLASSINFO(nsPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, 1.121 + NS_PRINCIPAL_CID) 1.122 +NS_IMPL_QUERY_INTERFACE_CI(nsPrincipal, 1.123 + nsIPrincipal, 1.124 + nsISerializable) 1.125 +NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal, 1.126 + nsIPrincipal, 1.127 + nsISerializable) 1.128 +NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal) 1.129 +NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal) 1.130 + 1.131 +nsPrincipal::nsPrincipal() 1.132 + : mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID) 1.133 + , mInMozBrowser(false) 1.134 + , mCodebaseImmutable(false) 1.135 + , mDomainImmutable(false) 1.136 + , mInitialized(false) 1.137 +{ } 1.138 + 1.139 +nsPrincipal::~nsPrincipal() 1.140 +{ } 1.141 + 1.142 +nsresult 1.143 +nsPrincipal::Init(nsIURI *aCodebase, 1.144 + uint32_t aAppId, 1.145 + bool aInMozBrowser) 1.146 +{ 1.147 + NS_ENSURE_STATE(!mInitialized); 1.148 + NS_ENSURE_ARG(aCodebase); 1.149 + 1.150 + mInitialized = true; 1.151 + 1.152 + mCodebase = NS_TryToMakeImmutable(aCodebase); 1.153 + mCodebaseImmutable = URIIsImmutable(mCodebase); 1.154 + 1.155 + mAppId = aAppId; 1.156 + mInMozBrowser = aInMozBrowser; 1.157 + 1.158 + return NS_OK; 1.159 +} 1.160 + 1.161 +void 1.162 +nsPrincipal::GetScriptLocation(nsACString &aStr) 1.163 +{ 1.164 + mCodebase->GetSpec(aStr); 1.165 +} 1.166 + 1.167 +/* static */ nsresult 1.168 +nsPrincipal::GetOriginForURI(nsIURI* aURI, char **aOrigin) 1.169 +{ 1.170 + if (!aURI) { 1.171 + return NS_ERROR_FAILURE; 1.172 + } 1.173 + 1.174 + *aOrigin = nullptr; 1.175 + 1.176 + nsCOMPtr<nsIURI> origin = NS_GetInnermostURI(aURI); 1.177 + if (!origin) { 1.178 + return NS_ERROR_FAILURE; 1.179 + } 1.180 + 1.181 + nsAutoCString hostPort; 1.182 + 1.183 + // chrome: URLs don't have a meaningful origin, so make 1.184 + // sure we just get the full spec for them. 1.185 + // XXX this should be removed in favor of the solution in 1.186 + // bug 160042. 1.187 + bool isChrome; 1.188 + nsresult rv = origin->SchemeIs("chrome", &isChrome); 1.189 + if (NS_SUCCEEDED(rv) && !isChrome) { 1.190 + rv = origin->GetAsciiHost(hostPort); 1.191 + // Some implementations return an empty string, treat it as no support 1.192 + // for asciiHost by that implementation. 1.193 + if (hostPort.IsEmpty()) { 1.194 + rv = NS_ERROR_FAILURE; 1.195 + } 1.196 + } 1.197 + 1.198 + int32_t port; 1.199 + if (NS_SUCCEEDED(rv) && !isChrome) { 1.200 + rv = origin->GetPort(&port); 1.201 + } 1.202 + 1.203 + if (NS_SUCCEEDED(rv) && !isChrome) { 1.204 + if (port != -1) { 1.205 + hostPort.AppendLiteral(":"); 1.206 + hostPort.AppendInt(port, 10); 1.207 + } 1.208 + 1.209 + nsAutoCString scheme; 1.210 + rv = origin->GetScheme(scheme); 1.211 + NS_ENSURE_SUCCESS(rv, rv); 1.212 + 1.213 + *aOrigin = ToNewCString(scheme + NS_LITERAL_CSTRING("://") + hostPort); 1.214 + } 1.215 + else { 1.216 + // Some URIs (e.g., nsSimpleURI) don't support asciiHost. Just 1.217 + // get the full spec. 1.218 + nsAutoCString spec; 1.219 + // XXX nsMozIconURI and nsJARURI don't implement this correctly, they 1.220 + // both fall back to GetSpec. That needs to be fixed. 1.221 + rv = origin->GetAsciiSpec(spec); 1.222 + NS_ENSURE_SUCCESS(rv, rv); 1.223 + 1.224 + *aOrigin = ToNewCString(spec); 1.225 + } 1.226 + 1.227 + return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY; 1.228 +} 1.229 + 1.230 +NS_IMETHODIMP 1.231 +nsPrincipal::GetOrigin(char **aOrigin) 1.232 +{ 1.233 + return GetOriginForURI(mCodebase, aOrigin); 1.234 +} 1.235 + 1.236 +NS_IMETHODIMP 1.237 +nsPrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult) 1.238 +{ 1.239 + *aResult = false; 1.240 + 1.241 + if (!aOther) { 1.242 + NS_WARNING("Need a principal to compare this to!"); 1.243 + return NS_OK; 1.244 + } 1.245 + 1.246 + if (aOther == this) { 1.247 + *aResult = true; 1.248 + return NS_OK; 1.249 + } 1.250 + 1.251 + if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) { 1.252 + return NS_OK; 1.253 + } 1.254 + 1.255 + // If either the subject or the object has changed its principal by 1.256 + // explicitly setting document.domain then the other must also have 1.257 + // done so in order to be considered the same origin. This prevents 1.258 + // DNS spoofing based on document.domain (154930) 1.259 + 1.260 + nsCOMPtr<nsIURI> thisURI; 1.261 + this->GetDomain(getter_AddRefs(thisURI)); 1.262 + bool thisSetDomain = !!thisURI; 1.263 + if (!thisURI) { 1.264 + this->GetURI(getter_AddRefs(thisURI)); 1.265 + } 1.266 + 1.267 + nsCOMPtr<nsIURI> otherURI; 1.268 + aOther->GetDomain(getter_AddRefs(otherURI)); 1.269 + bool otherSetDomain = !!otherURI; 1.270 + if (!otherURI) { 1.271 + aOther->GetURI(getter_AddRefs(otherURI)); 1.272 + } 1.273 + 1.274 + *aResult = thisSetDomain == otherSetDomain && 1.275 + nsScriptSecurityManager::SecurityCompareURIs(thisURI, otherURI); 1.276 + return NS_OK; 1.277 +} 1.278 + 1.279 +NS_IMETHODIMP 1.280 +nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult) 1.281 +{ 1.282 + *aResult = false; 1.283 + 1.284 + if (!aOther) { 1.285 + NS_WARNING("Need a principal to compare this to!"); 1.286 + return NS_OK; 1.287 + } 1.288 + 1.289 + if (aOther == this) { 1.290 + *aResult = true; 1.291 + return NS_OK; 1.292 + } 1.293 + 1.294 + if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) { 1.295 + return NS_OK; 1.296 + } 1.297 + 1.298 + nsCOMPtr<nsIURI> otherURI; 1.299 + nsresult rv = aOther->GetURI(getter_AddRefs(otherURI)); 1.300 + if (NS_FAILED(rv)) { 1.301 + return rv; 1.302 + } 1.303 + 1.304 + NS_ASSERTION(mCodebase, 1.305 + "shouldn't be calling this on principals from preferences"); 1.306 + 1.307 + // Compare codebases. 1.308 + *aResult = nsScriptSecurityManager::SecurityCompareURIs(mCodebase, 1.309 + otherURI); 1.310 + return NS_OK; 1.311 +} 1.312 + 1.313 +NS_IMETHODIMP 1.314 +nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult) 1.315 +{ 1.316 + return Equals(aOther, aResult); 1.317 +} 1.318 + 1.319 +NS_IMETHODIMP 1.320 +nsPrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult) 1.321 +{ 1.322 + return EqualsConsideringDomain(aOther, aResult); 1.323 +} 1.324 + 1.325 +NS_IMETHODIMP 1.326 +nsPrincipal::GetURI(nsIURI** aURI) 1.327 +{ 1.328 + if (mCodebaseImmutable) { 1.329 + NS_ADDREF(*aURI = mCodebase); 1.330 + return NS_OK; 1.331 + } 1.332 + 1.333 + if (!mCodebase) { 1.334 + *aURI = nullptr; 1.335 + return NS_OK; 1.336 + } 1.337 + 1.338 + return NS_EnsureSafeToReturn(mCodebase, aURI); 1.339 +} 1.340 + 1.341 +NS_IMETHODIMP 1.342 +nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal) 1.343 +{ 1.344 + if (aAllowIfInheritsPrincipal) { 1.345 + // If the caller specified to allow loads of URIs that inherit 1.346 + // our principal, allow the load if this URI inherits its principal 1.347 + if (nsPrincipal::IsPrincipalInherited(aURI)) { 1.348 + return NS_OK; 1.349 + } 1.350 + } 1.351 + 1.352 + if (nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) { 1.353 + return NS_OK; 1.354 + } 1.355 + 1.356 + // If strict file origin policy is in effect, local files will always fail 1.357 + // SecurityCompareURIs unless they are identical. Explicitly check file origin 1.358 + // policy, in that case. 1.359 + if (nsScriptSecurityManager::GetStrictFileOriginPolicy() && 1.360 + NS_URIIsLocalFile(aURI) && 1.361 + NS_RelaxStrictFileOriginPolicy(aURI, mCodebase)) { 1.362 + return NS_OK; 1.363 + } 1.364 + 1.365 + if (aReport) { 1.366 + nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI); 1.367 + } 1.368 + return NS_ERROR_DOM_BAD_URI; 1.369 +} 1.370 + 1.371 +void 1.372 +nsPrincipal::SetURI(nsIURI* aURI) 1.373 +{ 1.374 + mCodebase = NS_TryToMakeImmutable(aURI); 1.375 + mCodebaseImmutable = URIIsImmutable(mCodebase); 1.376 +} 1.377 + 1.378 +NS_IMETHODIMP 1.379 +nsPrincipal::GetHashValue(uint32_t* aValue) 1.380 +{ 1.381 + NS_PRECONDITION(mCodebase, "Need a codebase"); 1.382 + 1.383 + *aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this); 1.384 + return NS_OK; 1.385 +} 1.386 + 1.387 +NS_IMETHODIMP 1.388 +nsPrincipal::GetDomain(nsIURI** aDomain) 1.389 +{ 1.390 + if (!mDomain) { 1.391 + *aDomain = nullptr; 1.392 + return NS_OK; 1.393 + } 1.394 + 1.395 + if (mDomainImmutable) { 1.396 + NS_ADDREF(*aDomain = mDomain); 1.397 + return NS_OK; 1.398 + } 1.399 + 1.400 + return NS_EnsureSafeToReturn(mDomain, aDomain); 1.401 +} 1.402 + 1.403 +NS_IMETHODIMP 1.404 +nsPrincipal::SetDomain(nsIURI* aDomain) 1.405 +{ 1.406 + mDomain = NS_TryToMakeImmutable(aDomain); 1.407 + mDomainImmutable = URIIsImmutable(mDomain); 1.408 + 1.409 + // Recompute all wrappers between compartments using this principal and other 1.410 + // non-chrome compartments. 1.411 + AutoSafeJSContext cx; 1.412 + JSPrincipals *principals = nsJSPrincipals::get(static_cast<nsIPrincipal*>(this)); 1.413 + bool success = js::RecomputeWrappers(cx, js::ContentCompartmentsOnly(), 1.414 + js::CompartmentsWithPrincipals(principals)); 1.415 + NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); 1.416 + success = js::RecomputeWrappers(cx, js::CompartmentsWithPrincipals(principals), 1.417 + js::ContentCompartmentsOnly()); 1.418 + NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); 1.419 + 1.420 + return NS_OK; 1.421 +} 1.422 + 1.423 +NS_IMETHODIMP 1.424 +nsPrincipal::GetJarPrefix(nsACString& aJarPrefix) 1.425 +{ 1.426 + MOZ_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID); 1.427 + 1.428 + mozilla::GetJarPrefix(mAppId, mInMozBrowser, aJarPrefix); 1.429 + return NS_OK; 1.430 +} 1.431 + 1.432 +NS_IMETHODIMP 1.433 +nsPrincipal::GetAppStatus(uint16_t* aAppStatus) 1.434 +{ 1.435 + *aAppStatus = GetAppStatus(); 1.436 + return NS_OK; 1.437 +} 1.438 + 1.439 +NS_IMETHODIMP 1.440 +nsPrincipal::GetAppId(uint32_t* aAppId) 1.441 +{ 1.442 + if (mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) { 1.443 + MOZ_ASSERT(false); 1.444 + *aAppId = nsIScriptSecurityManager::NO_APP_ID; 1.445 + return NS_OK; 1.446 + } 1.447 + 1.448 + *aAppId = mAppId; 1.449 + return NS_OK; 1.450 +} 1.451 + 1.452 +NS_IMETHODIMP 1.453 +nsPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement) 1.454 +{ 1.455 + *aIsInBrowserElement = mInMozBrowser; 1.456 + return NS_OK; 1.457 +} 1.458 + 1.459 +NS_IMETHODIMP 1.460 +nsPrincipal::GetUnknownAppId(bool* aUnknownAppId) 1.461 +{ 1.462 + *aUnknownAppId = mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID; 1.463 + return NS_OK; 1.464 +} 1.465 + 1.466 +NS_IMETHODIMP 1.467 +nsPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal) 1.468 +{ 1.469 + *aIsNullPrincipal = false; 1.470 + return NS_OK; 1.471 +} 1.472 + 1.473 +NS_IMETHODIMP 1.474 +nsPrincipal::GetBaseDomain(nsACString& aBaseDomain) 1.475 +{ 1.476 + // For a file URI, we return the file path. 1.477 + if (NS_URIIsLocalFile(mCodebase)) { 1.478 + nsCOMPtr<nsIURL> url = do_QueryInterface(mCodebase); 1.479 + 1.480 + if (url) { 1.481 + return url->GetFilePath(aBaseDomain); 1.482 + } 1.483 + } 1.484 + 1.485 + // For everything else, we ask the TLD service via 1.486 + // the ThirdPartyUtil. 1.487 + nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = 1.488 + do_GetService(THIRDPARTYUTIL_CONTRACTID); 1.489 + if (thirdPartyUtil) { 1.490 + return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain); 1.491 + } 1.492 + 1.493 + return NS_OK; 1.494 +} 1.495 + 1.496 +NS_IMETHODIMP 1.497 +nsPrincipal::Read(nsIObjectInputStream* aStream) 1.498 +{ 1.499 + nsCOMPtr<nsISupports> supports; 1.500 + nsCOMPtr<nsIURI> codebase; 1.501 + nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); 1.502 + if (NS_FAILED(rv)) { 1.503 + return rv; 1.504 + } 1.505 + 1.506 + codebase = do_QueryInterface(supports); 1.507 + 1.508 + nsCOMPtr<nsIURI> domain; 1.509 + rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); 1.510 + if (NS_FAILED(rv)) { 1.511 + return rv; 1.512 + } 1.513 + 1.514 + domain = do_QueryInterface(supports); 1.515 + 1.516 + uint32_t appId; 1.517 + rv = aStream->Read32(&appId); 1.518 + NS_ENSURE_SUCCESS(rv, rv); 1.519 + 1.520 + bool inMozBrowser; 1.521 + rv = aStream->ReadBoolean(&inMozBrowser); 1.522 + NS_ENSURE_SUCCESS(rv, rv); 1.523 + 1.524 + rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); 1.525 + NS_ENSURE_SUCCESS(rv, rv); 1.526 + 1.527 + // This may be null. 1.528 + nsCOMPtr<nsIContentSecurityPolicy> csp = do_QueryInterface(supports, &rv); 1.529 + 1.530 + rv = Init(codebase, appId, inMozBrowser); 1.531 + NS_ENSURE_SUCCESS(rv, rv); 1.532 + 1.533 + rv = SetCsp(csp); 1.534 + NS_ENSURE_SUCCESS(rv, rv); 1.535 + 1.536 + // need to link in the CSP context here (link in a reference to this 1.537 + // nsIPrincipal and to the URI of the protected resource). 1.538 + if (csp) { 1.539 + csp->SetRequestContext(codebase, nullptr, this, nullptr); 1.540 + } 1.541 + 1.542 + SetDomain(domain); 1.543 + 1.544 + return NS_OK; 1.545 +} 1.546 + 1.547 +NS_IMETHODIMP 1.548 +nsPrincipal::Write(nsIObjectOutputStream* aStream) 1.549 +{ 1.550 + NS_ENSURE_STATE(mCodebase); 1.551 + 1.552 + nsresult rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI), 1.553 + true); 1.554 + if (NS_FAILED(rv)) { 1.555 + return rv; 1.556 + } 1.557 + 1.558 + rv = NS_WriteOptionalCompoundObject(aStream, mDomain, NS_GET_IID(nsIURI), 1.559 + true); 1.560 + if (NS_FAILED(rv)) { 1.561 + return rv; 1.562 + } 1.563 + 1.564 + aStream->Write32(mAppId); 1.565 + aStream->WriteBoolean(mInMozBrowser); 1.566 + 1.567 + rv = NS_WriteOptionalCompoundObject(aStream, mCSP, 1.568 + NS_GET_IID(nsIContentSecurityPolicy), 1.569 + true); 1.570 + if (NS_FAILED(rv)) { 1.571 + return rv; 1.572 + } 1.573 + 1.574 + // mCodebaseImmutable and mDomainImmutable will be recomputed based 1.575 + // on the deserialized URIs in Read(). 1.576 + 1.577 + return NS_OK; 1.578 +} 1.579 + 1.580 +uint16_t 1.581 +nsPrincipal::GetAppStatus() 1.582 +{ 1.583 + NS_WARN_IF_FALSE(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, 1.584 + "Asking for app status on a principal with an unknown app id"); 1.585 + // Installed apps have a valid app id (not NO_APP_ID or UNKNOWN_APP_ID) 1.586 + // and they are not inside a mozbrowser. 1.587 + if (mAppId == nsIScriptSecurityManager::NO_APP_ID || 1.588 + mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID || mInMozBrowser) { 1.589 + return nsIPrincipal::APP_STATUS_NOT_INSTALLED; 1.590 + } 1.591 + 1.592 + nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); 1.593 + NS_ENSURE_TRUE(appsService, nsIPrincipal::APP_STATUS_NOT_INSTALLED); 1.594 + 1.595 + nsCOMPtr<mozIApplication> app; 1.596 + appsService->GetAppByLocalId(mAppId, getter_AddRefs(app)); 1.597 + NS_ENSURE_TRUE(app, nsIPrincipal::APP_STATUS_NOT_INSTALLED); 1.598 + 1.599 + uint16_t status = nsIPrincipal::APP_STATUS_INSTALLED; 1.600 + NS_ENSURE_SUCCESS(app->GetAppStatus(&status), 1.601 + nsIPrincipal::APP_STATUS_NOT_INSTALLED); 1.602 + 1.603 + nsAutoCString origin; 1.604 + NS_ENSURE_SUCCESS(GetOrigin(getter_Copies(origin)), 1.605 + nsIPrincipal::APP_STATUS_NOT_INSTALLED); 1.606 + nsString appOrigin; 1.607 + NS_ENSURE_SUCCESS(app->GetOrigin(appOrigin), 1.608 + nsIPrincipal::APP_STATUS_NOT_INSTALLED); 1.609 + 1.610 + // We go from string -> nsIURI -> origin to be sure we 1.611 + // compare two punny-encoded origins. 1.612 + nsCOMPtr<nsIURI> appURI; 1.613 + NS_ENSURE_SUCCESS(NS_NewURI(getter_AddRefs(appURI), appOrigin), 1.614 + nsIPrincipal::APP_STATUS_NOT_INSTALLED); 1.615 + 1.616 + nsAutoCString appOriginPunned; 1.617 + NS_ENSURE_SUCCESS(GetOriginForURI(appURI, getter_Copies(appOriginPunned)), 1.618 + nsIPrincipal::APP_STATUS_NOT_INSTALLED); 1.619 + 1.620 + if (!appOriginPunned.Equals(origin)) { 1.621 + return nsIPrincipal::APP_STATUS_NOT_INSTALLED; 1.622 + } 1.623 + 1.624 + return status; 1.625 +} 1.626 + 1.627 +/************************************************************************************************************************/ 1.628 + 1.629 +static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]"; 1.630 + 1.631 +NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, 1.632 + NS_EXPANDEDPRINCIPAL_CID) 1.633 +NS_IMPL_QUERY_INTERFACE_CI(nsExpandedPrincipal, 1.634 + nsIPrincipal, 1.635 + nsIExpandedPrincipal) 1.636 +NS_IMPL_CI_INTERFACE_GETTER(nsExpandedPrincipal, 1.637 + nsIPrincipal, 1.638 + nsIExpandedPrincipal) 1.639 +NS_IMPL_ADDREF_INHERITED(nsExpandedPrincipal, nsBasePrincipal) 1.640 +NS_IMPL_RELEASE_INHERITED(nsExpandedPrincipal, nsBasePrincipal) 1.641 + 1.642 +nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr <nsIPrincipal> > &aWhiteList) 1.643 +{ 1.644 + mPrincipals.AppendElements(aWhiteList); 1.645 +} 1.646 + 1.647 +nsExpandedPrincipal::~nsExpandedPrincipal() 1.648 +{ } 1.649 + 1.650 +NS_IMETHODIMP 1.651 +nsExpandedPrincipal::GetDomain(nsIURI** aDomain) 1.652 +{ 1.653 + *aDomain = nullptr; 1.654 + return NS_OK; 1.655 +} 1.656 + 1.657 +NS_IMETHODIMP 1.658 +nsExpandedPrincipal::SetDomain(nsIURI* aDomain) 1.659 +{ 1.660 + return NS_OK; 1.661 +} 1.662 + 1.663 +NS_IMETHODIMP 1.664 +nsExpandedPrincipal::GetOrigin(char** aOrigin) 1.665 +{ 1.666 + *aOrigin = ToNewCString(NS_LITERAL_CSTRING(EXPANDED_PRINCIPAL_SPEC)); 1.667 + return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY; 1.668 +} 1.669 + 1.670 +typedef nsresult (NS_STDCALL nsIPrincipal::*nsIPrincipalMemFn)(nsIPrincipal* aOther, 1.671 + bool* aResult); 1.672 +#define CALL_MEMBER_FUNCTION(THIS,MEM_FN) ((THIS)->*(MEM_FN)) 1.673 + 1.674 +// nsExpandedPrincipal::Equals and nsExpandedPrincipal::EqualsConsideringDomain 1.675 +// shares the same logic. The difference only that Equals requires 'this' 1.676 +// and 'aOther' to Subsume each other while EqualsConsideringDomain requires 1.677 +// bidirectional SubsumesConsideringDomain. 1.678 +static nsresult 1.679 +Equals(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther, 1.680 + bool* aResult) 1.681 +{ 1.682 + // If (and only if) 'aThis' and 'aOther' both Subsume/SubsumesConsideringDomain 1.683 + // each other, then they are Equal. 1.684 + *aResult = false; 1.685 + // Calling the corresponding subsume function on this (aFn). 1.686 + nsresult rv = CALL_MEMBER_FUNCTION(aThis, aFn)(aOther, aResult); 1.687 + NS_ENSURE_SUCCESS(rv, rv); 1.688 + if (!*aResult) 1.689 + return NS_OK; 1.690 + 1.691 + // Calling the corresponding subsume function on aOther (aFn). 1.692 + rv = CALL_MEMBER_FUNCTION(aOther, aFn)(aThis, aResult); 1.693 + NS_ENSURE_SUCCESS(rv, rv); 1.694 + return NS_OK; 1.695 +} 1.696 + 1.697 +NS_IMETHODIMP 1.698 +nsExpandedPrincipal::Equals(nsIPrincipal* aOther, bool* aResult) 1.699 +{ 1.700 + return ::Equals(this, &nsIPrincipal::Subsumes, aOther, aResult); 1.701 +} 1.702 + 1.703 +NS_IMETHODIMP 1.704 +nsExpandedPrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) 1.705 +{ 1.706 + return ::Equals(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult); 1.707 +} 1.708 + 1.709 +// nsExpandedPrincipal::Subsumes and nsExpandedPrincipal::SubsumesConsideringDomain 1.710 +// shares the same logic. The difference only that Subsumes calls are replaced 1.711 +//with SubsumesConsideringDomain calls in the second case. 1.712 +static nsresult 1.713 +Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther, 1.714 + bool* aResult) 1.715 +{ 1.716 + nsresult rv; 1.717 + nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aOther); 1.718 + if (expanded) { 1.719 + // If aOther is an ExpandedPrincipal too, check if all of its 1.720 + // principals are subsumed. 1.721 + nsTArray< nsCOMPtr<nsIPrincipal> >* otherList; 1.722 + expanded->GetWhiteList(&otherList); 1.723 + for (uint32_t i = 0; i < otherList->Length(); ++i){ 1.724 + rv = CALL_MEMBER_FUNCTION(aThis, aFn)((*otherList)[i], aResult); 1.725 + NS_ENSURE_SUCCESS(rv, rv); 1.726 + if (!*aResult) { 1.727 + // If we don't subsume at least one principal of aOther, return false. 1.728 + return NS_OK; 1.729 + } 1.730 + } 1.731 + } else { 1.732 + // For a regular aOther, one of our principals must subsume it. 1.733 + nsTArray< nsCOMPtr<nsIPrincipal> >* list; 1.734 + aThis->GetWhiteList(&list); 1.735 + for (uint32_t i = 0; i < list->Length(); ++i){ 1.736 + rv = CALL_MEMBER_FUNCTION((*list)[i], aFn)(aOther, aResult); 1.737 + NS_ENSURE_SUCCESS(rv, rv); 1.738 + if (*aResult) { 1.739 + // If one of our principal subsumes it, return true. 1.740 + return NS_OK; 1.741 + } 1.742 + } 1.743 + } 1.744 + return NS_OK; 1.745 +} 1.746 + 1.747 +#undef CALL_MEMBER_FUNCTION 1.748 + 1.749 +NS_IMETHODIMP 1.750 +nsExpandedPrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) 1.751 +{ 1.752 + return ::Subsumes(this, &nsIPrincipal::Subsumes, aOther, aResult); 1.753 +} 1.754 + 1.755 +NS_IMETHODIMP 1.756 +nsExpandedPrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) 1.757 +{ 1.758 + return ::Subsumes(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult); 1.759 +} 1.760 + 1.761 +NS_IMETHODIMP 1.762 +nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal) 1.763 +{ 1.764 + nsresult rv; 1.765 + for (uint32_t i = 0; i < mPrincipals.Length(); ++i){ 1.766 + rv = mPrincipals[i]->CheckMayLoad(uri, aReport, aAllowIfInheritsPrincipal); 1.767 + if (NS_SUCCEEDED(rv)) 1.768 + return rv; 1.769 + } 1.770 + 1.771 + return NS_ERROR_DOM_BAD_URI; 1.772 +} 1.773 + 1.774 +NS_IMETHODIMP 1.775 +nsExpandedPrincipal::GetHashValue(uint32_t* result) 1.776 +{ 1.777 + MOZ_CRASH("extended principal should never be used as key in a hash map"); 1.778 +} 1.779 + 1.780 +NS_IMETHODIMP 1.781 +nsExpandedPrincipal::GetURI(nsIURI** aURI) 1.782 +{ 1.783 + *aURI = nullptr; 1.784 + return NS_OK; 1.785 +} 1.786 + 1.787 +NS_IMETHODIMP 1.788 +nsExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList) 1.789 +{ 1.790 + *aWhiteList = &mPrincipals; 1.791 + return NS_OK; 1.792 +} 1.793 + 1.794 +NS_IMETHODIMP 1.795 +nsExpandedPrincipal::GetJarPrefix(nsACString& aJarPrefix) 1.796 +{ 1.797 + aJarPrefix.Truncate(); 1.798 + return NS_OK; 1.799 +} 1.800 + 1.801 +NS_IMETHODIMP 1.802 +nsExpandedPrincipal::GetAppStatus(uint16_t* aAppStatus) 1.803 +{ 1.804 + *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED; 1.805 + return NS_OK; 1.806 +} 1.807 + 1.808 +NS_IMETHODIMP 1.809 +nsExpandedPrincipal::GetAppId(uint32_t* aAppId) 1.810 +{ 1.811 + *aAppId = nsIScriptSecurityManager::NO_APP_ID; 1.812 + return NS_OK; 1.813 +} 1.814 + 1.815 +NS_IMETHODIMP 1.816 +nsExpandedPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement) 1.817 +{ 1.818 + *aIsInBrowserElement = false; 1.819 + return NS_OK; 1.820 +} 1.821 + 1.822 +NS_IMETHODIMP 1.823 +nsExpandedPrincipal::GetUnknownAppId(bool* aUnknownAppId) 1.824 +{ 1.825 + *aUnknownAppId = false; 1.826 + return NS_OK; 1.827 +} 1.828 + 1.829 +NS_IMETHODIMP 1.830 +nsExpandedPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal) 1.831 +{ 1.832 + *aIsNullPrincipal = false; 1.833 + return NS_OK; 1.834 +} 1.835 + 1.836 +NS_IMETHODIMP 1.837 +nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain) 1.838 +{ 1.839 + return NS_ERROR_NOT_AVAILABLE; 1.840 +} 1.841 + 1.842 +void 1.843 +nsExpandedPrincipal::GetScriptLocation(nsACString& aStr) 1.844 +{ 1.845 + // Is that a good idea to list it's principals? 1.846 + aStr.Assign(EXPANDED_PRINCIPAL_SPEC); 1.847 +} 1.848 + 1.849 +#ifdef DEBUG 1.850 +void nsExpandedPrincipal::dumpImpl() 1.851 +{ 1.852 + fprintf(stderr, "nsExpandedPrincipal (%p)\n", static_cast<void*>(this)); 1.853 +} 1.854 +#endif 1.855 + 1.856 +////////////////////////////////////////// 1.857 +// Methods implementing nsISerializable // 1.858 +////////////////////////////////////////// 1.859 + 1.860 +NS_IMETHODIMP 1.861 +nsExpandedPrincipal::Read(nsIObjectInputStream* aStream) 1.862 +{ 1.863 + return NS_ERROR_NOT_IMPLEMENTED; 1.864 +} 1.865 + 1.866 +NS_IMETHODIMP 1.867 +nsExpandedPrincipal::Write(nsIObjectOutputStream* aStream) 1.868 +{ 1.869 + return NS_ERROR_NOT_IMPLEMENTED; 1.870 +}