scriptsecuritymanager register for that and implement nsIChannelEventSink. Veto redirects if CheckLoadURI fails. Remove the explicit usage of nsIScriptSecurityManager from nsHttpChannel.cpp. This eliminates js and xpconnect from REQUIRES, and brings us closer to remove caps. r=darin sr=bz git-svn-id: svn://10.0.0.236/trunk@184313 18797224-902f-48f8-a5cc-f745e15eee43
567 lines
16 KiB
C++
567 lines
16 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Norris Boyd <nboyd@atg.com>
|
|
* Mitch Stoltz <mstoltz@netscape.com>
|
|
* Christopher A. Aillon <christopher@aillon.com>
|
|
* Giorgio Maone <g.maone@informaction.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#ifndef nsScriptSecurityManager_h__
|
|
#define nsScriptSecurityManager_h__
|
|
|
|
#include "nsIScriptSecurityManager.h"
|
|
#include "nsIPrincipal.h"
|
|
#include "jsapi.h"
|
|
#include "jsdbgapi.h"
|
|
#include "nsIXPCSecurityManager.h"
|
|
#include "nsInterfaceHashtable.h"
|
|
#include "nsHashtable.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIPrefService.h"
|
|
#include "nsISecurityPref.h"
|
|
#include "nsIChannelEventSink.h"
|
|
#include "nsIJSContextStack.h"
|
|
#include "nsIObserver.h"
|
|
#include "pldhash.h"
|
|
#include "plstr.h"
|
|
|
|
class nsIDocShell;
|
|
class nsString;
|
|
class nsIClassInfo;
|
|
class nsIIOService;
|
|
class nsIXPConnect;
|
|
class nsIStringBundle;
|
|
class nsSystemPrincipal;
|
|
struct ClassPolicy;
|
|
class ClassInfoData;
|
|
|
|
#if defined(DEBUG_mstoltz) || defined(DEBUG_caillon)
|
|
#define DEBUG_CAPS_HACKER
|
|
#endif
|
|
|
|
#ifdef DEBUG_CAPS_HACKER
|
|
#define DEBUG_CAPS_CheckPropertyAccessImpl
|
|
#define DEBUG_CAPS_LookupPolicy
|
|
#define DEBUG_CAPS_CheckComponentPermissions
|
|
#endif
|
|
|
|
#if 0
|
|
#define DEBUG_CAPS_CanCreateWrapper
|
|
#define DEBUG_CAPS_CanCreateInstance
|
|
#define DEBUG_CAPS_CanGetService
|
|
#define DEBUG_CAPS_DomainPolicyLifeCycle
|
|
#endif
|
|
|
|
/////////////////////
|
|
// PrincipalKey //
|
|
/////////////////////
|
|
|
|
class PrincipalKey : public PLDHashEntryHdr
|
|
{
|
|
public:
|
|
typedef const nsIPrincipal* KeyType;
|
|
typedef const nsIPrincipal* KeyTypePointer;
|
|
|
|
PrincipalKey(const nsIPrincipal* key)
|
|
: mKey(NS_CONST_CAST(nsIPrincipal*, key))
|
|
{
|
|
}
|
|
|
|
PrincipalKey(const PrincipalKey& toCopy)
|
|
: mKey(toCopy.mKey)
|
|
{
|
|
}
|
|
|
|
~PrincipalKey()
|
|
{
|
|
}
|
|
|
|
KeyType GetKey() const
|
|
{
|
|
return mKey;
|
|
}
|
|
|
|
KeyTypePointer GetKeyPointer() const
|
|
{
|
|
return mKey;
|
|
}
|
|
|
|
PRBool KeyEquals(KeyTypePointer aKey) const
|
|
{
|
|
PRBool eq;
|
|
mKey->Equals(NS_CONST_CAST(nsIPrincipal*, aKey),
|
|
&eq);
|
|
return eq;
|
|
}
|
|
|
|
static KeyTypePointer KeyToPointer(KeyType aKey)
|
|
{
|
|
return aKey;
|
|
}
|
|
|
|
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
|
{
|
|
PRUint32 hash;
|
|
NS_CONST_CAST(nsIPrincipal*, aKey)->GetHashValue(&hash);
|
|
return PLDHashNumber(hash);
|
|
}
|
|
|
|
enum { ALLOW_MEMMOVE = PR_TRUE };
|
|
|
|
private:
|
|
nsCOMPtr<nsIPrincipal> mKey;
|
|
};
|
|
|
|
////////////////////
|
|
// Policy Storage //
|
|
////////////////////
|
|
|
|
// Property Policy
|
|
union SecurityLevel
|
|
{
|
|
PRInt32 level;
|
|
char* capability;
|
|
};
|
|
|
|
// Security levels
|
|
// These values all have the low bit set (except UNDEFINED_ACCESS)
|
|
// to distinguish them from pointer values, because no pointer
|
|
// to allocated memory ever has the low bit set. A SecurityLevel
|
|
// contains either one of these constants or a pointer to a string
|
|
// representing the name of a capability.
|
|
|
|
#define SCRIPT_SECURITY_UNDEFINED_ACCESS 0
|
|
#define SCRIPT_SECURITY_ACCESS_IS_SET_BIT 1
|
|
#define SCRIPT_SECURITY_NO_ACCESS \
|
|
((1 << 0) | SCRIPT_SECURITY_ACCESS_IS_SET_BIT)
|
|
#define SCRIPT_SECURITY_SAME_ORIGIN_ACCESS \
|
|
((1 << 1) | SCRIPT_SECURITY_ACCESS_IS_SET_BIT)
|
|
#define SCRIPT_SECURITY_ALL_ACCESS \
|
|
((1 << 2) | SCRIPT_SECURITY_ACCESS_IS_SET_BIT)
|
|
|
|
#define SECURITY_ACCESS_LEVEL_FLAG(_sl) \
|
|
((_sl.level == 0) || \
|
|
(_sl.level & SCRIPT_SECURITY_ACCESS_IS_SET_BIT))
|
|
|
|
|
|
struct PropertyPolicy : public PLDHashEntryHdr
|
|
{
|
|
jsval key; // property name as jsval
|
|
SecurityLevel mGet;
|
|
SecurityLevel mSet;
|
|
};
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
InitPropertyPolicyEntry(PLDHashTable *table,
|
|
PLDHashEntryHdr *entry,
|
|
const void *key)
|
|
{
|
|
PropertyPolicy* pp = (PropertyPolicy*)entry;
|
|
pp->key = (jsval)key;
|
|
pp->mGet.level = SCRIPT_SECURITY_UNDEFINED_ACCESS;
|
|
pp->mSet.level = SCRIPT_SECURITY_UNDEFINED_ACCESS;
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(void)
|
|
ClearPropertyPolicyEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
|
{
|
|
PropertyPolicy* pp = (PropertyPolicy*)entry;
|
|
pp->key = JSVAL_VOID;
|
|
}
|
|
|
|
// Class Policy
|
|
#define NO_POLICY_FOR_CLASS (ClassPolicy*)1
|
|
|
|
struct ClassPolicy : public PLDHashEntryHdr
|
|
{
|
|
char* key;
|
|
PLDHashTable* mPolicy;
|
|
};
|
|
|
|
PR_STATIC_CALLBACK(void)
|
|
ClearClassPolicyEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
|
{
|
|
ClassPolicy* cp = (ClassPolicy *)entry;
|
|
if (cp->key)
|
|
{
|
|
PL_strfree(cp->key);
|
|
cp->key = nsnull;
|
|
}
|
|
PL_DHashTableDestroy(cp->mPolicy);
|
|
}
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
InitClassPolicyEntry(PLDHashTable *table,
|
|
PLDHashEntryHdr *entry,
|
|
const void *key)
|
|
{
|
|
static PLDHashTableOps classPolicyOps =
|
|
{
|
|
PL_DHashAllocTable,
|
|
PL_DHashFreeTable,
|
|
PL_DHashGetKeyStub,
|
|
PL_DHashVoidPtrKeyStub,
|
|
PL_DHashMatchEntryStub,
|
|
PL_DHashMoveEntryStub,
|
|
ClearPropertyPolicyEntry,
|
|
PL_DHashFinalizeStub,
|
|
InitPropertyPolicyEntry
|
|
};
|
|
|
|
ClassPolicy* cp = (ClassPolicy*)entry;
|
|
cp->key = PL_strdup((const char*)key);
|
|
if (!cp->key)
|
|
return PR_FALSE;
|
|
cp->mPolicy = PL_NewDHashTable(&classPolicyOps, nsnull,
|
|
sizeof(PropertyPolicy), 16);
|
|
if (!cp->mPolicy) {
|
|
PL_strfree(cp->key);
|
|
cp->key = nsnull;
|
|
return PR_FALSE;
|
|
}
|
|
return PR_TRUE;
|
|
}
|
|
|
|
// Domain Policy
|
|
class DomainPolicy : public PLDHashTable
|
|
{
|
|
public:
|
|
DomainPolicy() : mWildcardPolicy(nsnull),
|
|
mRefCount(0)
|
|
{
|
|
mGeneration = sGeneration;
|
|
|
|
#ifdef DEBUG_CAPS_DomainPolicyLifeCycle
|
|
++sObjects;
|
|
_printPopulationInfo();
|
|
#endif
|
|
|
|
}
|
|
|
|
PRBool Init()
|
|
{
|
|
static const PLDHashTableOps domainPolicyOps =
|
|
{
|
|
PL_DHashAllocTable,
|
|
PL_DHashFreeTable,
|
|
PL_DHashGetKeyStub,
|
|
PL_DHashStringKey,
|
|
PL_DHashMatchStringKey,
|
|
PL_DHashMoveEntryStub,
|
|
ClearClassPolicyEntry,
|
|
PL_DHashFinalizeStub,
|
|
InitClassPolicyEntry
|
|
};
|
|
|
|
return PL_DHashTableInit(this, &domainPolicyOps, nsnull,
|
|
sizeof(ClassPolicy), 16);
|
|
}
|
|
|
|
~DomainPolicy()
|
|
{
|
|
PL_DHashTableFinish(this);
|
|
NS_ASSERTION(mRefCount == 0, "Wrong refcount in DomainPolicy dtor");
|
|
#ifdef DEBUG_CAPS_DomainPolicyLifeCycle
|
|
printf("DomainPolicy deleted with mRefCount = %d\n", mRefCount);
|
|
--sObjects;
|
|
_printPopulationInfo();
|
|
#endif
|
|
|
|
}
|
|
|
|
void Hold()
|
|
{
|
|
mRefCount++;
|
|
}
|
|
|
|
void Drop()
|
|
{
|
|
if (--mRefCount == 0)
|
|
delete this;
|
|
}
|
|
|
|
static void InvalidateAll()
|
|
{
|
|
sGeneration++;
|
|
}
|
|
|
|
PRBool IsInvalid()
|
|
{
|
|
return mGeneration != sGeneration;
|
|
}
|
|
|
|
ClassPolicy* mWildcardPolicy;
|
|
|
|
private:
|
|
PRUint32 mRefCount;
|
|
PRUint32 mGeneration;
|
|
static PRUint32 sGeneration;
|
|
|
|
#ifdef DEBUG_CAPS_DomainPolicyLifeCycle
|
|
static PRUint32 sObjects;
|
|
static void _printPopulationInfo();
|
|
#endif
|
|
|
|
};
|
|
|
|
/////////////////////////////
|
|
// nsScriptSecurityManager //
|
|
/////////////////////////////
|
|
#define NS_SCRIPTSECURITYMANAGER_CID \
|
|
{ 0x7ee2a4c0, 0x4b93, 0x17d3, \
|
|
{ 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }}
|
|
|
|
class nsScriptSecurityManager : public nsIScriptSecurityManager,
|
|
public nsIPrefSecurityCheck,
|
|
public nsIChannelEventSink,
|
|
public nsIObserver
|
|
{
|
|
public:
|
|
static void Shutdown();
|
|
|
|
NS_DEFINE_STATIC_CID_ACCESSOR(NS_SCRIPTSECURITYMANAGER_CID)
|
|
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSISCRIPTSECURITYMANAGER
|
|
NS_DECL_NSIXPCSECURITYMANAGER
|
|
NS_DECL_NSIPREFSECURITYCHECK
|
|
NS_DECL_NSICHANNELEVENTSINK
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
static nsScriptSecurityManager*
|
|
GetScriptSecurityManager();
|
|
|
|
static nsSystemPrincipal*
|
|
SystemPrincipalSingletonConstructor();
|
|
|
|
JSContext* GetCurrentJSContext();
|
|
|
|
JSContext* GetSafeJSContext();
|
|
|
|
private:
|
|
|
|
// GetScriptSecurityManager is the only call that can make one
|
|
nsScriptSecurityManager();
|
|
virtual ~nsScriptSecurityManager();
|
|
|
|
static JSBool JS_DLL_CALLBACK
|
|
CheckObjectAccess(JSContext *cx, JSObject *obj,
|
|
jsval id, JSAccessMode mode,
|
|
jsval *vp);
|
|
|
|
// Returns null if a principal cannot be found; generally callers
|
|
// should error out at that point.
|
|
static nsIPrincipal*
|
|
doGetObjectPrincipal(JSContext *cx, JSObject *obj);
|
|
|
|
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
|
// when this happens -- this means that there was no JS running.
|
|
nsIPrincipal*
|
|
doGetSubjectPrincipal(nsresult* rv);
|
|
|
|
static nsresult
|
|
GetBaseURIScheme(nsIURI* aURI, nsCString& aScheme);
|
|
|
|
static nsresult
|
|
ReportError(JSContext* cx, const nsAString& messageTag,
|
|
nsIURI* aSource, nsIURI* aTarget);
|
|
|
|
nsresult
|
|
GetRootDocShell(JSContext* cx, nsIDocShell **result);
|
|
|
|
nsresult
|
|
CheckPropertyAccessImpl(PRUint32 aAction,
|
|
nsIXPCNativeCallContext* aCallContext,
|
|
JSContext* cx, JSObject* aJSObject,
|
|
nsISupports* aObj, nsIURI* aTargetURI,
|
|
nsIClassInfo* aClassInfo,
|
|
const char* aClassName, jsval aProperty,
|
|
void** aCachedClassPolicy);
|
|
|
|
nsresult
|
|
CheckSameOriginPrincipalInternal(nsIPrincipal* aSubject,
|
|
nsIPrincipal* aObject,
|
|
PRBool aIsCheckConnect);
|
|
|
|
nsresult
|
|
CheckSameOriginDOMProp(nsIPrincipal* aSubject,
|
|
nsIPrincipal* aObject,
|
|
PRUint32 aAction,
|
|
PRBool aIsCheckConnect);
|
|
|
|
nsresult
|
|
LookupPolicy(nsIPrincipal* principal,
|
|
ClassInfoData& aClassData, jsval aProperty,
|
|
PRUint32 aAction,
|
|
ClassPolicy** aCachedClassPolicy,
|
|
SecurityLevel* result);
|
|
|
|
nsresult
|
|
CreateCodebasePrincipal(nsIURI* aURI, nsIPrincipal** result);
|
|
|
|
// This is just like the API method, but it doesn't check that the subject
|
|
// name is non-empty or aCertificate is non-null, and it doesn't change the
|
|
// certificate in the table (if any) in any way if aModifyTable is false.
|
|
nsresult
|
|
DoGetCertificatePrincipal(const nsACString& aCertFingerprint,
|
|
const nsACString& aSubjectName,
|
|
const nsACString& aPrettyName,
|
|
nsISupports* aCertificate,
|
|
nsIURI* aURI,
|
|
PRBool aModifyTable,
|
|
nsIPrincipal **result);
|
|
|
|
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
|
// when this happens -- this means that there was no script for the
|
|
// context. Callers MUST pass in a non-null rv here.
|
|
static nsIPrincipal*
|
|
GetSubjectPrincipal(JSContext* cx, nsresult* rv);
|
|
|
|
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
|
// when this happens -- this means that there was no script for the frame.
|
|
// Callers MUST pass in a non-null rv here.
|
|
static nsIPrincipal*
|
|
GetFramePrincipal(JSContext* cx, JSStackFrame* fp, nsresult* rv);
|
|
|
|
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
|
// when this happens -- this means that there was no script. Callers MUST
|
|
// pass in a non-null rv here.
|
|
static nsIPrincipal*
|
|
GetScriptPrincipal(JSContext* cx, JSScript* script, nsresult* rv);
|
|
|
|
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
|
// when this happens -- this means that there was no script associated
|
|
// with the function object, and no global object associated with the scope
|
|
// of obj (the last object on its parent chain). If the caller is walking
|
|
// the JS stack, fp must point to the current frame in the stack iteration.
|
|
// Callers MUST pass in a non-null rv here.
|
|
static nsIPrincipal*
|
|
GetFunctionObjectPrincipal(JSContext* cx, JSObject* obj, JSStackFrame *fp,
|
|
nsresult* rv);
|
|
|
|
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
|
// when this happens -- this means that there was no script
|
|
// running. Callers MUST pass in a non-null rv here.
|
|
static nsIPrincipal*
|
|
GetPrincipalAndFrame(JSContext *cx,
|
|
JSStackFrame** frameResult,
|
|
nsresult* rv);
|
|
|
|
static PRBool
|
|
CheckConfirmDialog(JSContext* cx, nsIPrincipal* aPrincipal,
|
|
const char* aCapability, PRBool *checkValue);
|
|
|
|
static void
|
|
FormatCapabilityString(nsAString& aCapability);
|
|
|
|
nsresult
|
|
SavePrincipal(nsIPrincipal* aToSave);
|
|
|
|
nsresult
|
|
CheckXPCPermissions(nsISupports* aObj,
|
|
const char* aObjectSecurityLevel);
|
|
|
|
nsresult
|
|
Init();
|
|
|
|
nsresult
|
|
InitPrefs();
|
|
|
|
static nsresult
|
|
GetPrincipalPrefNames(const char* prefBase,
|
|
nsCString& grantedPref,
|
|
nsCString& deniedPref,
|
|
nsCString& subjectNamePref);
|
|
|
|
nsresult
|
|
InitPolicies();
|
|
|
|
nsresult
|
|
InitDomainPolicy(JSContext* cx, const char* aPolicyName,
|
|
DomainPolicy* aDomainPolicy);
|
|
|
|
nsresult
|
|
InitPrincipals(PRUint32 prefCount, const char** prefNames,
|
|
nsISecurityPref* securityPref);
|
|
|
|
#ifdef XPC_IDISPATCH_SUPPORT
|
|
// While this header is included outside of caps, this class isn't
|
|
// referenced so this should be fine.
|
|
nsresult
|
|
CheckComponentPermissions(JSContext *cx, const nsCID &aCID);
|
|
#endif
|
|
#ifdef DEBUG_CAPS_HACKER
|
|
void
|
|
PrintPolicyDB();
|
|
#endif
|
|
|
|
// JS strings we need to clean up on shutdown
|
|
static jsval sEnabledID;
|
|
|
|
inline void
|
|
JSEnabledPrefChanged(nsISecurityPref* aSecurityPref);
|
|
|
|
static const char sJSEnabledPrefName[];
|
|
static const char sJSMailEnabledPrefName[];
|
|
|
|
nsObjectHashtable* mOriginToPolicyMap;
|
|
DomainPolicy* mDefaultPolicy;
|
|
nsObjectHashtable* mCapabilities;
|
|
|
|
nsCOMPtr<nsIPrefBranch> mPrefBranch;
|
|
nsCOMPtr<nsISecurityPref> mSecurityPref;
|
|
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
|
|
nsCOMPtr<nsIPrincipal> mSystemCertificate;
|
|
nsInterfaceHashtable<PrincipalKey, nsIPrincipal> mPrincipals;
|
|
nsCOMPtr<nsIThreadJSContextStack> mJSContextStack;
|
|
PRPackedBool mIsJavaScriptEnabled;
|
|
PRPackedBool mIsMailJavaScriptEnabled;
|
|
PRPackedBool mIsWritingPrefs;
|
|
PRPackedBool mPolicyPrefsChanged;
|
|
#ifdef XPC_IDISPATCH_SUPPORT
|
|
PRPackedBool mXPCDefaultGrantAll;
|
|
static const char sXPCDefaultGrantAllName[];
|
|
#endif
|
|
|
|
static nsIIOService *sIOService;
|
|
static nsIXPConnect *sXPConnect;
|
|
static nsIStringBundle *sStrBundle;
|
|
static JSRuntime *sRuntime;
|
|
};
|
|
|
|
#endif // nsScriptSecurityManager_h__
|