diff --git a/mozilla/caps/idl/nsIScriptSecurityManager.idl b/mozilla/caps/idl/nsIScriptSecurityManager.idl index 2251a26524b..e1d53c08941 100644 --- a/mozilla/caps/idl/nsIScriptSecurityManager.idl +++ b/mozilla/caps/idl/nsIScriptSecurityManager.idl @@ -335,6 +335,33 @@ interface nsIScriptSecurityManager_1_9_0_BRANCH : nsIScriptSecurityManager out JSStackFramePtr fp); }; +[scriptable, uuid(83db3256-5ff6-4703-a21d-8a5f7c8af4b0)] +interface nsIScriptSecurityManager_1_9_2 : nsIScriptSecurityManager_1_9_0_BRANCH +{ + /** + * If no scripted code is running "above" (or called from) fp, then + * instead of looking at cx->globalObject, we will return |principal|. + * This function only affects |cx|. If someone pushes another context onto + * the context stack, then it supercedes this call. + * NOTE: If |fp| is non-null popContextPrincipal must be called before fp + * has finished executing. + * + * @param cx The context to clamp. + * @param fp The frame pointer to clamp at. May be 'null'. + * @param principal The principal to clamp to. + */ + [noscript] void pushContextPrincipal(in JSContextPtr cx, + in JSStackFramePtr fp, + in nsIPrincipal principal); + + /** + * Removes a clamp set by pushContextPrincipal from cx. This must be + * called in a stack-like fashion (e.g., given two contexts |a| and |b|, + * it is not legal to do: push(a) push(b) pop(a)). + */ + [noscript] void popContextPrincipal(in JSContextPtr cx); +}; + %{C++ #define NS_SCRIPTSECURITYMANAGER_CONTRACTID "@mozilla.org/scriptsecuritymanager;1" #define NS_SCRIPTSECURITYMANAGER_CLASSNAME "scriptsecuritymanager" diff --git a/mozilla/caps/include/nsScriptSecurityManager.h b/mozilla/caps/include/nsScriptSecurityManager.h index 6083dfa4c86..0485e7a916c 100644 --- a/mozilla/caps/include/nsScriptSecurityManager.h +++ b/mozilla/caps/include/nsScriptSecurityManager.h @@ -368,7 +368,7 @@ MoveClassPolicyEntry(PLDHashTable *table, { 0x7ee2a4c0, 0x4b93, 0x17d3, \ { 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }} -class nsScriptSecurityManager : public nsIScriptSecurityManager_1_9_0_BRANCH, +class nsScriptSecurityManager : public nsIScriptSecurityManager_1_9_2, public nsIPrefSecurityCheck, public nsIChannelEventSink, public nsIObserver @@ -381,6 +381,7 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSISCRIPTSECURITYMANAGER NS_DECL_NSISCRIPTSECURITYMANAGER_1_9_0_BRANCH + NS_DECL_NSISCRIPTSECURITYMANAGER_1_9_2 NS_DECL_NSIXPCSECURITYMANAGER NS_DECL_NSIPREFSECURITYCHECK NS_DECL_NSICHANNELEVENTSINK @@ -483,15 +484,15 @@ private: // 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* + 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* + 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. @@ -511,7 +512,7 @@ private: // 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* + nsIPrincipal* GetPrincipalAndFrame(JSContext *cx, JSStackFrame** frameResult, nsresult* rv); @@ -565,6 +566,17 @@ private: PrintPolicyDB(); #endif + struct ContextPrincipal { + ContextPrincipal(ContextPrincipal *next, JSContext *cx, + JSStackFrame *fp, nsIPrincipal *principal) + : mNext(next), mCx(cx), mFp(fp), mPrincipal(principal) {} + + ContextPrincipal *mNext; + JSContext *mCx; + JSStackFrame *mFp; + nsCOMPtr mPrincipal; + }; + // JS strings we need to clean up on shutdown static jsval sEnabledID; @@ -585,6 +597,7 @@ private: nsCOMPtr mSystemCertificate; nsInterfaceHashtable mPrincipals; nsCOMPtr mJSContextStack; + ContextPrincipal *mContextPrincipals; PRPackedBool mIsJavaScriptEnabled; PRPackedBool mIsMailJavaScriptEnabled; PRPackedBool mIsWritingPrefs; diff --git a/mozilla/caps/src/nsScriptSecurityManager.cpp b/mozilla/caps/src/nsScriptSecurityManager.cpp index f61cfad9095..1e4996a85be 100644 --- a/mozilla/caps/src/nsScriptSecurityManager.cpp +++ b/mozilla/caps/src/nsScriptSecurityManager.cpp @@ -454,6 +454,32 @@ nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFra return principal; } +NS_IMETHODIMP +nsScriptSecurityManager::PushContextPrincipal(JSContext *cx, + JSStackFrame *fp, + nsIPrincipal *principal) +{ + ContextPrincipal *cp = new ContextPrincipal(mContextPrincipals, cx, fp, + principal); + if (!cp) + return NS_ERROR_OUT_OF_MEMORY; + + mContextPrincipals = cp; + return NS_OK; +} + +NS_IMETHODIMP +nsScriptSecurityManager::PopContextPrincipal(JSContext *cx) +{ + NS_ASSERTION(mContextPrincipals->mCx == cx, "Mismatched push/pop"); + + ContextPrincipal *next = mContextPrincipals->mNext; + delete mContextPrincipals; + mContextPrincipals = next; + + return NS_OK; +} + //////////////////// // Policy Storage // //////////////////// @@ -529,13 +555,14 @@ DeleteDomainEntry(nsHashKey *aKey, void *aData, void* closure) //////////////////////////////////// // Methods implementing ISupports // //////////////////////////////////// -NS_IMPL_ISUPPORTS6(nsScriptSecurityManager, +NS_IMPL_ISUPPORTS7(nsScriptSecurityManager, nsIScriptSecurityManager, nsIXPCSecurityManager, nsIPrefSecurityCheck, nsIChannelEventSink, nsIObserver, - nsIScriptSecurityManager_1_9_0_BRANCH) + nsIScriptSecurityManager_1_9_0_BRANCH, + nsIScriptSecurityManager_1_9_2) /////////////////////////////////////////////////// // Methods implementing nsIScriptSecurityManager // @@ -2249,7 +2276,6 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx, return GetScriptPrincipal(cx, script, rv); } -// static nsIPrincipal* nsScriptSecurityManager::GetFramePrincipal(JSContext *cx, JSStackFrame *fp, @@ -2279,22 +2305,36 @@ nsScriptSecurityManager::GetFramePrincipal(JSContext *cx, return result; } -// static nsIPrincipal* nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx, JSStackFrame **frameResult, nsresult* rv) { - NS_PRECONDITION(rv, "Null out param"); + NS_PRECONDITION(rv, "Null out param"); //-- If there's no principal on the stack, look at the global object // and return the innermost frame for annotations. *rv = NS_OK; + if (cx) { - // Get principals from innermost frame of JavaScript or Java. + JSStackFrame *target = nsnull; + nsIPrincipal *targetPrincipal = nsnull; + for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext) + { + if (cp->mCx == cx) + { + target = cp->mFp; + targetPrincipal = cp->mPrincipal; + break; + } + } + + // Get principals from innermost JavaScript frame. JSStackFrame *fp = nsnull; // tell JS_FrameIterator to start at innermost for (fp = JS_FrameIterator(cx, &fp); fp; fp = JS_FrameIterator(cx, &fp)) { + if (fp == target) + break; nsIPrincipal* result = GetFramePrincipal(cx, fp, rv); if (result) { @@ -2304,6 +2344,25 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx, } } + // If targetPrincipal is non-null, then it means that someone wants to + // clamp the principals on this context to this principal. Note that + // fp might not equal target here (fp might be null) because someone + // could have set aside the frame chain in the meantime. + if (targetPrincipal) + { + if (fp && fp == target) + { + *frameResult = fp; + } + else + { + JSStackFrame *inner = nsnull; + *frameResult = JS_FrameIterator(cx, &inner); + } + + return targetPrincipal; + } + nsIScriptContext *scriptContext = GetScriptContext(cx); if (scriptContext) { @@ -2330,7 +2389,6 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx, return nsnull; } -// static nsIPrincipal* nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx, nsresult* rv) @@ -3293,6 +3351,7 @@ nsScriptSecurityManager::nsScriptSecurityManager(void) : mOriginToPolicyMap(nsnull), mDefaultPolicy(nsnull), mCapabilities(nsnull), + mContextPrincipals(nsnull), mIsJavaScriptEnabled(PR_FALSE), mIsMailJavaScriptEnabled(PR_FALSE), mIsWritingPrefs(PR_FALSE), @@ -3369,6 +3428,7 @@ jsval nsScriptSecurityManager::sEnabledID = JSVAL_VOID; nsScriptSecurityManager::~nsScriptSecurityManager(void) { + NS_ASSERTION(!mContextPrincipals, "Leaking mContextPrincipals"); delete mOriginToPolicyMap; if(mDefaultPolicy) mDefaultPolicy->Drop(); diff --git a/mozilla/js/src/xpconnect/shell/xpcshell.cpp b/mozilla/js/src/xpconnect/shell/xpcshell.cpp index e76341db086..7d34c3202d3 100644 --- a/mozilla/js/src/xpconnect/shell/xpcshell.cpp +++ b/mozilla/js/src/xpconnect/shell/xpcshell.cpp @@ -916,7 +916,7 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc) class FullTrustSecMan #ifndef XPCONNECT_STANDALONE - : public nsIScriptSecurityManager_1_9_0_BRANCH + : public nsIScriptSecurityManager_1_9_2 #else : public nsIXPCSecurityManager #endif @@ -927,6 +927,7 @@ public: #ifndef XPCONNECT_STANDALONE NS_DECL_NSISCRIPTSECURITYMANAGER NS_DECL_NSISCRIPTSECURITYMANAGER_1_9_0_BRANCH + NS_DECL_NSISCRIPTSECURITYMANAGER_1_9_2 #endif FullTrustSecMan(); @@ -946,6 +947,7 @@ NS_INTERFACE_MAP_BEGIN(FullTrustSecMan) NS_INTERFACE_MAP_ENTRY(nsIXPCSecurityManager) #ifndef XPCONNECT_STANDALONE NS_INTERFACE_MAP_ENTRY(nsIScriptSecurityManager) + NS_INTERFACE_MAP_ENTRY(nsIScriptSecurityManager_1_9_2) #endif NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCSecurityManager) NS_INTERFACE_MAP_END @@ -1078,6 +1080,20 @@ FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal **_retval) return *_retval ? NS_OK : NS_ERROR_FAILURE; } +/* [noscript] void pushContextPrincipal (in JSContextPtr cx, in JSStackFramePtr fp, in nsIPrincipal principal); */ +NS_IMETHODIMP +FullTrustSecMan::PushContextPrincipal(JSContext * cx, JSStackFrame * fp, nsIPrincipal *principal) +{ + return NS_OK; +} + +/* [noscript] void popContextPrincipal (in JSContextPtr cx); */ +NS_IMETHODIMP +FullTrustSecMan::PopContextPrincipal(JSContext * cx) +{ + return NS_OK; +} + /* [noscript] nsIPrincipal getSystemPrincipal (); */ NS_IMETHODIMP FullTrustSecMan::GetSystemPrincipal(nsIPrincipal **_retval) diff --git a/mozilla/js/src/xpconnect/src/XPCWrapper.h b/mozilla/js/src/xpconnect/src/XPCWrapper.h index fc57013d269..98f5e75ea8f 100644 --- a/mozilla/js/src/xpconnect/src/XPCWrapper.h +++ b/mozilla/js/src/xpconnect/src/XPCWrapper.h @@ -169,8 +169,8 @@ public: /** * Returns the script security manager used by XPConnect. */ - static nsIScriptSecurityManager_1_9_0_BRANCH *GetSecurityManager() { - extern nsIScriptSecurityManager_1_9_0_BRANCH *gScriptSecurityManager; + static nsIScriptSecurityManager_1_9_2 *GetSecurityManager() { + extern nsIScriptSecurityManager_1_9_2 *gScriptSecurityManager; return gScriptSecurityManager; } diff --git a/mozilla/js/src/xpconnect/src/nsXPConnect.cpp b/mozilla/js/src/xpconnect/src/nsXPConnect.cpp index a418d43d19a..d2ead08e802 100644 --- a/mozilla/js/src/xpconnect/src/nsXPConnect.cpp +++ b/mozilla/js/src/xpconnect/src/nsXPConnect.cpp @@ -65,7 +65,7 @@ PRUint32 nsXPConnect::gReportAllJSExceptions = 0; // Global cache of the default script security manager (QI'd to // nsIScriptSecurityManager) -nsIScriptSecurityManager_1_9_0_BRANCH *gScriptSecurityManager = nsnull; +nsIScriptSecurityManager_1_9_2 *gScriptSecurityManager = nsnull; const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1"; const char XPC_RUNTIME_CONTRACTID[] = "@mozilla.org/js/xpc/RuntimeService;1"; @@ -1685,7 +1685,7 @@ nsXPConnect::SetDefaultSecurityManager(nsIXPCSecurityManager *aManager, mDefaultSecurityManager = aManager; mDefaultSecurityManagerFlags = flags; - nsCOMPtr ssm = + nsCOMPtr ssm = do_QueryInterface(mDefaultSecurityManager); // Remember the result of the above QI for fast access to the diff --git a/mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp b/mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp index c8cda4c96d9..01febdb3abd 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappedjsclass.cpp @@ -42,6 +42,7 @@ /* Sharable code and data for wrapper around JSObjects. */ #include "xpcprivate.h" +#include "XPCWrapper.h" NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass) @@ -1122,6 +1123,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, XPCContext* xpcc; JSContext* cx; JSObject* thisObj; + JSBool popPrincipal = JS_FALSE; + nsIScriptSecurityManager_1_9_2* ssm = nsnull; // Make sure not to set the callee on ccx until after we've gone through // the whole nsIXPCFunctionThisTranslator bit. That code uses ccx to @@ -1449,8 +1452,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, *sp++ = val; } - - readyToDoTheCall = JS_TRUE; pre_call_clean_up: @@ -1512,6 +1513,31 @@ pre_call_clean_up: JS_ClearPendingException(cx); + if(XPCPerThreadData::IsMainThread(ccx)) + { + ssm = XPCWrapper::GetSecurityManager(); + if(ssm) + { + nsCOMPtr objPrincipal; + ssm->GetObjectPrincipal(ccx, obj, getter_AddRefs(objPrincipal)); + if(objPrincipal) + { + JSStackFrame* fp = nsnull; + nsresult rv = + ssm->PushContextPrincipal(ccx, JS_FrameIterator(ccx, &fp), + objPrincipal); + if(NS_FAILED(rv)) + { + JS_ReportOutOfMemory(ccx); + retval = NS_ERROR_OUT_OF_MEMORY; + goto done; + } + + popPrincipal = JS_TRUE; + } + } + } + if(XPT_MD_IS_GETTER(info->flags)) success = JS_GetProperty(cx, obj, name, &result); else if(XPT_MD_IS_SETTER(info->flags)) @@ -1548,7 +1574,10 @@ pre_call_clean_up: } } - if (!success) + if(popPrincipal) + ssm->PopContextPrincipal(ccx); + + if(!success) { PRBool forceReport; if(NS_FAILED(mInfo->IsFunction(&forceReport)))