2 Replies Latest reply on Feb 6, 2006 8:56 AM by Adrian Brock

    AOP Running in an applet

    Kabir Khan Master

      I'm assuming for the case of the microcontainer that the most urgent priority is determining if we can generate class proxies or not?

      The four problems main problems I have found so far when running in a standalone applet viewer with default security are:

      - - - -

      1) AspectManager.instance() calls System.getProperty()
      When it is not suitable to set the correct permissions, we can pass these in using an alternative initialise() method

      2) GenericAspectFactory.initEditors() initialises the PropertyEditorManager, which needs to call System.setProperty()
      If not allowed, we can avoid + log and warn the setting of attributes

      3) Javassist internally (LoaderClassPath.find()) calls ClassLoader.getResource(), and this cannot even find things like "java/lang/Object.class" in an applet

      Isolating this
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      System.out.println("ClassLoader: " + cl);
      URL coll = (URL)cl.getResource("java/util/Object.class");

      System.out.println("Resource: " + coll);

      which gives the following output when running with the appletviewer:

      ClassLoader: sun.applet.AppletClassLoader@17a1767
      Resource: null


      4) When generating a ClassProxy, we eventually need to pass the bytes into ClassLoader.defineClass()
      Class loaderClass = Class.forName("java.lang.ClassLoader");
      java.lang.reflect.Method method = loaderClass.getDeclaredMethod("defineClass",new Class[] { String.class, byte[].class,int.class, int.class });
      method.setAccessible(true);
      Object[] args = new Object[] { "applet.FromBytecode", realBytes, new Integer(0),new Integer(realBytes.length)};
      Class clazz = (Class)method.invoke(cl, args);
      method.setAccessible(false);
      clazz.newInstance();

      This gives the following error:
      java.lang.RuntimeException: java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers
      )
      at applet.TestApplet.initAspectManager(TestApplet.java:163)
      at applet.TestApplet.init(TestApplet.java:69)
      at sun.applet.AppletPanel.run(AppletPanel.java:374)
      at java.lang.Thread.run(Thread.java:595)
      Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)
      at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264)
      at java.security.AccessController.checkPermission(AccessController.java:427)
      at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
      at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1662)
      at java.lang.Class.checkMemberAccess(Class.java:2125)
      at java.lang.Class.getDeclaredMethod(Class.java:1906)
      at applet.TestApplet.initAspectManager(TestApplet.java:144)
      ... 3 more

      - - - -
      It all works fine when running within Eclipse, I assume since it automatically creates the following java.policy.applet file

      /* AUTOMATICALLY GENERATED ON Tue Apr 16 17:20:59 EDT 2002*/
      /* DO NOT EDIT */
      
      grant {
       permission java.security.AllPermission;
      };
      




      1 & 2 are workaroundable, for 3 something can possibly be added in javassist, but I see no workaround for 4. So I believe for this to work we will need to define a set of permissions that are required for AOP to work when running with a security manager. Otherwise, we are stuck with the dynamic proxy approach for the AOP proxies?


        • 1. Re: AOP Running in an applet
          Adrian Brock Master

           

          "kabir.khan@jboss.com" wrote:

          1) AspectManager.instance() calls System.getProperty()
          When it is not suitable to set the correct permissions, we can pass these in using an alternative initialise() method


          A better solution is to do what the Microcontainer does.
          It has a KernelConfig class.
          The default implementation is to use system properties, but other
          configs impls are possible.


          2) GenericAspectFactory.initEditors() initialises the PropertyEditorManager, which needs to call System.setProperty()
          If not allowed, we can avoid + log and warn the setting of attributes


          There is already a separate jira issue to fix this.


          3) Javassist internally (LoaderClassPath.find()) calls ClassLoader.getResource(), and this cannot even find things like "java/lang/Object.class" in an applet

          Isolating this
          ClassLoader cl = Thread.currentThread().getContextClassLoader();
          System.out.println("ClassLoader: " + cl);
          URL coll = (URL)cl.getResource("java/util/Object.class");

          System.out.println("Resource: " + coll);

          which gives the following output when running with the appletviewer:

          ClassLoader: sun.applet.AppletClassLoader@17a1767
          Resource: null


          The issue here is whether the applet is authorized to that url.
          i.e. does it (and its callers if you don't have a privileged block) have the permission
          to look at the user's file system inside a browser?


          4) When generating a ClassProxy, we eventually need to pass the bytes into ClassLoader.defineClass()
          Class loaderClass = Class.forName("java.lang.ClassLoader");
          java.lang.reflect.Method method = loaderClass.getDeclaredMethod("defineClass",new Class[] { String.class, byte[].class,int.class, int.class });
          method.setAccessible(true);
          Object[] args = new Object[] { "applet.FromBytecode", realBytes, new Integer(0),new Integer(realBytes.length)};
          Class clazz = (Class)method.invoke(cl, args);
          method.setAccessible(false);
          clazz.newInstance();

          This gives the following error:
          java.lang.RuntimeException: java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers
          )
          at applet.TestApplet.initAspectManager(TestApplet.java:163)
          at applet.TestApplet.init(TestApplet.java:69)
          at sun.applet.AppletPanel.run(AppletPanel.java:374)
          at java.lang.Thread.run(Thread.java:595)
          Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)
          at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264)
          at java.security.AccessController.checkPermission(AccessController.java:427)
          at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
          at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1662)
          at java.lang.Class.checkMemberAccess(Class.java:2125)
          at java.lang.Class.getDeclaredMethod(Class.java:1906)
          at applet.TestApplet.initAspectManager(TestApplet.java:144)
          ... 3 more


          Permissions and access control context again

          - - - -

          It all works fine when running within Eclipse, I assume since it automatically creates the following java.policy.applet file

          /* AUTOMATICALLY GENERATED ON Tue Apr 16 17:20:59 EDT 2002*/
          /* DO NOT EDIT */
          
          grant {
           permission java.security.AllPermission;
          };
          



          Eclipse loads the applet from the system classloader not the applet classloader.
          Try System.out.println(TestApplet.class.getProtectionDomain());


          1 & 2 are workaroundable, for 3 something can possibly be added in javassist, but I see no workaround for 4. So I believe for this to work we will need to define a set of permissions that are required for AOP to work when running with a security manager. Otherwise, we are stuck with the dynamic proxy approach for the AOP proxies?


          That isn't necessarily true. e.g. in an applet you can load whatever
          bytecode you like from the url of the applet. You just need something cleverer
          than something serving static files in reponse to
          GET com/example/MyClass.class

          This is an approach taken by JBoss/IIOP to automatically generate IIOP stubs
          for java clients.

          • 2. Re: AOP Running in an applet
            Adrian Brock Master

            I am actually more interested in getting the functionality correct at this stage.
            AOP (and javassist) do need fixing to work properly in a restricted environment.
            But that can be done later.

            e.g. I put a *stupid* hack in AspectManager just so you could get AOP to bootstrap
            with a SecurityManger.

            FYI: The Microcontainer testsuite extends AbstractTestCaseWithSetup
            to run all tests with a security manager enabled.
            This means I can catch security manager regressions early.

            see AbstractKernelTest

             /**
             * Default setup with security manager enabled
             *
             * @param clazz the class
             * @return the delegate
             * @throws Exception for any error
             */
             public static AbstractTestDelegate getDelegate(Class clazz) throws Exception
             {
             AbstractTestDelegate delegate = new AbstractTestDelegate(clazz);
             delegate.enableSecurity = true;
             return delegate;
             }