1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/caps/src/nsScriptSecurityManager.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1663 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set ts=4 et sw=4 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 "nsScriptSecurityManager.h" 1.11 + 1.12 +#include "mozilla/ArrayUtils.h" 1.13 + 1.14 +#include "js/OldDebugAPI.h" 1.15 +#include "xpcprivate.h" 1.16 +#include "XPCWrapper.h" 1.17 +#include "nsIServiceManager.h" 1.18 +#include "nsIScriptObjectPrincipal.h" 1.19 +#include "nsIScriptContext.h" 1.20 +#include "nsIURL.h" 1.21 +#include "nsINestedURI.h" 1.22 +#include "nspr.h" 1.23 +#include "nsJSPrincipals.h" 1.24 +#include "nsSystemPrincipal.h" 1.25 +#include "nsPrincipal.h" 1.26 +#include "nsNullPrincipal.h" 1.27 +#include "DomainPolicy.h" 1.28 +#include "nsXPIDLString.h" 1.29 +#include "nsCRT.h" 1.30 +#include "nsCRTGlue.h" 1.31 +#include "nsError.h" 1.32 +#include "nsDOMCID.h" 1.33 +#include "nsIXPConnect.h" 1.34 +#include "nsIXPCSecurityManager.h" 1.35 +#include "nsTextFormatter.h" 1.36 +#include "nsIStringBundle.h" 1.37 +#include "nsNetUtil.h" 1.38 +#include "nsIEffectiveTLDService.h" 1.39 +#include "nsIProperties.h" 1.40 +#include "nsDirectoryServiceDefs.h" 1.41 +#include "nsIFile.h" 1.42 +#include "nsIFileURL.h" 1.43 +#include "nsIZipReader.h" 1.44 +#include "nsIXPConnect.h" 1.45 +#include "nsIScriptGlobalObject.h" 1.46 +#include "nsPIDOMWindow.h" 1.47 +#include "nsIDocShell.h" 1.48 +#include "nsIPrompt.h" 1.49 +#include "nsIWindowWatcher.h" 1.50 +#include "nsIConsoleService.h" 1.51 +#include "nsIJSRuntimeService.h" 1.52 +#include "nsIObserverService.h" 1.53 +#include "nsIContent.h" 1.54 +#include "nsAutoPtr.h" 1.55 +#include "nsDOMJSUtils.h" 1.56 +#include "nsAboutProtocolUtils.h" 1.57 +#include "nsIClassInfo.h" 1.58 +#include "nsIURIFixup.h" 1.59 +#include "nsCDefaultURIFixup.h" 1.60 +#include "nsIChromeRegistry.h" 1.61 +#include "nsIContentSecurityPolicy.h" 1.62 +#include "nsIAsyncVerifyRedirectCallback.h" 1.63 +#include "mozilla/Preferences.h" 1.64 +#include "mozilla/dom/BindingUtils.h" 1.65 +#include <stdint.h> 1.66 +#include "mozilla/ClearOnShutdown.h" 1.67 +#include "mozilla/StaticPtr.h" 1.68 +#include "nsContentUtils.h" 1.69 +#include "nsCxPusher.h" 1.70 +#include "nsJSUtils.h" 1.71 + 1.72 +// This should be probably defined on some other place... but I couldn't find it 1.73 +#define WEBAPPS_PERM_NAME "webapps-manage" 1.74 + 1.75 +using namespace mozilla; 1.76 +using namespace mozilla::dom; 1.77 + 1.78 +static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); 1.79 + 1.80 +nsIIOService *nsScriptSecurityManager::sIOService = nullptr; 1.81 +nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr; 1.82 +JSRuntime *nsScriptSecurityManager::sRuntime = 0; 1.83 +bool nsScriptSecurityManager::sStrictFileOriginPolicy = true; 1.84 + 1.85 +bool 1.86 +nsScriptSecurityManager::SubjectIsPrivileged() 1.87 +{ 1.88 + JSContext *cx = GetCurrentJSContext(); 1.89 + if (cx && xpc::IsUniversalXPConnectEnabled(cx)) 1.90 + return true; 1.91 + bool isSystem = false; 1.92 + return NS_SUCCEEDED(SubjectPrincipalIsSystem(&isSystem)) && isSystem; 1.93 +} 1.94 + 1.95 +/////////////////////////// 1.96 +// Convenience Functions // 1.97 +/////////////////////////// 1.98 +// Result of this function should not be freed. 1.99 +static inline const char16_t * 1.100 +IDToString(JSContext *cx, jsid id_) 1.101 +{ 1.102 + JS::RootedId id(cx, id_); 1.103 + if (JSID_IS_STRING(id)) 1.104 + return JS_GetInternedStringChars(JSID_TO_STRING(id)); 1.105 + 1.106 + JS::Rooted<JS::Value> idval(cx); 1.107 + if (!JS_IdToValue(cx, id, &idval)) 1.108 + return nullptr; 1.109 + JSString *str = JS::ToString(cx, idval); 1.110 + if(!str) 1.111 + return nullptr; 1.112 + return JS_GetStringCharsZ(cx, str); 1.113 +} 1.114 + 1.115 +class nsAutoInPrincipalDomainOriginSetter { 1.116 +public: 1.117 + nsAutoInPrincipalDomainOriginSetter() { 1.118 + ++sInPrincipalDomainOrigin; 1.119 + } 1.120 + ~nsAutoInPrincipalDomainOriginSetter() { 1.121 + --sInPrincipalDomainOrigin; 1.122 + } 1.123 + static uint32_t sInPrincipalDomainOrigin; 1.124 +}; 1.125 +uint32_t nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin; 1.126 + 1.127 +static 1.128 +nsresult 1.129 +GetOriginFromURI(nsIURI* aURI, nsACString& aOrigin) 1.130 +{ 1.131 + if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin > 1) { 1.132 + // Allow a single recursive call to GetPrincipalDomainOrigin, since that 1.133 + // might be happening on a different principal from the first call. But 1.134 + // after that, cut off the recursion; it just indicates that something 1.135 + // we're doing in this method causes us to reenter a security check here. 1.136 + return NS_ERROR_NOT_AVAILABLE; 1.137 + } 1.138 + 1.139 + nsAutoInPrincipalDomainOriginSetter autoSetter; 1.140 + 1.141 + nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI); 1.142 + NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED); 1.143 + 1.144 + nsAutoCString hostPort; 1.145 + 1.146 + nsresult rv = uri->GetHostPort(hostPort); 1.147 + if (NS_SUCCEEDED(rv)) { 1.148 + nsAutoCString scheme; 1.149 + rv = uri->GetScheme(scheme); 1.150 + NS_ENSURE_SUCCESS(rv, rv); 1.151 + aOrigin = scheme + NS_LITERAL_CSTRING("://") + hostPort; 1.152 + } 1.153 + else { 1.154 + // Some URIs (e.g., nsSimpleURI) don't support host. Just 1.155 + // get the full spec. 1.156 + rv = uri->GetSpec(aOrigin); 1.157 + NS_ENSURE_SUCCESS(rv, rv); 1.158 + } 1.159 + 1.160 + return NS_OK; 1.161 +} 1.162 + 1.163 +static 1.164 +nsresult 1.165 +GetPrincipalDomainOrigin(nsIPrincipal* aPrincipal, 1.166 + nsACString& aOrigin) 1.167 +{ 1.168 + 1.169 + nsCOMPtr<nsIURI> uri; 1.170 + aPrincipal->GetDomain(getter_AddRefs(uri)); 1.171 + if (!uri) { 1.172 + aPrincipal->GetURI(getter_AddRefs(uri)); 1.173 + } 1.174 + NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED); 1.175 + 1.176 + return GetOriginFromURI(uri, aOrigin); 1.177 +} 1.178 + 1.179 +inline void SetPendingException(JSContext *cx, const char *aMsg) 1.180 +{ 1.181 + JS_ReportError(cx, "%s", aMsg); 1.182 +} 1.183 + 1.184 +inline void SetPendingException(JSContext *cx, const char16_t *aMsg) 1.185 +{ 1.186 + JS_ReportError(cx, "%hs", aMsg); 1.187 +} 1.188 + 1.189 +// Helper class to get stuff from the ClassInfo and not waste extra time with 1.190 +// virtual method calls for things it has already gotten 1.191 +class ClassInfoData 1.192 +{ 1.193 +public: 1.194 + ClassInfoData(nsIClassInfo *aClassInfo, const char *aName) 1.195 + : mClassInfo(aClassInfo), 1.196 + mName(const_cast<char *>(aName)), 1.197 + mDidGetFlags(false), 1.198 + mMustFreeName(false) 1.199 + { 1.200 + } 1.201 + 1.202 + ~ClassInfoData() 1.203 + { 1.204 + if (mMustFreeName) 1.205 + nsMemory::Free(mName); 1.206 + } 1.207 + 1.208 + uint32_t GetFlags() 1.209 + { 1.210 + if (!mDidGetFlags) { 1.211 + if (mClassInfo) { 1.212 + nsresult rv = mClassInfo->GetFlags(&mFlags); 1.213 + if (NS_FAILED(rv)) { 1.214 + mFlags = 0; 1.215 + } 1.216 + } else { 1.217 + mFlags = 0; 1.218 + } 1.219 + 1.220 + mDidGetFlags = true; 1.221 + } 1.222 + 1.223 + return mFlags; 1.224 + } 1.225 + 1.226 + bool IsDOMClass() 1.227 + { 1.228 + return !!(GetFlags() & nsIClassInfo::DOM_OBJECT); 1.229 + } 1.230 + 1.231 + const char* GetName() 1.232 + { 1.233 + if (!mName) { 1.234 + if (mClassInfo) { 1.235 + mClassInfo->GetClassDescription(&mName); 1.236 + } 1.237 + 1.238 + if (mName) { 1.239 + mMustFreeName = true; 1.240 + } else { 1.241 + mName = const_cast<char *>("UnnamedClass"); 1.242 + } 1.243 + } 1.244 + 1.245 + return mName; 1.246 + } 1.247 + 1.248 +private: 1.249 + nsIClassInfo *mClassInfo; // WEAK 1.250 + uint32_t mFlags; 1.251 + char *mName; 1.252 + bool mDidGetFlags; 1.253 + bool mMustFreeName; 1.254 +}; 1.255 + 1.256 +JSContext * 1.257 +nsScriptSecurityManager::GetCurrentJSContext() 1.258 +{ 1.259 + // Get JSContext from stack. 1.260 + return nsXPConnect::XPConnect()->GetCurrentJSContext(); 1.261 +} 1.262 + 1.263 +JSContext * 1.264 +nsScriptSecurityManager::GetSafeJSContext() 1.265 +{ 1.266 + // Get JSContext from stack. 1.267 + return nsXPConnect::XPConnect()->GetSafeJSContext(); 1.268 +} 1.269 + 1.270 +/* static */ 1.271 +bool 1.272 +nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI, 1.273 + nsIURI* aTargetURI) 1.274 +{ 1.275 + return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy); 1.276 +} 1.277 + 1.278 +// SecurityHashURI is consistent with SecurityCompareURIs because NS_SecurityHashURI 1.279 +// is consistent with NS_SecurityCompareURIs. See nsNetUtil.h. 1.280 +uint32_t 1.281 +nsScriptSecurityManager::SecurityHashURI(nsIURI* aURI) 1.282 +{ 1.283 + return NS_SecurityHashURI(aURI); 1.284 +} 1.285 + 1.286 +NS_IMETHODIMP 1.287 +nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel, 1.288 + nsIPrincipal** aPrincipal) 1.289 +{ 1.290 + NS_PRECONDITION(aChannel, "Must have channel!"); 1.291 + nsCOMPtr<nsISupports> owner; 1.292 + aChannel->GetOwner(getter_AddRefs(owner)); 1.293 + if (owner) { 1.294 + CallQueryInterface(owner, aPrincipal); 1.295 + if (*aPrincipal) { 1.296 + return NS_OK; 1.297 + } 1.298 + } 1.299 + 1.300 + // OK, get the principal from the URI. Make sure this does the same thing 1.301 + // as nsDocument::Reset and XULDocument::StartDocumentLoad. 1.302 + nsCOMPtr<nsIURI> uri; 1.303 + nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); 1.304 + NS_ENSURE_SUCCESS(rv, rv); 1.305 + 1.306 + nsCOMPtr<nsIDocShell> docShell; 1.307 + NS_QueryNotificationCallbacks(aChannel, docShell); 1.308 + 1.309 + if (docShell) { 1.310 + return GetDocShellCodebasePrincipal(uri, docShell, aPrincipal); 1.311 + } 1.312 + 1.313 + return GetCodebasePrincipalInternal(uri, UNKNOWN_APP_ID, 1.314 + /* isInBrowserElement */ false, aPrincipal); 1.315 +} 1.316 + 1.317 +NS_IMETHODIMP 1.318 +nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal, 1.319 + bool* aIsSystem) 1.320 +{ 1.321 + *aIsSystem = (aPrincipal == mSystemPrincipal); 1.322 + return NS_OK; 1.323 +} 1.324 + 1.325 +NS_IMETHODIMP_(nsIPrincipal *) 1.326 +nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext *cx) 1.327 +{ 1.328 + NS_ASSERTION(cx == GetCurrentJSContext(), 1.329 + "Uh, cx is not the current JS context!"); 1.330 + 1.331 + nsresult rv = NS_ERROR_FAILURE; 1.332 + nsIPrincipal *principal = GetSubjectPrincipal(cx, &rv); 1.333 + if (NS_FAILED(rv)) 1.334 + return nullptr; 1.335 + 1.336 + return principal; 1.337 +} 1.338 + 1.339 +///////////////////////////// 1.340 +// nsScriptSecurityManager // 1.341 +///////////////////////////// 1.342 + 1.343 +//////////////////////////////////// 1.344 +// Methods implementing ISupports // 1.345 +//////////////////////////////////// 1.346 +NS_IMPL_ISUPPORTS(nsScriptSecurityManager, 1.347 + nsIScriptSecurityManager, 1.348 + nsIXPCSecurityManager, 1.349 + nsIChannelEventSink, 1.350 + nsIObserver) 1.351 + 1.352 +/////////////////////////////////////////////////// 1.353 +// Methods implementing nsIScriptSecurityManager // 1.354 +/////////////////////////////////////////////////// 1.355 + 1.356 +///////////////// Security Checks ///////////////// 1.357 + 1.358 +bool 1.359 +nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx) 1.360 +{ 1.361 + // Get the security manager 1.362 + nsScriptSecurityManager *ssm = 1.363 + nsScriptSecurityManager::GetScriptSecurityManager(); 1.364 + 1.365 + NS_ASSERTION(ssm, "Failed to get security manager service"); 1.366 + if (!ssm) 1.367 + return false; 1.368 + 1.369 + nsresult rv; 1.370 + nsIPrincipal* subjectPrincipal = ssm->GetSubjectPrincipal(cx, &rv); 1.371 + 1.372 + NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get nsIPrincipal from js context"); 1.373 + if (NS_FAILED(rv)) 1.374 + return false; // Not just absence of principal, but failure. 1.375 + 1.376 + if (!subjectPrincipal) 1.377 + return true; 1.378 + 1.379 + nsCOMPtr<nsIContentSecurityPolicy> csp; 1.380 + rv = subjectPrincipal->GetCsp(getter_AddRefs(csp)); 1.381 + NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get CSP from principal."); 1.382 + 1.383 + // don't do anything unless there's a CSP 1.384 + if (!csp) 1.385 + return true; 1.386 + 1.387 + bool evalOK = true; 1.388 + bool reportViolation = false; 1.389 + rv = csp->GetAllowsEval(&reportViolation, &evalOK); 1.390 + 1.391 + if (NS_FAILED(rv)) 1.392 + { 1.393 + NS_WARNING("CSP: failed to get allowsEval"); 1.394 + return true; // fail open to not break sites. 1.395 + } 1.396 + 1.397 + if (reportViolation) { 1.398 + nsAutoString fileName; 1.399 + unsigned lineNum = 0; 1.400 + NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP"); 1.401 + 1.402 + JS::AutoFilename scriptFilename; 1.403 + if (JS::DescribeScriptedCaller(cx, &scriptFilename, &lineNum)) { 1.404 + if (const char *file = scriptFilename.get()) { 1.405 + CopyUTF8toUTF16(nsDependentCString(file), fileName); 1.406 + } 1.407 + } 1.408 + csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL, 1.409 + fileName, 1.410 + scriptSample, 1.411 + lineNum, 1.412 + EmptyString(), 1.413 + EmptyString()); 1.414 + } 1.415 + 1.416 + return evalOK; 1.417 +} 1.418 + 1.419 +// static 1.420 +bool 1.421 +nsScriptSecurityManager::JSPrincipalsSubsume(JSPrincipals *first, 1.422 + JSPrincipals *second) 1.423 +{ 1.424 + return nsJSPrincipals::get(first)->Subsumes(nsJSPrincipals::get(second)); 1.425 +} 1.426 + 1.427 +NS_IMETHODIMP 1.428 +nsScriptSecurityManager::CheckSameOrigin(JSContext* cx, 1.429 + nsIURI* aTargetURI) 1.430 +{ 1.431 + nsresult rv; 1.432 + 1.433 + // Get a context if necessary 1.434 + if (!cx) 1.435 + { 1.436 + cx = GetCurrentJSContext(); 1.437 + if (!cx) 1.438 + return NS_OK; // No JS context, so allow access 1.439 + } 1.440 + 1.441 + // Get a principal from the context 1.442 + nsIPrincipal* sourcePrincipal = GetSubjectPrincipal(cx, &rv); 1.443 + if (NS_FAILED(rv)) 1.444 + return rv; 1.445 + 1.446 + if (!sourcePrincipal) 1.447 + { 1.448 + NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?"); 1.449 + return NS_OK; 1.450 + } 1.451 + 1.452 + if (sourcePrincipal == mSystemPrincipal) 1.453 + { 1.454 + // This is a system (chrome) script, so allow access 1.455 + return NS_OK; 1.456 + } 1.457 + 1.458 + // Get the original URI from the source principal. 1.459 + // This has the effect of ignoring any change to document.domain 1.460 + // which must be done to avoid DNS spoofing (bug 154930) 1.461 + nsCOMPtr<nsIURI> sourceURI; 1.462 + sourcePrincipal->GetDomain(getter_AddRefs(sourceURI)); 1.463 + if (!sourceURI) { 1.464 + sourcePrincipal->GetURI(getter_AddRefs(sourceURI)); 1.465 + NS_ENSURE_TRUE(sourceURI, NS_ERROR_FAILURE); 1.466 + } 1.467 + 1.468 + // Compare origins 1.469 + if (!SecurityCompareURIs(sourceURI, aTargetURI)) 1.470 + { 1.471 + ReportError(cx, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI, aTargetURI); 1.472 + return NS_ERROR_DOM_BAD_URI; 1.473 + } 1.474 + return NS_OK; 1.475 +} 1.476 + 1.477 +NS_IMETHODIMP 1.478 +nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI, 1.479 + nsIURI* aTargetURI, 1.480 + bool reportError) 1.481 +{ 1.482 + if (!SecurityCompareURIs(aSourceURI, aTargetURI)) 1.483 + { 1.484 + if (reportError) { 1.485 + ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), 1.486 + aSourceURI, aTargetURI); 1.487 + } 1.488 + return NS_ERROR_DOM_BAD_URI; 1.489 + } 1.490 + return NS_OK; 1.491 +} 1.492 + 1.493 +/*static*/ uint32_t 1.494 +nsScriptSecurityManager::HashPrincipalByOrigin(nsIPrincipal* aPrincipal) 1.495 +{ 1.496 + nsCOMPtr<nsIURI> uri; 1.497 + aPrincipal->GetDomain(getter_AddRefs(uri)); 1.498 + if (!uri) 1.499 + aPrincipal->GetURI(getter_AddRefs(uri)); 1.500 + return SecurityHashURI(uri); 1.501 +} 1.502 + 1.503 +/* static */ bool 1.504 +nsScriptSecurityManager::AppAttributesEqual(nsIPrincipal* aFirst, 1.505 + nsIPrincipal* aSecond) 1.506 +{ 1.507 + MOZ_ASSERT(aFirst && aSecond, "Don't pass null pointers!"); 1.508 + 1.509 + uint32_t firstAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID; 1.510 + if (!aFirst->GetUnknownAppId()) { 1.511 + firstAppId = aFirst->GetAppId(); 1.512 + } 1.513 + 1.514 + uint32_t secondAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID; 1.515 + if (!aSecond->GetUnknownAppId()) { 1.516 + secondAppId = aSecond->GetAppId(); 1.517 + } 1.518 + 1.519 + return ((firstAppId == secondAppId) && 1.520 + (aFirst->GetIsInBrowserElement() == aSecond->GetIsInBrowserElement())); 1.521 +} 1.522 + 1.523 +NS_IMETHODIMP 1.524 +nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI) 1.525 +{ 1.526 + // Get principal of currently executing script. 1.527 + nsresult rv; 1.528 + nsIPrincipal* principal = GetSubjectPrincipal(cx, &rv); 1.529 + if (NS_FAILED(rv)) 1.530 + return rv; 1.531 + 1.532 + // Native code can load all URIs. 1.533 + if (!principal) 1.534 + return NS_OK; 1.535 + 1.536 + rv = CheckLoadURIWithPrincipal(principal, aURI, 1.537 + nsIScriptSecurityManager::STANDARD); 1.538 + if (NS_SUCCEEDED(rv)) { 1.539 + // OK to load 1.540 + return NS_OK; 1.541 + } 1.542 + 1.543 + // See if we're attempting to load a file: URI. If so, let a 1.544 + // UniversalXPConnect capability trump the above check. 1.545 + bool isFile = false; 1.546 + bool isRes = false; 1.547 + if (NS_FAILED(aURI->SchemeIs("file", &isFile)) || 1.548 + NS_FAILED(aURI->SchemeIs("resource", &isRes))) 1.549 + return NS_ERROR_FAILURE; 1.550 + if (isFile || isRes) 1.551 + { 1.552 + if (SubjectIsPrivileged()) 1.553 + return NS_OK; 1.554 + } 1.555 + 1.556 + // Report error. 1.557 + nsAutoCString spec; 1.558 + if (NS_FAILED(aURI->GetAsciiSpec(spec))) 1.559 + return NS_ERROR_FAILURE; 1.560 + nsAutoCString msg("Access to '"); 1.561 + msg.Append(spec); 1.562 + msg.AppendLiteral("' from script denied"); 1.563 + SetPendingException(cx, msg.get()); 1.564 + return NS_ERROR_DOM_BAD_URI; 1.565 +} 1.566 + 1.567 +/** 1.568 + * Helper method to handle cases where a flag passed to 1.569 + * CheckLoadURIWithPrincipal means denying loading if the given URI has certain 1.570 + * nsIProtocolHandler flags set. 1.571 + * @return if success, access is allowed. Otherwise, deny access 1.572 + */ 1.573 +static nsresult 1.574 +DenyAccessIfURIHasFlags(nsIURI* aURI, uint32_t aURIFlags) 1.575 +{ 1.576 + NS_PRECONDITION(aURI, "Must have URI!"); 1.577 + 1.578 + bool uriHasFlags; 1.579 + nsresult rv = 1.580 + NS_URIChainHasFlags(aURI, aURIFlags, &uriHasFlags); 1.581 + NS_ENSURE_SUCCESS(rv, rv); 1.582 + 1.583 + if (uriHasFlags) { 1.584 + return NS_ERROR_DOM_BAD_URI; 1.585 + } 1.586 + 1.587 + return NS_OK; 1.588 +} 1.589 + 1.590 +static bool 1.591 +EqualOrSubdomain(nsIURI* aProbeArg, nsIURI* aBase) 1.592 +{ 1.593 + // Make a clone of the incoming URI, because we're going to mutate it. 1.594 + nsCOMPtr<nsIURI> probe; 1.595 + nsresult rv = aProbeArg->Clone(getter_AddRefs(probe)); 1.596 + NS_ENSURE_SUCCESS(rv, false); 1.597 + 1.598 + nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); 1.599 + NS_ENSURE_TRUE(tldService, false); 1.600 + while (true) { 1.601 + if (nsScriptSecurityManager::SecurityCompareURIs(probe, aBase)) { 1.602 + return true; 1.603 + } 1.604 + 1.605 + nsAutoCString host, newHost; 1.606 + nsresult rv = probe->GetHost(host); 1.607 + NS_ENSURE_SUCCESS(rv, false); 1.608 + 1.609 + rv = tldService->GetNextSubDomain(host, newHost); 1.610 + if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) { 1.611 + return false; 1.612 + } 1.613 + NS_ENSURE_SUCCESS(rv, false); 1.614 + rv = probe->SetHost(newHost); 1.615 + NS_ENSURE_SUCCESS(rv, false); 1.616 + } 1.617 +} 1.618 + 1.619 +NS_IMETHODIMP 1.620 +nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal, 1.621 + nsIURI *aTargetURI, 1.622 + uint32_t aFlags) 1.623 +{ 1.624 + NS_PRECONDITION(aPrincipal, "CheckLoadURIWithPrincipal must have a principal"); 1.625 + // If someone passes a flag that we don't understand, we should 1.626 + // fail, because they may need a security check that we don't 1.627 + // provide. 1.628 + NS_ENSURE_FALSE(aFlags & ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT | 1.629 + nsIScriptSecurityManager::ALLOW_CHROME | 1.630 + nsIScriptSecurityManager::DISALLOW_SCRIPT | 1.631 + nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL | 1.632 + nsIScriptSecurityManager::DONT_REPORT_ERRORS), 1.633 + NS_ERROR_UNEXPECTED); 1.634 + NS_ENSURE_ARG_POINTER(aPrincipal); 1.635 + NS_ENSURE_ARG_POINTER(aTargetURI); 1.636 + 1.637 + // If DISALLOW_INHERIT_PRINCIPAL is set, we prevent loading of URIs which 1.638 + // would do such inheriting. That would be URIs that do not have their own 1.639 + // security context. We do this even for the system principal. 1.640 + if (aFlags & nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL) { 1.641 + nsresult rv = 1.642 + DenyAccessIfURIHasFlags(aTargetURI, 1.643 + nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT); 1.644 + NS_ENSURE_SUCCESS(rv, rv); 1.645 + } 1.646 + 1.647 + if (aPrincipal == mSystemPrincipal) { 1.648 + // Allow access 1.649 + return NS_OK; 1.650 + } 1.651 + 1.652 + nsCOMPtr<nsIURI> sourceURI; 1.653 + aPrincipal->GetURI(getter_AddRefs(sourceURI)); 1.654 + if (!sourceURI) { 1.655 + nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aPrincipal); 1.656 + if (expanded) { 1.657 + nsTArray< nsCOMPtr<nsIPrincipal> > *whiteList; 1.658 + expanded->GetWhiteList(&whiteList); 1.659 + for (uint32_t i = 0; i < whiteList->Length(); ++i) { 1.660 + nsresult rv = CheckLoadURIWithPrincipal((*whiteList)[i], 1.661 + aTargetURI, 1.662 + aFlags); 1.663 + if (NS_SUCCEEDED(rv)) { 1.664 + // Allow access if it succeeded with one of the white listed principals 1.665 + return NS_OK; 1.666 + } 1.667 + } 1.668 + // None of our whitelisted principals worked. 1.669 + return NS_ERROR_DOM_BAD_URI; 1.670 + } 1.671 + NS_ERROR("Non-system principals or expanded principal passed to CheckLoadURIWithPrincipal " 1.672 + "must have a URI!"); 1.673 + return NS_ERROR_UNEXPECTED; 1.674 + } 1.675 + 1.676 + // Automatic loads are not allowed from certain protocols. 1.677 + if (aFlags & nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT) { 1.678 + nsresult rv = 1.679 + DenyAccessIfURIHasFlags(sourceURI, 1.680 + nsIProtocolHandler::URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT); 1.681 + NS_ENSURE_SUCCESS(rv, rv); 1.682 + } 1.683 + 1.684 + // If either URI is a nested URI, get the base URI 1.685 + nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(sourceURI); 1.686 + nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI); 1.687 + 1.688 + //-- get the target scheme 1.689 + nsAutoCString targetScheme; 1.690 + nsresult rv = targetBaseURI->GetScheme(targetScheme); 1.691 + if (NS_FAILED(rv)) return rv; 1.692 + 1.693 + //-- Some callers do not allow loading javascript: 1.694 + if ((aFlags & nsIScriptSecurityManager::DISALLOW_SCRIPT) && 1.695 + targetScheme.EqualsLiteral("javascript")) 1.696 + { 1.697 + return NS_ERROR_DOM_BAD_URI; 1.698 + } 1.699 + 1.700 + NS_NAMED_LITERAL_STRING(errorTag, "CheckLoadURIError"); 1.701 + bool reportErrors = !(aFlags & nsIScriptSecurityManager::DONT_REPORT_ERRORS); 1.702 + 1.703 + // Check for uris that are only loadable by principals that subsume them 1.704 + bool hasFlags; 1.705 + rv = NS_URIChainHasFlags(targetBaseURI, 1.706 + nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS, 1.707 + &hasFlags); 1.708 + NS_ENSURE_SUCCESS(rv, rv); 1.709 + 1.710 + if (hasFlags) { 1.711 + return aPrincipal->CheckMayLoad(targetBaseURI, true, false); 1.712 + } 1.713 + 1.714 + //-- get the source scheme 1.715 + nsAutoCString sourceScheme; 1.716 + rv = sourceBaseURI->GetScheme(sourceScheme); 1.717 + if (NS_FAILED(rv)) return rv; 1.718 + 1.719 + if (sourceScheme.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME)) { 1.720 + // A null principal can target its own URI. 1.721 + if (sourceURI == aTargetURI) { 1.722 + return NS_OK; 1.723 + } 1.724 + } 1.725 + else if (targetScheme.Equals(sourceScheme, 1.726 + nsCaseInsensitiveCStringComparator())) 1.727 + { 1.728 + // every scheme can access another URI from the same scheme, 1.729 + // as long as they don't represent null principals... 1.730 + // Or they don't require an special permission to do so 1.731 + // See bug#773886 1.732 + 1.733 + bool hasFlags; 1.734 + rv = NS_URIChainHasFlags(targetBaseURI, 1.735 + nsIProtocolHandler::URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM, 1.736 + &hasFlags); 1.737 + NS_ENSURE_SUCCESS(rv, rv); 1.738 + 1.739 + if (hasFlags) { 1.740 + // In this case, we allow opening only if the source and target URIS 1.741 + // are on the same domain, or the opening URI has the webapps 1.742 + // permision granted 1.743 + if (!SecurityCompareURIs(sourceBaseURI,targetBaseURI) && 1.744 + !nsContentUtils::IsExactSitePermAllow(aPrincipal,WEBAPPS_PERM_NAME)){ 1.745 + return NS_ERROR_DOM_BAD_URI; 1.746 + } 1.747 + } 1.748 + return NS_OK; 1.749 + } 1.750 + 1.751 + // If the schemes don't match, the policy is specified by the protocol 1.752 + // flags on the target URI. Note that the order of policy checks here is 1.753 + // very important! We start from most restrictive and work our way down. 1.754 + // Note that since we're working with the innermost URI, we can just use 1.755 + // the methods that work on chains of nested URIs and they will only look 1.756 + // at the flags for our one URI. 1.757 + 1.758 + // Check for system target URI 1.759 + rv = DenyAccessIfURIHasFlags(targetBaseURI, 1.760 + nsIProtocolHandler::URI_DANGEROUS_TO_LOAD); 1.761 + if (NS_FAILED(rv)) { 1.762 + // Deny access, since the origin principal is not system 1.763 + if (reportErrors) { 1.764 + ReportError(nullptr, errorTag, sourceURI, aTargetURI); 1.765 + } 1.766 + return rv; 1.767 + } 1.768 + 1.769 + // Check for chrome target URI 1.770 + rv = NS_URIChainHasFlags(targetBaseURI, 1.771 + nsIProtocolHandler::URI_IS_UI_RESOURCE, 1.772 + &hasFlags); 1.773 + NS_ENSURE_SUCCESS(rv, rv); 1.774 + if (hasFlags) { 1.775 + if (aFlags & nsIScriptSecurityManager::ALLOW_CHROME) { 1.776 + if (!targetScheme.EqualsLiteral("chrome")) { 1.777 + // for now don't change behavior for resource: or moz-icon: 1.778 + return NS_OK; 1.779 + } 1.780 + 1.781 + // allow load only if chrome package is whitelisted 1.782 + nsCOMPtr<nsIXULChromeRegistry> reg(do_GetService( 1.783 + NS_CHROMEREGISTRY_CONTRACTID)); 1.784 + if (reg) { 1.785 + bool accessAllowed = false; 1.786 + reg->AllowContentToAccess(targetBaseURI, &accessAllowed); 1.787 + if (accessAllowed) { 1.788 + return NS_OK; 1.789 + } 1.790 + } 1.791 + } 1.792 + 1.793 + // resource: and chrome: are equivalent, securitywise 1.794 + // That's bogus!! Fix this. But watch out for 1.795 + // the view-source stylesheet? 1.796 + bool sourceIsChrome; 1.797 + rv = NS_URIChainHasFlags(sourceBaseURI, 1.798 + nsIProtocolHandler::URI_IS_UI_RESOURCE, 1.799 + &sourceIsChrome); 1.800 + NS_ENSURE_SUCCESS(rv, rv); 1.801 + if (sourceIsChrome) { 1.802 + return NS_OK; 1.803 + } 1.804 + if (reportErrors) { 1.805 + ReportError(nullptr, errorTag, sourceURI, aTargetURI); 1.806 + } 1.807 + return NS_ERROR_DOM_BAD_URI; 1.808 + } 1.809 + 1.810 + // Check for target URI pointing to a file 1.811 + rv = NS_URIChainHasFlags(targetBaseURI, 1.812 + nsIProtocolHandler::URI_IS_LOCAL_FILE, 1.813 + &hasFlags); 1.814 + NS_ENSURE_SUCCESS(rv, rv); 1.815 + if (hasFlags) { 1.816 + // Allow domains that were whitelisted in the prefs. In 99.9% of cases, 1.817 + // this array is empty. 1.818 + for (size_t i = 0; i < mFileURIWhitelist.Length(); ++i) { 1.819 + if (EqualOrSubdomain(sourceURI, mFileURIWhitelist[i])) { 1.820 + return NS_OK; 1.821 + } 1.822 + } 1.823 + 1.824 + // resource: and chrome: are equivalent, securitywise 1.825 + // That's bogus!! Fix this. But watch out for 1.826 + // the view-source stylesheet? 1.827 + bool sourceIsChrome; 1.828 + rv = NS_URIChainHasFlags(sourceURI, 1.829 + nsIProtocolHandler::URI_IS_UI_RESOURCE, 1.830 + &sourceIsChrome); 1.831 + NS_ENSURE_SUCCESS(rv, rv); 1.832 + if (sourceIsChrome) { 1.833 + return NS_OK; 1.834 + } 1.835 + 1.836 + if (reportErrors) { 1.837 + ReportError(nullptr, errorTag, sourceURI, aTargetURI); 1.838 + } 1.839 + return NS_ERROR_DOM_BAD_URI; 1.840 + } 1.841 + 1.842 + // OK, everyone is allowed to load this, since unflagged handlers are 1.843 + // deprecated but treated as URI_LOADABLE_BY_ANYONE. But check whether we 1.844 + // need to warn. At some point we'll want to make this warning into an 1.845 + // error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD. 1.846 + rv = NS_URIChainHasFlags(targetBaseURI, 1.847 + nsIProtocolHandler::URI_LOADABLE_BY_ANYONE, 1.848 + &hasFlags); 1.849 + NS_ENSURE_SUCCESS(rv, rv); 1.850 + if (!hasFlags) { 1.851 + nsXPIDLString message; 1.852 + NS_ConvertASCIItoUTF16 ucsTargetScheme(targetScheme); 1.853 + const char16_t* formatStrings[] = { ucsTargetScheme.get() }; 1.854 + rv = sStrBundle-> 1.855 + FormatStringFromName(MOZ_UTF16("ProtocolFlagError"), 1.856 + formatStrings, 1.857 + ArrayLength(formatStrings), 1.858 + getter_Copies(message)); 1.859 + if (NS_SUCCEEDED(rv)) { 1.860 + nsCOMPtr<nsIConsoleService> console( 1.861 + do_GetService("@mozilla.org/consoleservice;1")); 1.862 + NS_ENSURE_TRUE(console, NS_ERROR_FAILURE); 1.863 + 1.864 + console->LogStringMessage(message.get()); 1.865 + } 1.866 + } 1.867 + 1.868 + return NS_OK; 1.869 +} 1.870 + 1.871 +nsresult 1.872 +nsScriptSecurityManager::ReportError(JSContext* cx, const nsAString& messageTag, 1.873 + nsIURI* aSource, nsIURI* aTarget) 1.874 +{ 1.875 + nsresult rv; 1.876 + NS_ENSURE_TRUE(aSource && aTarget, NS_ERROR_NULL_POINTER); 1.877 + 1.878 + // Get the source URL spec 1.879 + nsAutoCString sourceSpec; 1.880 + rv = aSource->GetAsciiSpec(sourceSpec); 1.881 + NS_ENSURE_SUCCESS(rv, rv); 1.882 + 1.883 + // Get the target URL spec 1.884 + nsAutoCString targetSpec; 1.885 + rv = aTarget->GetAsciiSpec(targetSpec); 1.886 + NS_ENSURE_SUCCESS(rv, rv); 1.887 + 1.888 + // Localize the error message 1.889 + nsXPIDLString message; 1.890 + NS_ConvertASCIItoUTF16 ucsSourceSpec(sourceSpec); 1.891 + NS_ConvertASCIItoUTF16 ucsTargetSpec(targetSpec); 1.892 + const char16_t *formatStrings[] = { ucsSourceSpec.get(), ucsTargetSpec.get() }; 1.893 + rv = sStrBundle->FormatStringFromName(PromiseFlatString(messageTag).get(), 1.894 + formatStrings, 1.895 + ArrayLength(formatStrings), 1.896 + getter_Copies(message)); 1.897 + NS_ENSURE_SUCCESS(rv, rv); 1.898 + 1.899 + // If a JS context was passed in, set a JS exception. 1.900 + // Otherwise, print the error message directly to the JS console 1.901 + // and to standard output 1.902 + if (cx) 1.903 + { 1.904 + SetPendingException(cx, message.get()); 1.905 + } 1.906 + else // Print directly to the console 1.907 + { 1.908 + nsCOMPtr<nsIConsoleService> console( 1.909 + do_GetService("@mozilla.org/consoleservice;1")); 1.910 + NS_ENSURE_TRUE(console, NS_ERROR_FAILURE); 1.911 + 1.912 + console->LogStringMessage(message.get()); 1.913 + } 1.914 + return NS_OK; 1.915 +} 1.916 + 1.917 +NS_IMETHODIMP 1.918 +nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal* aPrincipal, 1.919 + const nsACString& aTargetURIStr, 1.920 + uint32_t aFlags) 1.921 +{ 1.922 + nsresult rv; 1.923 + nsCOMPtr<nsIURI> target; 1.924 + rv = NS_NewURI(getter_AddRefs(target), aTargetURIStr, 1.925 + nullptr, nullptr, sIOService); 1.926 + NS_ENSURE_SUCCESS(rv, rv); 1.927 + 1.928 + rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags); 1.929 + if (rv == NS_ERROR_DOM_BAD_URI) { 1.930 + // Don't warn because NS_ERROR_DOM_BAD_URI is one of the expected 1.931 + // return values. 1.932 + return rv; 1.933 + } 1.934 + NS_ENSURE_SUCCESS(rv, rv); 1.935 + 1.936 + // Now start testing fixup -- since aTargetURIStr is a string, not 1.937 + // an nsIURI, we may well end up fixing it up before loading. 1.938 + // Note: This needs to stay in sync with the nsIURIFixup api. 1.939 + nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID); 1.940 + if (!fixup) { 1.941 + return rv; 1.942 + } 1.943 + 1.944 + uint32_t flags[] = { 1.945 + nsIURIFixup::FIXUP_FLAG_NONE, 1.946 + nsIURIFixup::FIXUP_FLAG_FIX_SCHEME_TYPOS, 1.947 + nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP, 1.948 + nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI, 1.949 + nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP | 1.950 + nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI 1.951 + }; 1.952 + 1.953 + for (uint32_t i = 0; i < ArrayLength(flags); ++i) { 1.954 + rv = fixup->CreateFixupURI(aTargetURIStr, flags[i], nullptr, 1.955 + getter_AddRefs(target)); 1.956 + NS_ENSURE_SUCCESS(rv, rv); 1.957 + 1.958 + rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags); 1.959 + if (rv == NS_ERROR_DOM_BAD_URI) { 1.960 + // Don't warn because NS_ERROR_DOM_BAD_URI is one of the expected 1.961 + // return values. 1.962 + return rv; 1.963 + } 1.964 + NS_ENSURE_SUCCESS(rv, rv); 1.965 + } 1.966 + 1.967 + return rv; 1.968 +} 1.969 + 1.970 +bool 1.971 +nsScriptSecurityManager::ScriptAllowed(JSObject *aGlobal) 1.972 +{ 1.973 + MOZ_ASSERT(aGlobal); 1.974 + MOZ_ASSERT(JS_IsGlobalObject(aGlobal) || js::IsOuterObject(aGlobal)); 1.975 + AutoJSContext cx; 1.976 + JS::RootedObject global(cx, js::UncheckedUnwrap(aGlobal, /* stopAtOuter = */ false)); 1.977 + 1.978 + // Check the bits on the compartment private. 1.979 + return xpc::Scriptability::Get(aGlobal).Allowed(); 1.980 +} 1.981 + 1.982 +///////////////// Principals /////////////////////// 1.983 +NS_IMETHODIMP 1.984 +nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal **aSubjectPrincipal) 1.985 +{ 1.986 + nsresult rv; 1.987 + *aSubjectPrincipal = doGetSubjectPrincipal(&rv); 1.988 + if (NS_SUCCEEDED(rv)) 1.989 + NS_IF_ADDREF(*aSubjectPrincipal); 1.990 + return rv; 1.991 +} 1.992 + 1.993 +nsIPrincipal* 1.994 +nsScriptSecurityManager::doGetSubjectPrincipal(nsresult* rv) 1.995 +{ 1.996 + NS_PRECONDITION(rv, "Null out param"); 1.997 + JSContext *cx = GetCurrentJSContext(); 1.998 + if (!cx) 1.999 + { 1.1000 + *rv = NS_OK; 1.1001 + return nullptr; 1.1002 + } 1.1003 + return GetSubjectPrincipal(cx, rv); 1.1004 +} 1.1005 + 1.1006 +NS_IMETHODIMP 1.1007 +nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result) 1.1008 +{ 1.1009 + NS_ADDREF(*result = mSystemPrincipal); 1.1010 + 1.1011 + return NS_OK; 1.1012 +} 1.1013 + 1.1014 +NS_IMETHODIMP 1.1015 +nsScriptSecurityManager::SubjectPrincipalIsSystem(bool* aIsSystem) 1.1016 +{ 1.1017 + NS_ENSURE_ARG_POINTER(aIsSystem); 1.1018 + *aIsSystem = false; 1.1019 + 1.1020 + if (!mSystemPrincipal) 1.1021 + return NS_OK; 1.1022 + 1.1023 + nsCOMPtr<nsIPrincipal> subject; 1.1024 + nsresult rv = GetSubjectPrincipal(getter_AddRefs(subject)); 1.1025 + if (NS_FAILED(rv)) 1.1026 + return rv; 1.1027 + 1.1028 + if(!subject) 1.1029 + { 1.1030 + // No subject principal means no JS is running; 1.1031 + // this is the equivalent of system principal code 1.1032 + *aIsSystem = true; 1.1033 + return NS_OK; 1.1034 + } 1.1035 + 1.1036 + return mSystemPrincipal->Equals(subject, aIsSystem); 1.1037 +} 1.1038 + 1.1039 +nsresult 1.1040 +nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId, 1.1041 + bool aInMozBrowser, 1.1042 + nsIPrincipal **result) 1.1043 +{ 1.1044 + // I _think_ it's safe to not create null principals here based on aURI. 1.1045 + // At least all the callers would do the right thing in those cases, as far 1.1046 + // as I can tell. --bz 1.1047 + 1.1048 + nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI); 1.1049 + if (uriPrinc) { 1.1050 + nsCOMPtr<nsIPrincipal> principal; 1.1051 + uriPrinc->GetPrincipal(getter_AddRefs(principal)); 1.1052 + if (!principal || principal == mSystemPrincipal) { 1.1053 + return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID, result); 1.1054 + } 1.1055 + 1.1056 + principal.forget(result); 1.1057 + 1.1058 + return NS_OK; 1.1059 + } 1.1060 + 1.1061 + nsRefPtr<nsPrincipal> codebase = new nsPrincipal(); 1.1062 + if (!codebase) 1.1063 + return NS_ERROR_OUT_OF_MEMORY; 1.1064 + 1.1065 + nsresult rv = codebase->Init(aURI, aAppId, aInMozBrowser); 1.1066 + if (NS_FAILED(rv)) 1.1067 + return rv; 1.1068 + 1.1069 + NS_ADDREF(*result = codebase); 1.1070 + 1.1071 + return NS_OK; 1.1072 +} 1.1073 + 1.1074 +NS_IMETHODIMP 1.1075 +nsScriptSecurityManager::GetSimpleCodebasePrincipal(nsIURI* aURI, 1.1076 + nsIPrincipal** aPrincipal) 1.1077 +{ 1.1078 + return GetCodebasePrincipalInternal(aURI, 1.1079 + nsIScriptSecurityManager::UNKNOWN_APP_ID, 1.1080 + false, aPrincipal); 1.1081 +} 1.1082 + 1.1083 +NS_IMETHODIMP 1.1084 +nsScriptSecurityManager::GetNoAppCodebasePrincipal(nsIURI* aURI, 1.1085 + nsIPrincipal** aPrincipal) 1.1086 +{ 1.1087 + return GetCodebasePrincipalInternal(aURI, nsIScriptSecurityManager::NO_APP_ID, 1.1088 + false, aPrincipal); 1.1089 +} 1.1090 + 1.1091 +NS_IMETHODIMP 1.1092 +nsScriptSecurityManager::GetCodebasePrincipal(nsIURI* aURI, 1.1093 + nsIPrincipal** aPrincipal) 1.1094 +{ 1.1095 + return GetNoAppCodebasePrincipal(aURI, aPrincipal); 1.1096 +} 1.1097 + 1.1098 +NS_IMETHODIMP 1.1099 +nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI, 1.1100 + uint32_t aAppId, 1.1101 + bool aInMozBrowser, 1.1102 + nsIPrincipal** aPrincipal) 1.1103 +{ 1.1104 + NS_ENSURE_TRUE(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, 1.1105 + NS_ERROR_INVALID_ARG); 1.1106 + 1.1107 + return GetCodebasePrincipalInternal(aURI, aAppId, aInMozBrowser, aPrincipal); 1.1108 +} 1.1109 + 1.1110 +NS_IMETHODIMP 1.1111 +nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI, 1.1112 + nsIDocShell* aDocShell, 1.1113 + nsIPrincipal** aPrincipal) 1.1114 +{ 1.1115 + return GetCodebasePrincipalInternal(aURI, 1.1116 + aDocShell->GetAppId(), 1.1117 + aDocShell->GetIsInBrowserElement(), 1.1118 + aPrincipal); 1.1119 +} 1.1120 + 1.1121 +nsresult 1.1122 +nsScriptSecurityManager::GetCodebasePrincipalInternal(nsIURI *aURI, 1.1123 + uint32_t aAppId, 1.1124 + bool aInMozBrowser, 1.1125 + nsIPrincipal **result) 1.1126 +{ 1.1127 + NS_ENSURE_ARG(aURI); 1.1128 + 1.1129 + bool inheritsPrincipal; 1.1130 + nsresult rv = 1.1131 + NS_URIChainHasFlags(aURI, 1.1132 + nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, 1.1133 + &inheritsPrincipal); 1.1134 + if (NS_FAILED(rv) || inheritsPrincipal) { 1.1135 + return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID, result); 1.1136 + } 1.1137 + 1.1138 + nsCOMPtr<nsIPrincipal> principal; 1.1139 + rv = CreateCodebasePrincipal(aURI, aAppId, aInMozBrowser, 1.1140 + getter_AddRefs(principal)); 1.1141 + NS_ENSURE_SUCCESS(rv, rv); 1.1142 + NS_IF_ADDREF(*result = principal); 1.1143 + 1.1144 + return NS_OK; 1.1145 +} 1.1146 + 1.1147 +nsIPrincipal* 1.1148 +nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx, 1.1149 + nsresult* rv) 1.1150 +{ 1.1151 + *rv = NS_OK; 1.1152 + JSCompartment *compartment = js::GetContextCompartment(cx); 1.1153 + 1.1154 + // The context should always be in a compartment, either one it has entered 1.1155 + // or the one associated with its global. 1.1156 + MOZ_ASSERT(!!compartment); 1.1157 + 1.1158 + JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment); 1.1159 + return nsJSPrincipals::get(principals); 1.1160 +} 1.1161 + 1.1162 +// static 1.1163 +nsIPrincipal* 1.1164 +nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj) 1.1165 +{ 1.1166 + JSCompartment *compartment = js::GetObjectCompartment(aObj); 1.1167 + JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment); 1.1168 + return nsJSPrincipals::get(principals); 1.1169 +} 1.1170 + 1.1171 +//////////////////////////////////////////////// 1.1172 +// Methods implementing nsIXPCSecurityManager // 1.1173 +//////////////////////////////////////////////// 1.1174 + 1.1175 +NS_IMETHODIMP 1.1176 +nsScriptSecurityManager::CanCreateWrapper(JSContext *cx, 1.1177 + const nsIID &aIID, 1.1178 + nsISupports *aObj, 1.1179 + nsIClassInfo *aClassInfo) 1.1180 +{ 1.1181 +// XXX Special case for nsIXPCException ? 1.1182 + ClassInfoData objClassInfo = ClassInfoData(aClassInfo, nullptr); 1.1183 + if (objClassInfo.IsDOMClass()) 1.1184 + { 1.1185 + return NS_OK; 1.1186 + } 1.1187 + 1.1188 + // We give remote-XUL whitelisted domains a free pass here. See bug 932906. 1.1189 + if (!xpc::AllowXBLScope(js::GetContextCompartment(cx))) 1.1190 + { 1.1191 + return NS_OK; 1.1192 + } 1.1193 + 1.1194 + if (SubjectIsPrivileged()) 1.1195 + { 1.1196 + return NS_OK; 1.1197 + } 1.1198 + 1.1199 + //-- Access denied, report an error 1.1200 + NS_ConvertUTF8toUTF16 strName("CreateWrapperDenied"); 1.1201 + nsAutoCString origin; 1.1202 + nsresult rv2; 1.1203 + nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv2); 1.1204 + if (NS_SUCCEEDED(rv2) && subjectPrincipal) { 1.1205 + GetPrincipalDomainOrigin(subjectPrincipal, origin); 1.1206 + } 1.1207 + NS_ConvertUTF8toUTF16 originUnicode(origin); 1.1208 + NS_ConvertUTF8toUTF16 classInfoName(objClassInfo.GetName()); 1.1209 + const char16_t* formatStrings[] = { 1.1210 + classInfoName.get(), 1.1211 + originUnicode.get() 1.1212 + }; 1.1213 + uint32_t length = ArrayLength(formatStrings); 1.1214 + if (originUnicode.IsEmpty()) { 1.1215 + --length; 1.1216 + } else { 1.1217 + strName.AppendLiteral("ForOrigin"); 1.1218 + } 1.1219 + nsXPIDLString errorMsg; 1.1220 + // We need to keep our existing failure rv and not override it 1.1221 + // with a likely success code from the following string bundle 1.1222 + // call in order to throw the correct security exception later. 1.1223 + rv2 = sStrBundle->FormatStringFromName(strName.get(), 1.1224 + formatStrings, 1.1225 + length, 1.1226 + getter_Copies(errorMsg)); 1.1227 + NS_ENSURE_SUCCESS(rv2, rv2); 1.1228 + 1.1229 + SetPendingException(cx, errorMsg.get()); 1.1230 + return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; 1.1231 +} 1.1232 + 1.1233 +NS_IMETHODIMP 1.1234 +nsScriptSecurityManager::CanCreateInstance(JSContext *cx, 1.1235 + const nsCID &aCID) 1.1236 +{ 1.1237 + if (SubjectIsPrivileged()) { 1.1238 + return NS_OK; 1.1239 + } 1.1240 + 1.1241 + //-- Access denied, report an error 1.1242 + nsAutoCString errorMsg("Permission denied to create instance of class. CID="); 1.1243 + char cidStr[NSID_LENGTH]; 1.1244 + aCID.ToProvidedString(cidStr); 1.1245 + errorMsg.Append(cidStr); 1.1246 + SetPendingException(cx, errorMsg.get()); 1.1247 + return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; 1.1248 +} 1.1249 + 1.1250 +NS_IMETHODIMP 1.1251 +nsScriptSecurityManager::CanGetService(JSContext *cx, 1.1252 + const nsCID &aCID) 1.1253 +{ 1.1254 + if (SubjectIsPrivileged()) { 1.1255 + return NS_OK; 1.1256 + } 1.1257 + 1.1258 + //-- Access denied, report an error 1.1259 + nsAutoCString errorMsg("Permission denied to get service. CID="); 1.1260 + char cidStr[NSID_LENGTH]; 1.1261 + aCID.ToProvidedString(cidStr); 1.1262 + errorMsg.Append(cidStr); 1.1263 + SetPendingException(cx, errorMsg.get()); 1.1264 + return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; 1.1265 +} 1.1266 + 1.1267 +///////////////////////////////////////////// 1.1268 +// Method implementing nsIChannelEventSink // 1.1269 +///////////////////////////////////////////// 1.1270 +NS_IMETHODIMP 1.1271 +nsScriptSecurityManager::AsyncOnChannelRedirect(nsIChannel* oldChannel, 1.1272 + nsIChannel* newChannel, 1.1273 + uint32_t redirFlags, 1.1274 + nsIAsyncVerifyRedirectCallback *cb) 1.1275 +{ 1.1276 + nsCOMPtr<nsIPrincipal> oldPrincipal; 1.1277 + GetChannelPrincipal(oldChannel, getter_AddRefs(oldPrincipal)); 1.1278 + 1.1279 + nsCOMPtr<nsIURI> newURI; 1.1280 + newChannel->GetURI(getter_AddRefs(newURI)); 1.1281 + nsCOMPtr<nsIURI> newOriginalURI; 1.1282 + newChannel->GetOriginalURI(getter_AddRefs(newOriginalURI)); 1.1283 + 1.1284 + NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI); 1.1285 + 1.1286 + const uint32_t flags = 1.1287 + nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT | 1.1288 + nsIScriptSecurityManager::DISALLOW_SCRIPT; 1.1289 + nsresult rv = CheckLoadURIWithPrincipal(oldPrincipal, newURI, flags); 1.1290 + if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) { 1.1291 + rv = CheckLoadURIWithPrincipal(oldPrincipal, newOriginalURI, flags); 1.1292 + } 1.1293 + 1.1294 + if (NS_FAILED(rv)) 1.1295 + return rv; 1.1296 + 1.1297 + cb->OnRedirectVerifyCallback(NS_OK); 1.1298 + return NS_OK; 1.1299 +} 1.1300 + 1.1301 + 1.1302 +///////////////////////////////////// 1.1303 +// Method implementing nsIObserver // 1.1304 +///////////////////////////////////// 1.1305 +const char sJSEnabledPrefName[] = "javascript.enabled"; 1.1306 +const char sFileOriginPolicyPrefName[] = 1.1307 + "security.fileuri.strict_origin_policy"; 1.1308 + 1.1309 +static const char* kObservedPrefs[] = { 1.1310 + sJSEnabledPrefName, 1.1311 + sFileOriginPolicyPrefName, 1.1312 + "capability.policy.", 1.1313 + nullptr 1.1314 +}; 1.1315 + 1.1316 + 1.1317 +NS_IMETHODIMP 1.1318 +nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aTopic, 1.1319 + const char16_t* aMessage) 1.1320 +{ 1.1321 + ScriptSecurityPrefChanged(); 1.1322 + return NS_OK; 1.1323 +} 1.1324 + 1.1325 +///////////////////////////////////////////// 1.1326 +// Constructor, Destructor, Initialization // 1.1327 +///////////////////////////////////////////// 1.1328 +nsScriptSecurityManager::nsScriptSecurityManager(void) 1.1329 + : mPrefInitialized(false) 1.1330 + , mIsJavaScriptEnabled(false) 1.1331 +{ 1.1332 + static_assert(sizeof(intptr_t) == sizeof(void*), 1.1333 + "intptr_t and void* have different lengths on this platform. " 1.1334 + "This may cause a security failure with the SecurityLevel union."); 1.1335 +} 1.1336 + 1.1337 +nsresult nsScriptSecurityManager::Init() 1.1338 +{ 1.1339 + nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService); 1.1340 + NS_ENSURE_SUCCESS(rv, rv); 1.1341 + 1.1342 + InitPrefs(); 1.1343 + 1.1344 + nsCOMPtr<nsIStringBundleService> bundleService = 1.1345 + mozilla::services::GetStringBundleService(); 1.1346 + if (!bundleService) 1.1347 + return NS_ERROR_FAILURE; 1.1348 + 1.1349 + rv = bundleService->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle); 1.1350 + NS_ENSURE_SUCCESS(rv, rv); 1.1351 + 1.1352 + // Create our system principal singleton 1.1353 + nsRefPtr<nsSystemPrincipal> system = new nsSystemPrincipal(); 1.1354 + NS_ENSURE_TRUE(system, NS_ERROR_OUT_OF_MEMORY); 1.1355 + 1.1356 + mSystemPrincipal = system; 1.1357 + 1.1358 + //-- Register security check callback in the JS engine 1.1359 + // Currently this is used to control access to function.caller 1.1360 + rv = nsXPConnect::XPConnect()->GetRuntime(&sRuntime); 1.1361 + NS_ENSURE_SUCCESS(rv, rv); 1.1362 + 1.1363 + static const JSSecurityCallbacks securityCallbacks = { 1.1364 + ContentSecurityPolicyPermitsJSAction, 1.1365 + JSPrincipalsSubsume, 1.1366 + }; 1.1367 + 1.1368 + MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime)); 1.1369 + JS_SetSecurityCallbacks(sRuntime, &securityCallbacks); 1.1370 + JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy); 1.1371 + 1.1372 + JS_SetTrustedPrincipals(sRuntime, system); 1.1373 + 1.1374 + return NS_OK; 1.1375 +} 1.1376 + 1.1377 +static StaticRefPtr<nsScriptSecurityManager> gScriptSecMan; 1.1378 + 1.1379 +nsScriptSecurityManager::~nsScriptSecurityManager(void) 1.1380 +{ 1.1381 + Preferences::RemoveObservers(this, kObservedPrefs); 1.1382 + if (mDomainPolicy) 1.1383 + mDomainPolicy->Deactivate(); 1.1384 + MOZ_ASSERT(!mDomainPolicy); 1.1385 +} 1.1386 + 1.1387 +void 1.1388 +nsScriptSecurityManager::Shutdown() 1.1389 +{ 1.1390 + if (sRuntime) { 1.1391 + JS_SetSecurityCallbacks(sRuntime, nullptr); 1.1392 + JS_SetTrustedPrincipals(sRuntime, nullptr); 1.1393 + sRuntime = nullptr; 1.1394 + } 1.1395 + 1.1396 + NS_IF_RELEASE(sIOService); 1.1397 + NS_IF_RELEASE(sStrBundle); 1.1398 +} 1.1399 + 1.1400 +nsScriptSecurityManager * 1.1401 +nsScriptSecurityManager::GetScriptSecurityManager() 1.1402 +{ 1.1403 + if (!gScriptSecMan && nsXPConnect::XPConnect()) 1.1404 + { 1.1405 + nsRefPtr<nsScriptSecurityManager> ssManager = new nsScriptSecurityManager(); 1.1406 + 1.1407 + nsresult rv; 1.1408 + rv = ssManager->Init(); 1.1409 + if (NS_FAILED(rv)) { 1.1410 + return nullptr; 1.1411 + } 1.1412 + 1.1413 + rv = nsXPConnect::XPConnect()-> 1.1414 + SetDefaultSecurityManager(ssManager); 1.1415 + if (NS_FAILED(rv)) { 1.1416 + NS_WARNING("Failed to install xpconnect security manager!"); 1.1417 + return nullptr; 1.1418 + } 1.1419 + 1.1420 + ClearOnShutdown(&gScriptSecMan); 1.1421 + gScriptSecMan = ssManager; 1.1422 + } 1.1423 + return gScriptSecMan; 1.1424 +} 1.1425 + 1.1426 +// Currently this nsGenericFactory constructor is used only from FastLoad 1.1427 +// (XPCOM object deserialization) code, when "creating" the system principal 1.1428 +// singleton. 1.1429 +nsSystemPrincipal * 1.1430 +nsScriptSecurityManager::SystemPrincipalSingletonConstructor() 1.1431 +{ 1.1432 + nsIPrincipal *sysprin = nullptr; 1.1433 + if (gScriptSecMan) 1.1434 + NS_ADDREF(sysprin = gScriptSecMan->mSystemPrincipal); 1.1435 + return static_cast<nsSystemPrincipal*>(sysprin); 1.1436 +} 1.1437 + 1.1438 +struct IsWhitespace { 1.1439 + static bool Test(char aChar) { return NS_IsAsciiWhitespace(aChar); }; 1.1440 +}; 1.1441 +struct IsWhitespaceOrComma { 1.1442 + static bool Test(char aChar) { return aChar == ',' || NS_IsAsciiWhitespace(aChar); }; 1.1443 +}; 1.1444 + 1.1445 +template <typename Predicate> 1.1446 +uint32_t SkipPast(const nsCString& str, uint32_t base) 1.1447 +{ 1.1448 + while (base < str.Length() && Predicate::Test(str[base])) { 1.1449 + ++base; 1.1450 + } 1.1451 + return base; 1.1452 +} 1.1453 + 1.1454 +template <typename Predicate> 1.1455 +uint32_t SkipUntil(const nsCString& str, uint32_t base) 1.1456 +{ 1.1457 + while (base < str.Length() && !Predicate::Test(str[base])) { 1.1458 + ++base; 1.1459 + } 1.1460 + return base; 1.1461 +} 1.1462 + 1.1463 +inline void 1.1464 +nsScriptSecurityManager::ScriptSecurityPrefChanged() 1.1465 +{ 1.1466 + MOZ_ASSERT(mPrefInitialized); 1.1467 + mIsJavaScriptEnabled = 1.1468 + Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled); 1.1469 + sStrictFileOriginPolicy = 1.1470 + Preferences::GetBool(sFileOriginPolicyPrefName, false); 1.1471 + 1.1472 + // 1.1473 + // Rebuild the set of principals for which we allow file:// URI loads. This 1.1474 + // implements a small subset of an old pref-based CAPS people that people 1.1475 + // have come to depend on. See bug 995943. 1.1476 + // 1.1477 + 1.1478 + mFileURIWhitelist.Clear(); 1.1479 + auto policies = mozilla::Preferences::GetCString("capability.policy.policynames"); 1.1480 + for (uint32_t base = SkipPast<IsWhitespaceOrComma>(policies, 0), bound = 0; 1.1481 + base < policies.Length(); 1.1482 + base = SkipPast<IsWhitespaceOrComma>(policies, bound)) 1.1483 + { 1.1484 + // Grab the current policy name. 1.1485 + bound = SkipUntil<IsWhitespaceOrComma>(policies, base); 1.1486 + auto policyName = Substring(policies, base, bound - base); 1.1487 + 1.1488 + // Figure out if this policy allows loading file:// URIs. If not, we can skip it. 1.1489 + nsCString checkLoadURIPrefName = NS_LITERAL_CSTRING("capability.policy.") + 1.1490 + policyName + 1.1491 + NS_LITERAL_CSTRING(".checkloaduri.enabled"); 1.1492 + if (!Preferences::GetString(checkLoadURIPrefName.get()).LowerCaseEqualsLiteral("allaccess")) { 1.1493 + continue; 1.1494 + } 1.1495 + 1.1496 + // Grab the list of domains associated with this policy. 1.1497 + nsCString domainPrefName = NS_LITERAL_CSTRING("capability.policy.") + 1.1498 + policyName + 1.1499 + NS_LITERAL_CSTRING(".sites"); 1.1500 + auto siteList = Preferences::GetCString(domainPrefName.get()); 1.1501 + AddSitesToFileURIWhitelist(siteList); 1.1502 + } 1.1503 +} 1.1504 + 1.1505 +void 1.1506 +nsScriptSecurityManager::AddSitesToFileURIWhitelist(const nsCString& aSiteList) 1.1507 +{ 1.1508 + for (uint32_t base = SkipPast<IsWhitespace>(aSiteList, 0), bound = 0; 1.1509 + base < aSiteList.Length(); 1.1510 + base = SkipPast<IsWhitespace>(aSiteList, bound)) 1.1511 + { 1.1512 + // Grab the current site. 1.1513 + bound = SkipUntil<IsWhitespace>(aSiteList, base); 1.1514 + nsAutoCString site(Substring(aSiteList, base, bound - base)); 1.1515 + 1.1516 + // Check if the URI is schemeless. If so, add both http and https. 1.1517 + nsAutoCString unused; 1.1518 + if (NS_FAILED(sIOService->ExtractScheme(site, unused))) { 1.1519 + AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("http://") + site); 1.1520 + AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("https://") + site); 1.1521 + continue; 1.1522 + } 1.1523 + 1.1524 + // Convert it to a URI and add it to our list. 1.1525 + nsCOMPtr<nsIURI> uri; 1.1526 + nsresult rv = NS_NewURI(getter_AddRefs(uri), site, nullptr, nullptr, sIOService); 1.1527 + if (NS_SUCCEEDED(rv)) { 1.1528 + mFileURIWhitelist.AppendElement(uri); 1.1529 + } else { 1.1530 + nsCOMPtr<nsIConsoleService> console(do_GetService("@mozilla.org/consoleservice;1")); 1.1531 + if (console) { 1.1532 + nsAutoString msg = NS_LITERAL_STRING("Unable to to add site to file:// URI whitelist: ") + 1.1533 + NS_ConvertASCIItoUTF16(site); 1.1534 + console->LogStringMessage(msg.get()); 1.1535 + } 1.1536 + } 1.1537 + } 1.1538 +} 1.1539 + 1.1540 +nsresult 1.1541 +nsScriptSecurityManager::InitPrefs() 1.1542 +{ 1.1543 + nsIPrefBranch* branch = Preferences::GetRootBranch(); 1.1544 + NS_ENSURE_TRUE(branch, NS_ERROR_FAILURE); 1.1545 + 1.1546 + mPrefInitialized = true; 1.1547 + 1.1548 + // Set the initial value of the "javascript.enabled" prefs 1.1549 + ScriptSecurityPrefChanged(); 1.1550 + 1.1551 + // set observer callbacks in case the value of the prefs change 1.1552 + Preferences::AddStrongObservers(this, kObservedPrefs); 1.1553 + 1.1554 + return NS_OK; 1.1555 +} 1.1556 + 1.1557 +namespace mozilla { 1.1558 + 1.1559 +void 1.1560 +GetJarPrefix(uint32_t aAppId, bool aInMozBrowser, nsACString& aJarPrefix) 1.1561 +{ 1.1562 + MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID); 1.1563 + 1.1564 + if (aAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) { 1.1565 + aAppId = nsIScriptSecurityManager::NO_APP_ID; 1.1566 + } 1.1567 + 1.1568 + aJarPrefix.Truncate(); 1.1569 + 1.1570 + // Fallback. 1.1571 + if (aAppId == nsIScriptSecurityManager::NO_APP_ID && !aInMozBrowser) { 1.1572 + return; 1.1573 + } 1.1574 + 1.1575 + // aJarPrefix = appId + "+" + { 't', 'f' } + "+"; 1.1576 + aJarPrefix.AppendInt(aAppId); 1.1577 + aJarPrefix.Append('+'); 1.1578 + aJarPrefix.Append(aInMozBrowser ? 't' : 'f'); 1.1579 + aJarPrefix.Append('+'); 1.1580 + 1.1581 + return; 1.1582 +} 1.1583 + 1.1584 +} // namespace mozilla 1.1585 + 1.1586 +NS_IMETHODIMP 1.1587 +nsScriptSecurityManager::GetJarPrefix(uint32_t aAppId, 1.1588 + bool aInMozBrowser, 1.1589 + nsACString& aJarPrefix) 1.1590 +{ 1.1591 + MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID); 1.1592 + 1.1593 + mozilla::GetJarPrefix(aAppId, aInMozBrowser, aJarPrefix); 1.1594 + return NS_OK; 1.1595 +} 1.1596 + 1.1597 +NS_IMETHODIMP 1.1598 +nsScriptSecurityManager::GetDomainPolicyActive(bool *aRv) 1.1599 +{ 1.1600 + *aRv = !!mDomainPolicy; 1.1601 + return NS_OK; 1.1602 +} 1.1603 + 1.1604 +NS_IMETHODIMP 1.1605 +nsScriptSecurityManager::ActivateDomainPolicy(nsIDomainPolicy** aRv) 1.1606 +{ 1.1607 + // We only allow one domain policy at a time. The holder of the previous 1.1608 + // policy must explicitly deactivate it first. 1.1609 + if (mDomainPolicy) { 1.1610 + return NS_ERROR_SERVICE_NOT_AVAILABLE; 1.1611 + } 1.1612 + 1.1613 + mDomainPolicy = new DomainPolicy(); 1.1614 + nsCOMPtr<nsIDomainPolicy> ptr = mDomainPolicy; 1.1615 + ptr.forget(aRv); 1.1616 + return NS_OK; 1.1617 +} 1.1618 + 1.1619 +// Intentionally non-scriptable. Script must have a reference to the 1.1620 +// nsIDomainPolicy to deactivate it. 1.1621 +void 1.1622 +nsScriptSecurityManager::DeactivateDomainPolicy() 1.1623 +{ 1.1624 + mDomainPolicy = nullptr; 1.1625 +} 1.1626 + 1.1627 +NS_IMETHODIMP 1.1628 +nsScriptSecurityManager::PolicyAllowsScript(nsIURI* aURI, bool *aRv) 1.1629 +{ 1.1630 + nsresult rv; 1.1631 + 1.1632 + // Compute our rule. If we don't have any domain policy set up that might 1.1633 + // provide exceptions to this rule, we're done. 1.1634 + *aRv = mIsJavaScriptEnabled; 1.1635 + if (!mDomainPolicy) { 1.1636 + return NS_OK; 1.1637 + } 1.1638 + 1.1639 + // We have a domain policy. Grab the appropriate set of exceptions to the 1.1640 + // rule (either the blacklist or the whitelist, depending on whether script 1.1641 + // is enabled or disabled by default). 1.1642 + nsCOMPtr<nsIDomainSet> exceptions; 1.1643 + nsCOMPtr<nsIDomainSet> superExceptions; 1.1644 + if (*aRv) { 1.1645 + mDomainPolicy->GetBlacklist(getter_AddRefs(exceptions)); 1.1646 + mDomainPolicy->GetSuperBlacklist(getter_AddRefs(superExceptions)); 1.1647 + } else { 1.1648 + mDomainPolicy->GetWhitelist(getter_AddRefs(exceptions)); 1.1649 + mDomainPolicy->GetSuperWhitelist(getter_AddRefs(superExceptions)); 1.1650 + } 1.1651 + 1.1652 + bool contains; 1.1653 + rv = exceptions->Contains(aURI, &contains); 1.1654 + NS_ENSURE_SUCCESS(rv, rv); 1.1655 + if (contains) { 1.1656 + *aRv = !*aRv; 1.1657 + return NS_OK; 1.1658 + } 1.1659 + rv = superExceptions->ContainsSuperDomain(aURI, &contains); 1.1660 + NS_ENSURE_SUCCESS(rv, rv); 1.1661 + if (contains) { 1.1662 + *aRv = !*aRv; 1.1663 + } 1.1664 + 1.1665 + return NS_OK; 1.1666 +}