зеркало из https://github.com/mozilla/pjs.git
b=53849, r=mstoltz@netscape.com,edburns@acm.org, a=brendan@mozilla.org.
This fix makes Liveconnect smarter about getting a security principal when verifying that call from an applet to JS should be allowed.
This commit is contained in:
Родитель
2c05333359
Коммит
feccfe330f
|
@ -702,7 +702,7 @@ jsj_enter_js(JNIEnv *jEnv, void* applet_obj, jobject java_wrapper_obj,
|
|||
/* Invoke callback, presumably used to implement concurrency constraints */
|
||||
if (JSJ_callbacks && JSJ_callbacks->enter_js_from_java) {
|
||||
#ifdef OJI
|
||||
if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg, pNSIPrincipaArray, numPrincipals, pNSISecurityContext))
|
||||
if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg, pNSIPrincipaArray, numPrincipals, pNSISecurityContext,applet_obj))
|
||||
#else
|
||||
if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg))
|
||||
#endif
|
||||
|
|
|
@ -125,7 +125,7 @@ typedef struct JSJCallbacks {
|
|||
semantics of JavaScript. It is acceptable for either function pointer
|
||||
to be NULL. */
|
||||
#ifdef OJI
|
||||
JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp, void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext);
|
||||
JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp, void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext,void* applet_obj);
|
||||
#else
|
||||
JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp);
|
||||
#endif
|
||||
|
|
|
@ -28,7 +28,10 @@
|
|||
#include "lcglue.h"
|
||||
#include "nscore.h"
|
||||
#include "nsISecurityContext.h"
|
||||
#include "nsCSecurityContext.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
|
||||
extern "C" int XP_PROGRESS_STARTING_JAVA;
|
||||
extern "C" int XP_PROGRESS_STARTING_JAVA_DONE;
|
||||
|
@ -89,6 +92,7 @@ JVMContext* GetJVMContext()
|
|||
context->jsj_env = NULL;
|
||||
context->js_context = NULL;
|
||||
context->js_startframe = NULL;
|
||||
context->java_applet_obj = NULL;
|
||||
localContext.set(context);
|
||||
}
|
||||
return context;
|
||||
|
@ -370,27 +374,64 @@ unwrap_java_wrapper_impl(JNIEnv *pJNIEnv, jobject java_wrapper)
|
|||
|
||||
static JSBool PR_CALLBACK
|
||||
enter_js_from_java_impl(JNIEnv *jEnv, char **errp,
|
||||
void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext)
|
||||
void **pNSIPrincipaArray, int numPrincipals,
|
||||
void *pNSISecurityContext,
|
||||
void *java_applet_obj)
|
||||
{
|
||||
JVMContext* context = GetJVMContext();
|
||||
JSContext *pJSCX = context->js_context;
|
||||
|
||||
if (pNSISecurityContext != NULL) {
|
||||
// Get and Save the current applet object in the vm context.
|
||||
// There is not a 1:1 coorespondence between jvmcontexts and
|
||||
// jscontexts, but there is a 1:1 correspondence between
|
||||
// jvmcontexts and applet objects. So syncronize the two
|
||||
// here and use the applet object to get the jscontext when
|
||||
// needed.
|
||||
|
||||
nsCOMPtr<nsISecurityContext> jscontext = dont_AddRef(JVM_GetJSSecurityContext());
|
||||
if (java_applet_obj) {
|
||||
context->java_applet_obj = java_applet_obj;
|
||||
}
|
||||
else if (context->java_applet_obj) {
|
||||
java_applet_obj=context->java_applet_obj;
|
||||
}
|
||||
|
||||
JSContext *pJSCX = map_jsj_thread_to_js_context_impl(nsnull,java_applet_obj,jEnv,errp);
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
|
||||
if (pNSISecurityContext != nsnull) {
|
||||
if (pJSCX) {
|
||||
JSPrincipals *jsprin = nsnull;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scriptContext = (nsIScriptContext*)JS_GetContextPrivate(pJSCX);
|
||||
if (scriptContext) {
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = scriptContext->GetGlobalObject();
|
||||
NS_ASSERTION(global, "script context has no global object");
|
||||
|
||||
if (global) {
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> globalData = do_QueryInterface(global);
|
||||
if (globalData) {
|
||||
if (NS_FAILED(globalData->GetPrincipal(getter_AddRefs(principal))))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// What if !pJSCX?
|
||||
|
||||
nsCOMPtr<nsISecurityContext> jscontext = dont_AddRef(new nsCSecurityContext(principal));
|
||||
nsISecurityContext* jvcontext = NS_STATIC_CAST(nsISecurityContext*,pNSISecurityContext);
|
||||
// Should be NS_DYNAMIC_CAST, but no such define exists.
|
||||
// So for the sake of portability, we'll live
|
||||
// dangerously and use brute force.
|
||||
|
||||
if( !jscontext || !jvcontext ) {
|
||||
if (!jscontext || !jvcontext) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Check that the origin + certificate are the same.
|
||||
// If not, then return false.
|
||||
|
||||
const int buflen = 128;
|
||||
const int buflen = 512;
|
||||
char jsorigin[buflen];
|
||||
char jvorigin[buflen];
|
||||
*jsorigin = nsnull;
|
||||
|
@ -399,10 +440,14 @@ enter_js_from_java_impl(JNIEnv *jEnv, char **errp,
|
|||
jscontext->GetOrigin(jsorigin,buflen);
|
||||
jvcontext->GetOrigin(jvorigin,buflen);
|
||||
|
||||
if( nsCRT::strcasecmp(jsorigin,jvorigin) ) {
|
||||
if (nsCRT::strcasecmp(jsorigin,jvorigin)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#if 0 // ISSUE: Needs security review. We don't compare certificates.
|
||||
// because currently there is no basis for making a postive comparision.
|
||||
// If one or the other context is signed, the comparision will fail.
|
||||
|
||||
char jscertid[buflen];
|
||||
char jvcertid[buflen];
|
||||
*jscertid = nsnull;
|
||||
|
@ -411,12 +456,12 @@ enter_js_from_java_impl(JNIEnv *jEnv, char **errp,
|
|||
jscontext->GetCertificateID(jscertid,buflen);
|
||||
jvcontext->GetCertificateID(jvcertid,buflen);
|
||||
|
||||
if( nsCRT::strcasecmp(jscertid,jvcertid) ) {
|
||||
if (nsCRT::strcasecmp(jscertid,jvcertid)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
} else {
|
||||
return PR_FALSE;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
|
|
@ -52,6 +52,7 @@ struct JVMContext {
|
|||
JSJavaThreadState *jsj_env; /* thread local JavaScript execution env. */
|
||||
JSContext *js_context; /* thread local JavaScript context. */
|
||||
JSStackFrame *js_startframe; /* thread local JavaScript stack frame. */
|
||||
void *java_applet_obj;
|
||||
};
|
||||
|
||||
JVMContext* GetJVMContext();
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "nsCodebasePrincipal.h"
|
||||
#include "nsCertificatePrincipal.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
|
@ -102,8 +104,6 @@ nsCSecurityContext::Implies(const char* target, const char* action, PRBool *bAll
|
|||
NS_METHOD
|
||||
nsCSecurityContext::GetOrigin(char* buf, int buflen)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> principal = NULL;
|
||||
|
||||
// Get the Script Security Manager.
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -112,20 +112,49 @@ nsCSecurityContext::GetOrigin(char* buf, int buflen)
|
|||
if (NS_FAILED(rv) || !secMan) return NS_ERROR_FAILURE;
|
||||
|
||||
|
||||
if (NS_FAILED(secMan->GetSubjectPrincipal(getter_AddRefs(principal))))
|
||||
return NS_ERROR_FAILURE;
|
||||
// First, try to get the principal from the security manager.
|
||||
// Next, try to get it from the dom.
|
||||
// If neither of those work, the qi for codebase will fail.
|
||||
|
||||
nsCOMPtr<nsICodebasePrincipal> codebase = do_QueryInterface(principal);
|
||||
if (!m_pPrincipal) {
|
||||
if (NS_FAILED(secMan->GetSubjectPrincipal(&m_pPrincipal)))
|
||||
// return NS_ERROR_FAILURE;
|
||||
; // Don't return here because the security manager returns
|
||||
// NS_ERROR_FAILURE when there is no subject principal. In
|
||||
// that case we are not done.
|
||||
|
||||
if (!m_pPrincipal && m_pJSCX ) {
|
||||
JSPrincipals *jsprin = nsnull;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scriptContext = (nsIScriptContext*)JS_GetContextPrivate(m_pJSCX);
|
||||
if (scriptContext) {
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = scriptContext->GetGlobalObject();
|
||||
NS_ASSERTION(global, "script context has no global object");
|
||||
|
||||
if (global) {
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> globalData = do_QueryInterface(global);
|
||||
if (globalData) {
|
||||
// ISSUE: proper ref counting.
|
||||
if (NS_FAILED(globalData->GetPrincipal(&m_pPrincipal)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICodebasePrincipal> codebase = do_QueryInterface(m_pPrincipal);
|
||||
if (!codebase)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
char* origin=nsnull;
|
||||
codebase->GetOrigin(&origin);
|
||||
|
||||
if( origin ) {
|
||||
if (origin) {
|
||||
PRInt32 originlen = (PRInt32) nsCRT::strlen(origin);
|
||||
if(!buf || buflen<=originlen) {
|
||||
if( origin ) {
|
||||
if (!buf || buflen<=originlen) {
|
||||
if (origin) {
|
||||
nsCRT::free(origin);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -165,7 +194,7 @@ nsCSecurityContext::GetCertificateID(char* buf, int buflen)
|
|||
char* certificate = nsnull;
|
||||
cprincipal->GetCertificateID(&certificate);
|
||||
|
||||
if( certificate ) {
|
||||
if (certificate) {
|
||||
PRInt32 certlen = (PRInt32) nsCRT::strlen(certificate);
|
||||
if( buflen<=certlen ) {
|
||||
nsCRT::free(certificate);
|
||||
|
@ -219,8 +248,43 @@ nsCSecurityContext::nsCSecurityContext(JSContext* cx)
|
|||
|
||||
PRBool equals;
|
||||
if (!principal ||
|
||||
NS_SUCCEEDED(principal->Equals(sysprincipal, &equals)) && equals)
|
||||
{
|
||||
NS_SUCCEEDED(principal->Equals(sysprincipal, &equals)) && equals) {
|
||||
// We have native code or the system principal: just allow general access
|
||||
m_HasUniversalBrowserReadCapability = PR_TRUE;
|
||||
m_HasUniversalJavaCapability = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
// Otherwise, check with the js security manager.
|
||||
secMan->IsCapabilityEnabled("UniversalBrowserRead",&m_HasUniversalBrowserReadCapability);
|
||||
secMan->IsCapabilityEnabled("UniversalJavaPermission",&m_HasUniversalJavaCapability);
|
||||
}
|
||||
}
|
||||
|
||||
nsCSecurityContext::nsCSecurityContext(nsIPrincipal *principal)
|
||||
: m_pJStoJavaFrame(NULL), m_pJSCX(NULL),
|
||||
m_pPrincipal(principal),
|
||||
m_HasUniversalBrowserReadCapability(PR_FALSE),
|
||||
m_HasUniversalJavaCapability(PR_FALSE)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsCSecurityContext);
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
// Get the Script Security Manager.
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
NS_WITH_SERVICE(nsIScriptSecurityManager, secMan,
|
||||
NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv)
|
||||
if (NS_FAILED(rv) || !secMan) return;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> sysprincipal;
|
||||
if (NS_FAILED(secMan->GetSystemPrincipal(getter_AddRefs(sysprincipal))))
|
||||
return;
|
||||
|
||||
// Do early evaluation of "UniversalJavaPermission" capability.
|
||||
|
||||
PRBool equals;
|
||||
if (!m_pPrincipal ||
|
||||
NS_SUCCEEDED(m_pPrincipal->Equals(sysprincipal, &equals)) && equals) {
|
||||
// We have native code or the system principal: just allow general access
|
||||
m_HasUniversalBrowserReadCapability = PR_TRUE;
|
||||
m_HasUniversalJavaCapability = PR_TRUE;
|
||||
|
|
|
@ -86,6 +86,7 @@ public:
|
|||
// from nsCSecurityContext:
|
||||
|
||||
nsCSecurityContext(JSContext* cx);
|
||||
nsCSecurityContext(nsIPrincipal* principal);
|
||||
virtual ~nsCSecurityContext(void);
|
||||
|
||||
protected:
|
||||
|
@ -95,7 +96,6 @@ private:
|
|||
nsIPrincipal *m_pPrincipal;
|
||||
PRBool m_HasUniversalJavaCapability;
|
||||
PRBool m_HasUniversalBrowserReadCapability;
|
||||
|
||||
};
|
||||
|
||||
#endif // nsCSecurityContext_h___
|
||||
|
|
Загрузка…
Ссылка в новой задаче