зеркало из 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 */
|
/* Invoke callback, presumably used to implement concurrency constraints */
|
||||||
if (JSJ_callbacks && JSJ_callbacks->enter_js_from_java) {
|
if (JSJ_callbacks && JSJ_callbacks->enter_js_from_java) {
|
||||||
#ifdef OJI
|
#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
|
#else
|
||||||
if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg))
|
if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg))
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -125,7 +125,7 @@ typedef struct JSJCallbacks {
|
||||||
semantics of JavaScript. It is acceptable for either function pointer
|
semantics of JavaScript. It is acceptable for either function pointer
|
||||||
to be NULL. */
|
to be NULL. */
|
||||||
#ifdef OJI
|
#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
|
#else
|
||||||
JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp);
|
JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,7 +28,10 @@
|
||||||
#include "lcglue.h"
|
#include "lcglue.h"
|
||||||
#include "nscore.h"
|
#include "nscore.h"
|
||||||
#include "nsISecurityContext.h"
|
#include "nsISecurityContext.h"
|
||||||
|
#include "nsCSecurityContext.h"
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
|
#include "nsIScriptGlobalObject.h"
|
||||||
|
#include "nsIScriptObjectOwner.h"
|
||||||
|
|
||||||
extern "C" int XP_PROGRESS_STARTING_JAVA;
|
extern "C" int XP_PROGRESS_STARTING_JAVA;
|
||||||
extern "C" int XP_PROGRESS_STARTING_JAVA_DONE;
|
extern "C" int XP_PROGRESS_STARTING_JAVA_DONE;
|
||||||
|
@ -89,6 +92,7 @@ JVMContext* GetJVMContext()
|
||||||
context->jsj_env = NULL;
|
context->jsj_env = NULL;
|
||||||
context->js_context = NULL;
|
context->js_context = NULL;
|
||||||
context->js_startframe = NULL;
|
context->js_startframe = NULL;
|
||||||
|
context->java_applet_obj = NULL;
|
||||||
localContext.set(context);
|
localContext.set(context);
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
|
@ -370,27 +374,64 @@ unwrap_java_wrapper_impl(JNIEnv *pJNIEnv, jobject java_wrapper)
|
||||||
|
|
||||||
static JSBool PR_CALLBACK
|
static JSBool PR_CALLBACK
|
||||||
enter_js_from_java_impl(JNIEnv *jEnv, char **errp,
|
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();
|
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);
|
nsISecurityContext* jvcontext = NS_STATIC_CAST(nsISecurityContext*,pNSISecurityContext);
|
||||||
// Should be NS_DYNAMIC_CAST, but no such define exists.
|
// Should be NS_DYNAMIC_CAST, but no such define exists.
|
||||||
// So for the sake of portability, we'll live
|
// So for the sake of portability, we'll live
|
||||||
// dangerously and use brute force.
|
// dangerously and use brute force.
|
||||||
|
|
||||||
if( !jscontext || !jvcontext ) {
|
if (!jscontext || !jvcontext) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the origin + certificate are the same.
|
// Check that the origin + certificate are the same.
|
||||||
// If not, then return false.
|
// If not, then return false.
|
||||||
|
|
||||||
const int buflen = 128;
|
const int buflen = 512;
|
||||||
char jsorigin[buflen];
|
char jsorigin[buflen];
|
||||||
char jvorigin[buflen];
|
char jvorigin[buflen];
|
||||||
*jsorigin = nsnull;
|
*jsorigin = nsnull;
|
||||||
|
@ -399,10 +440,14 @@ enter_js_from_java_impl(JNIEnv *jEnv, char **errp,
|
||||||
jscontext->GetOrigin(jsorigin,buflen);
|
jscontext->GetOrigin(jsorigin,buflen);
|
||||||
jvcontext->GetOrigin(jvorigin,buflen);
|
jvcontext->GetOrigin(jvorigin,buflen);
|
||||||
|
|
||||||
if( nsCRT::strcasecmp(jsorigin,jvorigin) ) {
|
if (nsCRT::strcasecmp(jsorigin,jvorigin)) {
|
||||||
return PR_FALSE;
|
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 jscertid[buflen];
|
||||||
char jvcertid[buflen];
|
char jvcertid[buflen];
|
||||||
*jscertid = nsnull;
|
*jscertid = nsnull;
|
||||||
|
@ -411,12 +456,12 @@ enter_js_from_java_impl(JNIEnv *jEnv, char **errp,
|
||||||
jscontext->GetCertificateID(jscertid,buflen);
|
jscontext->GetCertificateID(jscertid,buflen);
|
||||||
jvcontext->GetCertificateID(jvcertid,buflen);
|
jvcontext->GetCertificateID(jvcertid,buflen);
|
||||||
|
|
||||||
if( nsCRT::strcasecmp(jscertid,jvcertid) ) {
|
if (nsCRT::strcasecmp(jscertid,jvcertid)) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
#endif
|
||||||
return PR_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
|
|
|
@ -52,6 +52,7 @@ struct JVMContext {
|
||||||
JSJavaThreadState *jsj_env; /* thread local JavaScript execution env. */
|
JSJavaThreadState *jsj_env; /* thread local JavaScript execution env. */
|
||||||
JSContext *js_context; /* thread local JavaScript context. */
|
JSContext *js_context; /* thread local JavaScript context. */
|
||||||
JSStackFrame *js_startframe; /* thread local JavaScript stack frame. */
|
JSStackFrame *js_startframe; /* thread local JavaScript stack frame. */
|
||||||
|
void *java_applet_obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
JVMContext* GetJVMContext();
|
JVMContext* GetJVMContext();
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
#include "nsCodebasePrincipal.h"
|
#include "nsCodebasePrincipal.h"
|
||||||
#include "nsCertificatePrincipal.h"
|
#include "nsCertificatePrincipal.h"
|
||||||
#include "nsScriptSecurityManager.h"
|
#include "nsScriptSecurityManager.h"
|
||||||
|
#include "nsIScriptGlobalObject.h"
|
||||||
|
#include "nsIScriptObjectOwner.h"
|
||||||
|
|
||||||
#include "nsTraceRefcnt.h"
|
#include "nsTraceRefcnt.h"
|
||||||
|
|
||||||
|
@ -102,8 +104,6 @@ nsCSecurityContext::Implies(const char* target, const char* action, PRBool *bAll
|
||||||
NS_METHOD
|
NS_METHOD
|
||||||
nsCSecurityContext::GetOrigin(char* buf, int buflen)
|
nsCSecurityContext::GetOrigin(char* buf, int buflen)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIPrincipal> principal = NULL;
|
|
||||||
|
|
||||||
// Get the Script Security Manager.
|
// Get the Script Security Manager.
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
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(rv) || !secMan) return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
|
||||||
if (NS_FAILED(secMan->GetSubjectPrincipal(getter_AddRefs(principal))))
|
// First, try to get the principal from the security manager.
|
||||||
return NS_ERROR_FAILURE;
|
// 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)
|
if (!codebase)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
char* origin=nsnull;
|
char* origin=nsnull;
|
||||||
codebase->GetOrigin(&origin);
|
codebase->GetOrigin(&origin);
|
||||||
|
|
||||||
if( origin ) {
|
if (origin) {
|
||||||
PRInt32 originlen = (PRInt32) nsCRT::strlen(origin);
|
PRInt32 originlen = (PRInt32) nsCRT::strlen(origin);
|
||||||
if(!buf || buflen<=originlen) {
|
if (!buf || buflen<=originlen) {
|
||||||
if( origin ) {
|
if (origin) {
|
||||||
nsCRT::free(origin);
|
nsCRT::free(origin);
|
||||||
}
|
}
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -165,7 +194,7 @@ nsCSecurityContext::GetCertificateID(char* buf, int buflen)
|
||||||
char* certificate = nsnull;
|
char* certificate = nsnull;
|
||||||
cprincipal->GetCertificateID(&certificate);
|
cprincipal->GetCertificateID(&certificate);
|
||||||
|
|
||||||
if( certificate ) {
|
if (certificate) {
|
||||||
PRInt32 certlen = (PRInt32) nsCRT::strlen(certificate);
|
PRInt32 certlen = (PRInt32) nsCRT::strlen(certificate);
|
||||||
if( buflen<=certlen ) {
|
if( buflen<=certlen ) {
|
||||||
nsCRT::free(certificate);
|
nsCRT::free(certificate);
|
||||||
|
@ -219,8 +248,43 @@ nsCSecurityContext::nsCSecurityContext(JSContext* cx)
|
||||||
|
|
||||||
PRBool equals;
|
PRBool equals;
|
||||||
if (!principal ||
|
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
|
// We have native code or the system principal: just allow general access
|
||||||
m_HasUniversalBrowserReadCapability = PR_TRUE;
|
m_HasUniversalBrowserReadCapability = PR_TRUE;
|
||||||
m_HasUniversalJavaCapability = PR_TRUE;
|
m_HasUniversalJavaCapability = PR_TRUE;
|
||||||
|
|
|
@ -86,6 +86,7 @@ public:
|
||||||
// from nsCSecurityContext:
|
// from nsCSecurityContext:
|
||||||
|
|
||||||
nsCSecurityContext(JSContext* cx);
|
nsCSecurityContext(JSContext* cx);
|
||||||
|
nsCSecurityContext(nsIPrincipal* principal);
|
||||||
virtual ~nsCSecurityContext(void);
|
virtual ~nsCSecurityContext(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -95,7 +96,6 @@ private:
|
||||||
nsIPrincipal *m_pPrincipal;
|
nsIPrincipal *m_pPrincipal;
|
||||||
PRBool m_HasUniversalJavaCapability;
|
PRBool m_HasUniversalJavaCapability;
|
||||||
PRBool m_HasUniversalBrowserReadCapability;
|
PRBool m_HasUniversalBrowserReadCapability;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsCSecurityContext_h___
|
#endif // nsCSecurityContext_h___
|
||||||
|
|
Загрузка…
Ссылка в новой задаче