Mercurial > hg > release > icedtea6-1.3
changeset 1077:86fbcf148d1f
- Implemented JS->Java security.
- Removed ambiguity from class finding mechanism for cases where JS needs a
signature involving an applet specific class.
- Rewrote code that parsed messages from C++ side -- now it can handle any
number of optional components.
author | Deepak Bhole <dbhole@redhat.com> |
---|---|
date | Wed, 08 Oct 2008 17:00:19 -0400 |
parents | ab8aa9425fc4 |
children | 6790b974078e |
files | ChangeLog IcedTeaPlugin.cc plugin/icedtea/sun/applet/AppletSecurityContextManager.java plugin/icedtea/sun/applet/PluginAppletSecurityContext.java plugin/icedtea/sun/applet/PluginAppletViewer.java plugin/icedtea/sun/applet/PluginObjectStore.java plugin/icedtea/sun/applet/PluginStreamHandler.java |
diffstat | 7 files changed, 723 insertions(+), 316 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Tue Oct 07 11:16:16 2008 -0400 +++ b/ChangeLog Wed Oct 08 17:00:19 2008 -0400 @@ -1,3 +1,16 @@ +2008-10-08 Deepak Bhole <dbhole@redhat.com> + * IcedTeaPlugin.cc: Implemented JS->Java security. + * plugin/icedtea/sun/applet/AppletSecurityContextManager.java: Same. + * plugin/icedtea/sun/applet/PluginAppletSecurityContext.java: Same. Also, + remove ambiguity from class finding mechanism for cases where JS needs a + signature involving an applet specific class. + * plugin/icedtea/sun/applet/PluginAppletViewer.java: Implemented JS->Java + security. + * plugin/icedtea/sun/applet/PluginObjectStore.java: Same. + * plugin/icedtea/sun/applet/PluginStreamHandler.java: Rewrote code that + parsed messages from C++ side -- now it can handle any number of optional + components. + 2008-10-07 Gary Benson <gbenson@redhat.com> Andrew Haley <aph@redhat.com>
--- a/IcedTeaPlugin.cc Tue Oct 07 11:16:16 2008 -0400 +++ b/IcedTeaPlugin.cc Wed Oct 08 17:00:19 2008 -0400 @@ -309,29 +309,36 @@ #include <nsIThread.h> // FIXME: create index from security context. -#define MESSAGE_CREATE(reference) \ - const char* addr; \ - char context[16]; \ - GetCurrentPageAddress(&addr); \ - GetCurrentContextAddr(context); \ +#define MESSAGE_CREATE() \ nsCString message ("context "); \ message.AppendInt (0); \ + +#define MESSAGE_ADD_STACK_REFERENCE(reference) \ message += " reference "; \ message.AppendInt (reference); \ - if (factory->codebase_map.find(nsCString(addr)) != factory->codebase_map.end()) \ - { \ - message += " src "; \ - message += factory->codebase_map[nsCString(addr)];\ - } \ - message += " "; \ - message += __func__; \ if (factory->result_map[reference] == NULL) { \ factory->result_map[reference] = new ResultContainer(); \ printf("ResultMap created -- %p %d\n", factory->result_map[reference], factory->result_map[reference]->returnIdentifier); \ } \ else \ - factory->result_map[reference]->Clear(); - + factory->result_map[reference]->Clear(); + +#define MESSAGE_ADD_SRC(src) \ + message += " src "; \ + message += src; + +#define MESSAGE_ADD_PRIVILEGES() \ + nsCString privileges(""); \ + GetEnabledPrivileges(&privileges); \ + if (privileges.Length() > 0) \ + { \ + message += " privileges "; \ + message += privileges; \ + } + +#define MESSAGE_ADD_FUNC() \ + message += " "; \ + message += __func__; #define MESSAGE_ADD_STRING(name) \ message += " "; \ @@ -396,7 +403,7 @@ #define PROCESS_PENDING_EVENTS_REF(reference) \ if (factory->shutting_down == PR_TRUE && \ - factory->result_map[reference]->errorOccured == PR_TRUE) \ + factory->result_map[reference]->errorOccurred == PR_TRUE) \ { \ printf("Error occured. Exiting function\n"); \ return NS_ERROR_FAILURE; \ @@ -424,13 +431,13 @@ nsresult res = NS_OK; \ printf ("RECEIVE 1\n"); \ while (factory->result_map[reference]->returnIdentifier == -1 &&\ - factory->result_map[reference]->errorOccured == PR_FALSE) \ + factory->result_map[reference]->errorOccurred == PR_FALSE) \ { \ PROCESS_PENDING_EVENTS_REF (reference); \ } \ printf ("RECEIVE 3\n"); \ if (factory->result_map[reference]->returnIdentifier == 0 || \ - factory->result_map[reference]->errorOccured == PR_TRUE) \ + factory->result_map[reference]->errorOccurred == PR_TRUE) \ { \ *name = NULL; \ } else { \ @@ -447,12 +454,12 @@ nsresult res = NS_OK; \ printf("RECEIVE ID 1\n"); \ while (factory->result_map[reference]->returnIdentifier == -1 &&\ - factory->result_map[reference]->errorOccured == PR_FALSE) \ + factory->result_map[reference]->errorOccurred == PR_FALSE) \ { \ PROCESS_PENDING_EVENTS_REF (reference); \ } \ \ - if (factory->result_map[reference]->errorOccured == PR_TRUE) \ + if (factory->result_map[reference]->errorOccurred == PR_TRUE) \ { \ *id = NULL; \ } else \ @@ -468,7 +475,7 @@ nsresult res = NS_OK; \ printf("RECEIVE VALUE 1\n"); \ while (factory->result_map[reference]->returnValue == "" && \ - factory->result_map[reference]->errorOccured == PR_FALSE) \ + factory->result_map[reference]->errorOccurred == PR_FALSE) \ { \ PROCESS_PENDING_EVENTS_REF (reference); \ } \ @@ -485,12 +492,12 @@ nsresult res = NS_OK; \ printf("RECEIVE SIZE 1\n"); \ while (factory->result_map[reference]->returnValue == "" && \ - factory->result_map[reference]->errorOccured == PR_FALSE) \ + factory->result_map[reference]->errorOccurred == PR_FALSE) \ { \ PROCESS_PENDING_EVENTS_REF (reference); \ } \ nsresult conversionResult; \ - if (factory->result_map[reference]->errorOccured == PR_TRUE) \ + if (factory->result_map[reference]->errorOccurred == PR_TRUE) \ *result = NULL; \ else \ { \ @@ -507,11 +514,11 @@ nsresult res = NS_OK; \ printf("RECEIVE STRING 1\n"); \ while (factory->result_map[reference]->returnValue == "" && \ - factory->result_map[reference]->errorOccured == PR_FALSE) \ + factory->result_map[reference]->errorOccurred == PR_FALSE) \ { \ PROCESS_PENDING_EVENTS_REF (reference); \ } \ - if (factory->result_map[reference]->errorOccured == PR_TRUE) \ + if (factory->result_map[reference]->errorOccurred == PR_TRUE) \ *result = NULL; \ else \ {\ @@ -529,11 +536,11 @@ nsresult res = NS_OK; \ printf("RECEIVE STRING UCS 1\n"); \ while (factory->result_map[reference]->returnValueUCS.IsEmpty() && \ - factory->result_map[reference]->errorOccured == PR_FALSE) \ + factory->result_map[reference]->errorOccurred == PR_FALSE) \ { \ PROCESS_PENDING_EVENTS_REF (reference); \ } \ - if (factory->result_map[reference]->errorOccured == PR_TRUE) \ + if (factory->result_map[reference]->errorOccurred == PR_TRUE) \ *result = NULL; \ else \ { \ @@ -554,11 +561,11 @@ nsresult res = NS_OK; \ printf("RECEIVE BOOLEAN 1\n"); \ while (factory->result_map[reference]->returnIdentifier == -1 && \ - factory->result_map[reference]->errorOccured == PR_FALSE) \ + factory->result_map[reference]->errorOccurred == PR_FALSE) \ { \ PROCESS_PENDING_EVENTS_REF (reference); \ } \ - if (factory->result_map[reference]->errorOccured == PR_TRUE) \ + if (factory->result_map[reference]->errorOccurred == PR_TRUE) \ *result = NULL; \ else \ *result = factory->result_map[reference]->returnIdentifier; @@ -717,8 +724,8 @@ PRUint32 returnIdentifier; nsCString returnValue; nsString returnValueUCS; - PRBool errorOccured; - + nsCString errorMessage; + PRBool errorOccurred; }; ResultContainer::ResultContainer () @@ -728,7 +735,8 @@ returnIdentifier = -1; returnValue.Truncate(); returnValueUCS.Truncate(); - errorOccured = PR_FALSE; + errorMessage.Truncate(); + errorOccurred = PR_FALSE; } ResultContainer::~ResultContainer () @@ -738,6 +746,7 @@ returnIdentifier = -1; returnValue.Truncate(); returnValueUCS.Truncate(); + errorMessage.Truncate(); } void @@ -748,7 +757,8 @@ returnIdentifier = -1; returnValue.Truncate(); returnValueUCS.Truncate(); - errorOccured = PR_FALSE; + errorMessage.Truncate(); + errorOccurred = PR_FALSE; } #include <nsTArray.h> @@ -1182,6 +1192,7 @@ void DecrementContextCounter(); nsresult GetCurrentContextAddr(char *addr); nsresult GetCurrentPageAddress(const char **addr); + nsresult GetEnabledPrivileges(nsCString *privileges); int contextCounter; }; @@ -2780,7 +2791,16 @@ else if (command == "Error") { printf("Error occured. Setting error flag for container @ %d to true\n", reference); - result_map[reference]->errorOccured = PR_TRUE; + result_map[reference]->errorOccurred = PR_TRUE; + result_map[reference]->errorMessage = (nsCString) rest; + + rest += "ERROR: "; + IcedTeaPluginInstance* instance = NULL; + instances.Get (identifier, &instance); + if (instance != 0) + { + instance->peer->ShowStatus (nsCString (rest).get ()); + } } } else if (prefix == "context") @@ -3916,93 +3936,74 @@ PR_ExitMonitor(contextCounterPRMonitor); } -#include <nsIJSContextStack.h> - nsresult -IcedTeaJNIEnv::GetCurrentContextAddr(char *addr) +IcedTeaJNIEnv::GetEnabledPrivileges(nsCString *privileges) { - return NS_OK; - PLUGIN_TRACE_JNIENV (); - - // Get JSContext from stack. - nsCOMPtr<nsIJSContextStack> mJSContextStack(do_GetService("@mozilla.org/js/xpc/ContextStack;1")); - if (mJSContextStack) { - JSContext *cx; - if (NS_FAILED(mJSContextStack->Peek(&cx))) - return NS_ERROR_FAILURE; - - printf("Context1: %p\n", cx); - - // address cannot be more than 8 bytes (8 bytes = 64 bits) - sprintf(addr, "%p", cx); - - printf("Context2: %s\n", addr); + nsresult rv; + nsCOMPtr<nsIScriptSecurityManager> sec_man = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); + + if (NS_FAILED(rv) || !sec_man) { + return NS_ERROR_FAILURE; } + PRBool isEnabled = PR_FALSE; + + // check privileges one by one + + privileges->Truncate(); + char available_privileges[1024]; + + // see: http://docs.sun.com/source/816-6170-10/index.htm + + // Should these other privileges be supported? According to + // http://java.sun.com/j2se/1.3/docs/guide/plugin/security.html it is + // either UniversalBrowserRead/UniversalJavaPermissions or the highway... + +/* + // broken down to make it clean... + sprintf(available_privileges, "%s %s %s %s %s %s %s %s %s %s %s %s", + "LimitedInstall FullInstall SilentInstall", + "UniversalAccept UniversalAwtEventQueueAccess UniversalConnect", + "UniversalConnectWithRedirect UniversalDialogModality", + "UniversalExecAccess UniversalExitAccess UniversalFdRead", + "UniversalFileDelete UniversalFileRead UniversalFileWrite", + "UniversalLinkAccess UniversalListen UniversalMulticast", + "UniversalJavaPermissions UniversalPackageAccess", + "UniversalPackageDefinition UniversalPrintJobAccess", + "UniversalPropertyRead UniversalPropertyWrite", + "UniversalSendMail UniversalSetFactory UniversalSystemClipboardAccess", + "UniversalThreadAccess UniversalThreadGroupAccess", + "UniversalTopLevelWindow"); +*/ + + sprintf(available_privileges, "%s", + "UniversalBrowserRead UniversalJavaPermissions"); + + + char *token = strtok(available_privileges, " "); + while (token != NULL) + { + isEnabled = PR_FALSE; + sec_man->IsCapabilityEnabled(token, &isEnabled); + + if (isEnabled == PR_TRUE) + { + printf("GetEnabledPrivileges : %s is enabled\n", token); + *privileges += token; + *privileges += ","; + } else { + printf("GetEnabledPrivileges : %s is _NOT_ enabled\n", token); + } + + token = strtok (NULL, " "); + } + + privileges->Trim(","); + return NS_OK; } -nsresult -IcedTeaJNIEnv::GetCurrentPageAddress(const char **addr) -{ - return NS_OK; - PLUGIN_TRACE_JNIENV (); - - nsIPrincipal *prin; - nsCOMPtr<nsIScriptSecurityManager> sec_man(do_GetService("@mozilla.org/scriptsecuritymanager;1")); - - if (sec_man) { - - PRBool isEnabled = PR_FALSE; - sec_man->IsCapabilityEnabled("UniversalBrowserRead", &isEnabled); - - if (isEnabled == PR_FALSE) { - printf("UniversalBrowserRead is NOT enabled\n"); - } else { - printf("UniversalBrowserRead IS enabled\n"); - } - - sec_man->IsCapabilityEnabled("UniversalBrowserWrite", &isEnabled); - - if (isEnabled == PR_FALSE) { - printf("UniversalBrowserWrite is NOT enabled\n"); - } else { - printf("UniversalBrowserWrite IS enabled\n"); - } - } - - if (sec_man) - { - sec_man->GetSubjectPrincipal(&prin); - } else { - return NS_ERROR_FAILURE; - } - - if (prin) - { - nsIURI *uri; - prin->GetURI(&uri); - - if (uri) - { - nsCAutoString str; - uri->GetSpec(str); - NS_CStringGetData(str, addr); - } else { - return NS_ERROR_FAILURE; - } - } else { - return NS_ERROR_FAILURE; - } - - - nsCOMPtr<nsIJSID> js_id(do_GetService("@mozilla.org/js/xpc/ID;1")); - printf("JS ID is: %s\n", js_id->GetID()->ToString()); - - return NS_OK; - -} - NS_IMETHODIMP IcedTeaJNIEnv::NewObject (jclass clazz, jmethodID methodID, @@ -4011,14 +4012,41 @@ nsISecurityContext* ctx) { PLUGIN_TRACE_JNIENV (); + + char origin[1024]; + sprintf(origin, ""); + + if (ctx) + ctx->GetOrigin(origin, 1024); + int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_ID (methodID); MESSAGE_ADD_ARGS (methodID, args); MESSAGE_SEND (); - printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); MESSAGE_RECEIVE_REFERENCE (reference, jobject, result); + + if (factory->result_map[reference]->errorOccurred == PR_TRUE && + factory->result_map[reference]->errorMessage.Find("LiveConnectPermissionNeeded") == 0) + { + // Permission error. Try again. This time, send permissions over the wire + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_PRIVILEGES(); + MESSAGE_ADD_FUNC(); + MESSAGE_ADD_REFERENCE (clazz); + MESSAGE_ADD_ID (methodID); + MESSAGE_ADD_ARGS (methodID, args); + MESSAGE_SEND (); + MESSAGE_RECEIVE_REFERENCE (reference, jobject, result); + } + + DecrementContextCounter (); return NS_OK; @@ -4033,15 +4061,43 @@ nsISecurityContext* ctx) { PLUGIN_TRACE_JNIENV (); + + char origin[1024]; + sprintf(origin, ""); + + if (ctx) + ctx->GetOrigin(origin, 1024); + int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (obj); MESSAGE_ADD_ID (methodID); MESSAGE_ADD_ARGS (methodID, args); - std::cout << "CALLMETHOD -- OBJ: " << obj << " METHOD: " << methodID << " ARGS: " << args << std::endl; MESSAGE_SEND (); - printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); MESSAGE_RECEIVE_VALUE (reference, type, result); + + if (factory->result_map[reference]->errorOccurred == PR_TRUE && + factory->result_map[reference]->errorMessage.Find("LiveConnectPermissionNeeded") == 0) + { + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_PRIVILEGES(); + MESSAGE_ADD_FUNC(); + MESSAGE_ADD_REFERENCE (obj); + MESSAGE_ADD_ID (methodID); + MESSAGE_ADD_ARGS (methodID, args); + MESSAGE_SEND (); + MESSAGE_RECEIVE_VALUE (reference, type, result); + + // if everything was OK, clear exception from previous access exception + if (factory->result_map[reference]->errorOccurred == PR_FALSE) + ExceptionClear(); + } + DecrementContextCounter (); return NS_OK; @@ -4307,13 +4363,37 @@ nsISecurityContext* ctx) { PLUGIN_TRACE_JNIENV (); + + char origin[1024]; + sprintf(origin, ""); + + if (ctx) + ctx->GetOrigin(origin, 1024); + int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (obj); MESSAGE_ADD_ID (fieldID); MESSAGE_SEND (); - printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); MESSAGE_RECEIVE_VALUE (reference, type, result); + + if (factory->result_map[reference]->errorOccurred == PR_TRUE && + factory->result_map[reference]->errorMessage.Find("LiveConnectPermissionNeeded") == 0) + { + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_PRIVILEGES(); + MESSAGE_ADD_FUNC(); + MESSAGE_ADD_REFERENCE (obj); + MESSAGE_ADD_ID (fieldID); + MESSAGE_SEND (); + MESSAGE_RECEIVE_VALUE (reference, type, result); + } + DecrementContextCounter (); return NS_OK; @@ -4327,7 +4407,17 @@ nsISecurityContext* ctx) { PLUGIN_TRACE_JNIENV (); - MESSAGE_CREATE (-1); + + char origin[1024]; + sprintf(origin, ""); + + if (ctx) + ctx->GetOrigin(origin, 1024); + + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(-1); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_TYPE (type); MESSAGE_ADD_REFERENCE (obj); MESSAGE_ADD_ID (fieldID); @@ -4346,14 +4436,43 @@ nsISecurityContext* ctx) { PLUGIN_TRACE_JNIENV (); + + char origin[1024]; + sprintf(origin, ""); + + if (ctx) + ctx->GetOrigin(origin, 1024); + int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_ID (methodID); MESSAGE_ADD_ARGS (methodID, args); MESSAGE_SEND (); - printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); MESSAGE_RECEIVE_VALUE (reference, type, result); + + if (factory->result_map[reference]->errorOccurred == PR_TRUE && + factory->result_map[reference]->errorMessage.Find("LiveConnectPermissionNeeded") == 0) + { + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_PRIVILEGES(); + MESSAGE_ADD_FUNC(); + MESSAGE_ADD_REFERENCE (clazz); + MESSAGE_ADD_ID (methodID); + MESSAGE_ADD_ARGS (methodID, args); + MESSAGE_SEND (); + MESSAGE_RECEIVE_VALUE (reference, type, result); + + // if everything was OK, clear exception from previous access exception + if (factory->result_map[reference]->errorOccurred == PR_FALSE) + ExceptionClear(); + } + DecrementContextCounter (); return NS_OK; @@ -4367,13 +4486,37 @@ nsISecurityContext* ctx) { PLUGIN_TRACE_JNIENV (); + + char origin[1024]; + sprintf(origin, ""); + + if (ctx) + ctx->GetOrigin(origin, 1024); + int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_ID (fieldID); MESSAGE_SEND (); - printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); MESSAGE_RECEIVE_VALUE (reference, type, result); + + if (factory->result_map[reference]->errorOccurred == PR_TRUE && + factory->result_map[reference]->errorMessage.Find("LiveConnectPermissionNeeded") == 0) + { + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_PRIVILEGES(); + MESSAGE_ADD_FUNC(); + MESSAGE_ADD_REFERENCE (clazz); + MESSAGE_ADD_ID (fieldID); + MESSAGE_SEND (); + MESSAGE_RECEIVE_VALUE (reference, type, result); + } + DecrementContextCounter (); return NS_OK; @@ -4387,7 +4530,17 @@ nsISecurityContext* ctx) { PLUGIN_TRACE_JNIENV (); - MESSAGE_CREATE (-1); + + char origin[1024]; + sprintf(origin, ""); + + if (ctx) + ctx->GetOrigin(origin, 1024); + + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(-1); + MESSAGE_ADD_SRC(origin); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_TYPE (type); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_ID (fieldID); @@ -4423,7 +4576,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_STRING (name); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4438,7 +4593,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (sub); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4454,7 +4611,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (sub); MESSAGE_ADD_REFERENCE (super); MESSAGE_SEND (); @@ -4488,7 +4647,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); // FIXME: potential leak here: when is result free'd? @@ -4510,9 +4671,10 @@ IcedTeaJNIEnv::ExceptionClear (void) { PLUGIN_TRACE_JNIENV (); - MESSAGE_CREATE (-1); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(-1); + MESSAGE_ADD_FUNC(); MESSAGE_SEND (); - printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); return NS_OK; } @@ -4530,7 +4692,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (lobj); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4543,7 +4707,9 @@ IcedTeaJNIEnv::DeleteGlobalRef (jobject gref) { PLUGIN_TRACE_JNIENV (); - MESSAGE_CREATE (-1); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(-1); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (gref); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4555,7 +4721,9 @@ IcedTeaJNIEnv::DeleteLocalRef (jobject obj) { PLUGIN_TRACE_JNIENV (); - MESSAGE_CREATE (-1); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(-1); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (obj); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4590,7 +4758,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (obj); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4606,7 +4776,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (obj); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_SEND (); @@ -4624,7 +4796,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_STRING (name); std::cout << "Args: " << clazz << " " << name << " " << sig << " " << *id << "@" << id << std::endl; @@ -4647,7 +4821,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_STRING (name); printf ("SIGNATURE: %s %s %s\n", __func__, name, sig); @@ -4667,7 +4843,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_STRING (name); printf ("SIGNATURE: %s %s\n", __func__, sig); @@ -4687,7 +4865,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_STRING (name); printf ("SIGNATURE: %s %s\n", __func__, sig); @@ -4706,7 +4886,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_SIZE (len); MESSAGE_ADD_STRING_UCS (unicode, len); MESSAGE_SEND (); @@ -4722,7 +4904,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (str); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4741,7 +4925,9 @@ *isCopy = JNI_TRUE; int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (str); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4765,7 +4951,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_STRING_UTF (utf); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4780,7 +4968,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (str); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4799,7 +4989,9 @@ *isCopy = JNI_TRUE; int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (str); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4823,7 +5015,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (array); MESSAGE_SEND (); printf("MSG SEND COMPLETE. NOW RECEIVING...\n"); @@ -4840,7 +5034,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_SIZE (len); MESSAGE_ADD_REFERENCE (clazz); MESSAGE_ADD_REFERENCE (init); @@ -4858,7 +5054,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (array); MESSAGE_ADD_SIZE (index); MESSAGE_SEND (); @@ -4874,7 +5072,9 @@ jobject val) { PLUGIN_TRACE_JNIENV (); - MESSAGE_CREATE (-1); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(-1); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_REFERENCE (array); MESSAGE_ADD_SIZE (index); MESSAGE_ADD_REFERENCE (val); @@ -4891,7 +5091,9 @@ { PLUGIN_TRACE_JNIENV (); int reference = IncrementContextCounter (); - MESSAGE_CREATE (reference); + MESSAGE_CREATE (); + MESSAGE_ADD_STACK_REFERENCE(reference); + MESSAGE_ADD_FUNC(); MESSAGE_ADD_TYPE (element_type); MESSAGE_ADD_SIZE (len); MESSAGE_SEND ();
--- a/plugin/icedtea/sun/applet/AppletSecurityContextManager.java Tue Oct 07 11:16:16 2008 -0400 +++ b/plugin/icedtea/sun/applet/AppletSecurityContextManager.java Wed Oct 08 17:00:19 2008 -0400 @@ -1,5 +1,6 @@ package sun.applet; +import java.security.AccessControlContext; import java.util.HashMap; public class AppletSecurityContextManager { @@ -20,8 +21,13 @@ contexts.get(identifier).dumpStore(); } - public static void handleMessage(int identifier, String src, int reference, String message) { + public static void handleMessage(int identifier, int reference, String src, String[] privileges, String message) { System.err.println(identifier + " -- " + src + " -- " + reference + " -- " + message + " CONTEXT= " + contexts.get(identifier)); - contexts.get(identifier).handleMessage(src, reference, message); + AccessControlContext callContext = null; + + privileges = privileges != null ? privileges : new String[0]; + callContext = contexts.get(identifier).getAccessControlContext(privileges, src); + + contexts.get(identifier).handleMessage(reference, src, callContext, message); } }
--- a/plugin/icedtea/sun/applet/PluginAppletSecurityContext.java Tue Oct 07 11:16:16 2008 -0400 +++ b/plugin/icedtea/sun/applet/PluginAppletSecurityContext.java Wed Oct 08 17:00:19 2008 -0400 @@ -37,21 +37,30 @@ package sun.applet; +import java.awt.AWTPermission; +import java.io.FilePermission; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.SocketPermission; +import java.net.URL; import java.security.AccessControlContext; +import java.security.AccessControlException; import java.security.AccessController; -import java.security.Permission; +import java.security.AllPermission; +import java.security.BasicPermission; +import java.security.CodeSource; import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.util.ArrayList; -import java.util.Enumeration; import java.util.HashMap; import java.util.List; -import java.util.StringTokenizer; +import java.util.PropertyPermission; import net.sourceforge.jnlp.runtime.JNLPRuntime; @@ -123,7 +132,7 @@ } } - public Signature(String signature, String src) { + public Signature(String signature, ClassLoader cl) { this.signature = signature; currentIndex = 0; typeList = new ArrayList<Class>(10); @@ -159,9 +168,9 @@ // System.out.println ("HERE4"); } else typeList.add(Array.newInstance( - getClass(arrayType, src), dims).getClass()); + getClass(arrayType, cl), dims).getClass()); } else { - typeList.add(getClass(elem, src)); + typeList.add(getClass(elem, cl)); } } } @@ -171,36 +180,22 @@ } } - public static Class getClass(String name, String src) { + public static Class getClass(String name, ClassLoader cl) { Class c = null; try { c = Class.forName(name); } catch (ClassNotFoundException cnfe) { - - StringTokenizer st = new StringTokenizer(src, ","); - - while (st.hasMoreTokens()) { - - String tok = st.nextToken(); - System.err.println("Searching for " + name + " at key " + tok); - - try { - c = PluginAppletSecurityContext.classLoaders.get(tok).loadClass(name); - } catch (ClassNotFoundException e) { - // do nothing .. thrown below - } - - if (c != null) - break; + + System.err.println("Class " + name + " not found in primordial loader. Looking in " + cl); + try { + c = cl.loadClass(name); + } catch (ClassNotFoundException e) { + throw (new RuntimeException(new ClassNotFoundException("Unable to find class " + name))); } } - if (c == null) { - throw (new RuntimeException(new ClassNotFoundException("Unable to find class " + name))); - } - return c; } @@ -234,7 +229,7 @@ public class PluginAppletSecurityContext { - public static HashMap<String, ClassLoader> classLoaders = new HashMap<String, ClassLoader>(); + public static HashMap<ClassLoader, String> classLoaders = new HashMap<ClassLoader, String>(); // FIXME: make private public PluginObjectStore store = new PluginObjectStore(); @@ -246,15 +241,24 @@ public PluginAppletSecurityContext(int identifier) { this.identifier = identifier; + + // We need a security manager.. and since there is a good chance that + // an applet will be loaded at some point, we should make it the SM + // that JNLPRuntime will try to install + if (System.getSecurityManager() == null) { + JNLPRuntime.initialize(); + } + + this.classLoaders.put(liveconnectLoader, "file://"); } - private static <V> V parseCall(String s, String src, Class<V> c) { + private static <V> V parseCall(String s, ClassLoader cl, Class<V> c) { if (c == Integer.class) return (V) new Integer(s); else if (c == String.class) return (V) new String(s); else if (c == Signature.class) - return (V) new Signature(s, src); + return (V) new Signature(s, cl); else throw new RuntimeException("Unexpected call value."); } @@ -284,25 +288,17 @@ return store.getObject(new Integer(s)); } - public void addClassLoader(String id, ClassLoader cl) { - this.classLoaders.put(id, cl); + public void associateSrc(ClassLoader cl, String src) { + System.err.println("Associating " + cl + " with " + src); + this.classLoaders.put(cl, src); } public static void setStreamhandler(PluginStreamHandler sh) { streamhandler = sh; } - public void handleMessage(String src, int reference, String message) { + public void handleMessage(int reference, String src, AccessControlContext callContext, String message) { - // We need a security manager.. and since there is a good chance that - // an applet will be loaded at some point, we should make it the SM - // that JNLPRuntime will try to install - if (System.getSecurityManager() == null) { - JNLPRuntime.initialize(); - } - - System.out.println("in handleMessage(), SecurityManager=" + System.getSecurityManager()); - try { if (message.startsWith("FindClass")) { ClassLoader cl = null; @@ -322,9 +318,9 @@ } else if (message.startsWith("GetStaticMethodID") || message.startsWith("GetMethodID")) { String[] args = message.split(" "); - Integer classID = parseCall(args[1], src, Integer.class); - String methodName = parseCall(args[2], src, String.class); - Signature signature = parseCall(args[3], src, Signature.class); + Integer classID = parseCall(args[1], null, Integer.class); + String methodName = parseCall(args[2], null, String.class); + Signature signature = parseCall(args[3], ((Class) store.getObject(classID)).getClassLoader(), Signature.class); Object[] a = signature.getClassArray(); Class c = (Class) store.getObject(classID); @@ -344,9 +340,9 @@ } else if (message.startsWith("GetStaticFieldID") || message.startsWith("GetFieldID")) { String[] args = message.split(" "); - Integer classID = parseCall(args[1], src, Integer.class); - String fieldName = parseCall(args[2], src, String.class); - Signature signature = parseCall(args[3], src, Signature.class); + Integer classID = parseCall(args[1], null, Integer.class); + String fieldName = parseCall(args[2], null, String.class); + Signature signature = parseCall(args[3], ((Class) store.getObject(classID)).getClassLoader(), Signature.class); Class c = (Class) store.getObject(classID); Field f = null; @@ -357,14 +353,15 @@ write(reference, "GetStaticFieldID " + store.getIdentifier(f)); } else if (message.startsWith("GetStaticField")) { String[] args = message.split(" "); - String type = parseCall(args[1], src, String.class); - Integer classID = parseCall(args[1], src, Integer.class); - Integer fieldID = parseCall(args[2], src, Integer.class); + String type = parseCall(args[1], null, String.class); + Integer classID = parseCall(args[1], null, Integer.class); + Integer fieldID = parseCall(args[2], null, Integer.class); final Class c = (Class) store.getObject(classID); final Field f = (Field) store.getObject(fieldID); - AccessControlContext acc = getAccessControlContext(identifier); + AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext(); + checkPermission(src, c, acc); Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () { public Object run() { @@ -399,9 +396,9 @@ } } else if (message.startsWith("SetStaticField")) { String[] args = message.split(" "); - String type = parseCall(args[1], src, String.class); - Integer classID = parseCall(args[2], src, Integer.class); - Integer fieldID = parseCall(args[3], src, Integer.class); + String type = parseCall(args[1], null, String.class); + Integer classID = parseCall(args[2], null, Integer.class); + Integer fieldID = parseCall(args[3], null, Integer.class); Object value = null; if (Signature.primitiveNameToType(type) != null) { @@ -417,7 +414,8 @@ final Field f = (Field) store.getObject(fieldID); final Object fValue = value; - AccessControlContext acc = getAccessControlContext(identifier); + AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext(); + checkPermission(src, c, acc); Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () { public Object run() { @@ -437,9 +435,9 @@ write(reference, "SetStaticField"); } else if (message.startsWith("SetField")) { String[] args = message.split(" "); - String type = parseCall(args[1], src, String.class); - Integer objectID = parseCall(args[2], src, Integer.class); - Integer fieldID = parseCall(args[3], src, Integer.class); + String type = parseCall(args[1], null, String.class); + Integer objectID = parseCall(args[2], null, Integer.class); + Integer fieldID = parseCall(args[3], null, Integer.class); Object value = null; if (Signature.primitiveNameToType(type) != null) { @@ -455,7 +453,8 @@ final Field f = (Field) store.getObject(fieldID); final Object fValue = value; - AccessControlContext acc = getAccessControlContext(identifier); + AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext(); + checkPermission(src, o.getClass(), acc); Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () { public Object run() { @@ -475,8 +474,8 @@ write(reference, "SetField"); } else if (message.startsWith("GetObjectArrayElement")) { String[] args = message.split(" "); - Integer arrayID = parseCall(args[1], src, Integer.class); - Integer index = parseCall(args[2], src, Integer.class); + Integer arrayID = parseCall(args[1], null, Integer.class); + Integer index = parseCall(args[2], null, Integer.class); Object[] o = (Object[]) store.getObject(arrayID); Object ret = null; @@ -490,9 +489,9 @@ + store.getIdentifier(ret)); } else if (message.startsWith("SetObjectArrayElement")) { String[] args = message.split(" "); - Integer arrayID = parseCall(args[1], src, Integer.class); - Integer index = parseCall(args[2], src, Integer.class); - Integer objectID = parseCall(args[3], src, Integer.class); + Integer arrayID = parseCall(args[1], null, Integer.class); + Integer index = parseCall(args[2], null, Integer.class); + Integer objectID = parseCall(args[3], null, Integer.class); Object[] o = (Object[]) store.getObject(arrayID); Object toSet = (Object) store.getObject(objectID); @@ -502,7 +501,7 @@ write(reference, "SetObjectArrayElement"); } else if (message.startsWith("GetArrayLength")) { String[] args = message.split(" "); - Integer arrayID = parseCall(args[1], src, Integer.class); + Integer arrayID = parseCall(args[1], null, Integer.class); System.out.println("ARRAYID: " + arrayID); Object o = (Object) store.getObject(arrayID); @@ -514,14 +513,15 @@ write(reference, "GetArrayLength " + Array.getLength(o)); } else if (message.startsWith("GetField")) { String[] args = message.split(" "); - String type = parseCall(args[1], src, String.class); - Integer objectID = parseCall(args[1], src, Integer.class); - Integer fieldID = parseCall(args[2], src, Integer.class); + String type = parseCall(args[1], null, String.class); + Integer objectID = parseCall(args[1], null, Integer.class); + Integer fieldID = parseCall(args[2], null, Integer.class); final Object o = (Object) store.getObject(objectID); final Field f = (Field) store.getObject(fieldID); - AccessControlContext acc = getAccessControlContext(identifier); + AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext(); + checkPermission(src, o.getClass(), acc); Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () { public Object run() { @@ -565,8 +565,8 @@ write(reference, "GetObjectClass " + store.getIdentifier(c)); } else if (message.startsWith("CallStaticMethod")) { String[] args = message.split(" "); - Integer classID = parseCall(args[1], src, Integer.class); - Integer methodID = parseCall(args[2], src, Integer.class); + Integer classID = parseCall(args[1], null, Integer.class); + Integer methodID = parseCall(args[2], null, Integer.class); System.out.println("GETTING: " + methodID); final Method m = (Method) store.getObject(methodID); @@ -583,7 +583,9 @@ // System.out.println ("Calling " + m); final Object[] fArguments = arguments; - AccessControlContext acc = getAccessControlContext(identifier); + AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext(); + Class c = (Class) store.getObject(classID); + checkPermission(src, c, acc); Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () { public Object run() { @@ -626,8 +628,8 @@ } } else if (message.startsWith("CallMethod")) { String[] args = message.split(" "); - Integer objectID = parseCall(args[1], src, Integer.class); - Integer methodID = parseCall(args[2], src, Integer.class); + Integer objectID = parseCall(args[1], null, Integer.class); + Integer methodID = parseCall(args[2], null, Integer.class); final Object o = (Object) store.getObject(objectID); final Method m = (Method) store.getObject(methodID); @@ -648,7 +650,8 @@ PluginDebug.debug("Calling method " + m + " on object " + o + " with " + arguments); - AccessControlContext acc = getAccessControlContext(identifier); + AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext(); + checkPermission(src, o.getClass(), acc); final Object[] fArguments = arguments; Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () { @@ -697,7 +700,7 @@ } } else if (message.startsWith("GetSuperclass")) { String[] args = message.split(" "); - Integer classID = parseCall(args[1], src, Integer.class); + Integer classID = parseCall(args[1], null, Integer.class); Class c = null; Class ret = null; @@ -708,8 +711,8 @@ write(reference, "GetSuperclass " + store.getIdentifier(ret)); } else if (message.startsWith("IsAssignableFrom")) { String[] args = message.split(" "); - Integer classID = parseCall(args[1], src, Integer.class); - Integer superclassID = parseCall(args[2], src, Integer.class); + Integer classID = parseCall(args[1], null, Integer.class); + Integer superclassID = parseCall(args[2], null, Integer.class); boolean result = false; Class clz = (Class) store.getObject(classID); @@ -720,8 +723,8 @@ write(reference, "IsAssignableFrom " + (result ? "1" : "0")); } else if (message.startsWith("IsInstanceOf")) { String[] args = message.split(" "); - Integer objectID = parseCall(args[1], src, Integer.class); - Integer classID = parseCall(args[2], src, Integer.class); + Integer objectID = parseCall(args[1], null, Integer.class); + Integer classID = parseCall(args[2], null, Integer.class); boolean result = false; Object o = (Object) store.getObject(objectID); @@ -732,7 +735,7 @@ write(reference, "IsInstanceOf " + (result ? "1" : "0")); } else if (message.startsWith("GetStringUTFLength")) { String[] args = message.split(" "); - Integer stringID = parseCall(args[1], src, Integer.class); + Integer stringID = parseCall(args[1], null, Integer.class); String o = null; byte[] b = null; @@ -744,7 +747,7 @@ write(reference, "GetStringUTFLength " + o.length()); } else if (message.startsWith("GetStringLength")) { String[] args = message.split(" "); - Integer stringID = parseCall(args[1], src, Integer.class); + Integer stringID = parseCall(args[1], null, Integer.class); String o = null; byte[] b = null; @@ -757,7 +760,7 @@ write(reference, "GetStringLength " + o.length()); } else if (message.startsWith("GetStringUTFChars")) { String[] args = message.split(" "); - Integer stringID = parseCall(args[1], src, Integer.class); + Integer stringID = parseCall(args[1], null, Integer.class); String o = null; byte[] b = null; @@ -777,7 +780,7 @@ write(reference, "GetStringUTFChars " + buf); } else if (message.startsWith("GetStringChars")) { String[] args = message.split(" "); - Integer stringID = parseCall(args[1], src, Integer.class); + Integer stringID = parseCall(args[1], null, Integer.class); String o = null; byte[] b = null; @@ -798,8 +801,8 @@ write(reference, "GetStringChars " + buf); } else if (message.startsWith("NewArray")) { String[] args = message.split(" "); - String type = parseCall(args[1], src, String.class); - Integer length = parseCall(args[2], src, Integer.class); + String type = parseCall(args[1], null, String.class); + Integer length = parseCall(args[2], null, Integer.class); // System.out.println ("CALLING: NewArray: " + type + " " + // length + " " @@ -813,9 +816,9 @@ write(reference, "NewArray " + store.getIdentifier(newArray)); } else if (message.startsWith("NewObjectArray")) { String[] args = message.split(" "); - Integer length = parseCall(args[1], src, Integer.class); - Integer classID = parseCall(args[2], src, Integer.class); - Integer objectID = parseCall(args[3], src, Integer.class); + Integer length = parseCall(args[1], null, Integer.class); + Integer classID = parseCall(args[2], null, Integer.class); + Integer objectID = parseCall(args[3], null, Integer.class); // System.out.println ("CALLING: NewObjectArray: " + // classID + " " + length + " " @@ -833,8 +836,8 @@ + store.getIdentifier(newArray)); } else if (message.startsWith("NewObject")) { String[] args = message.split(" "); - Integer classID = parseCall(args[1], src, Integer.class); - Integer methodID = parseCall(args[2], src, Integer.class); + Integer classID = parseCall(args[1], null, Integer.class); + Integer methodID = parseCall(args[2], null, Integer.class); final Constructor m = (Constructor) store.getObject(methodID); Class[] argTypes = m.getParameterTypes(); @@ -848,7 +851,10 @@ } final Object[] fArguments = arguments; - AccessControlContext acc = getAccessControlContext(identifier); + AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext(); + + Class c = (Class) store.getObject(classID); + checkPermission(src, c, acc); Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () { public Object run() { @@ -870,12 +876,12 @@ } else if (message.startsWith("NewString")) { System.out.println("MESSAGE: " + message); String[] args = message.split(" "); - Integer strlength = parseCall(args[1], src, Integer.class); + Integer strlength = parseCall(args[1], null, Integer.class); int bytelength = 2 * strlength; byte[] byteArray = new byte[bytelength]; String ret = null; for (int i = 0; i < strlength; i++) { - int c = parseCall(args[2 + i], src, Integer.class); + int c = parseCall(args[2 + i], null, Integer.class); System.out.println("char " + i + " " + c); // Low. byteArray[2 * i] = (byte) (c & 0x0ff); @@ -898,7 +904,7 @@ int i = 0; int c = 0; while (((byte) c) != 0) { - c = parseCall(args[1 + i], src, Integer.class); + c = parseCall(args[1 + i], null, Integer.class); byteArray[i] = (byte) c; i++; if (i == byteArray.length) { @@ -921,29 +927,36 @@ write(reference, "ExceptionOccurred " + store.getIdentifier(throwable)); } else if (message.startsWith("ExceptionClear")) { - if (throwable != null) + if (throwable != null && store.contains(throwable)) store.unreference(store.getIdentifier(throwable)); throwable = null; write(reference, "ExceptionClear"); } else if (message.startsWith("DeleteGlobalRef")) { String[] args = message.split(" "); - Integer id = parseCall(args[1], src, Integer.class); + Integer id = parseCall(args[1], null, Integer.class); store.unreference(id); write(reference, "DeleteGlobalRef"); } else if (message.startsWith("DeleteLocalRef")) { String[] args = message.split(" "); - Integer id = parseCall(args[1], src, Integer.class); + Integer id = parseCall(args[1], null, Integer.class); store.unreference(id); write(reference, "DeleteLocalRef"); } else if (message.startsWith("NewGlobalRef")) { String[] args = message.split(" "); - Integer id = parseCall(args[1], src, Integer.class); + Integer id = parseCall(args[1], null, Integer.class); store.reference(store.getObject(id)); write(reference, "NewGlobalRef " + id); } } catch (Throwable t) { t.printStackTrace(); String msg = t.getCause() != null ? t.getCause().getMessage() : t.getMessage(); + + // add an identifier string to let javaside know of the type of error + // check for cause as well, since the top level exception will be InvocationTargetException in most cases + if (t instanceof AccessControlException || t.getCause() instanceof AccessControlException) { + msg = "LiveConnectPermissionNeeded " + msg; + } + this.streamhandler.write("instance " + identifier + " reference " + reference + " Error " + msg); // ExceptionOccured is only called after Callmethod() by mozilla. So @@ -960,6 +973,32 @@ } } + /** + * Checks if the calling script is allowed to access the specified class + * + * See http://java.sun.com/j2se/1.3/docs/guide/plugin/security.html#liveconnect for details + * + * @param jsSrc The source of the script + * @param target The target class that the script is trying to access + * @param acc AccessControlContext for this execution + * @throws AccessControlException If the script has insufficient permissions + */ + public void checkPermission(String jsSrc, Class target, AccessControlContext acc) throws AccessControlException { + + // target classloader == null => primordial loader. Allow this. + if (target.getClassLoader() == null) + return; + + String classSrc = this.classLoaders.get(target.getClassLoader()); + + System.err.println("jsSrc=" + jsSrc + " classSrc=" + classSrc); + + // if src is not a file and class loader does not map to the same base, UniversalBrowserRead (BrowserReadPermission) must be set + if (jsSrc != "file://" && !classSrc.equals(jsSrc)) { + acc.checkPermission(new BrowserReadPermission()); + } + } + private void write(int reference, String message) { PluginDebug.debug("appletviewer writing " + message); streamhandler.write("context " + identifier + " reference " + reference @@ -983,39 +1022,150 @@ } /** - * Returns an - * - * @param identifier The unique instance identity of the applet for which the context is needed - * @return The context associated with the given applet + * Returns a "closed" AccessControlContext i.e. no permissions to get out of sandbox. */ - public AccessControlContext getAccessControlContext(int identifier) { - - // TODO: - // 1. Find applet URL - // 2. If startsWith file://, some permissions are lax - // 3. If not, find out associated permissions - - // Deny everything for now - PermissionCollection pc = new PermissionCollection(){ - @Override - public boolean implies(Permission permission) { - // TODO Auto-generated method stub - return false; - } - - @Override - public Enumeration<Permission> elements() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void add(Permission permission) { - // TODO Auto-generated method stub - } - }; - - ProtectionDomain pd = new ProtectionDomain(PluginAppletSecurityContext.class.getProtectionDomain().getCodeSource(), pc); + public AccessControlContext getClosedAccessControlContext() { + // Deny everything + Permissions p = new Permissions(); + ProtectionDomain pd = new ProtectionDomain(PluginAppletSecurityContext.class.getProtectionDomain().getCodeSource(), p); return new AccessControlContext(new ProtectionDomain[] {pd}); } + + public AccessControlContext getAccessControlContext(String[] nsPrivilegeList, String src) { + +/* + for (int i=0; i < nsPrivilegeList.length; i++) { + String privilege = nsPrivilegeList[i]; + + if (privilege.equals("UniversalAccept")) { + SocketPermission sp = new SocketPermission("*", "accept,resolve"); + grantedPermissions.add(sp); + } else if (privilege.equals("UniversalAwtEventQueueAccess")) { + AWTPermission awtp = new AWTPermission("accessEventQueue"); + grantedPermissions.add(awtp); + } else if (privilege.equals("UniversalConnect")) { + SocketPermission sp = new SocketPermission("*", "connect,resolve"); + grantedPermissions.add(sp); + } else if (privilege.equals("UniversalListen")) { + SocketPermission sp = new SocketPermission("*", "listen,resolve"); + grantedPermissions.add(sp); + } else if (privilege.equals("UniversalExecAccess")) { + FilePermission fp = new FilePermission("<<ALL FILES>>", "execute"); + RuntimePermission rtp = new RuntimePermission("setIO"); + grantedPermissions.add(fp); + grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalExitAccess")) { + // Doesn't matter what the permissions are. Do not allow VM to exit.. we + // use a single VM for the entire browser lifecycle once invoked, we + // cannot let it exit + + //RuntimePermission rtp = new RuntimePermission("exitVM.*"); + //grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalFileDelete")) { + FilePermission fp = new FilePermission("<<ALL FILES>>", "delete"); + grantedPermissions.add(fp); + } else if (privilege.equals("UniversalFileRead")) { + FilePermission fp = new FilePermission("<<ALL FILES>>", "read"); + grantedPermissions.add(fp); + } else if (privilege.equals("UniversalFileWrite")) { + FilePermission fp = new FilePermission("<<ALL FILES>>", "write"); + grantedPermissions.add(fp); + } else if (privilege.equals("UniversalFdRead")) { + RuntimePermission rtp = new RuntimePermission("readFileDescriptor"); + grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalFdWrite")) { + RuntimePermission rtp = new RuntimePermission("writeFileDescriptor"); + grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalLinkAccess")) { + RuntimePermission rtp = new RuntimePermission("loadLibrary.*"); + grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalListen")) { + SocketPermission sp = new SocketPermission("*", "listen"); + grantedPermissions.add(sp); + } else if (privilege.equals("UniversalMulticast")) { + SocketPermission sp = new SocketPermission("*", "accept,connect,resolve"); + grantedPermissions.add(sp); + } else if (privilege.equals("UniversalPackageAccess")) { + RuntimePermission rtp = new RuntimePermission("defineClassInPackage.*"); + grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalPackageDefinition")) { + RuntimePermission rtp = new RuntimePermission("accessClassInPackage.*"); + grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalPrintJobAccess")) { + RuntimePermission rtp = new RuntimePermission("queuePrintJob"); + grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalPropertyRead")) { + PropertyPermission pp = new PropertyPermission("*", "read"); + grantedPermissions.add(pp); + } else if (privilege.equals("UniversalPropertyWrite")) { + PropertyPermission pp = new PropertyPermission("*", "write"); + grantedPermissions.add(pp); + } else if (privilege.equals("UniversalSetFactory")) { + RuntimePermission rtp = new RuntimePermission("setFactory"); + grantedPermissions.add(rtp); + } else if (privilege.equals("UniversalSystemClipboardAccess")) { + AWTPermission awtp = new AWTPermission("accessClipboard"); + grantedPermissions.add(awtp); + } else if (privilege.equals("UniversalThreadAccess")) { + RuntimePermission rtp1 = new RuntimePermission("modifyThread"); + RuntimePermission rtp2 = new RuntimePermission("stopThread"); + grantedPermissions.add(rtp1); + grantedPermissions.add(rtp2); + } else if (privilege.equals("UniversalThreadGroupAccess")) { + RuntimePermission rtp1 = new RuntimePermission("modifyThreadGroup"); + RuntimePermission rtp2 = new RuntimePermission("modifyThread"); + RuntimePermission rtp3 = new RuntimePermission("stopThread"); + grantedPermissions.add(rtp1); + grantedPermissions.add(rtp2); + grantedPermissions.add(rtp3); + } else if (privilege.equals("UniversalTopLevelWindow")) { + AWTPermission awtp = new AWTPermission("topLevelWindow"); + grantedPermissions.add(awtp); + } else if (privilege.equals("UniversalBrowserRead")) { + BrowserReadPermission bp = new BrowserReadPermission(); + grantedPermissions.add(bp); + } else if (privilege.equals("UniversalJavaPermissions")) { + AllPermission ap = new AllPermission(); + grantedPermissions.add(ap); + } + } + + // what to do with these is unknown: UniversalConnectWithRedirect, UniversalDialogModality, UniversalSendMail, LimitedInstall, FullInstall, SilentInstall +*/ + + Permissions grantedPermissions = new Permissions(); + + for (int i=0; i < nsPrivilegeList.length; i++) { + String privilege = nsPrivilegeList[i]; + + if (privilege.equals("UniversalBrowserRead")) { + BrowserReadPermission bp = new BrowserReadPermission(); + grantedPermissions.add(bp); + } else if (privilege.equals("UniversalJavaPermissions")) { + AllPermission ap = new AllPermission(); + grantedPermissions.add(ap); + } + } + + CodeSource cs = new CodeSource((URL) null, (java.security.cert.Certificate [])null); + + if (src != null) { + try { + cs = new CodeSource(new URL(src + "/"), (java.security.cert.Certificate[]) null); + } catch (MalformedURLException mfue) { + // do nothing + } + } + + ProtectionDomain pd = new ProtectionDomain(cs, grantedPermissions, null, null); + + // Add to hashmap + return new AccessControlContext(new ProtectionDomain[] {pd}); + } + + class BrowserReadPermission extends BasicPermission { + public BrowserReadPermission() { + super("browserRead"); + } + } }
--- a/plugin/icedtea/sun/applet/PluginAppletViewer.java Tue Oct 07 11:16:16 2008 -0400 +++ b/plugin/icedtea/sun/applet/PluginAppletViewer.java Wed Oct 08 17:00:19 2008 -0400 @@ -47,9 +47,11 @@ import java.io.PrintStream; import java.io.Reader; import java.io.StringReader; +import java.net.MalformedURLException; import java.net.SocketPermission; import java.net.URL; import java.security.AccessController; +import java.security.Policy; import java.security.PrivilegedAction; import java.util.Enumeration; import java.util.HashMap; @@ -59,7 +61,6 @@ import java.util.Vector; import net.sourceforge.jnlp.NetxPanel; - import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.X11.XEmbeddedFrame; @@ -266,20 +267,31 @@ } PluginDebug.debug("Applet initialized"); - + // Applet initialized. Find out it's classloader and add it to the list - AppletSecurityContextManager.getSecurityContext(0).addClassLoader(Integer.toString(identifier), a.getClass().getClassLoader()); + String codeBase = doc.getProtocol() + "://" + doc.getHost(); + + if (atts.get("codebase") != null) { + try { + URL appletSrcURL = new URL((String) atts.get("codebase")); + codeBase = appletSrcURL.getProtocol() + "://" + appletSrcURL.getHost(); + } catch (MalformedURLException mfue) { + // do nothing + } + } + + AppletSecurityContextManager.getSecurityContext(0).associateSrc(a.getClass().getClassLoader(), codeBase); } - + public static void setStreamhandler(PluginStreamHandler sh) { streamhandler = sh; } - + public static void setPluginCallRequestFactory(PluginCallRequestFactory rf) { requestFactory = rf; } - + /** * Handle an incoming message from the plugin. */ @@ -287,7 +299,7 @@ { PluginDebug.debug("PAV handling: " + message); - + try { if (message.startsWith("tag")) { @@ -320,6 +332,7 @@ PluginDebug.debug ("REQUEST HANDLE NOT SET: " + request.handle + ". BYPASSING"); } } + } else if (message.startsWith("handle")) { synchronized(requests) { PluginParseRequest request = requests.get(identifier); @@ -360,11 +373,13 @@ int width = Integer.parseInt(message.substring("width".length() + 1)); //panel.setAppletSizeIfNeeded(width, -1); + panel.setSize(width, getHeight()); setSize(width, getHeight()); } else if (message.startsWith("height")) { int height = Integer.parseInt(message.substring("height".length() + 1)); //panel.setAppletSizeIfNeeded(-1, height); + panel.setSize(getWidth(), height); setSize(getWidth(), height); } else if (message.startsWith("destroy")) { dispose();
--- a/plugin/icedtea/sun/applet/PluginObjectStore.java Tue Oct 07 11:16:16 2008 -0400 +++ b/plugin/icedtea/sun/applet/PluginObjectStore.java Wed Oct 08 17:00:19 2008 -0400 @@ -70,6 +70,17 @@ return 0; return identifiers.get(object); } + + public boolean contains(Object object) { + if (object == null) + return identifiers.containsKey(object); + + return false; + } + + public boolean contains(int identifier) { + return objects.containsKey(identifier); + } public void reference(Object object) { Integer identifier = identifiers.get(object);
--- a/plugin/icedtea/sun/applet/PluginStreamHandler.java Tue Oct 07 11:16:16 2008 -0400 +++ b/plugin/icedtea/sun/applet/PluginStreamHandler.java Wed Oct 08 17:00:19 2008 -0400 @@ -146,34 +146,44 @@ public void handleMessage(String message) throws PluginException { - StringTokenizer st = new StringTokenizer(message, " "); - - String type = st.nextToken(); - final int identifier = Integer.parseInt(st.nextToken()); - - String rest = ""; + int nextIndex = 0; int reference = -1; String src = null; - - String potentialReference = st.hasMoreTokens() ? st.nextToken() : ""; + String[] privileges = null; + String rest = ""; - // if the next token is reference, read it, else reset "rest" - if (potentialReference.equals("reference")) { - reference = Integer.parseInt(st.nextToken()); - } else { - rest += potentialReference + " "; + String[] msgComponents = message.split(" "); + + // type and identifier are guaranteed to be there + String type = msgComponents[0]; + final int identifier = Integer.parseInt(msgComponents[1]); + nextIndex = 2; + + // reference, src and privileges are optional components, + // and are guaranteed to be in that order, if they occur + + // is there a reference ? + if (msgComponents[nextIndex].equals("reference")) { + reference = Integer.parseInt(msgComponents[nextIndex+1]); + nextIndex += 2; } - String potentialSrc = st.hasMoreTokens() ? st.nextToken() : ""; - - if (potentialSrc.equals("src")) { - src = st.nextToken(); - } else { - rest += potentialSrc + " "; + // is there a src? + if (msgComponents[nextIndex].equals("src")) { + src = msgComponents[nextIndex+1]; + nextIndex += 2; } - while (st.hasMoreElements()) { - rest += st.nextToken(); + // is there a privileges? + if (msgComponents[nextIndex].equals("privileges")) { + String privs = msgComponents[nextIndex+1]; + privileges = privs.split(","); + nextIndex += 2; + } + + // rest + for (int i=nextIndex; i < msgComponents.length; i++) { + rest += msgComponents[i]; rest += " "; } @@ -181,7 +191,7 @@ try { - System.err.println("Breakdown -- type: " + type + " identifier: " + identifier + " reference: " + reference + " src: " + src + " rest: " + rest); + System.err.println("Breakdown -- type: " + type + " identifier: " + identifier + " reference: " + reference + " src: " + src + " privileges: " + privileges + " rest: \"" + rest + "\""); if (rest.contains("JavaScriptGetWindow") || rest.contains("JavaScriptGetMember") @@ -205,7 +215,7 @@ PluginAppletViewer.handleMessage(identifier, freference,frest); } else if (type.equals("context")) { PluginDebug.debug("Sending to PASC: " + identifier + "/" + reference + " and " + rest); - AppletSecurityContextManager.handleMessage(identifier, src, reference, rest); + AppletSecurityContextManager.handleMessage(identifier, reference, src, privileges, rest); } } catch (Exception e) { throw new PluginException(this, identifier, reference, e);