2

After doing a lot of reading and testing I've been unable to give all permissions to an intranet applet through the codeBase grant option. This applet need full permissions because it will have to acess driver libs for OCR readers (which also write image files to HDD) and other such external devices.

I've configured my java.policy file and added the following:

grant codebase "http://myIntranetServer/-" { permission java.security.AllPermission; };

After reloading the policy file in the console, and even restarting the browser, I get an java.security.AccessControlException:access denied for many of my operations, including reading the "user.name" system property which is not granted by default.

For debugging I've also tried the giving the all permission by default and it works, so my problem is basically related to de codeBase option. I am runnig Windows 7 and linux clients, with JRE1.6-u17, and both have the same behavior.

Can anyone help?

Thanks in advance,

MadeiraA

MadeiraA
  • 23
  • 1
  • 5
  • Maybe you need to sign the applet for all permissions? (with a self generated certificate even?) – rsp Nov 17 '09 at 21:38
  • I've tried self-signing the applet, but the box that should appear for the user to allow the applet to run under the certificate never shows up. I checked the jar file and in the metadata there was the RSA certificate. Moreover, sun states that the certificate approval box might not appear with self-signed certificates. Because of that I've been exploring changing the java.policy file permissions. – MadeiraA Nov 19 '09 at 09:41

2 Answers2

4

I'm not sure if I understood your last comment correctly. As you state two (for me) different things:

  • You use plugin.jar (which means to me your java calls javascript functions)
  • "I call the same functions from the Javascript" (which means to me your javascript calls java functions)

I assume the later one is the right interpretation.

If you just call java methods (via liveconnect) which don't do anything security related all is ok. And you can just do (assuming applet with id="myapplet") myapplet.safeMethod(); directly in your javascript code.

The main problem with calling java methods, which do something normally restricted for applets, from javascript is that the calls seem to run in a different context in the JVM then the applet itself. Thus are treated as unprivileged code and you get the AccessControlException. While e.g. like in my other answer, methods which are executed by the applet itself, get the right permissions and are executed.

Now if you read this LiveConnect Support in the New Java™ Plug-In Technology in section 2.8 Security Model of JavaScript-to-Java Calls SUN states

When a JavaScript-to-Java call is made, the JavaScript code is modeled as though it were coming from an untrusted applet whose code origin is the document base (i.e., the URL of the directory containing the document).

I read this as: If applet and javascript come from the same site than the javascript-to-java calls should run with the same permissions as the applet itself. Which in our case means with whatever rights we set in our grant.

But this only works in Opera for me. FF and IE6 both throw AccessControlException. But it might still work out for you in all browsers.

The following code has two methods userName2() and userName(). userName2() WFM in all browsers. userName() only works in Opera. Check by pushing the buttons on the html page.

As you can see userName2() is not usable like this for a real usecase (can only be called once). But you can look into a solution someone else came up with when having a similar problem, and accordingly extend userName2()

Java Applet using LiveConnect

Additionally you might consider something I didn't try out. All calls from javascript-to-java do nothing security related just (if needed) pass in data and return immediately. Then the applet does the actual work (like in the link shown above). Then when finished the applet could fire a callback into the html page via the JSObject (plugin.jar)

TestApp.java

import java.applet.Applet;
import java.awt.*;
import java.security.AccessControlException;

public class TestApp extends Applet {
  Label output = new Label("What is the value of user.name?");
  String userName;
  Thread access = new Thread() {
    @Override
    public void run() {
      try {
        userName = System.getProperty("user.name");
      } catch (AccessControlException e) {
        userName = "Oops, failed in thread. No read permissions!";
      }
    }
  };
  public void init() {
    setLayout(new BorderLayout());
    add(BorderLayout.CENTER, output);
  }
  public String userName2() throws InterruptedException {
    access.start();
    access.join();
    output.setText(userName);
    return userName;
  }
  public String userName() {
    String userName = "Oops, failed in liveconnect-context. No read permissions!";
    try {
      userName = System.getProperty("user.name");
    } catch (AccessControlException e) {
      e.printStackTrace();
    }
    output.setText(userName);
    return userName;
  }
}

test.html

<html><head><title>test</title></head><body>
  <applet id="myapplet" code="TestApp" width="350px" height="80px"></applet><br>
  <input type="button" value="liveconnect version" onclick="javascript:alert(myapplet.userName());"><br>
  <input type="button" value="hacky thread version" onclick="javascript:alert(myapplet.userName2());">
</body></html>

Policy: .java.policy (created manually in C:/Documents and Settings/[USERNAME]/ Note the leading .)

grant codeBase "http://[domain].xxx/-" {
  permission java.util.PropertyPermission "user.name", "read";
};
jitter
  • 53,475
  • 11
  • 111
  • 124
  • Jitter, After some reading of the links you provided, I came up with using AccessController.doPrivileged to loose the permission restriction imposed by the stack, and It is finally working! Once again, thanks for thrownig all the right pointers and taking the tinme to help. – MadeiraA Nov 25 '09 at 10:09
  • That's interesting, as that didn't work out for me at all. Did play around a bit with AccessController and PrivilegedAction too but that didn't change any of the behavior for me. Well good for you. As this is an intranet thing you might have the luck that it will work on all of your clients too. – jitter Nov 25 '09 at 10:19
  • Now consider upvoting my answers and maybe even accepting one for all the effort and time I put in – jitter Nov 25 '09 at 10:20
  • I've accepted your last answer. I can't upvote yet since I haven't 15 reputation points on my profile. – MadeiraA Nov 26 '09 at 11:30
0

Tried it myself now.

  • class files + html file located on a server http://[domain].xxx/~someusername/somefolder/
  • class files + html file located on local file system C:/Documents and Settings/[USERNAME]/Desktop/somefolder

Policy: .java.policy (located in C:/Documents and Settings/[USERNAME]/. Note the leading .)

When using these applet works and displays [USERNAME]

grant codeBase "file:///-" {
  permission java.util.PropertyPermission "user.name", "read";
};
grant codeBase "http://[domain].xxx/-" {
  permission java.util.PropertyPermission "user.name", "read";
};

Then used these (reloaded policy file in java console) applet fails to display [USERNAME]

grant codeBase "file:///c/*" {
  permission java.util.PropertyPermission "user.name", "read";
};
grant codeBase "http://[domain].xxx/*" {
  permission java.util.PropertyPermission "user.name", "read";
};

Appelt: TestApp.java

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.security.*;

public class TestApp extends Applet {
  Label output = new Label("What is the value of user.name?");
  public void init() {
    Button button = new Button("Click me!");
    setLayout(new BorderLayout());
    add(BorderLayout.NORTH, button);
    add(BorderLayout.CENTER, output);
    button.addActionListener(
      new ActionListener() {
        @Override
        public void actionPerformed( ActionEvent ev ) {
          try {
            output.setText(System.getProperty("user.name"));
          } catch (AccessControlException e) {
            output.setText("Oops, failed. No read permissions");
          }
        }
      }
    );
  }
}

HTML: index.html

<html><body>
  <applet code="TestApp.class" width=350 height=80></applet>
</body></html>

I'm a little confused right now. You state that the above grant statement doesn't work and at the same moment state that "giving the all permission by default ... works"?

A few questions

  • What browser are you using?
  • Which java.policy file did you edit / Where did you place it
  • What does the URL really look like? Is myIntranetServer something that can be resolved via DNS? If not maybe java has some problem applying the rule
jitter
  • 53,475
  • 11
  • 111
  • 124
  • Yes. If I have the permission as grant{ permission java.security.AllPermission; }; it works fine. If I apply the codebase it does not. I have tried a brute force attack of the problem using either the simple machine name and the full machine name (the one with the domain), and various combinations of case because I have read in another forum that the codeBase is handled case-sentive. Fact is nothing seems to work. – MadeiraA Nov 18 '09 at 20:17
  • I'm using both IE8 and Firefox. The policy file is the right one for I can get different behaviors as I change it. like I said above I'm trying several possibilities for myIntranetServer : {servername, servername.domainname.pt} and some combinations of the same values changing the case of the letters. Thanks for your interest. – MadeiraA Nov 18 '09 at 20:22
  • The only thing related to case sensitivity known to me is that codeBase should be written all lower case execpt the B. codeBase – jitter Nov 19 '09 at 00:00
  • Made a quick test now by myself. Check answer for details – jitter Nov 19 '09 at 00:07
  • Yes, that's how I write the codeBase attribute. The case issue I refered applies to the content of the attribute, the path itself. I've been checking your quick test and everything appears to checkout with what I have, although I do not find the .java.policy file you refer. I am using directly te $JAVA_HOME\lib\security\java.policy and I do see changes in behavior when I change it and reload it in the console. – MadeiraA Nov 19 '09 at 09:58
  • You refer the codeBase path you used in your quick test to be like "http://[domain].xxx/-", and it seems to be the same structure as the ones I use "http://[MachineName].[Domain]/-" and "http://[MachineName]/-". The domain name I am using is a NTDomain not an internet domain, for the machine is just internal to the organization. Could this problem of mine be related somehow with the proxy? – MadeiraA Nov 19 '09 at 09:59
  • I included your code in my applet and it works! when I call it through the buttons. My problem seems to be related to calling my functions externally, in this case, from the Javascript in my page. I am using Live Connect (plugin.jar) and when I call the same functions from the Javascript I get the AccessControlException. How can I solve this situation? – MadeiraA Nov 23 '09 at 20:16
  • Added second answer. Partial success with calling restricted functionality from javascript – jitter Nov 24 '09 at 01:07