2013-01-02 21:47:50 -08:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* vim: set ts=4 et sw=4 tw=80: */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2011-10-10 22:50:08 -07:00
|
|
|
|
2013-08-26 19:05:20 -07:00
|
|
|
#include "nsScriptSecurityManager.h"
|
|
|
|
|
2013-12-08 18:52:54 -08:00
|
|
|
#include "mozilla/ArrayUtils.h"
|
2011-10-10 22:50:08 -07:00
|
|
|
|
2013-08-26 19:05:20 -07:00
|
|
|
#include "js/OldDebugAPI.h"
|
2010-04-11 06:55:24 -07:00
|
|
|
#include "xpcprivate.h"
|
2012-05-18 01:29:40 -07:00
|
|
|
#include "XPCWrapper.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsIScriptObjectPrincipal.h"
|
|
|
|
#include "nsIScriptContext.h"
|
|
|
|
#include "nsIURL.h"
|
|
|
|
#include "nsINestedURI.h"
|
|
|
|
#include "nspr.h"
|
|
|
|
#include "nsJSPrincipals.h"
|
|
|
|
#include "nsSystemPrincipal.h"
|
|
|
|
#include "nsPrincipal.h"
|
|
|
|
#include "nsNullPrincipal.h"
|
2013-11-12 16:43:35 -08:00
|
|
|
#include "DomainPolicy.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsXPIDLString.h"
|
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsCRTGlue.h"
|
2012-07-27 07:03:27 -07:00
|
|
|
#include "nsError.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsDOMCID.h"
|
|
|
|
#include "nsIXPConnect.h"
|
|
|
|
#include "nsIXPCSecurityManager.h"
|
|
|
|
#include "nsTextFormatter.h"
|
|
|
|
#include "nsIStringBundle.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsIProperties.h"
|
|
|
|
#include "nsDirectoryServiceDefs.h"
|
|
|
|
#include "nsIFile.h"
|
2007-09-06 00:02:57 -07:00
|
|
|
#include "nsIFileURL.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIZipReader.h"
|
|
|
|
#include "nsIXPConnect.h"
|
|
|
|
#include "nsIScriptGlobalObject.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIPrompt.h"
|
|
|
|
#include "nsIWindowWatcher.h"
|
|
|
|
#include "nsIConsoleService.h"
|
|
|
|
#include "nsISecurityCheckedComponent.h"
|
|
|
|
#include "nsIJSRuntimeService.h"
|
|
|
|
#include "nsIObserverService.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsAutoPtr.h"
|
|
|
|
#include "nsDOMJSUtils.h"
|
|
|
|
#include "nsAboutProtocolUtils.h"
|
|
|
|
#include "nsIClassInfo.h"
|
|
|
|
#include "nsIURIFixup.h"
|
|
|
|
#include "nsCDefaultURIFixup.h"
|
2008-04-12 14:26:19 -07:00
|
|
|
#include "nsIChromeRegistry.h"
|
2010-03-08 00:24:50 -08:00
|
|
|
#include "nsIContentSecurityPolicy.h"
|
2010-08-04 19:15:55 -07:00
|
|
|
#include "nsIAsyncVerifyRedirectCallback.h"
|
2011-06-19 20:00:16 -07:00
|
|
|
#include "mozilla/Preferences.h"
|
2012-05-02 21:35:38 -07:00
|
|
|
#include "mozilla/dom/BindingUtils.h"
|
2013-07-30 07:25:31 -07:00
|
|
|
#include <stdint.h>
|
2012-06-19 10:20:34 -07:00
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
2012-07-26 12:33:45 -07:00
|
|
|
#include "mozilla/StaticPtr.h"
|
2012-09-25 12:33:01 -07:00
|
|
|
#include "nsContentUtils.h"
|
2013-05-22 09:05:26 -07:00
|
|
|
#include "nsCxPusher.h"
|
2013-11-12 16:43:31 -08:00
|
|
|
#include "nsJSUtils.h"
|
2012-09-25 12:33:01 -07:00
|
|
|
|
|
|
|
// This should be probably defined on some other place... but I couldn't find it
|
|
|
|
#define WEBAPPS_PERM_NAME "webapps-manage"
|
2011-06-19 20:00:16 -07:00
|
|
|
|
|
|
|
using namespace mozilla;
|
2012-03-30 21:42:20 -07:00
|
|
|
using namespace mozilla::dom;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
nsIIOService *nsScriptSecurityManager::sIOService = nullptr;
|
|
|
|
nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
JSRuntime *nsScriptSecurityManager::sRuntime = 0;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-10-21 23:29:55 -07:00
|
|
|
bool
|
|
|
|
nsScriptSecurityManager::SubjectIsPrivileged()
|
|
|
|
{
|
|
|
|
JSContext *cx = GetCurrentJSContext();
|
|
|
|
if (cx && xpc::IsUniversalXPConnectEnabled(cx))
|
|
|
|
return true;
|
|
|
|
bool isSystem = false;
|
|
|
|
return NS_SUCCEEDED(SubjectPrincipalIsSystem(&isSystem)) && isSystem;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
///////////////////////////
|
|
|
|
// Convenience Functions //
|
|
|
|
///////////////////////////
|
|
|
|
// Result of this function should not be freed.
|
|
|
|
static inline const PRUnichar *
|
2013-05-12 12:52:21 -07:00
|
|
|
IDToString(JSContext *cx, jsid id_)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2013-05-12 12:52:21 -07:00
|
|
|
JS::RootedId id(cx, id_);
|
2010-07-14 23:19:36 -07:00
|
|
|
if (JSID_IS_STRING(id))
|
2010-12-03 00:24:17 -08:00
|
|
|
return JS_GetInternedStringChars(JSID_TO_STRING(id));
|
2010-07-14 23:19:36 -07:00
|
|
|
|
2013-11-16 04:31:36 -08:00
|
|
|
JS::Rooted<JS::Value> idval(cx);
|
|
|
|
if (!JS_IdToValue(cx, id, idval.address()))
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2013-11-16 04:31:36 -08:00
|
|
|
JSString *str = JS::ToString(cx, idval);
|
2007-03-22 10:30:00 -07:00
|
|
|
if(!str)
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2010-12-03 00:24:17 -08:00
|
|
|
return JS_GetStringCharsZ(cx, str);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-05-20 18:49:42 -07:00
|
|
|
class nsAutoInPrincipalDomainOriginSetter {
|
|
|
|
public:
|
|
|
|
nsAutoInPrincipalDomainOriginSetter() {
|
|
|
|
++sInPrincipalDomainOrigin;
|
|
|
|
}
|
|
|
|
~nsAutoInPrincipalDomainOriginSetter() {
|
|
|
|
--sInPrincipalDomainOrigin;
|
|
|
|
}
|
2012-08-22 08:56:38 -07:00
|
|
|
static uint32_t sInPrincipalDomainOrigin;
|
2009-05-20 18:49:42 -07:00
|
|
|
};
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin;
|
2009-05-20 18:49:42 -07:00
|
|
|
|
2008-07-28 23:37:58 -07:00
|
|
|
static
|
|
|
|
nsresult
|
2009-07-26 18:27:33 -07:00
|
|
|
GetOriginFromURI(nsIURI* aURI, nsACString& aOrigin)
|
2008-07-28 23:37:58 -07:00
|
|
|
{
|
2009-05-21 12:46:05 -07:00
|
|
|
if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin > 1) {
|
|
|
|
// Allow a single recursive call to GetPrincipalDomainOrigin, since that
|
|
|
|
// might be happening on a different principal from the first call. But
|
|
|
|
// after that, cut off the recursion; it just indicates that something
|
|
|
|
// we're doing in this method causes us to reenter a security check here.
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2009-05-20 18:49:42 -07:00
|
|
|
nsAutoInPrincipalDomainOriginSetter autoSetter;
|
2008-07-28 23:37:58 -07:00
|
|
|
|
2009-07-26 18:27:33 -07:00
|
|
|
nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
|
2008-07-28 23:37:58 -07:00
|
|
|
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
|
|
|
|
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString hostPort;
|
2008-07-28 23:37:58 -07:00
|
|
|
|
|
|
|
nsresult rv = uri->GetHostPort(hostPort);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString scheme;
|
2008-07-28 23:37:58 -07:00
|
|
|
rv = uri->GetScheme(scheme);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
aOrigin = scheme + NS_LITERAL_CSTRING("://") + hostPort;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Some URIs (e.g., nsSimpleURI) don't support host. Just
|
|
|
|
// get the full spec.
|
|
|
|
rv = uri->GetSpec(aOrigin);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-07-26 18:27:33 -07:00
|
|
|
static
|
|
|
|
nsresult
|
|
|
|
GetPrincipalDomainOrigin(nsIPrincipal* aPrincipal,
|
|
|
|
nsACString& aOrigin)
|
|
|
|
{
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
aPrincipal->GetDomain(getter_AddRefs(uri));
|
|
|
|
if (!uri) {
|
|
|
|
aPrincipal->GetURI(getter_AddRefs(uri));
|
|
|
|
}
|
|
|
|
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
|
|
|
|
|
|
|
|
return GetOriginFromURI(uri, aOrigin);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
inline void SetPendingException(JSContext *cx, const char *aMsg)
|
|
|
|
{
|
2008-03-20 01:19:15 -07:00
|
|
|
JS_ReportError(cx, "%s", aMsg);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void SetPendingException(JSContext *cx, const PRUnichar *aMsg)
|
|
|
|
{
|
2008-03-20 01:19:15 -07:00
|
|
|
JS_ReportError(cx, "%hs", aMsg);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Helper class to get stuff from the ClassInfo and not waste extra time with
|
|
|
|
// virtual method calls for things it has already gotten
|
|
|
|
class ClassInfoData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ClassInfoData(nsIClassInfo *aClassInfo, const char *aName)
|
|
|
|
: mClassInfo(aClassInfo),
|
2007-07-08 00:08:04 -07:00
|
|
|
mName(const_cast<char *>(aName)),
|
2011-10-17 07:59:28 -07:00
|
|
|
mDidGetFlags(false),
|
|
|
|
mMustFreeName(false)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~ClassInfoData()
|
|
|
|
{
|
|
|
|
if (mMustFreeName)
|
|
|
|
nsMemory::Free(mName);
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t GetFlags()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
if (!mDidGetFlags) {
|
|
|
|
if (mClassInfo) {
|
|
|
|
nsresult rv = mClassInfo->GetFlags(&mFlags);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
mFlags = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mFlags = 0;
|
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
mDidGetFlags = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return mFlags;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool IsDOMClass()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2007-11-12 13:47:11 -08:00
|
|
|
return !!(GetFlags() & nsIClassInfo::DOM_OBJECT);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const char* GetName()
|
|
|
|
{
|
|
|
|
if (!mName) {
|
|
|
|
if (mClassInfo) {
|
|
|
|
mClassInfo->GetClassDescription(&mName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mName) {
|
2011-10-17 07:59:28 -07:00
|
|
|
mMustFreeName = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
} else {
|
2007-07-08 00:08:04 -07:00
|
|
|
mName = const_cast<char *>("UnnamedClass");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mName;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsIClassInfo *mClassInfo; // WEAK
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t mFlags;
|
2007-03-22 10:30:00 -07:00
|
|
|
char *mName;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool mDidGetFlags;
|
|
|
|
bool mMustFreeName;
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
2008-10-08 15:05:25 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
JSContext *
|
|
|
|
nsScriptSecurityManager::GetCurrentJSContext()
|
|
|
|
{
|
|
|
|
// Get JSContext from stack.
|
2013-05-29 16:49:11 -07:00
|
|
|
return nsXPConnect::XPConnect()->GetCurrentJSContext();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
JSContext *
|
|
|
|
nsScriptSecurityManager::GetSafeJSContext()
|
|
|
|
{
|
|
|
|
// Get JSContext from stack.
|
2013-05-29 16:49:11 -07:00
|
|
|
return nsXPConnect::XPConnect()->GetSafeJSContext();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-02-26 19:45:29 -08:00
|
|
|
/* static */
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2007-03-22 10:30:00 -07:00
|
|
|
nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
|
|
|
|
nsIURI* aTargetURI)
|
|
|
|
{
|
2008-08-27 18:15:32 -07:00
|
|
|
return NS_SecurityCompareURIs(aSourceURI, aTargetURI, sStrictFileOriginPolicy);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-10-08 06:16:27 -07:00
|
|
|
// SecurityHashURI is consistent with SecurityCompareURIs because NS_SecurityHashURI
|
|
|
|
// is consistent with NS_SecurityCompareURIs. See nsNetUtil.h.
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t
|
2008-10-08 06:16:27 -07:00
|
|
|
nsScriptSecurityManager::SecurityHashURI(nsIURI* aURI)
|
|
|
|
{
|
|
|
|
return NS_SecurityHashURI(aURI);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel,
|
|
|
|
nsIPrincipal** aPrincipal)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aChannel, "Must have channel!");
|
|
|
|
nsCOMPtr<nsISupports> owner;
|
|
|
|
aChannel->GetOwner(getter_AddRefs(owner));
|
|
|
|
if (owner) {
|
|
|
|
CallQueryInterface(owner, aPrincipal);
|
|
|
|
if (*aPrincipal) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// OK, get the principal from the URI. Make sure this does the same thing
|
2013-03-26 08:31:53 -07:00
|
|
|
// as nsDocument::Reset and XULDocument::StartDocumentLoad.
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
2007-10-23 14:56:41 -07:00
|
|
|
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-20 00:07:49 -07:00
|
|
|
nsCOMPtr<nsIDocShell> docShell;
|
|
|
|
NS_QueryNotificationCallbacks(aChannel, docShell);
|
|
|
|
|
|
|
|
if (docShell) {
|
2012-11-10 10:32:36 -08:00
|
|
|
return GetDocShellCodebasePrincipal(uri, docShell, aPrincipal);
|
2012-07-20 00:07:49 -07:00
|
|
|
}
|
|
|
|
|
2012-11-10 10:32:36 -08:00
|
|
|
return GetCodebasePrincipalInternal(uri, UNKNOWN_APP_ID,
|
|
|
|
/* isInBrowserElement */ false, aPrincipal);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-06-18 08:12:09 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool* aIsSystem)
|
2007-06-18 08:12:09 -07:00
|
|
|
{
|
|
|
|
*aIsSystem = (aPrincipal == mSystemPrincipal);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-01-04 15:59:12 -08:00
|
|
|
NS_IMETHODIMP_(nsIPrincipal *)
|
|
|
|
nsScriptSecurityManager::GetCxSubjectPrincipal(JSContext *cx)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(cx == GetCurrentJSContext(),
|
|
|
|
"Uh, cx is not the current JS context!");
|
|
|
|
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsIPrincipal *principal = GetSubjectPrincipal(cx, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2008-01-04 15:59:12 -08:00
|
|
|
|
|
|
|
return principal;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
/////////////////////////////
|
|
|
|
// nsScriptSecurityManager //
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
////////////////////////////////////
|
|
|
|
// Methods implementing ISupports //
|
|
|
|
////////////////////////////////////
|
2010-06-08 16:43:54 -07:00
|
|
|
NS_IMPL_ISUPPORTS4(nsScriptSecurityManager,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIScriptSecurityManager,
|
|
|
|
nsIXPCSecurityManager,
|
|
|
|
nsIChannelEventSink,
|
|
|
|
nsIObserver)
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
// Methods implementing nsIScriptSecurityManager //
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
|
|
|
|
///////////////// Security Checks /////////////////
|
2012-03-09 01:48:50 -08:00
|
|
|
|
2013-08-08 15:53:04 -07:00
|
|
|
bool
|
2010-03-08 00:24:50 -08:00
|
|
|
nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
|
|
|
|
{
|
|
|
|
// Get the security manager
|
|
|
|
nsScriptSecurityManager *ssm =
|
|
|
|
nsScriptSecurityManager::GetScriptSecurityManager();
|
|
|
|
|
|
|
|
NS_ASSERTION(ssm, "Failed to get security manager service");
|
|
|
|
if (!ssm)
|
2013-08-06 23:59:54 -07:00
|
|
|
return false;
|
2010-03-08 00:24:50 -08:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
nsIPrincipal* subjectPrincipal = ssm->GetSubjectPrincipal(cx, &rv);
|
|
|
|
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get nsIPrincipal from js context");
|
|
|
|
if (NS_FAILED(rv))
|
2013-08-06 23:59:54 -07:00
|
|
|
return false; // Not just absence of principal, but failure.
|
2010-03-08 00:24:50 -08:00
|
|
|
|
2012-08-23 09:51:09 -07:00
|
|
|
if (!subjectPrincipal)
|
2013-08-06 23:59:54 -07:00
|
|
|
return true;
|
2010-03-08 00:24:50 -08:00
|
|
|
|
|
|
|
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
|
|
|
rv = subjectPrincipal->GetCsp(getter_AddRefs(csp));
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "CSP: Failed to get CSP from principal.");
|
|
|
|
|
|
|
|
// don't do anything unless there's a CSP
|
|
|
|
if (!csp)
|
2013-08-06 23:59:54 -07:00
|
|
|
return true;
|
2010-03-08 00:24:50 -08:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool evalOK = true;
|
2012-10-15 13:54:58 -07:00
|
|
|
bool reportViolation = false;
|
|
|
|
rv = csp->GetAllowsEval(&reportViolation, &evalOK);
|
2010-03-08 00:24:50 -08:00
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
NS_WARNING("CSP: failed to get allowsEval");
|
2013-08-06 23:59:54 -07:00
|
|
|
return true; // fail open to not break sites.
|
2010-03-08 00:24:50 -08:00
|
|
|
}
|
|
|
|
|
2012-10-15 13:54:58 -07:00
|
|
|
if (reportViolation) {
|
2011-01-31 10:09:44 -08:00
|
|
|
nsAutoString fileName;
|
2012-04-16 12:30:00 -07:00
|
|
|
unsigned lineNum = 0;
|
2011-01-31 10:09:44 -08:00
|
|
|
NS_NAMED_LITERAL_STRING(scriptSample, "call to eval() or related function blocked by CSP");
|
|
|
|
|
2013-09-20 02:22:59 -07:00
|
|
|
JS::RootedScript script(cx);
|
2012-04-16 12:30:00 -07:00
|
|
|
if (JS_DescribeScriptedCaller(cx, &script, &lineNum)) {
|
|
|
|
if (const char *file = JS_GetScriptFilename(cx, script)) {
|
|
|
|
CopyUTF8toUTF16(nsDependentCString(file), fileName);
|
2011-01-31 10:09:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
|
|
|
|
fileName,
|
|
|
|
scriptSample,
|
2013-11-08 15:44:39 -08:00
|
|
|
lineNum,
|
|
|
|
EmptyString());
|
2011-01-31 10:09:44 -08:00
|
|
|
}
|
|
|
|
|
2010-03-08 00:24:50 -08:00
|
|
|
return evalOK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-08 15:53:04 -07:00
|
|
|
bool
|
2013-06-21 06:12:46 -07:00
|
|
|
nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JS::Handle<JSObject*> obj,
|
|
|
|
JS::Handle<jsid> id, JSAccessMode mode,
|
2013-06-19 03:32:27 -07:00
|
|
|
JS::MutableHandle<JS::Value> vp)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// Get the security manager
|
|
|
|
nsScriptSecurityManager *ssm =
|
|
|
|
nsScriptSecurityManager::GetScriptSecurityManager();
|
|
|
|
|
2013-07-09 10:30:58 -07:00
|
|
|
NS_WARN_IF_FALSE(ssm, "Failed to get security manager service");
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!ssm)
|
2013-08-06 23:59:54 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Get the object being accessed. We protect these cases:
|
|
|
|
// 1. The Function.prototype.caller property's value, which might lead
|
|
|
|
// an attacker up a call-stack to a function or another object from
|
|
|
|
// a different trust domain.
|
|
|
|
// 2. A user-defined getter or setter function accessible on another
|
|
|
|
// trust domain's window or document object.
|
2012-09-04 16:40:12 -07:00
|
|
|
// vp can be a primitive, in that case, we use obj as the target
|
2007-03-22 10:30:00 -07:00
|
|
|
// object.
|
2012-09-04 16:40:12 -07:00
|
|
|
JSObject* target = JSVAL_IS_PRIMITIVE(vp) ? obj : JSVAL_TO_OBJECT(vp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Do the same-origin check -- this sets a JS exception if the check fails.
|
|
|
|
// Pass the parent object's class name, as we have no class-info for it.
|
2007-08-30 17:52:58 -07:00
|
|
|
nsresult rv =
|
2011-10-04 07:06:54 -07:00
|
|
|
ssm->CheckPropertyAccess(cx, target, js::GetObjectClass(obj)->name, id,
|
2007-08-30 17:52:58 -07:00
|
|
|
(mode & JSACC_WRITE) ?
|
2012-08-22 08:56:38 -07:00
|
|
|
(int32_t)nsIXPCSecurityManager::ACCESS_SET_PROPERTY :
|
|
|
|
(int32_t)nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
2013-08-06 23:59:54 -07:00
|
|
|
return false; // Security check failed (XXX was an error reported?)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2013-08-06 23:59:54 -07:00
|
|
|
return true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CheckPropertyAccess(JSContext* cx,
|
|
|
|
JSObject* aJSObject,
|
|
|
|
const char* aClassName,
|
2010-07-14 23:19:36 -07:00
|
|
|
jsid aProperty,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aAction)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
return CheckPropertyAccessImpl(aAction, nullptr, cx, aJSObject,
|
|
|
|
nullptr, nullptr,
|
2013-12-13 19:15:43 -08:00
|
|
|
aClassName, aProperty);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
|
|
|
|
nsIURI* aTargetURI)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// Get a context if necessary
|
|
|
|
if (!cx)
|
|
|
|
{
|
|
|
|
cx = GetCurrentJSContext();
|
|
|
|
if (!cx)
|
|
|
|
return NS_OK; // No JS context, so allow access
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a principal from the context
|
|
|
|
nsIPrincipal* sourcePrincipal = GetSubjectPrincipal(cx, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (!sourcePrincipal)
|
|
|
|
{
|
|
|
|
NS_WARNING("CheckSameOrigin called on script w/o principals; should this happen?");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sourcePrincipal == mSystemPrincipal)
|
|
|
|
{
|
|
|
|
// This is a system (chrome) script, so allow access
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the original URI from the source principal.
|
|
|
|
// This has the effect of ignoring any change to document.domain
|
|
|
|
// which must be done to avoid DNS spoofing (bug 154930)
|
|
|
|
nsCOMPtr<nsIURI> sourceURI;
|
|
|
|
sourcePrincipal->GetDomain(getter_AddRefs(sourceURI));
|
|
|
|
if (!sourceURI) {
|
|
|
|
sourcePrincipal->GetURI(getter_AddRefs(sourceURI));
|
|
|
|
NS_ENSURE_TRUE(sourceURI, NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compare origins
|
|
|
|
if (!SecurityCompareURIs(sourceURI, aTargetURI))
|
|
|
|
{
|
|
|
|
ReportError(cx, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI, aTargetURI);
|
2008-03-17 07:10:48 -07:00
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
|
2007-10-26 18:46:09 -07:00
|
|
|
nsIURI* aTargetURI,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool reportError)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
if (!SecurityCompareURIs(aSourceURI, aTargetURI))
|
|
|
|
{
|
2007-10-26 18:46:09 -07:00
|
|
|
if (reportError) {
|
2012-07-30 07:20:58 -07:00
|
|
|
ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"),
|
2007-03-22 10:30:00 -07:00
|
|
|
aSourceURI, aTargetURI);
|
2007-10-26 18:46:09 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2012-08-22 08:56:38 -07:00
|
|
|
nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction,
|
2008-01-15 07:50:57 -08:00
|
|
|
nsAXPCNativeCallContext* aCallContext,
|
2007-03-22 10:30:00 -07:00
|
|
|
JSContext* cx, JSObject* aJSObject,
|
2012-07-17 22:28:47 -07:00
|
|
|
nsISupports* aObj,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIClassInfo* aClassInfo,
|
2013-12-13 19:15:43 -08:00
|
|
|
const char* aClassName, jsid aProperty)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsresult rv;
|
2013-05-12 12:52:21 -07:00
|
|
|
JS::RootedObject jsObject(cx, aJSObject);
|
|
|
|
JS::RootedId property(cx, aProperty);
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIPrincipal* subjectPrincipal = GetSubjectPrincipal(cx, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (!subjectPrincipal || subjectPrincipal == mSystemPrincipal)
|
|
|
|
// We have native code or the system principal: just allow access
|
|
|
|
return NS_OK;
|
|
|
|
|
2008-07-28 23:03:19 -07:00
|
|
|
nsCOMPtr<nsIPrincipal> objectPrincipal;
|
|
|
|
|
Bug 913734 - Stop consulting domain policies in CAPS. r=mrbkap
The whole LookupPolicy juggernaut is basically a mechanism for setting custom
per-(protocol, origin, property, action) access control in the preferences
service.
There are two sets of preferences currently in all.js. One of them is set up
for mailnews, for the mailbox:, imap:, and news: protocols. According to jst,
this was designed as a whack-a-mole security mechanism for javascript running
in HTML email. IIUC, we no longer allow JS to run at all in mailnews, so this
is obsolete.
The other mechanism appears to be our old-fashioned implementation of the
same-origin policy, which has been obsoleted by the new compartment
architecture.
In addition, most of this stuff was obsoleted by the new dom bindings, since
these DOM classes no longer go through XPCWrappedNativeJSOps, and thus no
longer trigger these security checks at all.
We stop using the infrastructure in this patch, and rip it out in the next one.
2013-12-13 19:15:43 -08:00
|
|
|
// Even though security wrappers have handled our cross-origin access policy
|
|
|
|
// since FF4, we've still always called into this function, and have relied
|
|
|
|
// on the CAPS policy mechanism to manually approve each cross-origin property
|
|
|
|
// based on a whitelist in all.js. This whitelist has drifted out of sync
|
|
|
|
// with the canonical one in AccessCheck.cpp, but it's always been more
|
|
|
|
// permissive, so we never noticed. This machinery is going away, so for now
|
|
|
|
// let's just skip the check for cross-origin property accesses that we know
|
|
|
|
// we get right.
|
|
|
|
//
|
|
|
|
// Note that while it would be nice to just rely on aClassName here, it
|
|
|
|
// isn't set reliably by callers. :-(
|
|
|
|
const char *className = aClassName;
|
|
|
|
if (!className && jsObject) {
|
|
|
|
className = JS_GetClass(jsObject)->name;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
Bug 913734 - Stop consulting domain policies in CAPS. r=mrbkap
The whole LookupPolicy juggernaut is basically a mechanism for setting custom
per-(protocol, origin, property, action) access control in the preferences
service.
There are two sets of preferences currently in all.js. One of them is set up
for mailnews, for the mailbox:, imap:, and news: protocols. According to jst,
this was designed as a whack-a-mole security mechanism for javascript running
in HTML email. IIUC, we no longer allow JS to run at all in mailnews, so this
is obsolete.
The other mechanism appears to be our old-fashioned implementation of the
same-origin policy, which has been obsoleted by the new compartment
architecture.
In addition, most of this stuff was obsoleted by the new dom bindings, since
these DOM classes no longer go through XPCWrappedNativeJSOps, and thus no
longer trigger these security checks at all.
We stop using the infrastructure in this patch, and rip it out in the next one.
2013-12-13 19:15:43 -08:00
|
|
|
if (className &&
|
|
|
|
(!strcmp(className, "Window") || !strcmp(className, "Location")))
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
Bug 913734 - Stop consulting domain policies in CAPS. r=mrbkap
The whole LookupPolicy juggernaut is basically a mechanism for setting custom
per-(protocol, origin, property, action) access control in the preferences
service.
There are two sets of preferences currently in all.js. One of them is set up
for mailnews, for the mailbox:, imap:, and news: protocols. According to jst,
this was designed as a whack-a-mole security mechanism for javascript running
in HTML email. IIUC, we no longer allow JS to run at all in mailnews, so this
is obsolete.
The other mechanism appears to be our old-fashioned implementation of the
same-origin policy, which has been obsoleted by the new compartment
architecture.
In addition, most of this stuff was obsoleted by the new dom bindings, since
these DOM classes no longer go through XPCWrappedNativeJSOps, and thus no
longer trigger these security checks at all.
We stop using the infrastructure in this patch, and rip it out in the next one.
2013-12-13 19:15:43 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Bug 913734 - Stop consulting domain policies in CAPS. r=mrbkap
The whole LookupPolicy juggernaut is basically a mechanism for setting custom
per-(protocol, origin, property, action) access control in the preferences
service.
There are two sets of preferences currently in all.js. One of them is set up
for mailnews, for the mailbox:, imap:, and news: protocols. According to jst,
this was designed as a whack-a-mole security mechanism for javascript running
in HTML email. IIUC, we no longer allow JS to run at all in mailnews, so this
is obsolete.
The other mechanism appears to be our old-fashioned implementation of the
same-origin policy, which has been obsoleted by the new compartment
architecture.
In addition, most of this stuff was obsoleted by the new dom bindings, since
these DOM classes no longer go through XPCWrappedNativeJSOps, and thus no
longer trigger these security checks at all.
We stop using the infrastructure in this patch, and rip it out in the next one.
2013-12-13 19:15:43 -08:00
|
|
|
// Hold the class info data here so we don't have to go back to virtual
|
|
|
|
// methods all the time
|
|
|
|
ClassInfoData classInfoData(aClassInfo, aClassName);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Bug 913734 - Stop consulting domain policies in CAPS. r=mrbkap
The whole LookupPolicy juggernaut is basically a mechanism for setting custom
per-(protocol, origin, property, action) access control in the preferences
service.
There are two sets of preferences currently in all.js. One of them is set up
for mailnews, for the mailbox:, imap:, and news: protocols. According to jst,
this was designed as a whack-a-mole security mechanism for javascript running
in HTML email. IIUC, we no longer allow JS to run at all in mailnews, so this
is obsolete.
The other mechanism appears to be our old-fashioned implementation of the
same-origin policy, which has been obsoleted by the new compartment
architecture.
In addition, most of this stuff was obsoleted by the new dom bindings, since
these DOM classes no longer go through XPCWrappedNativeJSOps, and thus no
longer trigger these security checks at all.
We stop using the infrastructure in this patch, and rip it out in the next one.
2013-12-13 19:15:43 -08:00
|
|
|
// If we were called from somewhere other than XPConnect
|
|
|
|
// (no XPC call context), assume this is a DOM class. Otherwise,
|
|
|
|
// ask the ClassInfo.
|
|
|
|
if (aCallContext && !classInfoData.IsDOMClass()) {
|
|
|
|
rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
|
|
|
} else {
|
|
|
|
if (!jsObject) {
|
|
|
|
NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
Bug 913734 - Stop consulting domain policies in CAPS. r=mrbkap
The whole LookupPolicy juggernaut is basically a mechanism for setting custom
per-(protocol, origin, property, action) access control in the preferences
service.
There are two sets of preferences currently in all.js. One of them is set up
for mailnews, for the mailbox:, imap:, and news: protocols. According to jst,
this was designed as a whack-a-mole security mechanism for javascript running
in HTML email. IIUC, we no longer allow JS to run at all in mailnews, so this
is obsolete.
The other mechanism appears to be our old-fashioned implementation of the
same-origin policy, which has been obsoleted by the new compartment
architecture.
In addition, most of this stuff was obsoleted by the new dom bindings, since
these DOM classes no longer go through XPCWrappedNativeJSOps, and thus no
longer trigger these security checks at all.
We stop using the infrastructure in this patch, and rip it out in the next one.
2013-12-13 19:15:43 -08:00
|
|
|
nsCOMPtr<nsIPrincipal> principalHolder;
|
|
|
|
objectPrincipal = doGetObjectPrincipal(jsObject);
|
|
|
|
if (!objectPrincipal)
|
|
|
|
rv = NS_ERROR_DOM_SECURITY_ERR;
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
rv = CheckSameOriginDOMProp(subjectPrincipal, objectPrincipal,
|
|
|
|
aAction);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--See if the object advertises a non-default level of access
|
|
|
|
// using nsISecurityCheckedComponent
|
|
|
|
nsCOMPtr<nsISecurityCheckedComponent> checkedComponent =
|
|
|
|
do_QueryInterface(aObj);
|
|
|
|
|
|
|
|
nsXPIDLCString objectSecurityLevel;
|
|
|
|
if (checkedComponent)
|
|
|
|
{
|
2007-08-30 17:52:58 -07:00
|
|
|
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
|
|
|
nsCOMPtr<nsIInterfaceInfo> interfaceInfo;
|
2012-07-30 07:20:58 -07:00
|
|
|
const nsIID* objIID = nullptr;
|
2007-08-30 17:52:58 -07:00
|
|
|
rv = aCallContext->GetCalleeWrapper(getter_AddRefs(wrapper));
|
2010-03-22 15:50:04 -07:00
|
|
|
if (NS_SUCCEEDED(rv) && wrapper)
|
2013-05-12 12:52:21 -07:00
|
|
|
rv = wrapper->FindInterfaceWithMember(property, getter_AddRefs(interfaceInfo));
|
2010-03-22 15:50:04 -07:00
|
|
|
if (NS_SUCCEEDED(rv) && interfaceInfo)
|
2007-08-30 17:52:58 -07:00
|
|
|
rv = interfaceInfo->GetIIDShared(&objIID);
|
2010-03-22 15:50:04 -07:00
|
|
|
if (NS_SUCCEEDED(rv) && objIID)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
switch (aAction)
|
|
|
|
{
|
|
|
|
case nsIXPCSecurityManager::ACCESS_GET_PROPERTY:
|
|
|
|
checkedComponent->CanGetProperty(objIID,
|
2013-05-12 12:52:21 -07:00
|
|
|
IDToString(cx, property),
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_Copies(objectSecurityLevel));
|
|
|
|
break;
|
|
|
|
case nsIXPCSecurityManager::ACCESS_SET_PROPERTY:
|
|
|
|
checkedComponent->CanSetProperty(objIID,
|
2013-05-12 12:52:21 -07:00
|
|
|
IDToString(cx, property),
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_Copies(objectSecurityLevel));
|
|
|
|
break;
|
|
|
|
case nsIXPCSecurityManager::ACCESS_CALL_METHOD:
|
|
|
|
checkedComponent->CanCallMethod(objIID,
|
2013-05-12 12:52:21 -07:00
|
|
|
IDToString(cx, property),
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_Copies(objectSecurityLevel));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-05-12 12:52:21 -07:00
|
|
|
rv = CheckXPCPermissions(cx, aObj, jsObject, subjectPrincipal,
|
2009-05-13 15:01:01 -07:00
|
|
|
objectSecurityLevel);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (NS_FAILED(rv)) //-- Security tests failed, access is denied, report error
|
|
|
|
{
|
|
|
|
nsAutoString stringName;
|
|
|
|
switch(aAction)
|
|
|
|
{
|
|
|
|
case nsIXPCSecurityManager::ACCESS_GET_PROPERTY:
|
2008-07-28 23:03:19 -07:00
|
|
|
stringName.AssignLiteral("GetPropertyDeniedOrigins");
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
case nsIXPCSecurityManager::ACCESS_SET_PROPERTY:
|
2008-07-28 23:03:19 -07:00
|
|
|
stringName.AssignLiteral("SetPropertyDeniedOrigins");
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
case nsIXPCSecurityManager::ACCESS_CALL_METHOD:
|
2008-07-28 23:03:19 -07:00
|
|
|
stringName.AssignLiteral("CallMethodDeniedOrigins");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2010-12-22 16:55:42 -08:00
|
|
|
// Null out objectPrincipal for now, so we don't leak information about
|
|
|
|
// it. Whenever we can report different error strings to content and
|
|
|
|
// the UI we can take this out again.
|
2012-07-30 07:20:58 -07:00
|
|
|
objectPrincipal = nullptr;
|
2010-12-22 16:55:42 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ConvertUTF8toUTF16 className(classInfoData.GetName());
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString subjectOrigin;
|
|
|
|
nsAutoCString subjectDomain;
|
2009-05-20 18:49:42 -07:00
|
|
|
if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin) {
|
2009-07-26 18:27:33 -07:00
|
|
|
nsCOMPtr<nsIURI> uri, domain;
|
|
|
|
subjectPrincipal->GetURI(getter_AddRefs(uri));
|
2012-08-20 11:22:34 -07:00
|
|
|
if (uri) { // Object principal might be expanded
|
|
|
|
GetOriginFromURI(uri, subjectOrigin);
|
|
|
|
}
|
2009-07-26 18:27:33 -07:00
|
|
|
subjectPrincipal->GetDomain(getter_AddRefs(domain));
|
|
|
|
if (domain) {
|
|
|
|
GetOriginFromURI(domain, subjectDomain);
|
|
|
|
}
|
2009-05-20 18:49:42 -07:00
|
|
|
} else {
|
|
|
|
subjectOrigin.AssignLiteral("the security manager");
|
|
|
|
}
|
2008-07-28 23:03:19 -07:00
|
|
|
NS_ConvertUTF8toUTF16 subjectOriginUnicode(subjectOrigin);
|
2009-07-26 18:27:33 -07:00
|
|
|
NS_ConvertUTF8toUTF16 subjectDomainUnicode(subjectDomain);
|
2008-07-28 23:03:19 -07:00
|
|
|
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString objectOrigin;
|
|
|
|
nsAutoCString objectDomain;
|
2009-05-20 18:49:42 -07:00
|
|
|
if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin &&
|
|
|
|
objectPrincipal) {
|
2009-07-26 18:27:33 -07:00
|
|
|
nsCOMPtr<nsIURI> uri, domain;
|
|
|
|
objectPrincipal->GetURI(getter_AddRefs(uri));
|
|
|
|
if (uri) { // Object principal might be system
|
|
|
|
GetOriginFromURI(uri, objectOrigin);
|
|
|
|
}
|
|
|
|
objectPrincipal->GetDomain(getter_AddRefs(domain));
|
|
|
|
if (domain) {
|
|
|
|
GetOriginFromURI(domain, objectDomain);
|
|
|
|
}
|
2008-07-28 23:03:19 -07:00
|
|
|
}
|
|
|
|
NS_ConvertUTF8toUTF16 objectOriginUnicode(objectOrigin);
|
2009-07-26 18:27:33 -07:00
|
|
|
NS_ConvertUTF8toUTF16 objectDomainUnicode(objectDomain);
|
|
|
|
|
2008-07-28 23:03:19 -07:00
|
|
|
nsXPIDLString errorMsg;
|
2007-03-22 10:30:00 -07:00
|
|
|
const PRUnichar *formatStrings[] =
|
|
|
|
{
|
2008-07-28 23:03:19 -07:00
|
|
|
subjectOriginUnicode.get(),
|
2007-03-22 10:30:00 -07:00
|
|
|
className.get(),
|
2013-05-12 12:52:21 -07:00
|
|
|
IDToString(cx, property),
|
2009-07-26 18:27:33 -07:00
|
|
|
objectOriginUnicode.get(),
|
|
|
|
subjectDomainUnicode.get(),
|
|
|
|
objectDomainUnicode.get()
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t length = ArrayLength(formatStrings);
|
2008-07-28 23:03:19 -07:00
|
|
|
|
2009-07-26 18:27:33 -07:00
|
|
|
// XXXbz Our localization system is stupid and can't handle not showing
|
|
|
|
// some strings that get passed in. Which means that we have to get
|
|
|
|
// our length precisely right: it has to be exactly the number of
|
|
|
|
// strings our format string wants. This means we'll have to move
|
|
|
|
// strings in the array as needed, sadly...
|
2009-05-20 18:49:42 -07:00
|
|
|
if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin ||
|
|
|
|
!objectPrincipal) {
|
2008-07-28 23:03:19 -07:00
|
|
|
stringName.AppendLiteral("OnlySubject");
|
2009-07-26 18:27:33 -07:00
|
|
|
length -= 3;
|
|
|
|
} else {
|
|
|
|
// default to a length that doesn't include the domains, then
|
|
|
|
// increase it as needed.
|
|
|
|
length -= 2;
|
|
|
|
if (!subjectDomainUnicode.IsEmpty()) {
|
|
|
|
stringName.AppendLiteral("SubjectDomain");
|
|
|
|
length += 1;
|
|
|
|
}
|
|
|
|
if (!objectDomainUnicode.IsEmpty()) {
|
|
|
|
stringName.AppendLiteral("ObjectDomain");
|
|
|
|
length += 1;
|
2011-10-10 22:50:08 -07:00
|
|
|
if (length != ArrayLength(formatStrings)) {
|
2009-07-26 18:27:33 -07:00
|
|
|
// We have an object domain but not a subject domain.
|
|
|
|
// Scoot our string over one slot. See the XXX comment
|
|
|
|
// above for why we need to do this.
|
|
|
|
formatStrings[length-1] = formatStrings[length];
|
|
|
|
}
|
|
|
|
}
|
2008-07-28 23:03:19 -07:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// We need to keep our existing failure rv and not override it
|
|
|
|
// with a likely success code from the following string bundle
|
|
|
|
// call in order to throw the correct security exception later.
|
|
|
|
nsresult rv2 = sStrBundle->FormatStringFromName(stringName.get(),
|
|
|
|
formatStrings,
|
2008-07-28 23:03:19 -07:00
|
|
|
length,
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_Copies(errorMsg));
|
2008-07-28 23:03:19 -07:00
|
|
|
if (NS_FAILED(rv2)) {
|
|
|
|
// Might just be missing the string... Do our best
|
|
|
|
errorMsg = stringName;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
SetPendingException(cx, errorMsg.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2008-03-18 14:14:49 -07:00
|
|
|
/* static */
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult
|
2008-03-18 14:14:49 -07:00
|
|
|
nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
|
2010-02-02 02:29:15 -08:00
|
|
|
nsIPrincipal* aObject)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
** Get origin of subject and object and compare.
|
|
|
|
*/
|
|
|
|
if (aSubject == aObject)
|
|
|
|
return NS_OK;
|
|
|
|
|
2012-10-24 10:50:25 -07:00
|
|
|
if (!AppAttributesEqual(aSubject, aObject)) {
|
|
|
|
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
2010-02-02 02:29:15 -08:00
|
|
|
// Default to false, and change if that turns out wrong.
|
2011-09-28 23:19:26 -07:00
|
|
|
bool subjectSetDomain = false;
|
|
|
|
bool objectSetDomain = false;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> subjectURI;
|
|
|
|
nsCOMPtr<nsIURI> objectURI;
|
|
|
|
|
2010-02-02 02:29:15 -08:00
|
|
|
aSubject->GetDomain(getter_AddRefs(subjectURI));
|
|
|
|
if (!subjectURI) {
|
2007-03-22 10:30:00 -07:00
|
|
|
aSubject->GetURI(getter_AddRefs(subjectURI));
|
2010-02-02 02:29:15 -08:00
|
|
|
} else {
|
2011-10-17 07:59:28 -07:00
|
|
|
subjectSetDomain = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2010-02-02 02:29:15 -08:00
|
|
|
aObject->GetDomain(getter_AddRefs(objectURI));
|
|
|
|
if (!objectURI) {
|
|
|
|
aObject->GetURI(getter_AddRefs(objectURI));
|
|
|
|
} else {
|
2011-10-17 07:59:28 -07:00
|
|
|
objectSetDomain = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (SecurityCompareURIs(subjectURI, objectURI))
|
|
|
|
{ // If either the subject or the object has changed its principal by
|
|
|
|
// explicitly setting document.domain then the other must also have
|
|
|
|
// done so in order to be considered the same origin. This prevents
|
|
|
|
// DNS spoofing based on document.domain (154930)
|
|
|
|
|
|
|
|
// If both or neither explicitly set their domain, allow the access
|
|
|
|
if (subjectSetDomain == objectSetDomain)
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Access tests failed, so now report error.
|
|
|
|
*/
|
|
|
|
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
2008-10-08 06:16:27 -07:00
|
|
|
// It's important that
|
|
|
|
//
|
2010-02-02 02:29:15 -08:00
|
|
|
// CheckSameOriginPrincipal(A, B) == NS_OK
|
2008-10-08 06:16:27 -07:00
|
|
|
//
|
|
|
|
// imply
|
|
|
|
//
|
|
|
|
// HashPrincipalByOrigin(A) == HashPrincipalByOrigin(B)
|
|
|
|
//
|
|
|
|
// if principals A and B could ever be used as keys in a hashtable.
|
|
|
|
// Violation of this invariant leads to spurious failures of hashtable
|
|
|
|
// lookups. See bug 454850.
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
/*static*/ uint32_t
|
2008-10-08 06:16:27 -07:00
|
|
|
nsScriptSecurityManager::HashPrincipalByOrigin(nsIPrincipal* aPrincipal)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
aPrincipal->GetDomain(getter_AddRefs(uri));
|
|
|
|
if (!uri)
|
|
|
|
aPrincipal->GetURI(getter_AddRefs(uri));
|
|
|
|
return SecurityHashURI(uri);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-10-24 10:50:25 -07:00
|
|
|
/* static */ bool
|
|
|
|
nsScriptSecurityManager::AppAttributesEqual(nsIPrincipal* aFirst,
|
|
|
|
nsIPrincipal* aSecond)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aFirst && aSecond, "Don't pass null pointers!");
|
|
|
|
|
|
|
|
uint32_t firstAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
|
|
|
|
if (!aFirst->GetUnknownAppId()) {
|
|
|
|
firstAppId = aFirst->GetAppId();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t secondAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
|
|
|
|
if (!aSecond->GetUnknownAppId()) {
|
|
|
|
secondAppId = aSecond->GetAppId();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((firstAppId == secondAppId) &&
|
|
|
|
(aFirst->GetIsInBrowserElement() == aSecond->GetIsInBrowserElement()));
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult
|
|
|
|
nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
|
|
|
|
nsIPrincipal* aObject,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aAction)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-03-18 14:14:49 -07:00
|
|
|
nsresult rv;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool subsumes;
|
2010-02-02 02:29:15 -08:00
|
|
|
rv = aSubject->Subsumes(aObject, &subsumes);
|
|
|
|
if (NS_SUCCEEDED(rv) && !subsumes) {
|
|
|
|
rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
2008-03-18 14:14:49 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Content can't ever touch chrome (we check for UniversalXPConnect later)
|
|
|
|
*/
|
|
|
|
if (aObject == mSystemPrincipal)
|
|
|
|
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Access tests failed, so now report error.
|
|
|
|
*/
|
|
|
|
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI)
|
|
|
|
{
|
|
|
|
// Get principal of currently executing script.
|
|
|
|
nsresult rv;
|
|
|
|
nsIPrincipal* principal = GetSubjectPrincipal(cx, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
// Native code can load all URIs.
|
|
|
|
if (!principal)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
rv = CheckLoadURIWithPrincipal(principal, aURI,
|
|
|
|
nsIScriptSecurityManager::STANDARD);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// OK to load
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if we're attempting to load a file: URI. If so, let a
|
2011-12-30 09:35:52 -08:00
|
|
|
// UniversalXPConnect capability trump the above check.
|
2011-09-28 23:19:26 -07:00
|
|
|
bool isFile = false;
|
|
|
|
bool isRes = false;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(aURI->SchemeIs("file", &isFile)) ||
|
|
|
|
NS_FAILED(aURI->SchemeIs("resource", &isRes)))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (isFile || isRes)
|
|
|
|
{
|
2012-10-21 23:29:55 -07:00
|
|
|
if (SubjectIsPrivileged())
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Report error.
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString spec;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(aURI->GetAsciiSpec(spec)))
|
|
|
|
return NS_ERROR_FAILURE;
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString msg("Access to '");
|
2009-05-19 21:57:37 -07:00
|
|
|
msg.Append(spec);
|
|
|
|
msg.AppendLiteral("' from script denied");
|
|
|
|
SetPendingException(cx, msg.get());
|
2008-03-17 07:10:48 -07:00
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method to handle cases where a flag passed to
|
|
|
|
* CheckLoadURIWithPrincipal means denying loading if the given URI has certain
|
|
|
|
* nsIProtocolHandler flags set.
|
|
|
|
* @return if success, access is allowed. Otherwise, deny access
|
|
|
|
*/
|
|
|
|
static nsresult
|
2012-08-22 08:56:38 -07:00
|
|
|
DenyAccessIfURIHasFlags(nsIURI* aURI, uint32_t aURIFlags)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aURI, "Must have URI!");
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool uriHasFlags;
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv =
|
|
|
|
NS_URIChainHasFlags(aURI, aURIFlags, &uriHasFlags);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (uriHasFlags) {
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
|
|
|
nsIURI *aTargetURI,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aFlags)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aPrincipal, "CheckLoadURIWithPrincipal must have a principal");
|
|
|
|
// If someone passes a flag that we don't understand, we should
|
|
|
|
// fail, because they may need a security check that we don't
|
|
|
|
// provide.
|
|
|
|
NS_ENSURE_FALSE(aFlags & ~(nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
|
|
|
|
nsIScriptSecurityManager::ALLOW_CHROME |
|
|
|
|
nsIScriptSecurityManager::DISALLOW_SCRIPT |
|
2012-09-13 07:16:17 -07:00
|
|
|
nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL |
|
|
|
|
nsIScriptSecurityManager::DONT_REPORT_ERRORS),
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ERROR_UNEXPECTED);
|
|
|
|
NS_ENSURE_ARG_POINTER(aPrincipal);
|
2009-01-01 15:45:23 -08:00
|
|
|
NS_ENSURE_ARG_POINTER(aTargetURI);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-03-14 11:55:47 -07:00
|
|
|
// If DISALLOW_INHERIT_PRINCIPAL is set, we prevent loading of URIs which
|
|
|
|
// would do such inheriting. That would be URIs that do not have their own
|
|
|
|
// security context. We do this even for the system principal.
|
|
|
|
if (aFlags & nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL) {
|
|
|
|
nsresult rv =
|
|
|
|
DenyAccessIfURIHasFlags(aTargetURI,
|
|
|
|
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (aPrincipal == mSystemPrincipal) {
|
|
|
|
// Allow access
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-03-14 11:55:47 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIURI> sourceURI;
|
|
|
|
aPrincipal->GetURI(getter_AddRefs(sourceURI));
|
2007-08-06 19:09:16 -07:00
|
|
|
if (!sourceURI) {
|
2012-06-10 16:44:50 -07:00
|
|
|
nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aPrincipal);
|
|
|
|
if (expanded) {
|
|
|
|
nsTArray< nsCOMPtr<nsIPrincipal> > *whiteList;
|
|
|
|
expanded->GetWhiteList(&whiteList);
|
|
|
|
for (uint32_t i = 0; i < whiteList->Length(); ++i) {
|
|
|
|
nsresult rv = CheckLoadURIWithPrincipal((*whiteList)[i],
|
|
|
|
aTargetURI,
|
|
|
|
aFlags);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// Allow access if it succeeded with one of the white listed principals
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2013-04-27 16:49:43 -07:00
|
|
|
// None of our whitelisted principals worked.
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
2012-06-10 16:44:50 -07:00
|
|
|
}
|
|
|
|
NS_ERROR("Non-system principals or expanded principal passed to CheckLoadURIWithPrincipal "
|
2007-08-06 19:09:16 -07:00
|
|
|
"must have a URI!");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Automatic loads are not allowed from certain protocols.
|
|
|
|
if (aFlags & nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT) {
|
|
|
|
nsresult rv =
|
|
|
|
DenyAccessIfURIHasFlags(sourceURI,
|
|
|
|
nsIProtocolHandler::URI_FORBIDS_AUTOMATIC_DOCUMENT_REPLACEMENT);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If either URI is a nested URI, get the base URI
|
|
|
|
nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(sourceURI);
|
|
|
|
nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
|
|
|
|
|
|
|
|
//-- get the target scheme
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString targetScheme;
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv = targetBaseURI->GetScheme(targetScheme);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
//-- Some callers do not allow loading javascript:
|
|
|
|
if ((aFlags & nsIScriptSecurityManager::DISALLOW_SCRIPT) &&
|
|
|
|
targetScheme.EqualsLiteral("javascript"))
|
|
|
|
{
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
|
2010-03-02 23:51:09 -08:00
|
|
|
NS_NAMED_LITERAL_STRING(errorTag, "CheckLoadURIError");
|
2012-09-13 07:16:17 -07:00
|
|
|
bool reportErrors = !(aFlags & nsIScriptSecurityManager::DONT_REPORT_ERRORS);
|
2010-03-02 23:51:09 -08:00
|
|
|
|
|
|
|
// Check for uris that are only loadable by principals that subsume them
|
2011-09-28 23:19:26 -07:00
|
|
|
bool hasFlags;
|
2010-03-02 23:51:09 -08:00
|
|
|
rv = NS_URIChainHasFlags(targetBaseURI,
|
|
|
|
nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS,
|
|
|
|
&hasFlags);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (hasFlags) {
|
2012-08-20 11:34:33 -07:00
|
|
|
return aPrincipal->CheckMayLoad(targetBaseURI, true, false);
|
2010-03-02 23:51:09 -08:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//-- get the source scheme
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString sourceScheme;
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = sourceBaseURI->GetScheme(sourceScheme);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2008-03-27 20:46:15 -07:00
|
|
|
if (sourceScheme.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME)) {
|
|
|
|
// A null principal can target its own URI.
|
|
|
|
if (sourceURI == aTargetURI) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (targetScheme.Equals(sourceScheme,
|
|
|
|
nsCaseInsensitiveCStringComparator()))
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// every scheme can access another URI from the same scheme,
|
2012-09-25 12:33:01 -07:00
|
|
|
// as long as they don't represent null principals...
|
|
|
|
// Or they don't require an special permission to do so
|
|
|
|
// See bug#773886
|
|
|
|
|
|
|
|
bool hasFlags;
|
|
|
|
rv = NS_URIChainHasFlags(targetBaseURI,
|
|
|
|
nsIProtocolHandler::URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM,
|
|
|
|
&hasFlags);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (hasFlags) {
|
|
|
|
// In this case, we allow opening only if the source and target URIS
|
|
|
|
// are on the same domain, or the opening URI has the webapps
|
|
|
|
// permision granted
|
|
|
|
if (!SecurityCompareURIs(sourceBaseURI,targetBaseURI) &&
|
|
|
|
!nsContentUtils::IsExactSitePermAllow(aPrincipal,WEBAPPS_PERM_NAME)){
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the schemes don't match, the policy is specified by the protocol
|
|
|
|
// flags on the target URI. Note that the order of policy checks here is
|
|
|
|
// very important! We start from most restrictive and work our way down.
|
|
|
|
// Note that since we're working with the innermost URI, we can just use
|
|
|
|
// the methods that work on chains of nested URIs and they will only look
|
|
|
|
// at the flags for our one URI.
|
|
|
|
|
|
|
|
// Check for system target URI
|
|
|
|
rv = DenyAccessIfURIHasFlags(targetBaseURI,
|
|
|
|
nsIProtocolHandler::URI_DANGEROUS_TO_LOAD);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
// Deny access, since the origin principal is not system
|
2012-09-13 07:16:17 -07:00
|
|
|
if (reportErrors) {
|
|
|
|
ReportError(nullptr, errorTag, sourceURI, aTargetURI);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for chrome target URI
|
|
|
|
rv = NS_URIChainHasFlags(targetBaseURI,
|
|
|
|
nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
|
|
|
&hasFlags);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (hasFlags) {
|
|
|
|
if (aFlags & nsIScriptSecurityManager::ALLOW_CHROME) {
|
2008-04-12 14:26:19 -07:00
|
|
|
if (!targetScheme.EqualsLiteral("chrome")) {
|
|
|
|
// for now don't change behavior for resource: or moz-icon:
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// allow load only if chrome package is whitelisted
|
|
|
|
nsCOMPtr<nsIXULChromeRegistry> reg(do_GetService(
|
|
|
|
NS_CHROMEREGISTRY_CONTRACTID));
|
|
|
|
if (reg) {
|
2011-09-28 23:19:26 -07:00
|
|
|
bool accessAllowed = false;
|
2008-04-12 14:26:19 -07:00
|
|
|
reg->AllowContentToAccess(targetBaseURI, &accessAllowed);
|
|
|
|
if (accessAllowed) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// resource: and chrome: are equivalent, securitywise
|
|
|
|
// That's bogus!! Fix this. But watch out for
|
|
|
|
// the view-source stylesheet?
|
2011-09-28 23:19:26 -07:00
|
|
|
bool sourceIsChrome;
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = NS_URIChainHasFlags(sourceBaseURI,
|
|
|
|
nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
|
|
|
&sourceIsChrome);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (sourceIsChrome) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-09-13 07:16:17 -07:00
|
|
|
if (reportErrors) {
|
|
|
|
ReportError(nullptr, errorTag, sourceURI, aTargetURI);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for target URI pointing to a file
|
|
|
|
rv = NS_URIChainHasFlags(targetBaseURI,
|
|
|
|
nsIProtocolHandler::URI_IS_LOCAL_FILE,
|
|
|
|
&hasFlags);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (hasFlags) {
|
|
|
|
// resource: and chrome: are equivalent, securitywise
|
|
|
|
// That's bogus!! Fix this. But watch out for
|
|
|
|
// the view-source stylesheet?
|
2011-09-28 23:19:26 -07:00
|
|
|
bool sourceIsChrome;
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = NS_URIChainHasFlags(sourceURI,
|
|
|
|
nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
|
|
|
&sourceIsChrome);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (sourceIsChrome) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-09-13 07:16:17 -07:00
|
|
|
if (reportErrors) {
|
|
|
|
ReportError(nullptr, errorTag, sourceURI, aTargetURI);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// OK, everyone is allowed to load this, since unflagged handlers are
|
|
|
|
// deprecated but treated as URI_LOADABLE_BY_ANYONE. But check whether we
|
|
|
|
// need to warn. At some point we'll want to make this warning into an
|
|
|
|
// error and treat unflagged handlers as URI_DANGEROUS_TO_LOAD.
|
|
|
|
rv = NS_URIChainHasFlags(targetBaseURI,
|
|
|
|
nsIProtocolHandler::URI_LOADABLE_BY_ANYONE,
|
|
|
|
&hasFlags);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (!hasFlags) {
|
|
|
|
nsXPIDLString message;
|
|
|
|
NS_ConvertASCIItoUTF16 ucsTargetScheme(targetScheme);
|
|
|
|
const PRUnichar* formatStrings[] = { ucsTargetScheme.get() };
|
|
|
|
rv = sStrBundle->
|
2013-12-12 17:50:01 -08:00
|
|
|
FormatStringFromName(MOZ_UTF16("ProtocolFlagError"),
|
2007-03-22 10:30:00 -07:00
|
|
|
formatStrings,
|
2011-10-10 22:50:08 -07:00
|
|
|
ArrayLength(formatStrings),
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_Copies(message));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsCOMPtr<nsIConsoleService> console(
|
|
|
|
do_GetService("@mozilla.org/consoleservice;1"));
|
|
|
|
NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
console->LogStringMessage(message.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsScriptSecurityManager::ReportError(JSContext* cx, const nsAString& messageTag,
|
|
|
|
nsIURI* aSource, nsIURI* aTarget)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
NS_ENSURE_TRUE(aSource && aTarget, NS_ERROR_NULL_POINTER);
|
|
|
|
|
|
|
|
// Get the source URL spec
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString sourceSpec;
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = aSource->GetAsciiSpec(sourceSpec);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Get the target URL spec
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString targetSpec;
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = aTarget->GetAsciiSpec(targetSpec);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Localize the error message
|
|
|
|
nsXPIDLString message;
|
|
|
|
NS_ConvertASCIItoUTF16 ucsSourceSpec(sourceSpec);
|
|
|
|
NS_ConvertASCIItoUTF16 ucsTargetSpec(targetSpec);
|
|
|
|
const PRUnichar *formatStrings[] = { ucsSourceSpec.get(), ucsTargetSpec.get() };
|
|
|
|
rv = sStrBundle->FormatStringFromName(PromiseFlatString(messageTag).get(),
|
|
|
|
formatStrings,
|
2011-10-10 22:50:08 -07:00
|
|
|
ArrayLength(formatStrings),
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_Copies(message));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// If a JS context was passed in, set a JS exception.
|
|
|
|
// Otherwise, print the error message directly to the JS console
|
|
|
|
// and to standard output
|
|
|
|
if (cx)
|
|
|
|
{
|
|
|
|
SetPendingException(cx, message.get());
|
|
|
|
}
|
|
|
|
else // Print directly to the console
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIConsoleService> console(
|
|
|
|
do_GetService("@mozilla.org/consoleservice;1"));
|
|
|
|
NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
console->LogStringMessage(message.get());
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal* aPrincipal,
|
|
|
|
const nsACString& aTargetURIStr,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aFlags)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIURI> target;
|
|
|
|
rv = NS_NewURI(getter_AddRefs(target), aTargetURIStr,
|
2012-07-30 07:20:58 -07:00
|
|
|
nullptr, nullptr, sIOService);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
|
2013-10-08 19:32:38 -07:00
|
|
|
if (rv == NS_ERROR_DOM_BAD_URI) {
|
|
|
|
// Don't warn because NS_ERROR_DOM_BAD_URI is one of the expected
|
|
|
|
// return values.
|
|
|
|
return rv;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Now start testing fixup -- since aTargetURIStr is a string, not
|
|
|
|
// an nsIURI, we may well end up fixing it up before loading.
|
|
|
|
// Note: This needs to stay in sync with the nsIURIFixup api.
|
|
|
|
nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
|
|
|
|
if (!fixup) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t flags[] = {
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIURIFixup::FIXUP_FLAG_NONE,
|
|
|
|
nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
|
|
|
|
nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
|
|
|
|
nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP |
|
|
|
|
nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
|
|
|
|
};
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
for (uint32_t i = 0; i < ArrayLength(flags); ++i) {
|
2013-05-01 04:04:21 -07:00
|
|
|
rv = fixup->CreateFixupURI(aTargetURIStr, flags[i], nullptr,
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_AddRefs(target));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
|
2013-10-08 19:32:38 -07:00
|
|
|
if (rv == NS_ERROR_DOM_BAD_URI) {
|
|
|
|
// Don't warn because NS_ERROR_DOM_BAD_URI is one of the expected
|
|
|
|
// return values.
|
|
|
|
return rv;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2013-11-12 16:43:35 -08:00
|
|
|
bool
|
|
|
|
nsScriptSecurityManager::ScriptAllowed(JSObject *aGlobal)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2013-11-12 16:43:35 -08:00
|
|
|
MOZ_ASSERT(aGlobal);
|
|
|
|
MOZ_ASSERT(JS_IsGlobalObject(aGlobal) || js::IsOuterObject(aGlobal));
|
|
|
|
AutoJSContext cx;
|
|
|
|
JS::RootedObject global(cx, js::UncheckedUnwrap(aGlobal, /* stopAtOuter = */ false));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2013-11-12 16:43:35 -08:00
|
|
|
// Check the bits on the compartment private.
|
Bug 913734 - Stop consulting domain policies in CAPS. r=mrbkap
The whole LookupPolicy juggernaut is basically a mechanism for setting custom
per-(protocol, origin, property, action) access control in the preferences
service.
There are two sets of preferences currently in all.js. One of them is set up
for mailnews, for the mailbox:, imap:, and news: protocols. According to jst,
this was designed as a whack-a-mole security mechanism for javascript running
in HTML email. IIUC, we no longer allow JS to run at all in mailnews, so this
is obsolete.
The other mechanism appears to be our old-fashioned implementation of the
same-origin policy, which has been obsoleted by the new compartment
architecture.
In addition, most of this stuff was obsoleted by the new dom bindings, since
these DOM classes no longer go through XPCWrappedNativeJSOps, and thus no
longer trigger these security checks at all.
We stop using the infrastructure in this patch, and rip it out in the next one.
2013-12-13 19:15:43 -08:00
|
|
|
return xpc::Scriptability::Get(aGlobal).Allowed();
|
2013-11-12 16:43:31 -08:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
///////////////// Principals ///////////////////////
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal **aSubjectPrincipal)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
*aSubjectPrincipal = doGetSubjectPrincipal(&rv);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
NS_IF_ADDREF(*aSubjectPrincipal);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPrincipal*
|
|
|
|
nsScriptSecurityManager::doGetSubjectPrincipal(nsresult* rv)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(rv, "Null out param");
|
|
|
|
JSContext *cx = GetCurrentJSContext();
|
|
|
|
if (!cx)
|
|
|
|
{
|
|
|
|
*rv = NS_OK;
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return GetSubjectPrincipal(cx, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
|
|
|
|
{
|
|
|
|
NS_ADDREF(*result = mSystemPrincipal);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
nsScriptSecurityManager::SubjectPrincipalIsSystem(bool* aIsSystem)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aIsSystem);
|
2011-10-17 07:59:28 -07:00
|
|
|
*aIsSystem = false;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (!mSystemPrincipal)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrincipal> subject;
|
|
|
|
nsresult rv = GetSubjectPrincipal(getter_AddRefs(subject));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if(!subject)
|
|
|
|
{
|
|
|
|
// No subject principal means no JS is running;
|
|
|
|
// this is the equivalent of system principal code
|
2011-10-17 07:59:28 -07:00
|
|
|
*aIsSystem = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mSystemPrincipal->Equals(subject, aIsSystem);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2012-08-22 08:56:38 -07:00
|
|
|
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId,
|
2012-07-19 15:32:08 -07:00
|
|
|
bool aInMozBrowser,
|
|
|
|
nsIPrincipal **result)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// I _think_ it's safe to not create null principals here based on aURI.
|
|
|
|
// At least all the callers would do the right thing in those cases, as far
|
|
|
|
// as I can tell. --bz
|
2010-03-02 23:51:09 -08:00
|
|
|
|
|
|
|
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
|
|
|
|
if (uriPrinc) {
|
|
|
|
nsCOMPtr<nsIPrincipal> principal;
|
|
|
|
uriPrinc->GetPrincipal(getter_AddRefs(principal));
|
|
|
|
if (!principal || principal == mSystemPrincipal) {
|
|
|
|
return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
principal.forget(result);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
|
|
|
|
if (!codebase)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2012-10-21 23:29:56 -07:00
|
|
|
nsresult rv = codebase->Init(aURI, aAppId, aInMozBrowser);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
NS_ADDREF(*result = codebase);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-07-21 00:29:40 -07:00
|
|
|
nsScriptSecurityManager::GetSimpleCodebasePrincipal(nsIURI* aURI,
|
2012-07-19 20:28:08 -07:00
|
|
|
nsIPrincipal** aPrincipal)
|
|
|
|
{
|
2012-07-21 00:29:40 -07:00
|
|
|
return GetCodebasePrincipalInternal(aURI,
|
|
|
|
nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
|
|
|
false, aPrincipal);
|
2012-07-19 20:28:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetNoAppCodebasePrincipal(nsIURI* aURI,
|
|
|
|
nsIPrincipal** aPrincipal)
|
|
|
|
{
|
|
|
|
return GetCodebasePrincipalInternal(aURI, nsIScriptSecurityManager::NO_APP_ID,
|
2012-07-21 00:29:40 -07:00
|
|
|
false, aPrincipal);
|
2012-07-19 20:28:08 -07:00
|
|
|
}
|
|
|
|
|
2012-10-30 14:24:41 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetCodebasePrincipal(nsIURI* aURI,
|
|
|
|
nsIPrincipal** aPrincipal)
|
|
|
|
{
|
|
|
|
return GetNoAppCodebasePrincipal(aURI, aPrincipal);
|
|
|
|
}
|
|
|
|
|
2012-07-19 20:28:08 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aAppId,
|
2012-07-19 20:28:08 -07:00
|
|
|
bool aInMozBrowser,
|
|
|
|
nsIPrincipal** aPrincipal)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
|
|
|
|
NS_ERROR_INVALID_ARG);
|
|
|
|
|
|
|
|
return GetCodebasePrincipalInternal(aURI, aAppId, aInMozBrowser, aPrincipal);
|
|
|
|
}
|
|
|
|
|
2012-07-20 00:06:24 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
|
|
|
|
nsIDocShell* aDocShell,
|
|
|
|
nsIPrincipal** aPrincipal)
|
|
|
|
{
|
2012-11-10 10:32:36 -08:00
|
|
|
return GetCodebasePrincipalInternal(aURI,
|
|
|
|
aDocShell->GetAppId(),
|
|
|
|
aDocShell->GetIsInBrowserElement(),
|
2012-07-20 00:06:24 -07:00
|
|
|
aPrincipal);
|
|
|
|
}
|
|
|
|
|
2012-07-19 20:28:08 -07:00
|
|
|
nsresult
|
|
|
|
nsScriptSecurityManager::GetCodebasePrincipalInternal(nsIURI *aURI,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aAppId,
|
2012-07-21 00:29:40 -07:00
|
|
|
bool aInMozBrowser,
|
|
|
|
nsIPrincipal **result)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2007-08-06 19:09:16 -07:00
|
|
|
NS_ENSURE_ARG(aURI);
|
2012-07-19 20:28:08 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool inheritsPrincipal;
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv =
|
|
|
|
NS_URIChainHasFlags(aURI,
|
|
|
|
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
|
|
|
&inheritsPrincipal);
|
|
|
|
if (NS_FAILED(rv) || inheritsPrincipal) {
|
|
|
|
return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID, result);
|
|
|
|
}
|
2012-07-19 15:32:08 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIPrincipal> principal;
|
2012-07-19 20:28:08 -07:00
|
|
|
rv = CreateCodebasePrincipal(aURI, aAppId, aInMozBrowser,
|
|
|
|
getter_AddRefs(principal));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IF_ADDREF(*result = principal);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPrincipal*
|
|
|
|
nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
|
|
|
|
nsresult* rv)
|
|
|
|
{
|
2012-06-28 14:47:55 -07:00
|
|
|
*rv = NS_OK;
|
|
|
|
JSCompartment *compartment = js::GetContextCompartment(cx);
|
|
|
|
|
|
|
|
// The context should always be in a compartment, either one it has entered
|
|
|
|
// or the one associated with its global.
|
|
|
|
MOZ_ASSERT(!!compartment);
|
|
|
|
|
|
|
|
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
|
|
|
return nsJSPrincipals::get(principals);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
|
|
|
|
nsIPrincipal **result)
|
|
|
|
{
|
2013-05-20 05:40:06 -07:00
|
|
|
JS::Rooted<JSObject*> obj(aCx, aObj);
|
|
|
|
*result = doGetObjectPrincipal(obj);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!*result)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
NS_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
nsIPrincipal*
|
2013-11-12 16:43:35 -08:00
|
|
|
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
|
2012-06-28 14:47:55 -07:00
|
|
|
{
|
|
|
|
JSCompartment *compartment = js::GetObjectCompartment(aObj);
|
|
|
|
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
2013-09-17 15:29:11 -07:00
|
|
|
return nsJSPrincipals::get(principals);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
// Methods implementing nsIXPCSecurityManager //
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
|
|
|
|
const nsIID &aIID,
|
|
|
|
nsISupports *aObj,
|
2013-12-13 19:15:43 -08:00
|
|
|
nsIClassInfo *aClassInfo)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// XXX Special case for nsIXPCException ?
|
2012-07-30 07:20:58 -07:00
|
|
|
ClassInfoData objClassInfo = ClassInfoData(aClassInfo, nullptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (objClassInfo.IsDOMClass())
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-12-04 19:15:40 -08:00
|
|
|
// We give remote-XUL whitelisted domains a free pass here. See bug 932906.
|
|
|
|
if (!xpc::AllowXBLScope(js::GetContextCompartment(cx)))
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//--See if the object advertises a non-default level of access
|
|
|
|
// using nsISecurityCheckedComponent
|
|
|
|
nsCOMPtr<nsISecurityCheckedComponent> checkedComponent =
|
|
|
|
do_QueryInterface(aObj);
|
|
|
|
|
|
|
|
nsXPIDLCString objectSecurityLevel;
|
|
|
|
if (checkedComponent)
|
|
|
|
checkedComponent->CanCreateWrapper((nsIID *)&aIID, getter_Copies(objectSecurityLevel));
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
nsresult rv = CheckXPCPermissions(cx, aObj, nullptr, nullptr, objectSecurityLevel);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
//-- Access denied, report an error
|
2008-07-28 23:03:19 -07:00
|
|
|
NS_ConvertUTF8toUTF16 strName("CreateWrapperDenied");
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString origin;
|
2008-07-28 23:03:19 -07:00
|
|
|
nsresult rv2;
|
|
|
|
nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv2);
|
|
|
|
if (NS_SUCCEEDED(rv2) && subjectPrincipal) {
|
|
|
|
GetPrincipalDomainOrigin(subjectPrincipal, origin);
|
|
|
|
}
|
|
|
|
NS_ConvertUTF8toUTF16 originUnicode(origin);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ConvertUTF8toUTF16 className(objClassInfo.GetName());
|
2008-07-28 23:03:19 -07:00
|
|
|
const PRUnichar* formatStrings[] = {
|
|
|
|
className.get(),
|
|
|
|
originUnicode.get()
|
|
|
|
};
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t length = ArrayLength(formatStrings);
|
2008-07-28 23:03:19 -07:00
|
|
|
if (originUnicode.IsEmpty()) {
|
|
|
|
--length;
|
|
|
|
} else {
|
|
|
|
strName.AppendLiteral("ForOrigin");
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
nsXPIDLString errorMsg;
|
|
|
|
// We need to keep our existing failure rv and not override it
|
|
|
|
// with a likely success code from the following string bundle
|
|
|
|
// call in order to throw the correct security exception later.
|
2008-07-28 23:03:19 -07:00
|
|
|
rv2 = sStrBundle->FormatStringFromName(strName.get(),
|
|
|
|
formatStrings,
|
|
|
|
length,
|
|
|
|
getter_Copies(errorMsg));
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv2, rv2);
|
|
|
|
|
|
|
|
SetPendingException(cx, errorMsg.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CanCreateInstance(JSContext *cx,
|
|
|
|
const nsCID &aCID)
|
|
|
|
{
|
2013-06-04 12:14:17 -07:00
|
|
|
nsresult rv = CheckXPCPermissions(cx, nullptr, nullptr, nullptr, nullptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
//-- Access denied, report an error
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString errorMsg("Permission denied to create instance of class. CID=");
|
2008-01-11 20:30:42 -08:00
|
|
|
char cidStr[NSID_LENGTH];
|
|
|
|
aCID.ToProvidedString(cidStr);
|
2007-03-22 10:30:00 -07:00
|
|
|
errorMsg.Append(cidStr);
|
|
|
|
SetPendingException(cx, errorMsg.get());
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::CanGetService(JSContext *cx,
|
|
|
|
const nsCID &aCID)
|
|
|
|
{
|
2013-06-04 12:14:17 -07:00
|
|
|
nsresult rv = CheckXPCPermissions(cx, nullptr, nullptr, nullptr, nullptr);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
{
|
|
|
|
//-- Access denied, report an error
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString errorMsg("Permission denied to get service. CID=");
|
2008-01-11 20:30:42 -08:00
|
|
|
char cidStr[NSID_LENGTH];
|
|
|
|
aCID.ToProvidedString(cidStr);
|
2007-03-22 10:30:00 -07:00
|
|
|
errorMsg.Append(cidStr);
|
|
|
|
SetPendingException(cx, errorMsg.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 08:56:38 -07:00
|
|
|
nsScriptSecurityManager::CanAccess(uint32_t aAction,
|
2008-01-15 07:50:57 -08:00
|
|
|
nsAXPCNativeCallContext* aCallContext,
|
2007-03-22 10:30:00 -07:00
|
|
|
JSContext* cx,
|
|
|
|
JSObject* aJSObject,
|
|
|
|
nsISupports* aObj,
|
|
|
|
nsIClassInfo* aClassInfo,
|
2013-12-13 19:15:43 -08:00
|
|
|
jsid aPropertyName)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
return CheckPropertyAccessImpl(aAction, aCallContext, cx,
|
2012-07-17 22:28:47 -07:00
|
|
|
aJSObject, aObj, aClassInfo,
|
2013-12-13 19:15:43 -08:00
|
|
|
nullptr, aPropertyName);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2009-08-06 20:26:33 -07:00
|
|
|
nsScriptSecurityManager::CheckXPCPermissions(JSContext* cx,
|
|
|
|
nsISupports* aObj, JSObject* aJSObject,
|
2009-05-13 15:01:01 -07:00
|
|
|
nsIPrincipal* aSubjectPrincipal,
|
2007-03-22 10:30:00 -07:00
|
|
|
const char* aObjectSecurityLevel)
|
|
|
|
{
|
2013-06-04 12:14:17 -07:00
|
|
|
MOZ_ASSERT(cx);
|
2013-05-12 12:52:21 -07:00
|
|
|
JS::RootedObject jsObject(cx, aJSObject);
|
2012-10-21 23:29:55 -07:00
|
|
|
// Check if the subject is privileged.
|
|
|
|
if (SubjectIsPrivileged())
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
//-- If the object implements nsISecurityCheckedComponent, it has a non-default policy.
|
|
|
|
if (aObjectSecurityLevel)
|
|
|
|
{
|
|
|
|
if (PL_strcasecmp(aObjectSecurityLevel, "allAccess") == 0)
|
|
|
|
return NS_OK;
|
2009-08-06 20:26:33 -07:00
|
|
|
if (cx && PL_strcasecmp(aObjectSecurityLevel, "sameOrigin") == 0)
|
2009-05-13 15:01:01 -07:00
|
|
|
{
|
2009-08-06 20:26:33 -07:00
|
|
|
nsresult rv;
|
2013-05-12 12:52:21 -07:00
|
|
|
if (!jsObject)
|
2009-08-06 20:26:33 -07:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIXPConnectWrappedJS> xpcwrappedjs =
|
|
|
|
do_QueryInterface(aObj);
|
|
|
|
if (xpcwrappedjs)
|
|
|
|
{
|
2013-05-20 05:44:18 -07:00
|
|
|
jsObject = xpcwrappedjs->GetJSObject();
|
|
|
|
NS_ENSURE_STATE(jsObject);
|
2009-08-06 20:26:33 -07:00
|
|
|
}
|
|
|
|
}
|
2009-05-13 15:01:01 -07:00
|
|
|
|
2009-08-06 20:26:33 -07:00
|
|
|
if (!aSubjectPrincipal)
|
2009-05-13 15:01:01 -07:00
|
|
|
{
|
2009-08-06 20:26:33 -07:00
|
|
|
// No subject principal passed in. Compute it.
|
|
|
|
aSubjectPrincipal = GetSubjectPrincipal(cx, &rv);
|
2009-05-13 15:01:01 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2009-08-06 20:26:33 -07:00
|
|
|
}
|
2013-05-12 12:52:21 -07:00
|
|
|
if (aSubjectPrincipal && jsObject)
|
2009-08-06 20:26:33 -07:00
|
|
|
{
|
2013-05-12 12:52:21 -07:00
|
|
|
nsIPrincipal* objectPrincipal = doGetObjectPrincipal(jsObject);
|
2009-08-06 20:26:33 -07:00
|
|
|
|
|
|
|
// Only do anything if we have both a subject and object
|
|
|
|
// principal.
|
|
|
|
if (objectPrincipal)
|
|
|
|
{
|
2011-09-28 23:19:26 -07:00
|
|
|
bool subsumes;
|
2009-08-06 20:26:33 -07:00
|
|
|
rv = aSubjectPrincipal->Subsumes(objectPrincipal, &subsumes);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (subsumes)
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2009-05-13 15:01:01 -07:00
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
else if (PL_strcasecmp(aObjectSecurityLevel, "noAccess") != 0)
|
|
|
|
{
|
2012-10-21 23:29:55 -07:00
|
|
|
if (SubjectIsPrivileged())
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-- Access tests failed
|
|
|
|
return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
// Method implementing nsIChannelEventSink //
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
NS_IMETHODIMP
|
2010-08-04 19:15:55 -07:00
|
|
|
nsScriptSecurityManager::AsyncOnChannelRedirect(nsIChannel* oldChannel,
|
|
|
|
nsIChannel* newChannel,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t redirFlags,
|
2010-08-04 19:15:55 -07:00
|
|
|
nsIAsyncVerifyRedirectCallback *cb)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPrincipal> oldPrincipal;
|
|
|
|
GetChannelPrincipal(oldChannel, getter_AddRefs(oldPrincipal));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> newURI;
|
|
|
|
newChannel->GetURI(getter_AddRefs(newURI));
|
2008-11-25 17:50:04 -08:00
|
|
|
nsCOMPtr<nsIURI> newOriginalURI;
|
|
|
|
newChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-11-25 17:50:04 -08:00
|
|
|
NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
const uint32_t flags =
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
|
|
|
|
nsIScriptSecurityManager::DISALLOW_SCRIPT;
|
2008-11-25 17:50:04 -08:00
|
|
|
nsresult rv = CheckLoadURIWithPrincipal(oldPrincipal, newURI, flags);
|
|
|
|
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
|
|
|
|
rv = CheckLoadURIWithPrincipal(oldPrincipal, newOriginalURI, flags);
|
|
|
|
}
|
2010-08-04 19:15:55 -07:00
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
cb->OnRedirectVerifyCallback(NS_OK);
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////
|
|
|
|
// Method implementing nsIObserver //
|
|
|
|
/////////////////////////////////////
|
2011-06-19 20:00:16 -07:00
|
|
|
const char sJSEnabledPrefName[] = "javascript.enabled";
|
|
|
|
const char sFileOriginPolicyPrefName[] =
|
|
|
|
"security.fileuri.strict_origin_policy";
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-06-19 20:00:16 -07:00
|
|
|
static const char* kObservedPrefs[] = {
|
|
|
|
sJSEnabledPrefName,
|
|
|
|
sFileOriginPolicyPrefName,
|
2012-07-30 07:20:58 -07:00
|
|
|
nullptr
|
2011-06-19 20:00:16 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aTopic,
|
|
|
|
const PRUnichar* aMessage)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
NS_ConvertUTF16toUTF8 messageStr(aMessage);
|
|
|
|
const char *message = messageStr.get();
|
|
|
|
|
|
|
|
static const char jsPrefix[] = "javascript.";
|
2007-09-06 00:02:57 -07:00
|
|
|
static const char securityPrefix[] = "security.";
|
|
|
|
if ((PL_strncmp(message, jsPrefix, sizeof(jsPrefix)-1) == 0) ||
|
|
|
|
(PL_strncmp(message, securityPrefix, sizeof(securityPrefix)-1) == 0) )
|
|
|
|
{
|
|
|
|
ScriptSecurityPrefChanged();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
// Constructor, Destructor, Initialization //
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
nsScriptSecurityManager::nsScriptSecurityManager(void)
|
2013-12-13 19:15:43 -08:00
|
|
|
: mPrefInitialized(false)
|
|
|
|
, mIsJavaScriptEnabled(false)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2013-07-18 10:59:53 -07:00
|
|
|
static_assert(sizeof(intptr_t) == sizeof(void*),
|
|
|
|
"intptr_t and void* have different lengths on this platform. "
|
|
|
|
"This may cause a security failure with the SecurityLevel union.");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsScriptSecurityManager::Init()
|
|
|
|
{
|
2009-01-07 20:42:15 -08:00
|
|
|
InitPrefs();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-04-11 06:55:24 -07:00
|
|
|
nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2010-05-14 02:24:41 -07:00
|
|
|
nsCOMPtr<nsIStringBundleService> bundleService =
|
|
|
|
mozilla::services::GetStringBundleService();
|
|
|
|
if (!bundleService)
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
rv = bundleService->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Create our system principal singleton
|
|
|
|
nsRefPtr<nsSystemPrincipal> system = new nsSystemPrincipal();
|
|
|
|
NS_ENSURE_TRUE(system, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
mSystemPrincipal = system;
|
|
|
|
|
|
|
|
//-- Register security check callback in the JS engine
|
|
|
|
// Currently this is used to control access to function.caller
|
2013-05-29 16:49:11 -07:00
|
|
|
rv = nsXPConnect::XPConnect()->GetRuntime(&sRuntime);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2012-03-09 01:48:50 -08:00
|
|
|
static const JSSecurityCallbacks securityCallbacks = {
|
2010-03-08 00:24:50 -08:00
|
|
|
CheckObjectAccess,
|
2012-06-28 14:47:55 -07:00
|
|
|
ContentSecurityPolicyPermitsJSAction
|
2008-09-05 16:26:04 -07:00
|
|
|
};
|
|
|
|
|
2012-03-09 01:48:50 -08:00
|
|
|
MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
|
|
|
|
JS_SetSecurityCallbacks(sRuntime, &securityCallbacks);
|
|
|
|
JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-03-09 01:48:50 -08:00
|
|
|
JS_SetTrustedPrincipals(sRuntime, system);
|
2011-06-30 09:26:56 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-26 12:33:45 -07:00
|
|
|
static StaticRefPtr<nsScriptSecurityManager> gScriptSecMan;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsScriptSecurityManager::~nsScriptSecurityManager(void)
|
|
|
|
{
|
2011-06-19 20:00:16 -07:00
|
|
|
Preferences::RemoveObservers(this, kObservedPrefs);
|
2013-11-12 16:43:35 -08:00
|
|
|
if (mDomainPolicy)
|
|
|
|
mDomainPolicy->Deactivate();
|
|
|
|
MOZ_ASSERT(!mDomainPolicy);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsScriptSecurityManager::Shutdown()
|
|
|
|
{
|
|
|
|
if (sRuntime) {
|
2013-04-02 17:16:25 -07:00
|
|
|
JS_SetSecurityCallbacks(sRuntime, nullptr);
|
|
|
|
JS_SetTrustedPrincipals(sRuntime, nullptr);
|
2012-07-30 07:20:58 -07:00
|
|
|
sRuntime = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IF_RELEASE(sIOService);
|
|
|
|
NS_IF_RELEASE(sStrBundle);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsScriptSecurityManager *
|
|
|
|
nsScriptSecurityManager::GetScriptSecurityManager()
|
|
|
|
{
|
2013-07-09 10:30:58 -07:00
|
|
|
if (!gScriptSecMan && nsXPConnect::XPConnect())
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-06-19 10:20:34 -07:00
|
|
|
nsRefPtr<nsScriptSecurityManager> ssManager = new nsScriptSecurityManager();
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv;
|
|
|
|
rv = ssManager->Init();
|
|
|
|
if (NS_FAILED(rv)) {
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2013-05-29 16:49:11 -07:00
|
|
|
rv = nsXPConnect::XPConnect()->
|
2013-06-07 05:40:56 -07:00
|
|
|
SetDefaultSecurityManager(ssManager);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("Failed to install xpconnect security manager!");
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-06-19 10:20:34 -07:00
|
|
|
ClearOnShutdown(&gScriptSecMan);
|
2007-03-22 10:30:00 -07:00
|
|
|
gScriptSecMan = ssManager;
|
|
|
|
}
|
|
|
|
return gScriptSecMan;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Currently this nsGenericFactory constructor is used only from FastLoad
|
|
|
|
// (XPCOM object deserialization) code, when "creating" the system principal
|
|
|
|
// singleton.
|
|
|
|
nsSystemPrincipal *
|
|
|
|
nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
|
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
nsIPrincipal *sysprin = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (gScriptSecMan)
|
|
|
|
NS_ADDREF(sysprin = gScriptSecMan->mSystemPrincipal);
|
2007-07-08 00:08:04 -07:00
|
|
|
return static_cast<nsSystemPrincipal*>(sysprin);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
2007-09-06 00:02:57 -07:00
|
|
|
nsScriptSecurityManager::ScriptSecurityPrefChanged()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// JavaScript defaults to enabled in failure cases.
|
2011-10-17 07:59:28 -07:00
|
|
|
mIsJavaScriptEnabled = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
sStrictFileOriginPolicy = true;
|
2009-01-07 20:42:15 -08:00
|
|
|
|
|
|
|
nsresult rv;
|
2011-06-19 20:00:16 -07:00
|
|
|
if (!mPrefInitialized) {
|
2009-01-07 20:42:15 -08:00
|
|
|
rv = InitPrefs();
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-06-19 20:00:16 -07:00
|
|
|
mIsJavaScriptEnabled =
|
|
|
|
Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled);
|
2009-01-07 20:42:15 -08:00
|
|
|
|
2011-06-19 20:00:16 -07:00
|
|
|
sStrictFileOriginPolicy =
|
2011-09-28 23:19:26 -07:00
|
|
|
Preferences::GetBool(sFileOriginPolicyPrefName, false);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsScriptSecurityManager::InitPrefs()
|
|
|
|
{
|
2011-06-19 20:00:16 -07:00
|
|
|
nsIPrefBranch* branch = Preferences::GetRootBranch();
|
|
|
|
NS_ENSURE_TRUE(branch, NS_ERROR_FAILURE);
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
mPrefInitialized = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Set the initial value of the "javascript.enabled" prefs
|
2007-09-06 00:02:57 -07:00
|
|
|
ScriptSecurityPrefChanged();
|
2011-06-19 20:00:16 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// set observer callbacks in case the value of the prefs change
|
2011-06-19 20:00:16 -07:00
|
|
|
Preferences::AddStrongObservers(this, kObservedPrefs);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-19 22:44:03 -07:00
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
void
|
2013-09-10 21:18:36 -07:00
|
|
|
GetJarPrefix(uint32_t aAppId, bool aInMozBrowser, nsACString& aJarPrefix)
|
2012-07-18 21:25:19 -07:00
|
|
|
{
|
2012-07-19 22:44:03 -07:00
|
|
|
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
2012-07-18 21:25:19 -07:00
|
|
|
|
2012-07-19 22:44:03 -07:00
|
|
|
if (aAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
|
|
|
aAppId = nsIScriptSecurityManager::NO_APP_ID;
|
2012-07-18 21:25:19 -07:00
|
|
|
}
|
|
|
|
|
2013-09-10 21:18:36 -07:00
|
|
|
aJarPrefix.Truncate();
|
2012-07-19 22:44:03 -07:00
|
|
|
|
2012-07-18 21:25:19 -07:00
|
|
|
// Fallback.
|
|
|
|
if (aAppId == nsIScriptSecurityManager::NO_APP_ID && !aInMozBrowser) {
|
2012-07-19 22:44:03 -07:00
|
|
|
return;
|
2012-07-18 21:25:19 -07:00
|
|
|
}
|
|
|
|
|
2013-09-10 21:18:36 -07:00
|
|
|
// aJarPrefix = appId + "+" + { 't', 'f' } + "+";
|
|
|
|
aJarPrefix.AppendInt(aAppId);
|
|
|
|
aJarPrefix.Append('+');
|
|
|
|
aJarPrefix.Append(aInMozBrowser ? 't' : 'f');
|
|
|
|
aJarPrefix.Append('+');
|
2012-07-18 21:25:19 -07:00
|
|
|
|
2012-07-19 22:44:03 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-09-10 21:18:36 -07:00
|
|
|
nsScriptSecurityManager::GetJarPrefix(uint32_t aAppId,
|
|
|
|
bool aInMozBrowser,
|
|
|
|
nsACString& aJarPrefix)
|
2012-07-19 22:44:03 -07:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
|
|
|
|
2013-09-10 21:18:36 -07:00
|
|
|
mozilla::GetJarPrefix(aAppId, aInMozBrowser, aJarPrefix);
|
2012-07-18 21:25:19 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2013-11-12 16:43:35 -08:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::GetDomainPolicyActive(bool *aRv)
|
|
|
|
{
|
|
|
|
*aRv = !!mDomainPolicy;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::ActivateDomainPolicy(nsIDomainPolicy** aRv)
|
|
|
|
{
|
|
|
|
// We only allow one domain policy at a time. The holder of the previous
|
|
|
|
// policy must explicitly deactivate it first.
|
|
|
|
if (mDomainPolicy) {
|
|
|
|
return NS_ERROR_SERVICE_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2013-12-13 19:15:44 -08:00
|
|
|
mDomainPolicy = new DomainPolicy();
|
2013-11-12 16:43:35 -08:00
|
|
|
nsCOMPtr<nsIDomainPolicy> ptr = mDomainPolicy;
|
|
|
|
ptr.forget(aRv);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Intentionally non-scriptable. Script must have a reference to the
|
|
|
|
// nsIDomainPolicy to deactivate it.
|
|
|
|
void
|
|
|
|
nsScriptSecurityManager::DeactivateDomainPolicy()
|
|
|
|
{
|
|
|
|
mDomainPolicy = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsScriptSecurityManager::PolicyAllowsScript(nsIURI* aURI, bool *aRv)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// Compute our rule. If we don't have any domain policy set up that might
|
|
|
|
// provide exceptions to this rule, we're done.
|
|
|
|
*aRv = mIsJavaScriptEnabled;
|
|
|
|
if (!mDomainPolicy) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have a domain policy. Grab the appropriate set of exceptions to the
|
|
|
|
// rule (either the blacklist or the whitelist, depending on whether script
|
|
|
|
// is enabled or disabled by default).
|
|
|
|
nsCOMPtr<nsIDomainSet> exceptions;
|
|
|
|
nsCOMPtr<nsIDomainSet> superExceptions;
|
|
|
|
if (*aRv) {
|
|
|
|
mDomainPolicy->GetBlacklist(getter_AddRefs(exceptions));
|
|
|
|
mDomainPolicy->GetSuperBlacklist(getter_AddRefs(superExceptions));
|
|
|
|
} else {
|
|
|
|
mDomainPolicy->GetWhitelist(getter_AddRefs(exceptions));
|
|
|
|
mDomainPolicy->GetSuperWhitelist(getter_AddRefs(superExceptions));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool contains;
|
|
|
|
rv = exceptions->Contains(aURI, &contains);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (contains) {
|
|
|
|
*aRv = !*aRv;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
rv = superExceptions->ContainsSuperDomain(aURI, &contains);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (contains) {
|
|
|
|
*aRv = !*aRv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|