Mindoo Blog - Cutting edge technologies - About Java, Lotus Notes and iPhone

  • XPages series #7: Running under a restricted Java context - or: Why doesn’t my XPages application work in the Notes Client?!

    Karsten Lehmann  21 October 2009 14:25:51
    As an experienced XPages developer, Lotus Notes 8.5.1 user and reader of this XPages blog series, you may already have tried to use your XPages applications in the new Lotus Notes Client.
    As long as they only contain program code in JavaScript and a few simple Java routines, you will probably have succeeded. Your application looks quite the same as on the web and you can now begin to tweak the UI with a client-specific theme and enhance the application features by integrating it into a Composite Application.

    Any visual issues?

    If there are any visual issues (for instance I heard about dojo dialog boxes not resizing as expected, but haven't tested yet), keep in mind that the 8.5.1 Notes Client uses Xulrunner version 1.8.1.3 to display the XPages, which is the render engine of Firefox 1.5 as far as I know. So make sure to have everything you do compatible with that "nearly recent" Firefox version. ;-)
    (the Xulrunner executable is located in the folder \framework\rcp\eclipse\plugins\com.ibm.rcp.xulrunner.runtime.win32.x86_6.2.1.20090925-1604\xulrunner)
    It should be possible to do that (1.5 was already quite powerful), although I'm a bit confused because this page says that the dijit widgets are only supported in Firefox 2+x. But I saw at least the dijit tabbedpane work without problems in one of my apps.

    Java execution errors?

    Let's say that you followed this blog series and did your homework. You have tried to use JSF managed beans in your application, understood the concept and like it.
    Well, then you may have already seen this Java exception thrown in a few methods, for example in those that call our JSF managed bean helper class:

    javax.faces.FacesException: java.lang.SecurityException: ECL Permission Denied
       com.sun.faces.application.ApplicationAssociate.createAndMaybeStoreManagedBeans(Unknown Source)
       com.sun.faces.el.VariableResolverImpl.resolveVariable(Unknown Source)
       com.ibm.xsp.el.VariableResolverImpl.resolveVariable(Unknown Source)
       com.sun.faces.el.impl.NamedValue.evaluate(Unknown Source)
       com.sun.faces.el.impl.ExpressionEvaluatorImpl.evaluate(Unknown Source)
       com.sun.faces.el.ValueBindingImpl.getValue(Unknown Source)
       com.sun.faces.el.ValueBindingImpl.getValue(Unknown Source)
       com.acme.tools.JSFUtil.getBindingValue(Unknown Source)


    When I first saw this, I yelled something comparable to "Interesting! How fascinating! A welcome challenge for me!". Ok, maybe less polite ;-).

    That was 2-3 days ago. Since then, I did some research and testing to find out what is causing this problem and how to deal with it.
    I'd like to share it with you.

    The Domino Server - a secure environment

    So far, we did our Xpages development on a Domino server. We were allowed to do this, because our administrator granted us developer rights on a database on the server, and he gave us the power to execute our code on that machine. He does not allow anybody to do this. He knows us and trusts us.

    Controlling access in the Notes Client

    It's a slightly different situation for the Notes client. A Notes user could download a Notes database with malicious code from anywhere on the internet.
    That's the reason why there is an Execution Control List (ECL) in the client to restrict what applications may do on the user's workstation. Critical operations like accessing the machine's filesystem need to be confirmed (trusted) by the user - and the administrator can prevent Notes users from easily trusting anyone.
    The ECL is not a new invention. It's been in the client for many years and controlled the program code of forms, views, agents and other design elements.

    For Eclipse plugins extending the Lotus Notes Standard client, there is no such thing as an ECL (because Eclipse does not have it), only the installation of plugins can be controlled by policy.
    This has produced a lot of discussion about the security of Eclipse plugins.

    Security for local Xpages

    For the first implementation of XPages in the Notes client, IBM chose a more conservative security model. The Java programming language has a built-in security system, called the SecurityManager, that IBM connected to the ECL system of Lotus Notes. Everything that is not connected to the ECL system of Lotus Notes, is considered insecure and is therefore denied.

    Java developers may already know the impact of the SecurityManager when they try to do restricted operations (like accessing files) in Java applets. They just don't work.

    So that's what happens behind the scenes in our method "JSFUtil.getBindingValue(String)". It calls JSF functions and deep in the calling tree, there is a restricted method and the JVM says "no".

    The good news

    The administrator does not have to worry about end users that download and open XPages applications from the web.

    The bad news

    The developers and ISVs have to worry about what their application code is allowed to do and how to deal with the restrictions.

    What is allowed?

    Here is a table with the available classes of allowed Java operations and their equivalent ECL levels in Notes 8.5.1:

    Java PermissionNote Client ECL Access (Workstation)
    java.util.PropertyPermissionEnvironment variables
    java.io.FilePermissionFile system
    java.net.SocketPermissionNetwork

    (plus using the Notes Java API)

    Calling a Java operation that needs one of these permissions results in a Notes ECL confirmation dialog if the XPage's signer is not trusted. Any other restricted Java operation that is not listed in the table will fail for Xpages in the Notes Client 8.5.1.

    What is not allowed?

    Ok, this is the "not so funny" part of this blog posting. I did a few tests. I don't have a complete list, but I have some of the things that hurt the most:
    • using java.net.URLConnection, e.g. to easily connect to a web server
    • XML parsing with javax.xml.parsers.DocumentBuilder
    • Loading Java resources with Class.getResourceAsStream()
    All three are prohibited because java.net.NetPermission is not connected to the ECL system.
    Regarding the URLConnection: Please note that you can use networking. I have a working demo of an XPages application in the client that downloads a HTML file from a web server (by using Java's Socket class and the HTTP protocol) and analyzes it in an XPages application in the client. Actually, at the moment, it's not 100% working any more, because I just upgraded to a new version of JTidy which now internally loads Java resources with Class.getResourceAsStream(). Ouch... ;-)

    Workaround for developers

    Add the grant command shown below to the java.policy file under the Notes directory and restart the client.

    grant {
         permission java.security.AllPermission;
    };


    This completely disables the security restrictions of the platform. That's why it's an extremely bad idea to do this on a user's machine. :-)
    But it makes it easy for you to work on your Java code and test it in the client.

    Workaround for customer installations

    This is not really a workaround. It's the only thing we have. ;-)

    You can put all your restricted code in a JAR file and store it in the jvm/lib/ext directory of the Notes Client. That code then has the right to run with a higher security level and may do the things that your XPages Java code is not allowed to.
    Please note that you need a special syntax in your code to ask Java for that higher privilege level:

    public class ExternalWorkaroundClass {
       public String tryWorkaround(final String anArgument) throws Exception {

           String result = AccessController.doPrivileged(
                   new PrivilegedExceptionAction() {
                       public String run() throws Exception {
                           String result=null;

                           //do some restricted operations here to compute result

                           return result,
                       }
                   }
           );
           return result;
       }


    How should I automatically deploy this to a few hundred customers???

    Don't ask me. Be creative. ;-). IBM dev is working on a better solution and more supported Java permissions in a future version (hopefully 8.5.2 or some kind of 8.5.1 fix pack).
    Looks like they thought that most of the XPages developers do not use those restricted (or any) Java classes at all. So the impact of this would not be too big.

    And they were probably right. But for us, this really hurts.

    What about managed Java beans?

    I guess the JSF method that produces the Java exception shown at the beginning of this article either wants to load the JSF configuration XML file faces-config.xml as a Java resource or it wants to parse it using the JVM's XML parser.
    But hey, remember I said something similar to "A welcome challenge for me!"? :-)

    I'm currently writing my own bean manager. The whole bean concept is about creating a bean, feeding it with default values and storing it in the right scope. Who needs the JSF bean manager for that? :-)
    Comments

    1Karsten Lehmann  22.10.2009 19:58:32  XPages series #7: Running under a restricted Java context - or: Why doesn’t my XPages application work in the Notes Client?!

    One additional information regarding the workaround for customer installations:

    You should avoid to create new security holes. Any XPages application could potentially call your external Java code in the jvm/lib/ext directory.

    I would recommend to check in your external code that

    com.ibm.domino.xsp.module.nsf.NotesContext.getCurrent().getCurrentDatabase()

    returns the right Database. The NotesContext class is located in -notesdir-\xsp\nsf\lib\lwpd.xsp.domino.jar

    2Karsten Lehmann  17.11.2009 15:37:21  XPages series #7: Running under a restricted Java context - or: Why doesn’t my XPages application work in the Notes Client?!

    Update:

    Today Jim Quill from IBM published a Wiki article about the security topic.

    You can find it here:

    { Link }

    3Nicolas Kauffmann  16.03.2010 09:26:34  XPages series #7: Running under a restricted Java context - or: Why doesn’t my XPages application work in the Notes Client?!

    Hi!

    A very helpful article ! Thanks !

    :-)

    The 2nd link regarding "browser compatibility" (on top, 2nd paragraph) runs into 404.

    The correct href should be { Link }

    ("o" instead of "www").

    Nicolas

    4wei  13.12.2010 17:15:50  XPages series #7: Running under a restricted Java context - or: Why doesn’t my XPages application work in the Notes Client?!

    Hi, I made a BeanFactory class creating dynamic beans at run time with javassist

    "

    I'm currently writing my own bean manager. The whole bean concept is about creating a bean, feeding it with default values and storing it in the right scope. Who needs the JSF bean manager for that? :-) "

    But I just wonder what kind of cool things I can do with that?

    5Bernd Hort  04.01.2011 14:44:16  XPages series #7: Running under a restricted Java context - or: Why doesn’t my XPages application work in the Notes Client?!

    While trying to create a XPages validator object I get an error „Access denied (java.lang.RuntimePermission getClassLoader)“

    The code in the beforePageLoad event is

    var validator = facesContext.getApplication().createValidator("javax.faces.Length");

    Is this error also caused because of the access to the file system in order to load the class?

    Thanks

    Bernd

    6Karsten Lehmann  04.01.2011 15:24:52  XPages series #7: Running under a restricted Java context - or: Why doesn’t my XPages application work in the Notes Client?!

    Yes, probably.

    If you can load the class in your own code, you could try to use the classloader returned by

    ClassLoader cl=com.ibm.domino.xsp.module.nsf.NotesContext.getCurrent().getModule().getModuleClassLoader();

    That one might be safe to use.