diff --git a/mozilla/caps/idl/nsIScriptSecurityManager.idl b/mozilla/caps/idl/nsIScriptSecurityManager.idl index 226d1453fe2..521281c3095 100644 --- a/mozilla/caps/idl/nsIScriptSecurityManager.idl +++ b/mozilla/caps/idl/nsIScriptSecurityManager.idl @@ -51,7 +51,7 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager [noscript] void checkPropertyAccess(in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in string aClassName, - in string aProperty, + in JSVal aProperty, in PRUint32 aAction); /** @@ -60,7 +60,7 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager [noscript] void checkConnect(in JSContextPtr aJSContext, in nsIURI aTargetURI, in string aClassName, - in string aPropertyName); + in string aProperty); /** * Check that the script currently running in context "cx" can load "uri". @@ -197,6 +197,12 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager */ [noscript] nsIPrincipal getObjectPrincipal(in JSContextPtr cx, in JSObjectPtr obj); + + /** + * Forget all currently stored security policies and reread from prefs. + * This must be called after any capability.policy prefs have changed. + */ + void reloadSecurityPolicies(); }; %{C++ diff --git a/mozilla/caps/include/nsScriptSecurityManager.h b/mozilla/caps/include/nsScriptSecurityManager.h index fececf8d7a1..0da0a235895 100644 --- a/mozilla/caps/include/nsScriptSecurityManager.h +++ b/mozilla/caps/include/nsScriptSecurityManager.h @@ -20,7 +20,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * + * Norris Boyd + * Mitch Stoltz * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -50,12 +51,13 @@ #include "nsISecurityPref.h" #include "nsIJSContextStack.h" #include "nsIObserver.h" -#include "nsWeakPtr.h" +#include "pldhash.h" class nsIDocShell; class nsString; class nsIClassInfo; class nsSystemPrincipal; +struct ClassPolicy; ///////////////////// // nsIPrincipalKey // @@ -92,15 +94,172 @@ protected: nsIPrincipal* mKey; }; +//////////////////// +// Policy Storage // +//////////////////// + +// Property Policy +union SecurityLevel +{ + long 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(void) +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; +} + +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; + ClassPolicy* mDefault; + ClassPolicy* mWildcard; +}; + +PR_STATIC_CALLBACK(PRBool) +MatchClassPolicyKey(PLDHashTable *table, + const PLDHashEntryHdr *entry, + const void *key) +{ + ClassPolicy* cp = (ClassPolicy *)entry; + return (cp->key == (char*)key) || (PL_strcmp(cp->key, (char*)key) == 0); +} + +PR_STATIC_CALLBACK(void) +ClearClassPolicyEntry(PLDHashTable *table, PLDHashEntryHdr *entry) +{ + ClassPolicy* cp = (ClassPolicy *)entry; + if (cp->key) + { + PL_strfree(cp->key); + cp->key = nsnull; + } + PL_DHashTableFinish(&cp->mPolicy); +} + +PR_STATIC_CALLBACK(void) +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); + PL_DHashTableInit(&cp->mPolicy, &classPolicyOps, nsnull, + sizeof(PropertyPolicy), 16); +} + +// Domain Policy +class DomainPolicy : public PLDHashTable +{ +public: + DomainPolicy() : mRefCount(0) + { + static PLDHashTableOps domainPolicyOps = + { + PL_DHashAllocTable, + PL_DHashFreeTable, + PL_DHashGetKeyStub, + PL_DHashStringKey, + MatchClassPolicyKey, + PL_DHashMoveEntryStub, + ClearClassPolicyEntry, + PL_DHashFinalizeStub, + InitClassPolicyEntry + }; + + PL_DHashTableInit(this, &domainPolicyOps, nsnull, + sizeof(ClassPolicy), 16); + } + + void Hold() + { + mRefCount++; + } + + void Drop() + { + if (--mRefCount == 0) + delete this; + } + +private: + PRUint32 mRefCount; +}; + +///////////////////////////// +// nsScriptSecurityManager // +///////////////////////////// #define NS_SCRIPTSECURITYMANAGER_CID \ { 0x7ee2a4c0, 0x4b93, 0x17d3, \ { 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }} -class nsScriptSecurityManager : public nsIScriptSecurityManager, public nsIObserver +class nsScriptSecurityManager : public nsIScriptSecurityManager, + public nsIObserver { public: nsScriptSecurityManager(); virtual ~nsScriptSecurityManager(); + + static void Shutdown(); NS_DEFINE_STATIC_CID_ACCESSOR(NS_SCRIPTSECURITYMANAGER_CID) @@ -115,11 +274,19 @@ public: static nsSystemPrincipal* SystemPrincipalSingletonConstructor(); - JSContext* GetCurrentContextQuick(); + JSContext* GetCurrentJSContext(); + + JSContext* GetSafeJSContext(); private: - static PRBool IsDOMClass(nsIClassInfo* aClassInfo); + static JSBool + CheckJSFunctionCallerAccess(JSContext *cx, JSObject *obj, + jsval id, JSAccessMode mode, + jsval *vp); + + static PRBool + IsDOMClass(nsIClassInfo* aClassInfo); nsresult GetBaseURIScheme(nsIURI* aURI, char** aScheme); @@ -131,12 +298,13 @@ private: GetRootDocShell(JSContext* cx, nsIDocShell **result); nsresult - CheckPropertyAccessImpl(PRUint32 aAction, nsIXPCNativeCallContext* aCallContext, - JSContext* aJSContext, JSObject* aJSObject, + CheckPropertyAccessImpl(PRUint32 aAction, + nsIXPCNativeCallContext* aCallContext, + JSContext* cx, JSObject* aJSObject, nsISupports* aObj, nsIURI* aTargetURI, nsIClassInfo* aClassInfo, - jsval aName, const char* aClassName, - const char* aProperty, void** aPolicy); + const char* aClassName, jsval aProperty, + void** aCachedClassPolicy); nsresult CheckSameOrigin(JSContext* aCx, nsIPrincipal* aSubject, @@ -148,18 +316,13 @@ private: const char* aClassName, const char* aProperty, PRUint32 aAction, nsCString &capability, void** aPolicy); - static nsresult - TryToGetPref(nsISecurityPref* aSecurityPref, - nsCString &aPrefName, - const char* aClassName, - const char* aPropertyName, - PRInt32 aClassPolicy, - PRUint32 aAction, char** result); - nsresult - GetPolicy(nsIPrincipal* principal, - const char* aClassName, const char* aPropertyName, - PRInt32 aClassPolicy, PRUint32 aAction, char** result); + GetClassPolicy(nsIPrincipal* principal, const char* aClassName, + ClassPolicy** result); + + SecurityLevel + GetPropertyPolicy(jsval aProperty, ClassPolicy* aClassPolicy, + PRUint32 aAction); nsresult CreateCodebasePrincipal(nsIURI* aURI, nsIPrincipal** result); @@ -196,13 +359,25 @@ private: PrincipalPrefNames(const char* pref, char** grantedPref, char** deniedPref); nsresult - InitPolicies(PRUint32 prefCount, const char** prefNames, - nsISecurityPref* securityPref); + InitPolicies(); + + nsresult + InitDomainPolicy(JSContext* cx,const char* aPolicyName, + DomainPolicy* aDomainPolicy); nsresult InitPrincipals(PRUint32 prefCount, const char** prefNames, nsISecurityPref* securityPref); +#ifdef DEBUG_mstoltz + void + PrintPolicyDB(); +#endif + + // JS strings we need to clean up on shutdown + static jsval sCallerID; + static jsval sEnabledID; + inline void JSEnabledPrefChanged(nsISecurityPref* aSecurityPref); @@ -210,15 +385,18 @@ private: static const char* sJSMailEnabledPrefName; nsObjectHashtable* mOriginToPolicyMap; - nsHashtable* mClassPolicies; - nsWeakPtr mPrefBranchWeakRef; + DomainPolicy* mDefaultPolicy; + nsObjectHashtable* mCapabilities; + + nsCOMPtr mPrefBranch; + nsCOMPtr mSecurityPref; nsIPrincipal* mSystemPrincipal; nsCOMPtr mSystemCertificate; nsSupportsHashtable* mPrincipals; PRBool mIsJavaScriptEnabled; PRBool mIsMailJavaScriptEnabled; PRBool mIsWritingPrefs; - nsCOMPtr mThreadJSContextStack; + nsCOMPtr mJSContextStack; PRBool mNameSetRegistered; }; diff --git a/mozilla/caps/src/makefile.win b/mozilla/caps/src/makefile.win index 893a1eabaae..c5992c9e6ab 100755 --- a/mozilla/caps/src/makefile.win +++ b/mozilla/caps/src/makefile.win @@ -57,6 +57,7 @@ REQUIRES = xpcom \ intl \ docshell \ windowwatcher \ + embedding \ $(NULL) #//------------------------------------------------------------------------ diff --git a/mozilla/caps/src/nsScriptSecurityManager.cpp b/mozilla/caps/src/nsScriptSecurityManager.cpp index b97e8cd1261..6999e305258 100644 --- a/mozilla/caps/src/nsScriptSecurityManager.cpp +++ b/mozilla/caps/src/nsScriptSecurityManager.cpp @@ -38,7 +38,6 @@ * the terms of any one of the NPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nscore.h" #include "nsScriptSecurityManager.h" #include "nsIServiceManager.h" #include "nsIScriptObjectPrincipal.h" @@ -51,9 +50,7 @@ #include "nsCodebasePrincipal.h" #include "nsCertificatePrincipal.h" #include "nsAggregatePrincipal.h" -#include "nsCRT.h" #include "nsXPIDLString.h" -#include "nsReadableUtils.h" #include "nsIJSContextStack.h" #include "nsDOMError.h" #include "nsDOMCID.h" @@ -81,6 +78,7 @@ #include "nsISecurityCheckedComponent.h" #include "nsIPrefBranchInternal.h" #include "nsIJSRuntimeService.h" +#include "nsIObserverService.h" static NS_DEFINE_IID(kIIOServiceIID, NS_IIOSERVICE_IID); static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); @@ -89,26 +87,15 @@ static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); static NS_DEFINE_CID(kCScriptNameSetRegistryCID, NS_SCRIPT_NAMESET_REGISTRY_CID); static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); +static NS_DEFINE_IID(kObserverServiceIID, NS_IOBSERVERSERVICE_IID); -//-- All values of this enum except the first map to odd numbers so they can be -// stored in a void* without being confused for a pointer value (which is always even). -enum { - SCRIPT_SECURITY_UNDEFINED_ACCESS = 0, - SCRIPT_SECURITY_CAPABILITY_ONLY = 1, - SCRIPT_SECURITY_SAME_ORIGIN_ACCESS = 3, - SCRIPT_SECURITY_ALL_ACCESS = 5, - SCRIPT_SECURITY_NO_ACCESS = 7 -}; - -#define CLASS_HAS_DEFAULT_POLICY 1 << 0 -#define CLASS_HAS_SITE_POLICY 1 << 1 -#define CLASS_HAS_ACCESSTYPE 1 << 2 - - +/////////////////////////// +// Convenience Functions // +/////////////////////////// // Result of this function should not be freed. static const PRUnichar * -JSValIDToString(JSContext *aJSContext, const jsval idval) { - JSString *str = JS_ValueToString(aJSContext, idval); +JSValIDToString(JSContext *cx, const jsval idval) { + JSString *str = JS_ValueToString(cx, idval); if(!str) return nsnull; return NS_REINTERPRET_CAST(PRUnichar*, JS_GetStringChars(str)); @@ -118,21 +105,139 @@ JSValIDToString(JSContext *aJSContext, const jsval idval) { // Uses cached JSContextStack service instead of calling through // to the service manager. JSContext * -nsScriptSecurityManager::GetCurrentContextQuick() +nsScriptSecurityManager::GetCurrentJSContext() { // Get JSContext from stack. - nsresult rv; - if (!mThreadJSContextStack) { - mThreadJSContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv); + if (!mJSContextStack) + { + mJSContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); + if (!mJSContextStack) + return nsnull; } - if (!mThreadJSContextStack) - return nsnull; JSContext *cx; - if (NS_FAILED(mThreadJSContextStack->Peek(&cx))) + if (NS_FAILED(mJSContextStack->Peek(&cx))) return nsnull; return cx; } +JSContext * +nsScriptSecurityManager::GetSafeJSContext() +{ + // Get JSContext from stack. + if (!mJSContextStack) { + mJSContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); + } + + JSContext *cx; + if (NS_FAILED(mJSContextStack->GetSafeJSContext(&cx))) + return nsnull; + return cx; +} + + +class ClassNameHolder +{ +public: + ClassNameHolder(const char* aClassName, nsIClassInfo* aClassInfo) : + mClassName((char*)aClassName), mClassInfo(aClassInfo), mMustFree(PR_FALSE) + { + } + + ~ClassNameHolder() + { + if (mMustFree) + nsMemory::Free(mClassName); + } + + char* get() + { + if (mClassName) + return mClassName; + + if (mClassInfo) + mClassInfo->GetClassDescription(&mClassName); + if (mClassName) + mMustFree = PR_TRUE; + else + mClassName = "UnnamedClass"; + + return mClassName; + } + +private: + char* mClassName; + nsCOMPtr mClassInfo; + PRBool mMustFree; +}; + +//////////////////// +// Policy Storage // +//////////////////// + +// Table of security levels +PR_STATIC_CALLBACK(PRBool) +DeleteCapability(nsHashKey *aKey, void *aData, void* closure) +{ + nsMemory::Free(aData); + return PR_TRUE; +} + +//-- Per-Domain Policy - applies to one or more protocols or hosts +struct DomainEntry +{ + DomainEntry(const char* aOrigin, + DomainPolicy* aDomainPolicy) : mOrigin(aOrigin), + mDomainPolicy(aDomainPolicy), + mNext(nsnull) + { + mDomainPolicy->Hold(); + } + + ~DomainEntry() + { + mDomainPolicy->Drop(); + } + + PRBool Matches(const char *anOrigin) + { + int len = nsCRT::strlen(anOrigin); + int thisLen = mOrigin.Length(); + if (len < thisLen) + return PR_FALSE; + if (mOrigin.RFindChar(':', thisLen-1, 1) != -1) + //-- Policy applies to all URLs of this scheme, compare scheme only + return mOrigin.EqualsWithConversion(anOrigin, PR_TRUE, thisLen); + + //-- Policy applies to a particular host; compare domains + if (!mOrigin.Equals(anOrigin + (len - thisLen))) + return PR_FALSE; + if (len == thisLen) + return PR_TRUE; + char charBefore = anOrigin[len-thisLen-1]; + return (charBefore == '.' || charBefore == ':' || charBefore == '/'); + } + + nsCString mOrigin; + DomainPolicy* mDomainPolicy; + DomainEntry* mNext; +#ifdef DEBUG + nsCString mPolicyName_DEBUG; +#endif +}; + +PR_STATIC_CALLBACK(PRBool) +DeleteDomainEntry(nsHashKey *aKey, void *aData, void* closure) +{ + DomainEntry *entry = (DomainEntry*) aData; + do + { + DomainEntry *next = entry->mNext; + delete entry; + entry = next; + } while (entry); + return PR_TRUE; +} + ///////////////////////////// // nsScriptSecurityManager // ///////////////////////////// @@ -140,8 +245,7 @@ nsScriptSecurityManager::GetCurrentContextQuick() //////////////////////////////////// // Methods implementing ISupports // //////////////////////////////////// - -NS_IMPL_THREADSAFE_ISUPPORTS3(nsScriptSecurityManager, +NS_IMPL_ISUPPORTS3(nsScriptSecurityManager, nsIScriptSecurityManager, nsIXPCSecurityManager, nsIObserver) @@ -151,9 +255,10 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsScriptSecurityManager, /////////////////////////////////////////////////// ///////////////// Security Checks ///////////////// -static JSBool JS_DLL_CALLBACK -CheckJSFunctionCallerAccess(JSContext *cx, JSObject *obj, jsval id, - JSAccessMode mode, jsval *vp) +JSBool JS_DLL_CALLBACK +nsScriptSecurityManager::CheckJSFunctionCallerAccess(JSContext *cx, JSObject *obj, + jsval id, JSAccessMode mode, + jsval *vp) { // Currently, this function will be called only when function.caller // is accessed. If that changes, we will need to change this function. @@ -177,7 +282,7 @@ CheckJSFunctionCallerAccess(JSContext *cx, JSObject *obj, jsval id, JSObject* target = JSVAL_TO_OBJECT(*vp); // Do the same-origin check - this sets a JS exception if the check fails - rv = ssm->CheckPropertyAccess(cx, target, "Function", "caller", + rv = ssm->CheckPropertyAccess(cx, target, "Function", sCallerID, nsIXPCSecurityManager::ACCESS_GET_PROPERTY); if (NS_FAILED(rv)) @@ -187,50 +292,54 @@ CheckJSFunctionCallerAccess(JSContext *cx, JSObject *obj, jsval id, } NS_IMETHODIMP -nsScriptSecurityManager::CheckPropertyAccess(JSContext* aJSContext, +nsScriptSecurityManager::CheckPropertyAccess(JSContext* cx, JSObject* aJSObject, const char* aClassName, - const char* aPropertyName, + jsval aProperty, PRUint32 aAction) { - return CheckPropertyAccessImpl(aAction, nsnull, aJSContext, aJSObject, - nsnull, nsnull, nsnull, nsnull, - aClassName, aPropertyName, nsnull); + return CheckPropertyAccessImpl(aAction, nsnull, cx, aJSObject, + nsnull, nsnull, nsnull, + aClassName, aProperty, nsnull); } NS_IMETHODIMP -nsScriptSecurityManager::CheckConnect(JSContext* aJSContext, +nsScriptSecurityManager::CheckConnect(JSContext* cx, nsIURI* aTargetURI, const char* aClassName, const char* aPropertyName) { // Get a context if necessary - if (!aJSContext) + if (!cx) { - aJSContext = GetCurrentContextQuick(); - if (!aJSContext) + cx = GetCurrentJSContext(); + if (!cx) return NS_OK; // No JS context, so allow the load } - nsresult rv = CheckLoadURIFromScript(aJSContext, aTargetURI); + nsresult rv = CheckLoadURIFromScript(cx, aTargetURI); if (NS_FAILED(rv)) return rv; + JSString* propertyName = ::JS_InternString(cx, aPropertyName); + if (!propertyName) + return NS_ERROR_OUT_OF_MEMORY; + return CheckPropertyAccessImpl(nsIXPCSecurityManager::ACCESS_CALL_METHOD, nsnull, - aJSContext, nsnull, nsnull, aTargetURI, - nsnull, nsnull, aClassName, aPropertyName, nsnull); + cx, nsnull, nsnull, aTargetURI, + nsnull, aClassName, STRING_TO_JSVAL(propertyName), nsnull); } nsresult nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, nsIXPCNativeCallContext* aCallContext, - JSContext* aJSContext, JSObject* aJSObject, + JSContext* cx, JSObject* aJSObject, nsISupports* aObj, nsIURI* aTargetURI, nsIClassInfo* aClassInfo, - jsval aName, const char* aClassName, - const char* aProperty, void** aPolicy) + const char* aClassName, jsval aProperty, + void** aCachedClassPolicy) { nsCOMPtr subjectPrincipal; - if (NS_FAILED(GetSubjectPrincipal(aJSContext, getter_AddRefs(subjectPrincipal)))) + if (NS_FAILED(GetSubjectPrincipal(cx, getter_AddRefs(subjectPrincipal)))) return NS_ERROR_FAILURE; PRBool equals; @@ -239,123 +348,137 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, // We have native code or the system principal: just allow access return NS_OK; - static const char unknownClassName[] = "UnknownClass"; -#ifdef DEBUG_mstoltz - if (aProperty) - printf("### CheckPropertyAccess(%s.%s, %i) ", aClassName, aProperty, aAction); - else - { - nsXPIDLCString classNameStr; - const char* className; - if (aClassInfo) - aClassInfo->GetClassDescription(getter_Copies(classNameStr)); - className = classNameStr.get(); - if(!className) - className = unknownClassName; - nsCAutoString propertyStr(className); - propertyStr += '.'; - propertyStr.AppendWithConversion((PRUnichar*)JSValIDToString(aJSContext, aName)); - - char* property; - property = ToNewCString(propertyStr); - printf("### CanAccess(%s, %i) ", property, aAction); - PR_FREEIF(property); - } -#endif - - //-- Look up the policy for this property/method - PRInt32 secLevel; - nsCAutoString capability; - if (aPolicy && *aPolicy) - { -#ifdef DEBUG_mstoltz - printf("Cached "); -#endif - secLevel = NS_PTR_TO_INT32(*aPolicy); - } - else - { - nsXPIDLCString classNameStr; - const char* className; - - nsCAutoString propertyName(aProperty); - if (aClassName) - className = aClassName; - else - //-- Get className and propertyName from aClassInfo and aName, repectively - { - if(aClassInfo) - aClassInfo->GetClassDescription(getter_Copies(classNameStr)); - className = classNameStr.get(); - - if (!className) - className = unknownClassName; - propertyName.AssignWithConversion((PRUnichar*)JSValIDToString(aJSContext, aName)); - } - - // if (aProperty), we were called from CheckPropertyAccess or checkConnect, - // so we can assume this is a DOM class. Otherwise, we ask the ClassInfo. - secLevel = GetSecurityLevel(subjectPrincipal, - (aProperty || IsDOMClass(aClassInfo)), - className, propertyName.get(), aAction, capability, aPolicy); - } - nsresult rv; - switch (secLevel) + ClassNameHolder className(aClassName, aClassInfo); +#ifdef DEBUG_mstoltz + nsCAutoString propertyName; + propertyName.AssignWithConversion((PRUnichar*)JSValIDToString(cx, aProperty)); + printf("### CanAccess(%s.%s, %i) ", className.get(), + propertyName.get(), aAction); +#endif + + //-- Initialize policies if necessary + if (!mDefaultPolicy) { - case SCRIPT_SECURITY_ALL_ACCESS: + rv = InitPolicies(); + if (NS_FAILED(rv)) + return rv; + } + + //-- Look up the policy for this class + ClassPolicy* cpolicy = aCachedClassPolicy ? + NS_REINTERPRET_CAST(ClassPolicy*, *aCachedClassPolicy) : nsnull; + if (!cpolicy) + { + //-- No cached policy for this class, need to look it up #ifdef DEBUG_mstoltz - printf("Level: AllAccess "); + printf("Miss! "); #endif - rv = NS_OK; - break; - case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS: + rv = GetClassPolicy(subjectPrincipal, className.get(), &cpolicy); + if (NS_FAILED(rv)) + return rv; + if (aCachedClassPolicy) + *aCachedClassPolicy = cpolicy; + } + + SecurityLevel securityLevel = GetPropertyPolicy(aProperty, cpolicy, aAction); + + // If the class policy we have is a wildcard policy, then we may + // still need to try the default for this class + if (cpolicy != NO_POLICY_FOR_CLASS && + cpolicy->key[0] == '*' && cpolicy->key[1] == '\0' && + securityLevel.level == SCRIPT_SECURITY_UNDEFINED_ACCESS) + { + cpolicy = + NS_REINTERPRET_CAST(ClassPolicy*, + PL_DHashTableOperate(mDefaultPolicy, + className.get(), + PL_DHASH_LOOKUP)); + if (PL_DHASH_ENTRY_IS_LIVE(cpolicy)) + securityLevel = GetPropertyPolicy(aProperty, cpolicy, aAction); + } + + if (securityLevel.level == SCRIPT_SECURITY_UNDEFINED_ACCESS) + { + // No policy found for this property so use the default of last resort. + // 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 || IsDOMClass(aClassInfo)) + securityLevel.level = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS; + else + securityLevel.level = SCRIPT_SECURITY_NO_ACCESS; + } + + if (SECURITY_ACCESS_LEVEL_FLAG(securityLevel)) + // This flag means securityLevel is allAccess, noAccess, or sameOrigin + { + switch (securityLevel.level) { + case SCRIPT_SECURITY_NO_ACCESS: #ifdef DEBUG_mstoltz - printf("Level: SameOrigin "); + printf("noAccess "); #endif - nsCOMPtr objectPrincipal; - if(aJSObject) + rv = NS_ERROR_DOM_SECURITY_ERR; + break; + + case SCRIPT_SECURITY_ALL_ACCESS: +#ifdef DEBUG_mstoltz + printf("allAccess "); +#endif + rv = NS_OK; + break; + + case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS: { - if (NS_FAILED(GetObjectPrincipal(aJSContext, - NS_REINTERPRET_CAST(JSObject*, aJSObject), - getter_AddRefs(objectPrincipal)))) +#ifdef DEBUG_mstoltz + printf("sameOrigin "); +#endif + nsCOMPtr objectPrincipal; + if(aJSObject) + { + if (NS_FAILED( + GetObjectPrincipal( + cx, + NS_REINTERPRET_CAST(JSObject*, aJSObject), + getter_AddRefs(objectPrincipal)))) + return NS_ERROR_FAILURE; + } + else if(aTargetURI) + { + if (NS_FAILED(GetCodebasePrincipal( + aTargetURI, getter_AddRefs(objectPrincipal)))) + return NS_ERROR_FAILURE; + } + else + { + NS_ERROR("CheckPropertyAccessImpl called without a target object or URL"); return NS_ERROR_FAILURE; - } - else if(aTargetURI) - { - if (NS_FAILED(GetCodebasePrincipal(aTargetURI, getter_AddRefs(objectPrincipal)))) - return NS_ERROR_FAILURE; - } - else - { - rv = NS_ERROR_DOM_SECURITY_ERR; + } + rv = CheckSameOrigin( + cx, subjectPrincipal, objectPrincipal, + aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY); break; } - rv = CheckSameOrigin(aJSContext, subjectPrincipal, objectPrincipal, - aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY); - - break; - } - case SCRIPT_SECURITY_CAPABILITY_ONLY: - { + default: #ifdef DEBUG_mstoltz - printf("Level: Capability "); + printf("ERROR "); #endif - PRBool capabilityEnabled = PR_FALSE; - rv = IsCapabilityEnabled(capability.get(), &capabilityEnabled); - if (NS_FAILED(rv) || !capabilityEnabled) - rv = NS_ERROR_DOM_SECURITY_ERR; - else - rv = NS_OK; - break; + NS_ERROR("Bad Security Level Value"); + return NS_ERROR_FAILURE; } - default: - // Default is no access + } + else // if SECURITY_ACCESS_LEVEL_FLAG is false, securityLevel is a capability + { #ifdef DEBUG_mstoltz - printf("Level: NoAccess (%i)",secLevel); + printf("Cap:%s ", securityLevel.capability); #endif - rv = NS_ERROR_DOM_SECURITY_ERR; + PRBool capabilityEnabled = PR_FALSE; + rv = IsCapabilityEnabled(securityLevel.capability, &capabilityEnabled); + if (NS_FAILED(rv) || !capabilityEnabled) + rv = NS_ERROR_DOM_SECURITY_ERR; + else + rv = NS_OK; } if NS_SUCCEEDED(rv) @@ -379,7 +502,7 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, const nsIID* objIID; rv = aCallContext->GetCalleeWrapper(getter_AddRefs(wrapper)); if (NS_SUCCEEDED(rv)) - rv = wrapper->FindInterfaceWithMember(aName, getter_AddRefs(interfaceInfo)); + rv = wrapper->FindInterfaceWithMember(aProperty, getter_AddRefs(interfaceInfo)); if (NS_SUCCEEDED(rv)) rv = interfaceInfo->GetIIDShared(&objIID); if (NS_SUCCEEDED(rv)) @@ -388,17 +511,17 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, { case nsIXPCSecurityManager::ACCESS_GET_PROPERTY: checkedComponent->CanGetProperty(objIID, - JSValIDToString(aJSContext, aName), + JSValIDToString(cx, aProperty), getter_Copies(objectSecurityLevel)); break; case nsIXPCSecurityManager::ACCESS_SET_PROPERTY: checkedComponent->CanSetProperty(objIID, - JSValIDToString(aJSContext, aName), + JSValIDToString(cx, aProperty), getter_Copies(objectSecurityLevel)); break; case nsIXPCSecurityManager::ACCESS_CALL_METHOD: checkedComponent->CanCallMethod(objIID, - JSValIDToString(aJSContext, aName), + JSValIDToString(cx, aProperty), getter_Copies(objectSecurityLevel)); } } @@ -413,6 +536,7 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, if (NS_FAILED(rv)) //-- Security tests failed, access is denied, report error { + //XXX Clean up string usage here too nsCAutoString errorMsg("Permission denied to "); switch(aAction) { @@ -425,42 +549,22 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, case nsIXPCSecurityManager::ACCESS_CALL_METHOD: errorMsg += "call method "; } + errorMsg += className.get(); + errorMsg += '.'; + errorMsg.AppendWithConversion((PRUnichar*)JSValIDToString(cx, aProperty)); - if (aProperty) + JS_SetPendingException(cx, + STRING_TO_JSVAL(JS_NewStringCopyZ(cx, errorMsg.get()))); + nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID()); + if (xpc) { - errorMsg += aClassName; - errorMsg += '.'; - errorMsg += aProperty; - } - else - { - nsXPIDLCString className; - if (aClassInfo) - aClassInfo->GetClassDescription(getter_Copies(className)); - if(className) - errorMsg += className; - else - errorMsg += unknownClassName; - errorMsg += '.'; - errorMsg.AppendWithConversion(JSValIDToString(aJSContext, aName)); - } - - JS_SetPendingException(aJSContext, - STRING_TO_JSVAL(JS_NewStringCopyZ(aJSContext, errorMsg.get()))); - //-- if (aProperty) we were called from somewhere other than xpconnect, so we need to - // tell xpconnect that an exception was thrown. - if (aProperty) - { - nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID()); - if (xpc) - { - nsCOMPtr xpcCallContext; - xpc->GetCurrentNativeCallContext(getter_AddRefs(xpcCallContext)); - if (xpcCallContext) - xpcCallContext->SetExceptionWasThrown(PR_TRUE); - } + nsCOMPtr xpcCallContext; + xpc->GetCurrentNativeCallContext(getter_AddRefs(xpcCallContext)); + if (xpcCallContext) + xpcCallContext->SetExceptionWasThrown(PR_TRUE); } } + return rv; } @@ -521,148 +625,15 @@ nsScriptSecurityManager::IsDOMClass(nsIClassInfo* aClassInfo) return NS_SUCCEEDED(rv) && (classFlags & nsIClassInfo::DOM_OBJECT); } -PRInt32 -nsScriptSecurityManager::GetSecurityLevel(nsIPrincipal *principal, - PRBool aIsDOM, - const char* aClassName, - const char* aPropertyName, - PRUint32 aAction, - nsCString &aCapability, - void** aPolicy) -{ - nsresult rv = NS_ERROR_FAILURE; - PRInt32 secLevel = SCRIPT_SECURITY_NO_ACCESS; - - nsXPIDLCString propertyPolicy; - PRInt32 classPolicy = 0; - if(mClassPolicies) - { - nsCStringKey classKey(aClassName); - classPolicy = NS_PTR_TO_INT32(mClassPolicies->Get(&classKey)); - if (classPolicy != 0) - { - //-- Look up the security policy for this property - rv = GetPolicy(principal, aClassName, aPropertyName, - classPolicy, aAction, getter_Copies(propertyPolicy)); - } - if (NS_FAILED(rv)) - { //-- Look for a wildcard policy for this property - nsCAutoString wildcardName("*."); - wildcardName += aPropertyName; - nsCStringKey wildcardKey(wildcardName); - PRInt32 wcPolicy = NS_PTR_TO_INT32(mClassPolicies->Get(&wildcardKey)); - if (wcPolicy != 0) - { - //-- Look up the security policy for this property - rv = GetPolicy(principal, "*", aPropertyName, - wcPolicy, aAction, getter_Copies(propertyPolicy)); - } - } - } - if (NS_SUCCEEDED(rv) && propertyPolicy) - { - if (PL_strcmp(propertyPolicy, "sameOrigin") == 0) - secLevel = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS; - else if (PL_strcmp(propertyPolicy, "allAccess") == 0) - secLevel = SCRIPT_SECURITY_ALL_ACCESS; - else if (PL_strcmp(propertyPolicy, "noAccess") == 0) - secLevel = SCRIPT_SECURITY_NO_ACCESS; - else - { - // string should be the name of a capability - aCapability = propertyPolicy; - secLevel = SCRIPT_SECURITY_CAPABILITY_ONLY; - } - } - else - { - //-- No policy for this property. - // Use the default policy: sameOrigin for DOM, noAccess for everything else - if(aIsDOM) - secLevel = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS; - if ((classPolicy == 0) && aPolicy) - { - //-- If there's no stored policy for this property, - // we can annotate the class's aPolicy field and avoid checking - // policy prefs next time. - *aPolicy = (void*)secLevel; - } - } - return secLevel; -} - -struct nsDomainEntry -{ - nsDomainEntry(const char *anOrigin, const char *aPolicy, - int aPolicyLength) - : mNext(nsnull), mOrigin(anOrigin), mPolicy(aPolicy, aPolicyLength) - { } - PRBool Matches(const char *anOrigin) - { - int len = nsCRT::strlen(anOrigin); - int thisLen = mOrigin.Length(); - if (len < thisLen) - return PR_FALSE; - if (mOrigin.RFindChar(':', thisLen-1, 1) != -1) - //-- Policy applies to all URLs of this scheme, compare scheme only - return mOrigin.EqualsWithConversion(anOrigin, PR_TRUE, thisLen); - - //-- Policy applies to a particular host; compare scheme://host.domain - if (!mOrigin.Equals(anOrigin + (len - thisLen))) - return PR_FALSE; - if (len == thisLen) - return PR_TRUE; - char charBefore = anOrigin[len-thisLen-1]; - return (charBefore == '.' || charBefore == ':' || charBefore == '/'); - } - nsDomainEntry *mNext; - nsCString mOrigin; - nsCString mPolicy; -}; - nsresult -nsScriptSecurityManager::TryToGetPref(nsISecurityPref* aSecurityPref, - nsCString &aPrefName, - const char* aClassName, - const char* aPropertyName, - PRInt32 aClassPolicy, - PRUint32 aAction, char** result) -{ - //-- Add the class and property names to the pref - aPrefName += aClassName; - aPrefName += '.'; - aPrefName += aPropertyName; - - //-- Try to look up the pref - if (NS_SUCCEEDED(aSecurityPref->SecurityGetCharPref(aPrefName.get(), result))) - return NS_OK; - - //-- If appropriate, try adding .get or .set and looking up again - if (aClassPolicy & CLASS_HAS_ACCESSTYPE) - { - aPrefName += - (aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY ? ".set" : ".get"); - return aSecurityPref->SecurityGetCharPref(aPrefName.get(), result); - } - - //-- Couldn't find a pref - return NS_ERROR_FAILURE; -} - -nsresult -nsScriptSecurityManager::GetPolicy(nsIPrincipal* principal, - const char* aClassName, const char* aPropertyName, - PRInt32 aClassPolicy, PRUint32 aAction, char** result) +nsScriptSecurityManager::GetClassPolicy(nsIPrincipal* principal, const char* aClassName, + ClassPolicy** result) { nsresult rv; *result = nsnull; - - nsCOMPtr securityPref(do_QueryReferent(mPrefBranchWeakRef)); - if (!securityPref) - return NS_ERROR_FAILURE; - - if ((aClassPolicy & CLASS_HAS_SITE_POLICY) && mOriginToPolicyMap) - { //-- Look up the name of the relevant per-site policy + DomainPolicy* dpolicy = nsnull; + if (mOriginToPolicyMap) + { //-- Look up the relevant domain policy, if any nsCOMPtr codebase(do_QueryInterface(principal)); if (!codebase) return NS_ERROR_FAILURE; @@ -670,12 +641,12 @@ nsScriptSecurityManager::GetPolicy(nsIPrincipal* principal, nsXPIDLCString origin; if (NS_FAILED(rv = codebase->GetOrigin(getter_Copies(origin)))) return rv; - - const char *s = origin; + + const char *start = origin; const char *nextToLastDot = nsnull; const char *lastDot = nsnull; const char *colon = nsnull; - const char *p = s; + const char *p = start; while (*p) { if (*p == '.') @@ -688,54 +659,115 @@ nsScriptSecurityManager::GetPolicy(nsIPrincipal* principal, p++; } - nsCStringKey key(nextToLastDot ? nextToLastDot+1 : s); - nsDomainEntry *de = (nsDomainEntry *) mOriginToPolicyMap->Get(&key); + nsCStringKey key(nextToLastDot ? nextToLastDot+1 : start); + DomainEntry *de = (DomainEntry*) mOriginToPolicyMap->Get(&key); if (!de) { - nsCAutoString scheme(s, colon-s+1); + nsCAutoString scheme(start, colon-start+1); nsCStringKey schemeKey(scheme); - de = (nsDomainEntry *) mOriginToPolicyMap->Get(&schemeKey); + de = (DomainEntry*) mOriginToPolicyMap->Get(&schemeKey); } - nsCString *policy = nsnull; while (de) { - if (de->Matches(s)) + if (de->Matches(start)) { - policy = &de->mPolicy; + dpolicy = de->mDomainPolicy; break; } de = de->mNext; } + } - if (policy) + ClassPolicy* wildcardPolicy = nsnull; + if (dpolicy) + { + //-- Now get the class policy + *result = + NS_REINTERPRET_CAST(ClassPolicy*, + PL_DHashTableOperate(dpolicy, + aClassName, + PL_DHASH_LOOKUP)); + + //-- and the wildcard policy (class "*" for this domain) + wildcardPolicy = + NS_REINTERPRET_CAST(ClassPolicy*, + PL_DHashTableOperate(dpolicy, + "*", + PL_DHASH_LOOKUP)); + } + + //-- and the default policy for this class + ClassPolicy* defaultClassPolicy = + NS_REINTERPRET_CAST(ClassPolicy*, + PL_DHashTableOperate(mDefaultPolicy, + aClassName, + PL_DHASH_LOOKUP)); + + if (*result && PL_DHASH_ENTRY_IS_LIVE(*result)) + { + if (PL_DHASH_ENTRY_IS_LIVE(wildcardPolicy)) + (*result)->mWildcard = wildcardPolicy; + if (PL_DHASH_ENTRY_IS_LIVE(defaultClassPolicy)) + (*result)->mDefault = defaultClassPolicy; + } + else + { + if (wildcardPolicy && PL_DHASH_ENTRY_IS_LIVE(wildcardPolicy)) + *result = wildcardPolicy; + else if (PL_DHASH_ENTRY_IS_LIVE(defaultClassPolicy)) + *result = defaultClassPolicy; + else + *result = NO_POLICY_FOR_CLASS; + } + + return NS_OK; +} + +SecurityLevel +nsScriptSecurityManager::GetPropertyPolicy(jsval aProperty, ClassPolicy* aClassPolicy, + PRUint32 aAction) +{ + //-- Look up the policy for this property/method + PropertyPolicy* ppolicy = nsnull; + if (aClassPolicy && aClassPolicy != NO_POLICY_FOR_CLASS) + { + ppolicy = + (PropertyPolicy*) PL_DHashTableOperate(&aClassPolicy->mPolicy, + NS_REINTERPRET_CAST(void*, aProperty), + PL_DHASH_LOOKUP); + if (!PL_DHASH_ENTRY_IS_LIVE(ppolicy)) + { // No domain policy for this property, look for a wildcard policy + if (aClassPolicy->mWildcard) + { + ppolicy = NS_REINTERPRET_CAST(PropertyPolicy*, + PL_DHashTableOperate(&aClassPolicy->mWildcard->mPolicy, + NS_REINTERPRET_CAST(void*, aProperty), + PL_DHASH_LOOKUP)); + } + if (!PL_DHASH_ENTRY_IS_LIVE(ppolicy) && aClassPolicy->mDefault) + { // Now look for a default policy + ppolicy = NS_REINTERPRET_CAST(PropertyPolicy*, + PL_DHashTableOperate(&aClassPolicy->mDefault->mPolicy, + NS_REINTERPRET_CAST(void*, aProperty), + PL_DHASH_LOOKUP)); + } + } + if (PL_DHASH_ENTRY_IS_LIVE(ppolicy)) { - //-- build the pref name and look it up - //-- the form is "capability.policy.policyname.class.property" - nsCAutoString prefName("capability.policy."); - prefName += *policy; - prefName += '.'; - rv = TryToGetPref(securityPref, prefName, aClassName, aPropertyName, - aClassPolicy, aAction, result); - if (NS_SUCCEEDED(rv)) - return NS_OK; + // Get the correct security level from the property policy + if (aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY) + return ppolicy->mSet; + return ppolicy->mGet; } } - //-- Now try looking up a default policy, if one exists - //-- the form is "capability.policy.default.class.property" - if (aClassPolicy & CLASS_HAS_DEFAULT_POLICY) - { - nsCAutoString prefName("capability.policy.default."); - rv = TryToGetPref(securityPref, prefName, aClassName, aPropertyName, - aClassPolicy, aAction, result); - if (NS_SUCCEEDED(rv)) - return NS_OK; - } - //-- Couldn't find a policy - return NS_ERROR_FAILURE; + SecurityLevel nopolicy; + nopolicy.level = SCRIPT_SECURITY_UNDEFINED_ACCESS; + return nopolicy; } + NS_IMETHODIMP nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsIURI *aURI) { @@ -931,11 +963,7 @@ nsScriptSecurityManager::CheckLoadURI(nsIURI *aSourceURI, nsIURI *aTargetURI, case PrefControlled: // Allow access if pref is false { - nsCOMPtr securityPref = - do_QueryReferent(mPrefBranchWeakRef); - if (!securityPref) - return NS_ERROR_FAILURE; - securityPref->SecurityGetBoolPref("security.checkloaduri", &doCheck); + mSecurityPref->SecurityGetBoolPref("security.checkloaduri", &doCheck); return doCheck ? ReportErrorToConsole(aTargetURI) : NS_OK; } case ChromeProtocol: @@ -1097,10 +1125,10 @@ nsScriptSecurityManager::GetRootDocShell(JSContext *cx, nsIDocShell **result) NS_IMETHODIMP nsScriptSecurityManager::CanExecuteScripts(JSContext* cx, - nsIPrincipal *principal, + nsIPrincipal *aPrincipal, PRBool *result) { - if (principal == mSystemPrincipal) + if (aPrincipal == mSystemPrincipal) { // Even if JavaScript is disabled, we must still execute system scripts *result = PR_TRUE; @@ -1113,7 +1141,7 @@ nsScriptSecurityManager::CanExecuteScripts(JSContext* cx, nsresult rv; if (!mIsJavaScriptEnabled) { - nsCOMPtr codebase(do_QueryInterface(principal)); + nsCOMPtr codebase(do_QueryInterface(aPrincipal)); if (codebase) { nsXPIDLCString origin; @@ -1155,18 +1183,28 @@ nsScriptSecurityManager::CanExecuteScripts(JSContext* cx, //-- Check for a per-site policy static const char jsPrefGroupName[] = "javascript"; - nsCStringKey jsKey(jsPrefGroupName); - PRInt32 classPolicy = mClassPolicies ? NS_PTR_TO_INT32(mClassPolicies->Get(&jsKey)) : 0; - if(classPolicy) + + // Initialize policies if necessary + if (!mDefaultPolicy) { - nsXPIDLCString policy; - rv = GetPolicy(principal, jsPrefGroupName, "enabled", classPolicy, 0, - getter_Copies(policy)); - if (NS_SUCCEEDED(rv) && (PL_strcmp("noAccess", policy) == 0)) - { - *result = PR_FALSE; - return NS_OK; - } + rv = InitPolicies(); + if (NS_FAILED(rv)) + return rv; + } + + ClassPolicy* cpolicy; + SecurityLevel secLevel; + rv = GetClassPolicy(aPrincipal, jsPrefGroupName, &cpolicy); + + if (NS_SUCCEEDED(rv)) + { + secLevel = GetPropertyPolicy(sEnabledID, cpolicy, + nsIXPCSecurityManager::ACCESS_GET_PROPERTY); + } + if (NS_FAILED(rv) || secLevel.level == SCRIPT_SECURITY_NO_ACCESS) + { + *result = PR_FALSE; + return rv; } //-- Nobody vetoed, so allow the JS to run. @@ -1178,7 +1216,7 @@ nsScriptSecurityManager::CanExecuteScripts(JSContext* cx, NS_IMETHODIMP nsScriptSecurityManager::GetSubjectPrincipal(nsIPrincipal **result) { - JSContext *cx = GetCurrentContextQuick(); + JSContext *cx = GetCurrentJSContext(); if (!cx) { *result = nsnull; @@ -1505,24 +1543,21 @@ nsScriptSecurityManager::SavePrincipal(nsIPrincipal* aToSave) getter_Copies(deniedPrefName) ); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; - nsCOMPtr securityPref(do_QueryReferent(mPrefBranchWeakRef)); - if (!securityPref) - return NS_ERROR_FAILURE; mIsWritingPrefs = PR_TRUE; if (grantedList) - securityPref->SecuritySetCharPref(grantedPrefName, grantedList); + mSecurityPref->SecuritySetCharPref(grantedPrefName, grantedList); else - securityPref->SecurityClearUserPref(grantedPrefName); + mSecurityPref->SecurityClearUserPref(grantedPrefName); if (deniedList) - securityPref->SecuritySetCharPref(deniedPrefName, deniedList); + mSecurityPref->SecuritySetCharPref(deniedPrefName, deniedList); else - securityPref->SecurityClearUserPref(deniedPrefName); + mSecurityPref->SecurityClearUserPref(deniedPrefName); if (grantedList || deniedList) - securityPref->SecuritySetCharPref(idPrefName, id); + mSecurityPref->SecuritySetCharPref(idPrefName, id); else - securityPref->SecurityClearUserPref(idPrefName); + mSecurityPref->SecurityClearUserPref(idPrefName); mIsWritingPrefs = PR_FALSE; @@ -1538,7 +1573,7 @@ nsScriptSecurityManager::IsCapabilityEnabled(const char *capability, { nsresult rv; JSStackFrame *fp = nsnull; - JSContext *cx = GetCurrentContextQuick(); + JSContext *cx = GetCurrentJSContext(); fp = cx ? JS_FrameIterator(cx, &fp) : nsnull; if (!fp) { @@ -1730,7 +1765,7 @@ nsScriptSecurityManager::RequestCapability(nsIPrincipal* aPrincipal, return NS_ERROR_FAILURE; PRUnichar *message = nsTextFormatter::smprintf(query.get(), source); Recycle(source); - JSContext *cx = GetCurrentContextQuick(); + JSContext *cx = GetCurrentJSContext(); if (CheckConfirmDialog(cx, message, check.get(), &remember)) *canEnable = nsIPrincipal::ENABLE_GRANTED; else @@ -1751,7 +1786,7 @@ nsScriptSecurityManager::RequestCapability(nsIPrincipal* aPrincipal, NS_IMETHODIMP nsScriptSecurityManager::EnableCapability(const char *capability) { - JSContext *cx = GetCurrentContextQuick(); + JSContext *cx = GetCurrentJSContext(); JSStackFrame *fp; //-- Error checks for capability string length (200) @@ -1792,7 +1827,7 @@ nsScriptSecurityManager::EnableCapability(const char *capability) NS_IMETHODIMP nsScriptSecurityManager::RevertCapability(const char *capability) { - JSContext *cx = GetCurrentContextQuick(); + JSContext *cx = GetCurrentJSContext(); JSStackFrame *fp; nsCOMPtr principal; if (NS_FAILED(GetPrincipalAndFrame(cx, getter_AddRefs(principal), &fp))) @@ -1806,7 +1841,7 @@ nsScriptSecurityManager::RevertCapability(const char *capability) NS_IMETHODIMP nsScriptSecurityManager::DisableCapability(const char *capability) { - JSContext *cx = GetCurrentContextQuick(); + JSContext *cx = GetCurrentJSContext(); JSStackFrame *fp; nsCOMPtr principal; if (NS_FAILED(GetPrincipalAndFrame(cx, getter_AddRefs(principal), &fp))) @@ -1871,7 +1906,7 @@ nsScriptSecurityManager::SetCanEnableCapability(const char* certificateID, } if (!isEqual) { - JSContext* cx = GetCurrentContextQuick(); + JSContext* cx = GetCurrentJSContext(); if (!cx) return NS_ERROR_FAILURE; static const char msg1[] = "Only code signed by the system certificate may call SetCanEnableCapability or Invalidate"; static const char msg2[] = "Attempt to call SetCanEnableCapability or Invalidate when no system certificate has been established"; @@ -1894,7 +1929,7 @@ nsScriptSecurityManager::SetCanEnableCapability(const char* certificateID, //////////////////////////////////////////////// NS_IMETHODIMP -nsScriptSecurityManager::CanCreateWrapper(JSContext *aJSContext, +nsScriptSecurityManager::CanCreateWrapper(JSContext *cx, const nsIID &aIID, nsISupports *aObj, nsIClassInfo *aClassInfo, @@ -1928,7 +1963,6 @@ nsScriptSecurityManager::CanCreateWrapper(JSContext *aJSContext, { //-- Access denied, report an error nsCAutoString errorMsg("Permission denied to create wrapper for object "); - // XXX get class name nsXPIDLCString className; if (aClassInfo) { @@ -1939,14 +1973,14 @@ nsScriptSecurityManager::CanCreateWrapper(JSContext *aJSContext, errorMsg += className; } } - JS_SetPendingException(aJSContext, - STRING_TO_JSVAL(JS_NewStringCopyZ(aJSContext, errorMsg.get()))); + JS_SetPendingException(cx, + STRING_TO_JSVAL(JS_NewStringCopyZ(cx, errorMsg.get()))); } return rv; } NS_IMETHODIMP -nsScriptSecurityManager::CanCreateInstance(JSContext *aJSContext, +nsScriptSecurityManager::CanCreateInstance(JSContext *cx, const nsCID &aCID) { nsresult rv = CheckXPCPermissions(nsnull, nsnull); @@ -1957,14 +1991,14 @@ nsScriptSecurityManager::CanCreateInstance(JSContext *aJSContext, nsXPIDLCString cidStr; cidStr += aCID.ToString(); errorMsg.Append(cidStr); - JS_SetPendingException(aJSContext, - STRING_TO_JSVAL(JS_NewStringCopyZ(aJSContext, errorMsg.get()))); + JS_SetPendingException(cx, + STRING_TO_JSVAL(JS_NewStringCopyZ(cx, errorMsg.get()))); } return rv; } NS_IMETHODIMP -nsScriptSecurityManager::CanGetService(JSContext *aJSContext, +nsScriptSecurityManager::CanGetService(JSContext *cx, const nsCID &aCID) { #if 0 @@ -1981,26 +2015,26 @@ nsScriptSecurityManager::CanGetService(JSContext *aJSContext, nsXPIDLCString cidStr; cidStr += aCID.ToString(); errorMsg.Append(cidStr); - JS_SetPendingException(aJSContext, - STRING_TO_JSVAL(JS_NewStringCopyZ(aJSContext, errorMsg.get()))); + JS_SetPendingException(cx, + STRING_TO_JSVAL(JS_NewStringCopyZ(cx, errorMsg.get()))); } return rv; } -/* void CanAccess (in PRUint32 aAction, in nsIXPCNativeCallContext aCallContext, in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in nsISupports aObj, in nsIClassInfo aClassInfo, in JSVal aName, inout voidPtr aPolicy); */ + NS_IMETHODIMP nsScriptSecurityManager::CanAccess(PRUint32 aAction, nsIXPCNativeCallContext* aCallContext, - JSContext* aJSContext, + JSContext* cx, JSObject* aJSObject, nsISupports* aObj, nsIClassInfo* aClassInfo, - jsval aName, + jsval aPropertyName, void** aPolicy) { - return CheckPropertyAccessImpl(aAction, aCallContext, aJSContext, + return CheckPropertyAccessImpl(aAction, aCallContext, cx, aJSObject, aObj, nsnull, aClassInfo, - aName, nsnull, nsnull, aPolicy); + nsnull, aPropertyName, aPolicy); } nsresult @@ -2038,10 +2072,7 @@ nsScriptSecurityManager::CheckXPCPermissions(nsISupports* aObj, static PRBool allowPluginAccess = PR_FALSE; if (!prefSet) { - nsCOMPtr securityPref(do_QueryReferent(mPrefBranchWeakRef)); - if (!securityPref) - return NS_ERROR_FAILURE; - rv = securityPref->SecurityGetBoolPref("security.xpconnect.plugin.unrestricted", + rv = mSecurityPref->SecurityGetBoolPref("security.xpconnect.plugin.unrestricted", &allowPluginAccess); prefSet = PR_TRUE; } @@ -2058,44 +2089,34 @@ nsScriptSecurityManager::CheckXPCPermissions(nsISupports* aObj, // Method implementing nsIObserver // ///////////////////////////////////// static const char sPrincipalPrefix[] = "capability.principal"; -static const char sPolicyPrefix[] = "capability.policy"; +static const char sProfileChangeMsg[] = "profile-after-change"; NS_IMETHODIMP -nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aAction, - const PRUnichar* aPrefName) +nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aTopic, + const PRUnichar* aMessage) { nsresult rv = NS_OK; - nsCAutoString prefNameStr; - prefNameStr.AssignWithConversion(aPrefName); - char* prefName = ToNewCString(prefNameStr); - if (!prefName) - return NS_ERROR_OUT_OF_MEMORY; - nsCOMPtr securityPref(do_QueryReferent(mPrefBranchWeakRef)); - if (!securityPref) - return NS_ERROR_FAILURE; + NS_ConvertUCS2toUTF8 messageStr(aMessage); + const char *message = messageStr.get(); static const char jsPrefix[] = "javascript."; - if(PL_strncmp(prefName, jsPrefix, sizeof(jsPrefix)-1) == 0) - JSEnabledPrefChanged(securityPref); - else if((PL_strncmp(prefName, sPrincipalPrefix, sizeof(sPrincipalPrefix)-1) == 0) && + if(PL_strncmp(message, jsPrefix, sizeof(jsPrefix)-1) == 0) + JSEnabledPrefChanged(mSecurityPref); + else if((PL_strncmp(message, sPrincipalPrefix, sizeof(sPrincipalPrefix)-1) == 0) && !mIsWritingPrefs) { static const char id[] = "id"; - char* lastDot = PL_strrchr(prefName, '.'); + char* lastDot = PL_strrchr(message, '.'); //-- This check makes sure the string copy below doesn't overwrite its bounds if(PL_strlen(lastDot) >= sizeof(id)) { PL_strcpy(lastDot + 1, id); - const char** idPrefArray = (const char**)&prefName; - rv = InitPrincipals(1, idPrefArray, securityPref); + const char** idPrefArray = (const char**)&message; + rv = InitPrincipals(1, idPrefArray, mSecurityPref); } } - else if((PL_strncmp(prefName, sPolicyPrefix, sizeof(sPolicyPrefix)-1) == 0)) - { - const char** prefArray = (const char**)&prefName; - rv = InitPolicies(1, prefArray, securityPref); - } - PR_Free(prefName); + else if((PL_strcmp(aTopic, sProfileChangeMsg) == 0)) + rv = InitPolicies(); return rv; } @@ -2104,7 +2125,8 @@ nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aAction, ///////////////////////////////////////////// nsScriptSecurityManager::nsScriptSecurityManager(void) : mOriginToPolicyMap(nsnull), - mClassPolicies(nsnull), + mDefaultPolicy(nsnull), + mCapabilities(nsnull), mSystemPrincipal(nsnull), mPrincipals(nsnull), mIsJavaScriptEnabled(PR_FALSE), mIsMailJavaScriptEnabled(PR_FALSE), @@ -2112,9 +2134,16 @@ nsScriptSecurityManager::nsScriptSecurityManager(void) mNameSetRegistered(PR_FALSE) { + NS_ASSERTION(sizeof(long) == sizeof(void*), "long and void* have different lengths on this platform. This may cause a security failure."); NS_INIT_REFCNT(); + + JSContext* cx = GetSafeJSContext(); + if (sCallerID == JSVAL_VOID) + sCallerID = STRING_TO_JSVAL(::JS_InternString(cx, "caller")); + if (sEnabledID == JSVAL_VOID) + sEnabledID = STRING_TO_JSVAL(::JS_InternString(cx, "enabled")); + InitPrefs(); - mThreadJSContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); //-- Register security check callback in the JS engine // Currently this is used to control access to function.caller @@ -2136,12 +2165,23 @@ nsScriptSecurityManager::nsScriptSecurityManager(void) NS_ASSERTION(!oldCallback, "Someone already set a JS CheckObjectAccess callback"); } +jsval nsScriptSecurityManager::sCallerID = JSVAL_VOID; +jsval nsScriptSecurityManager::sEnabledID = JSVAL_VOID; + nsScriptSecurityManager::~nsScriptSecurityManager(void) { delete mOriginToPolicyMap; - delete mClassPolicies; + delete mDefaultPolicy; NS_IF_RELEASE(mSystemPrincipal); delete mPrincipals; + delete mCapabilities; +} + +void +nsScriptSecurityManager::Shutdown() +{ + sCallerID = JSVAL_VOID; + sEnabledID = JSVAL_VOID; } static nsScriptSecurityManager *ssecMan = NULL; @@ -2192,155 +2232,279 @@ nsScriptSecurityManager::SystemPrincipalSingletonConstructor() return NS_STATIC_CAST(nsSystemPrincipal*, sysprin); } - -const char* nsScriptSecurityManager::sJSEnabledPrefName = "javascript.enabled"; -const char* nsScriptSecurityManager::sJSMailEnabledPrefName = "javascript.allow.mailnews"; - -PR_STATIC_CALLBACK(PRBool) -DeleteEntry(nsHashKey *aKey, void *aData, void* closure) +NS_IMETHODIMP +nsScriptSecurityManager::ReloadSecurityPolicies() { - nsDomainEntry *entry = (nsDomainEntry *) aData; - do - { - nsDomainEntry *next = entry->mNext; - delete entry; - entry = next; - } while (entry); - return PR_TRUE; + nsresult rv; + nsCOMPtr xpc(do_GetService(nsIXPConnect::GetCID(), &rv)); + if (NS_FAILED(rv)) return rv; + + rv = xpc->ClearAllWrappedNativeSecurityPolicies(); + if (NS_FAILED(rv)) return rv; + + return InitPolicies(); } +static NS_NAMED_LITERAL_CSTRING(policyPrefPrefix, "capability.policy."); + nsresult -nsScriptSecurityManager::InitPolicies(PRUint32 aPrefCount, const char** aPrefNames, - nsISecurityPref* aSecurityPref) +nsScriptSecurityManager::InitPolicies() { - for (PRUint32 c = 0; c < aPrefCount; c++) + nsresult rv; + //-- Reset mOriginToPolicyMap + delete mOriginToPolicyMap; + mOriginToPolicyMap = + new nsObjectHashtable(nsnull, nsnull, DeleteDomainEntry, nsnull); + + //-- Reset and initialize the default policy + delete mDefaultPolicy; + mDefaultPolicy = + new DomainPolicy(); + if (!mOriginToPolicyMap || !mDefaultPolicy) + return NS_ERROR_OUT_OF_MEMORY; + + //-- Initialize the table of security levels + if (!mCapabilities) { - unsigned count = 0; - const char *dots[5]; - const char *p; - for (p=aPrefNames[c]; *p; p++) - { - if (*p == '.') - { - dots[count++] = p; - if (count == sizeof(dots)/sizeof(dots[0])) - break; - } - } - if (count < sizeof(dots)/sizeof(dots[0])) - dots[count] = p; - if (count < 3) - continue; - const char *policyName = dots[1] + 1; - int policyLength = dots[2] - policyName; - PRBool isDefault = PL_strncmp("default", policyName, policyLength) == 0; - if (!isDefault && count == 3) - { - // capability.policy..sites - const char *sitesName = dots[2] + 1; - int sitesLength = dots[3] - sitesName; - if (PL_strncmp("sites", sitesName, sitesLength) == 0) - { - if (!mOriginToPolicyMap) - { - mOriginToPolicyMap = - new nsObjectHashtable(nsnull, nsnull, DeleteEntry, nsnull); - if (!mOriginToPolicyMap) - return NS_ERROR_OUT_OF_MEMORY; - } - char *s; - if (NS_FAILED(aSecurityPref->SecurityGetCharPref(aPrefNames[c], &s))) - return NS_ERROR_FAILURE; - char *q=s; - char *r=s; - char *lastDot = nsnull; - char *nextToLastDot = nsnull; - PRBool working = PR_TRUE; - while (working) - { - if (*r == ' ' || *r == '\0') - { - working = (*r != '\0'); - *r = '\0'; - nsCStringKey key(nextToLastDot ? nextToLastDot+1 : q); - nsDomainEntry *value = new nsDomainEntry(q, policyName, - policyLength); - if (!value) - break; - nsDomainEntry *de = (nsDomainEntry *) - mOriginToPolicyMap->Get(&key); - if (!de) - mOriginToPolicyMap->Put(&key, value); - else - { - if (de->Matches(q)) - { - value->mNext = de; - mOriginToPolicyMap->Put(&key, value); - } - else - { - while (de->mNext) - { - if (de->mNext->Matches(q)) - { - value->mNext = de->mNext; - de->mNext = value; - break; - } - de = de->mNext; - } - if (!de->mNext) - de->mNext = value; - } - } - q = r + 1; - lastDot = nextToLastDot = nsnull; - } - else if (*r == '.') - { - nextToLastDot = lastDot; - lastDot = r; - } - r++; - } - PR_Free(s); - } - } - else if (count > 3) - { // capability.policy...[.(get|set)] - // Store a notation for this class name in the classes hashtable. - // The stored value contains several bits of information. - if (!(mClassPolicies)) - mClassPolicies = new nsHashtable(31); - - // In most cases, we hash on the class name at dots[2]+1, - // unless the class name is '*' (wildcard), in which case we hash on - // '*.propertyname' - // Shoving nulls into the pref name string is unorthodox - // but it saves a malloc & copy - hash keys require null-terminated strings - if (!( (dots[2][1] == '*') && (dots[2][2] == '.') )) - *(char*)dots[3] = '\0'; - else if (count > 4) - { - // There's a .get or .set at the end - *(char*)dots[4] = '\0'; - } - - nsCStringKey classNameKey(dots[2] + 1); - PRInt32 classPolicy = NS_PTR_TO_INT32(mClassPolicies->Get(&classNameKey)); - if (isDefault) - classPolicy |= CLASS_HAS_DEFAULT_POLICY; - else - classPolicy |= CLASS_HAS_SITE_POLICY; - if (count > 4) - classPolicy |= CLASS_HAS_ACCESSTYPE; - mClassPolicies->Put(&classNameKey, NS_INT32_TO_PTR(classPolicy)); - } + mCapabilities = + new nsObjectHashtable(nsnull, nsnull, DeleteCapability, nsnull); + if (!mCapabilities) + return NS_ERROR_OUT_OF_MEMORY; } + + // Get a JS context - we need it to create internalized strings later. + JSContext* cx = GetSafeJSContext(); + NS_ASSERTION(cx, "failed to get JS context"); + rv = InitDomainPolicy(cx, "default", mDefaultPolicy); + NS_ENSURE_SUCCESS(rv, rv); + + nsXPIDLCString policyNames; + rv = mSecurityPref->SecurityGetCharPref("capability.policy.policynames", + getter_Copies(policyNames)); + + nsXPIDLCString defaultPolicyNames; + rv = mSecurityPref->SecurityGetCharPref("capability.policy.default_policynames", + getter_Copies(defaultPolicyNames)); + policyNames += NS_LITERAL_CSTRING(" ") + defaultPolicyNames; + + //-- Initialize domain policies + char* policyCurrent = (char*)policyNames.get(); + PRBool morePolicies = PR_TRUE; + while (morePolicies) + { + while(*policyCurrent == ' ' || *policyCurrent == ',') + policyCurrent++; + if (*policyCurrent == '\0') + break; + char* nameBegin = policyCurrent; + + while(*policyCurrent != '\0' && *policyCurrent != ' ' && *policyCurrent != ',') + policyCurrent++; + + morePolicies = (*policyCurrent != '\0'); + *policyCurrent = '\0'; + policyCurrent++; + + //XXX use better concatenation? + nsCAutoString sitesPrefName(policyPrefPrefix + + nsDependentCString(nameBegin) + + NS_LITERAL_CSTRING(".sites")); + nsXPIDLCString domainList; + rv = mSecurityPref->SecurityGetCharPref(sitesPrefName.get(), + getter_Copies(domainList)); + if (NS_FAILED(rv)) + continue; + + DomainPolicy* domainPolicy = new DomainPolicy(); + if (!domainPolicy) + return NS_ERROR_OUT_OF_MEMORY; + + //-- Parse list of sites and create an entry in mOriginToPolicyMap for each + char* domainStart = (char*)domainList.get(); + char* domainCurrent = domainStart; + char* lastDot = nsnull; + char* nextToLastDot = nsnull; + PRBool moreDomains = PR_TRUE; + while (moreDomains) + { + if (*domainCurrent == ' ' || *domainCurrent == '\0') + { + moreDomains = (*domainCurrent != '\0'); + *domainCurrent = '\0'; + nsCStringKey key(nextToLastDot ? nextToLastDot+1 : domainStart); + DomainEntry *newEntry = new DomainEntry(domainStart, domainPolicy); + if (!newEntry) + return NS_ERROR_OUT_OF_MEMORY; +#ifdef DEBUG + newEntry->mPolicyName_DEBUG = nameBegin; +#endif + DomainEntry *existingEntry = (DomainEntry *) + mOriginToPolicyMap->Get(&key); + if (!existingEntry) + mOriginToPolicyMap->Put(&key, newEntry); + else + { + if (existingEntry->Matches(domainStart)) + { + newEntry->mNext = existingEntry; + mOriginToPolicyMap->Put(&key, newEntry); + } + else + { + while (existingEntry->mNext) + { + if (existingEntry->mNext->Matches(domainStart)) + { + newEntry->mNext = existingEntry->mNext; + existingEntry->mNext = newEntry; + break; + } + existingEntry = existingEntry->mNext; + } + if (!existingEntry->mNext) + existingEntry->mNext = newEntry; + } + } + domainStart = domainCurrent + 1; + lastDot = nextToLastDot = nsnull; + } + else if (*domainCurrent == '.') + { + nextToLastDot = lastDot; + lastDot = domainCurrent; + } + domainCurrent++; + } + + rv = InitDomainPolicy(cx, nameBegin, domainPolicy); + NS_ENSURE_SUCCESS(rv, rv); + } + +#ifdef DEBUG_mstoltz + PrintPolicyDB(); +#endif return NS_OK; } + +nsresult +nsScriptSecurityManager::InitDomainPolicy(JSContext* cx, + const char* aPolicyName, + DomainPolicy* aDomainPolicy) +{ + nsresult rv; + nsCAutoString policyPrefix(policyPrefPrefix + + nsDependentCString(aPolicyName) + + NS_LITERAL_CSTRING(".")); + PRUint32 prefixLength = policyPrefix.Length() - 1; // subtract the '.' + + // XXX fix string use here. + PRUint32 prefCount; + char** prefNames; + rv = mPrefBranch->GetChildList(policyPrefix.get(), + &prefCount, &prefNames); + if (NS_FAILED(rv)) return rv; + if (prefCount == 0) + return NS_OK; + + //-- Populate the policy + PRUint32 currentPref = 0; + for (; currentPref < prefCount; currentPref++) + { + // Get the class name + const char* start = prefNames[currentPref] + prefixLength +1; + char* end = PL_strchr(start, '.'); + if (!end) // malformed pref, bail on this one + continue; + static const char sitesStr[] = "sites"; + + // We dealt with "sites" in InitPolicies(), so no need to do + // that again... + if (PL_strncmp(start, sitesStr, sizeof(sitesStr)-1) == 0) + continue; + + // Get the pref value + nsXPIDLCString prefValue; + rv = mSecurityPref->SecurityGetCharPref(prefNames[currentPref], + getter_Copies(prefValue)); + if (NS_FAILED(rv) || !prefValue) + continue; + + SecurityLevel secLevel; + if (PL_strcasecmp(prefValue, "noAccess") == 0) + secLevel.level = SCRIPT_SECURITY_NO_ACCESS; + else if (PL_strcasecmp(prefValue, "allAccess") == 0) + secLevel.level = SCRIPT_SECURITY_ALL_ACCESS; + else if (PL_strcasecmp(prefValue, "sameOrigin") == 0) + secLevel.level = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS; + else + { //-- pref value is the name of a capability + nsCStringKey secLevelKey(prefValue); + secLevel.capability = + NS_REINTERPRET_CAST(char*, mCapabilities->Get(&secLevelKey)); + if (!secLevel.capability) + { + secLevel.capability = nsCRT::strdup(prefValue); + if (!secLevel.capability) + break; + mCapabilities->Put(&secLevelKey, + secLevel.capability); + } + } + + *end = '\0'; + // Find or store this class in the classes table + ClassPolicy* cpolicy = + NS_REINTERPRET_CAST(ClassPolicy*, + PL_DHashTableOperate(aDomainPolicy, + start, + PL_DHASH_ADD)); + + if (!cpolicy) + break; + + // Get the property name + start = end + 1; + end = PL_strchr(start, '.'); + if (end) + *end = '\0'; + + JSString* propertyKey = ::JS_InternString(cx, start); + if (!propertyKey) + return NS_ERROR_OUT_OF_MEMORY; + + // Store this property in the class policy + PropertyPolicy* ppolicy = + (PropertyPolicy*) PL_DHashTableOperate(&cpolicy->mPolicy, + (void*)STRING_TO_JSVAL(propertyKey), + PL_DHASH_ADD); + if (!ppolicy) + break; + + if (end) // The pref specifies an access mode + { + start = end + 1; + if (PL_strcasecmp(start, "set") == 0) + ppolicy->mSet = secLevel; + else + ppolicy->mGet = secLevel; + } + else + { + if (ppolicy->mGet.level == SCRIPT_SECURITY_UNDEFINED_ACCESS) + ppolicy->mGet = secLevel; + if (ppolicy->mSet.level == SCRIPT_SECURITY_UNDEFINED_ACCESS) + ppolicy->mSet = secLevel; + } + } + + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames); + if (currentPref < prefCount) // Loop exited early because of out-of-memory error + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} + + nsresult nsScriptSecurityManager::PrincipalPrefNames(const char* pref, char** grantedPref, char** deniedPref) @@ -2396,7 +2560,7 @@ nsScriptSecurityManager::InitPrincipals(PRUint32 aPrefCount, const char** aPrefN continue; nsXPIDLCString id; - if (NS_FAILED(aSecurityPref->SecurityGetCharPref(aPrefNames[c], getter_Copies(id)))) + if (NS_FAILED(mSecurityPref->SecurityGetCharPref(aPrefNames[c], getter_Copies(id)))) return NS_ERROR_FAILURE; nsXPIDLCString grantedPrefName; @@ -2410,17 +2574,17 @@ nsScriptSecurityManager::InitPrincipals(PRUint32 aPrefCount, const char** aPrefN continue; char* grantedList = nsnull; - aSecurityPref->SecurityGetCharPref(grantedPrefName, &grantedList); + mSecurityPref->SecurityGetCharPref(grantedPrefName, &grantedList); char* deniedList = nsnull; - aSecurityPref->SecurityGetCharPref(deniedPrefName, &deniedList); + mSecurityPref->SecurityGetCharPref(deniedPrefName, &deniedList); //-- Delete prefs if their value is the empty string if ((!id || id[0] == '\0') || ((!grantedList || grantedList[0] == '\0') && (!deniedList || deniedList[0] == '\0'))) { - aSecurityPref->SecurityClearUserPref(aPrefNames[c]); - aSecurityPref->SecurityClearUserPref(grantedPrefName); - aSecurityPref->SecurityClearUserPref(deniedPrefName); + mSecurityPref->SecurityClearUserPref(aPrefNames[c]); + mSecurityPref->SecurityClearUserPref(grantedPrefName); + mSecurityPref->SecurityClearUserPref(deniedPrefName); PR_FREEIF(grantedList); PR_FREEIF(deniedList); continue; @@ -2475,16 +2639,18 @@ nsScriptSecurityManager::InitPrincipals(PRUint32 aPrefCount, const char** aPrefN return NS_OK; } +const char* nsScriptSecurityManager::sJSEnabledPrefName = "javascript.enabled"; +const char* nsScriptSecurityManager::sJSMailEnabledPrefName = "javascript.allow.mailnews"; inline void nsScriptSecurityManager::JSEnabledPrefChanged(nsISecurityPref* aSecurityPref) { - if (NS_FAILED(aSecurityPref->SecurityGetBoolPref(sJSEnabledPrefName, + if (NS_FAILED(mSecurityPref->SecurityGetBoolPref(sJSEnabledPrefName, &mIsJavaScriptEnabled))) // Default to enabled. mIsJavaScriptEnabled = PR_TRUE; - if (NS_FAILED(aSecurityPref->SecurityGetBoolPref(sJSMailEnabledPrefName, + if (NS_FAILED(mSecurityPref->SecurityGetBoolPref(sJSMailEnabledPrefName, &mIsMailJavaScriptEnabled))) // Default to enabled. mIsMailJavaScriptEnabled = PR_TRUE; @@ -2496,38 +2662,36 @@ nsScriptSecurityManager::InitPrefs() nsresult rv; nsCOMPtr prefService(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr prefBranch; - rv = prefService->GetBranch(nsnull, getter_AddRefs(prefBranch)); + rv = prefService->GetBranch(nsnull, getter_AddRefs(mPrefBranch)); NS_ENSURE_SUCCESS(rv, rv); - mPrefBranchWeakRef = getter_AddRefs(NS_GetWeakReference(prefBranch)); - nsCOMPtr prefBranchInternal(do_QueryInterface(prefBranch, &rv)); + nsCOMPtr prefBranchInternal(do_QueryInterface(mPrefBranch, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + mSecurityPref = do_QueryInterface(mPrefBranch, &rv); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr securityPref(do_QueryInterface(prefBranch)); // Set the initial value of the "javascript.enabled" prefs - JSEnabledPrefChanged(securityPref); - // set observer callbacks in case the value of the pref changes + JSEnabledPrefChanged(mSecurityPref); + // set observer callbacks in case the value of the prefs change prefBranchInternal->AddObserver(sJSEnabledPrefName, this, PR_FALSE); prefBranchInternal->AddObserver(sJSMailEnabledPrefName, this, PR_FALSE); PRUint32 prefCount; char** prefNames; - //-- Initialize the policy database from prefs - rv = prefBranch->GetChildList(sPolicyPrefix, &prefCount, &prefNames); - if (NS_SUCCEEDED(rv) && prefCount > 0) - { - rv = InitPolicies(prefCount, (const char**)prefNames, securityPref); - NS_ENSURE_SUCCESS(rv, rv); - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames); - } //-- Set a callback for policy changes - prefBranchInternal->AddObserver(sPolicyPrefix, this, PR_FALSE); + // Registering the security manager as an observer to the + // profile-after-change topic. We will build up the policy table + // after the initial profile loads and after profile switches. + nsCOMPtr observerService + (do_GetService("@mozilla.org/observer-service;1", &rv)); + NS_ENSURE_SUCCESS(rv, rv); + rv = observerService->AddObserver(this, sProfileChangeMsg, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); //-- Initialize the principals database from prefs - rv = prefBranch->GetChildList(sPrincipalPrefix, &prefCount, &prefNames); + rv = mPrefBranch->GetChildList(sPrincipalPrefix, &prefCount, &prefNames); if (NS_SUCCEEDED(rv) && prefCount > 0) { - rv = InitPrincipals(prefCount, (const char**)prefNames, securityPref); + rv = InitPrincipals(prefCount, (const char**)prefNames, mSecurityPref); NS_ENSURE_SUCCESS(rv, rv); NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames); } @@ -2536,3 +2700,88 @@ nsScriptSecurityManager::InitPrefs() return NS_OK; } + +/////////////////////////////////////////////////////////////////////////////// +// The following code prints the contents of the policy DB to the console. +#ifdef DEBUG_mstoltz + +//typedef PLDHashOperator +//(* PR_CALLBACK PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr, +// PRUint32 number, void *arg); +PR_STATIC_CALLBACK(PLDHashOperator) +PrintPropertyPolicy(PLDHashTable *table, PLDHashEntryHdr *entry, + PRUint32 number, void *arg) +{ + PropertyPolicy* pp = (PropertyPolicy*)entry; + nsCAutoString prop(" "); + JSContext* cx = (JSContext*)arg; + prop.AppendInt((PRUint32)pp->key); + prop += ' '; + prop.AppendWithConversion((PRUnichar*)JSValIDToString(cx, pp->key)); + prop += ": Get="; + if (SECURITY_ACCESS_LEVEL_FLAG(pp->mGet)) + prop.AppendInt(pp->mGet.level); + else + prop += pp->mGet.capability; + + prop += " Set="; + if (SECURITY_ACCESS_LEVEL_FLAG(pp->mSet)) + prop.AppendInt(pp->mSet.level); + else + prop += pp->mSet.capability; + + printf("%s.\n", prop.get()); + return PL_DHASH_NEXT; +} + +PR_STATIC_CALLBACK(PLDHashOperator) +PrintClassPolicy(PLDHashTable *table, PLDHashEntryHdr *entry, + PRUint32 number, void *arg) +{ + ClassPolicy* cp = (ClassPolicy*)entry; + printf(" %s\n", cp->key); + + PL_DHashTableEnumerate(&cp->mPolicy, PrintPropertyPolicy, arg); + return PL_DHASH_NEXT; +} + +// typedef PRBool +// (*PR_CALLBACK nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure); +PR_STATIC_CALLBACK(PRBool) +PrintDomainPolicy(nsHashKey *aKey, void *aData, void* aClosure) +{ + DomainEntry* de = (DomainEntry*)aData; + printf("----------------------------\n"); + printf("Domain: %s Policy Name: %s.\n", de->mOrigin.get(), + de->mPolicyName_DEBUG.get()); + PL_DHashTableEnumerate(de->mDomainPolicy, PrintClassPolicy, aClosure); + return PR_TRUE; +} + +PR_STATIC_CALLBACK(PRBool) +PrintCapability(nsHashKey *aKey, void *aData, void* aClosure) +{ + char* cap = (char*)aData; + printf(" %s.\n", cap); + return PR_TRUE; +} + +void +nsScriptSecurityManager::PrintPolicyDB() +{ + printf("############## Security Policies ###############\n"); + if(mOriginToPolicyMap) + { + JSContext* cx = GetCurrentJSContext(); + printf("----------------------------\n"); + printf("Domain: Default.\n"); + PL_DHashTableEnumerate(mDefaultPolicy, PrintClassPolicy, (void*)cx); + mOriginToPolicyMap->Enumerate(PrintDomainPolicy, (void*)cx); + } + printf("############ End Security Policies #############\n\n"); + printf("############## Capabilities ###############\n"); + mCapabilities->Enumerate(PrintCapability); + printf("############## End Capabilities ###############\n"); +} +#endif + diff --git a/mozilla/caps/src/nsSecurityManagerFactory.cpp b/mozilla/caps/src/nsSecurityManagerFactory.cpp index 66c2ffa4fb4..d2bb4152664 100644 --- a/mozilla/caps/src/nsSecurityManagerFactory.cpp +++ b/mozilla/caps/src/nsSecurityManagerFactory.cpp @@ -364,11 +364,17 @@ RegisterSecurityNameSet(nsIComponentManager *aCompMgr, PR_TRUE, PR_TRUE, getter_Copies(previous)); NS_ENSURE_SUCCESS(rv, rv); + rv = catman->AddCategoryEntry("app-startup", "service", + NS_SCRIPTSECURITYMANAGER_CONTRACTID, + PR_TRUE, PR_TRUE, + getter_Copies(previous)); + NS_ENSURE_SUCCESS(rv, rv); + return rv; } -static const nsModuleComponentInfo components[] = +static const nsModuleComponentInfo capsComponentInfo[] = { { NS_SCRIPTSECURITYMANAGER_CLASSNAME, NS_SCRIPTSECURITYMANAGER_CID, @@ -451,5 +457,12 @@ static const nsModuleComponentInfo components[] = }; -NS_IMPL_NSGETMODULE(nsSecurityManagerModule, components); +void PR_CALLBACK +CapsModuleDtor(nsIModule* thisModules) +{ + nsScriptSecurityManager::Shutdown(); +} + +NS_IMPL_NSGETMODULE_WITH_DTOR(nsSecurityManagerModule, capsComponentInfo, + CapsModuleDtor); diff --git a/mozilla/content/build/Makefile.in b/mozilla/content/build/Makefile.in index 70bc88827cd..cf1361e6987 100644 --- a/mozilla/content/build/Makefile.in +++ b/mozilla/content/build/Makefile.in @@ -61,7 +61,8 @@ REQUIRES = xpcom \ xuldoc \ xultmpl \ timer \ - webbrwsr \ + webbrwsr \ + caps \ $(NULL) CPPSRCS = \ diff --git a/mozilla/content/build/makefile.win b/mozilla/content/build/makefile.win index e08a66c634d..cdafab09a4e 100644 --- a/mozilla/content/build/makefile.win +++ b/mozilla/content/build/makefile.win @@ -53,6 +53,7 @@ REQUIRES = xpcom \ gfx \ layout_xul \ content_xul \ + caps \ $(NULL) LCFLAGS = \ diff --git a/mozilla/content/build/nsContentModule.cpp b/mozilla/content/build/nsContentModule.cpp index 21032d634fd..9645ce6a114 100644 --- a/mozilla/content/build/nsContentModule.cpp +++ b/mozilla/content/build/nsContentModule.cpp @@ -49,6 +49,7 @@ #include "nsDOMCID.h" #include "nsCSSOMFactory.h" #include "nsEventStateManager.h" +#include "nsEventListenerManager.h" #include "nsGenericElement.h" #include "nsGenericDOMDataNode.h" #include "nsHTMLAtoms.h" @@ -225,6 +226,7 @@ Shutdown(nsIModule* aSelf) nsRange::Shutdown(); nsGenericElement::Shutdown(); nsGenericDOMDataNode::Shutdown(); + nsEventListenerManager::Shutdown(); // Release all of our atoms nsColorNames::ReleaseTable(); diff --git a/mozilla/content/events/src/nsEventListenerManager.cpp b/mozilla/content/events/src/nsEventListenerManager.cpp index a42d119ffbc..604512d671a 100644 --- a/mozilla/content/events/src/nsEventListenerManager.cpp +++ b/mozilla/content/events/src/nsEventListenerManager.cpp @@ -180,6 +180,11 @@ nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly) return NS_OK; } +void nsEventListenerManager::Shutdown() +{ + sAddListenerID = JSVAL_VOID; +} + NS_IMPL_ADDREF(nsEventListenerManager) NS_IMPL_RELEASE(nsEventListenerManager) @@ -951,6 +956,9 @@ nsEventListenerManager::RemoveScriptEventListener(nsIAtom *aName) return result; } +jsval +nsEventListenerManager::sAddListenerID = JSVAL_VOID; + NS_IMETHODIMP nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext, nsISupports *aObject, @@ -992,8 +1000,12 @@ nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext, nsCOMPtr classInfo = do_QueryInterface(aObject); + if (sAddListenerID == JSVAL_VOID) { + sAddListenerID = STRING_TO_JSVAL(::JS_InternString(cx, "addEventListener")); + } + if (NS_FAILED(rv = securityManager->CheckPropertyAccess(cx, jsobj, - "EventTarget","addEventListener", + "EventTarget", sAddListenerID, nsIXPCSecurityManager::ACCESS_SET_PROPERTY))) { // XXX set pending exception on the native call context? return rv; diff --git a/mozilla/content/events/src/nsEventListenerManager.h b/mozilla/content/events/src/nsEventListenerManager.h index 941a450128a..6e64b0e4150 100644 --- a/mozilla/content/events/src/nsEventListenerManager.h +++ b/mozilla/content/events/src/nsEventListenerManager.h @@ -178,6 +178,8 @@ public: NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult); NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent); + static void Shutdown(); + protected: nsresult HandleEventSubType(nsListenerStruct* aListenerStruct, nsIDOMEvent* aDOMEvent, @@ -217,6 +219,8 @@ protected: nsCOMPtr mPrincipal; nsISupports* mTarget; //WEAK + + static jsval sAddListenerID; }; diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index fe2cf5d9983..3f4757a3032 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -871,6 +871,8 @@ JSString *nsDOMClassInfo::sOnresize_id = nsnull; JSString *nsDOMClassInfo::sOnscroll_id = nsnull; JSString *nsDOMClassInfo::sScrollIntoView_id = nsnull; JSString *nsDOMClassInfo::sOpen_id = nsnull; +JSString *nsDOMClassInfo::sItem_id = nsnull; +JSString *nsDOMClassInfo::sEnumerate_id = nsnull; const JSClass *nsDOMClassInfo::sObjectClass = nsnull; @@ -940,6 +942,8 @@ nsDOMClassInfo::DefineStaticJSStrings(JSContext *cx) sOnscroll_id = ::JS_InternString(cx, "onscroll"); sScrollIntoView_id = ::JS_InternString(cx, "scrollIntoView"); sOpen_id = ::JS_InternString(cx, "open"); + sItem_id = ::JS_InternString(cx, "item"); + sEnumerate_id = ::JS_InternString(cx, "enumerateProperties"); return NS_OK; } @@ -2391,7 +2395,7 @@ nsDOMClassInfo::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // Ask the security manager if it's OK to enumerate nsresult rv = sSecMan->CheckPropertyAccess(cx, obj, sClassInfoData[mID].mName, - "enumerateProperties", + STRING_TO_JSVAL(sEnumerate_id), nsIXPCSecurityManager::ACCESS_GET_PROPERTY); if (NS_FAILED(rv)) { @@ -2441,21 +2445,6 @@ nsDOMClassInfo::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_ERROR_UNEXPECTED; } -// Result of this function should not be freed. -static inline const PRUnichar * -JSValIDToString(JSContext *aJSContext, const jsval idval) -{ - JSString *str = JS_ValueToString(aJSContext, idval); - - if(!str) { - NS_ERROR("JS_ValueToString() returned null!"); - - return nsnull; - } - - return NS_REINTERPRET_CAST(const PRUnichar*, JS_GetStringChars(str)); -} - NS_IMETHODIMP nsDOMClassInfo::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsval id, PRUint32 mode, @@ -2463,23 +2452,13 @@ nsDOMClassInfo::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext *cx, { if ((mode == JSACC_WATCH || mode == JSACC_PROTO || mode == JSACC_PARENT) && sSecMan) { - JSString *str = ::JS_ValueToString(cx, id); - - if (!str) - return NS_ERROR_UNEXPECTED; JSObject *real_obj = nsnull; nsresult rv = wrapper->GetJSObject(&real_obj); NS_ENSURE_SUCCESS(rv, rv); - NS_ConvertUCS2toUTF8 - prop_name(NS_REINTERPRET_CAST(const PRUnichar *, - ::JS_GetStringChars(str)), - ::JS_GetStringLength(str)); - rv = - sSecMan->CheckPropertyAccess(cx, real_obj, sClassInfoData[mID].mName, - prop_name.get(), + sSecMan->CheckPropertyAccess(cx, real_obj, sClassInfoData[mID].mName, id, nsIXPCSecurityManager::ACCESS_GET_PROPERTY); if (NS_FAILED(rv)) { @@ -2629,6 +2608,8 @@ nsDOMClassInfo::ShutDown() sOnscroll_id = jsnullstring; sScrollIntoView_id = jsnullstring; sOpen_id = jsnullstring; + sItem_id = jsnullstring; + sEnumerate_id = jsnullstring; NS_IF_RELEASE(sXPConnect); NS_IF_RELEASE(sSecMan); @@ -2754,11 +2735,9 @@ nsWindowSH::doCheckPropertyAccess(JSContext *cx, JSObject *obj, jsval id, JSObject *global = sgo->GetGlobalJSObject(); - NS_ConvertUCS2toUTF8 prop_name(JSValIDToString(cx, id)); - return sSecMan->CheckPropertyAccess(cx, global, sClassInfoData[mID].mName, - prop_name.get(), accessMode); + id, accessMode); } NS_IMETHODIMP @@ -2943,7 +2922,7 @@ nsWindowSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, } nsresult rv = doCheckPropertyAccess(cx, obj, id, wrapper, - nsIXPCSecurityManager::ACCESS_SET_PROPERTY); + nsIXPCSecurityManager::ACCESS_SET_PROPERTY); if (NS_FAILED(rv)) { // Security check failed. The security manager set a JS @@ -5231,7 +5210,8 @@ nsHistorySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, } nsresult rv = - sSecMan->CheckPropertyAccess(cx, obj, sClassInfoData[mID].mName, "item", + sSecMan->CheckPropertyAccess(cx, obj, sClassInfoData[mID].mName, + STRING_TO_JSVAL(sItem_id), nsIXPCSecurityManager::ACCESS_CALL_METHOD); if (NS_FAILED(rv)) { diff --git a/mozilla/dom/src/base/nsDOMClassInfo.h b/mozilla/dom/src/base/nsDOMClassInfo.h index 68b4cf73bb9..047041f7343 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.h +++ b/mozilla/dom/src/base/nsDOMClassInfo.h @@ -185,6 +185,9 @@ protected: static JSString *sOnscroll_id; static JSString *sScrollIntoView_id; static JSString *sOpen_id; + static JSString *sItem_id; + static JSString *sEnumerate_id; + static const JSClass *sObjectClass; }; diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index 3e3898e92c6..85bafcbb77a 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -4620,6 +4620,7 @@ NavigatorImpl::~NavigatorImpl() { NS_IF_RELEASE(mMimeTypes); NS_IF_RELEASE(mPlugins); + sPrefInternal_id = JSVAL_VOID; } //***************************************************************************** @@ -4949,6 +4950,9 @@ NavigatorImpl::TaintEnabled(PRBool *aReturn) return NS_OK; } +jsval +NavigatorImpl::sPrefInternal_id = JSVAL_VOID; + NS_IMETHODIMP NavigatorImpl::Preference() { @@ -4985,7 +4989,10 @@ NavigatorImpl::Preference() NS_ENSURE_SUCCESS(rv, rv); //--Check to see if the caller is allowed to access prefs - nsCOMPtr secMan = + if (sPrefInternal_id = JSVAL_VOID) + sPrefInternal_id = STRING_TO_JSVAL(::JS_InternString(cx, "preferenceinternal")); + + nsCOMPtr secMan = do_GetService("@mozilla.org/scriptsecuritymanager;1", &rv); NS_ENSURE_SUCCESS(rv, rv); PRUint32 action; @@ -4993,8 +5000,9 @@ NavigatorImpl::Preference() action = nsIXPCSecurityManager::ACCESS_GET_PROPERTY; else action = nsIXPCSecurityManager::ACCESS_SET_PROPERTY; - rv = secMan->CheckPropertyAccess(cx, nsnull, - "Navigator", "preferenceinternal", action); + + rv = secMan->CheckPropertyAccess(cx, nsnull, + "Navigator", sPrefInternal_id, action); if (NS_FAILED(rv)) { return NS_OK; diff --git a/mozilla/dom/src/base/nsGlobalWindow.h b/mozilla/dom/src/base/nsGlobalWindow.h index d1781b10ad2..23340e4cae6 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.h +++ b/mozilla/dom/src/base/nsGlobalWindow.h @@ -373,6 +373,8 @@ protected: MimeTypeArrayImpl* mMimeTypes; PluginArrayImpl* mPlugins; nsIDocShell* mDocShell; // weak reference + + static jsval sPrefInternal_id; }; class nsIURI; diff --git a/mozilla/modules/libpref/src/init/all.js b/mozilla/modules/libpref/src/init/all.js index b73a0c7c2ef..3a87667174f 100644 --- a/mozilla/modules/libpref/src/init/all.js +++ b/mozilla/modules/libpref/src/init/all.js @@ -237,6 +237,9 @@ pref("print.print_edge_bottom", 0); // 1/100 of an inch // Editing these may create a security risk - be sure you know what you're doing //pref("capability.policy.default.barprop.visible.set", "UniversalBrowserWrite"); +pref("capability.policy.default_policynames", "mailnews"); +pref("capability.policy.policynames", ""); + pref("capability.policy.default.DOMException.code", "allAccess"); pref("capability.policy.default.DOMException.message", "allAccess"); pref("capability.policy.default.DOMException.name", "allAccess");