JOGL Applet Security

All right I’ve updated and cleaned up a bit the JOGLAppletLauncher

The class used are :

net.java.games.jogl.applets.JOGLAppletLauncher
net.java.games.jogl.applets.NativeInstaller (interface)

net.java.games.jogl.applets.nativeinstallers.WindowsNativeInstaller (implements NativeInstaller)
net.java.games.jogl.applets.nativeinstallers.MacOsNativeInstaller idem
net.java.games.jogl.applets.nativeinstallers.LinuxNativeInstaller idem

The 3 installer classes should go into their respective native jar (e.g. WindowsNativeInstaller goes into jogl-natives-win32.jar)

As the install process is contained into those 3 classes, this ensures noboby has replaced the dll/.so with malicious code (I’ve tried it… and it throws an applet security exception)

I’ve removed Swing references from the applet to improve startup time, and the applet launcher can be customized with a display name (see html page for details).

Now I’m goind to send the contributor agreement by fax, and I hope this will make it into jogl.jar soon !

The link is still here but the contents have been updated.

Lilian

Tried it again and got a different exception:


java.security.AccessControlException: access denied (java.util.PropertyPermission user.home read)
	at java.security.AccessControlContext.checkPermission(Unknown Source)
	at java.security.AccessController.checkPermission(Unknown Source)
	at java.lang.SecurityManager.checkPermission(Unknown Source)
	at java.lang.SecurityManager.checkPropertyAccess(Unknown Source)
	at java.lang.System.getProperty(Unknown Source)
	at net.java.games.jogl.applets.JOGLAppletLauncher.start(JOGLAppletLauncher.java:142)
	at com.opera.PluginPanel.startApplet(PluginPanel.java:325)
	at com.opera.PluginPanel.run(PluginPanel.java:445)
	at java.lang.Thread.run(Unknown Source)

Edit: Get exception when running threw Opera. It works in IE.

Tom, I’ve added a new link to a page which uses the java plug-in instead of the default applet tag, can you tell me if it solves your problem with opera (that will save me the download and install of this browser).

Thanks

Lilian

Still the same exception.

I’ve tried it on my pc… and I agree with you there’s definitely a problem with opera…

I’ll try again later with a single signed jar, just to see if it comes from the multiple archives (to file a proper bug to sun/opera)

Lilian

Thank you very much, but I got an error on my windows xp:


Java Plug-in 1.5.0_04
Using JRE version 1.5.0_04 Java HotSpot(TM) Client VM
User home directory = C:\Documents and Settings\xxx
java.net.ConnectException: Connection refused: connect
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.PlainSocketImpl.doConnect(Unknown Source)
	at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
	at java.net.PlainSocketImpl.connect(Unknown Source)
	at java.net.Socket.connect(Unknown Source)
	at sun.net.NetworkClient.doConnect(Unknown Source)
	at sun.net.www.http.HttpClient.openServer(Unknown Source)
	at sun.net.www.http.HttpClient.openServer(Unknown Source)
	at sun.net.www.http.HttpClient.<init>(Unknown Source)
	at sun.net.www.http.HttpClient.New(Unknown Source)
	at sun.net.www.http.HttpClient.New(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at com.sun.deploy.net.proxy.AbstractAutoProxyHandler.getJSFileFromURL(Unknown Source)
	at com.sun.deploy.net.proxy.AbstractAutoProxyHandler.init(Unknown Source)
	at com.sun.deploy.net.proxy.DynamicProxyManager.reset(Unknown Source)
	at com.sun.deploy.net.proxy.DeployProxySelector.reset(Unknown Source)
	at sun.plugin.AppletViewer.initEnvironment(Unknown Source)
	at sun.plugin.AppletViewer.initEnvironment(Unknown Source)

stop
destroy
Exception in thread "AWT-EventQueue-6" java.lang.UnsatisfiedLinkError: JAWT_GetAWT0
	at net.java.games.jogl.impl.JAWTFactory.JAWT_GetAWT0(Native Method)
	at net.java.games.jogl.impl.JAWTFactory.JAWT_GetAWT(JAWTFactory.java:37)
	at net.java.games.jogl.impl.windows.WindowsGLContext.getJAWT(WindowsGLContext.java:282)
	at net.java.games.jogl.impl.windows.WindowsOnscreenGLContext.lockSurface(WindowsOnscreenGLContext.java:167)
	at net.java.games.jogl.impl.windows.WindowsOnscreenGLContext.makeCurrent(WindowsOnscreenGLContext.java:126)
	at net.java.games.jogl.impl.GLContext.invokeGL(GLContext.java:248)
	at net.java.games.jogl.impl.windows.WindowsOnscreenGLContext.invokeGL(WindowsOnscreenGLContext.java:76)
	at net.java.games.jogl.GLCanvas.maybeDoSingleThreadedWorkaround(GLCanvas.java:236)
	at net.java.games.jogl.GLCanvas.reshape(GLCanvas.java:133)
	at java.awt.Component.setBounds(Unknown Source)
	at java.awt.BorderLayout.layoutContainer(Unknown Source)
	at java.awt.Container.layout(Unknown Source)
	at java.awt.Container.doLayout(Unknown Source)
	at java.awt.Container.validateTree(Unknown Source)
	at java.awt.Container.validate(Unknown Source)
	at untrusted.JOGLApplet.init(JOGLApplet.java:24)
	at net.java.games.jogl.applets.JOGLAppletLauncher.joglStart(JOGLAppletLauncher.java:178)
	at net.java.games.jogl.applets.JOGLAppletLauncher$3.run(JOGLAppletLauncher.java:284)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)


Looks the error from camac on page 3 of this thread… do you have a copy of JOGL.jar somewhere in your classpath (jre lib, etc.) ? removing the jar resolved the problem.

Lilian

Hi,

It is really a fantastic works. Its works fine for me with firefox on XP. I think that incorporating this code in JOGL and having jogl jars signed with sun certificat ( but it could maybe leads to some problem if the subapplet must also be signed) would be great and very useful for develloping jogl technologie by means of applets. I have make some another tests. On my pc, if jogl.jar and jogl.dll are respectively in the jre/lib/ext and jre/bin i have the following exception :

Exception in thread “AWT-EventQueue-2” java.lang.NoSuchMethodError: net.java.games.jogl.impl.NativeLibLoader.disableLoading()V
at net.java.games.jogl.applets.JOGLAppletLauncher$3.run(JOGLAppletLauncher.java:281)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

I think it is due to the fact that it use the jar and dll that are in the jre. I remove these file from the jre and it works. Another problem appears when I start a first time the applet (it works), then i go back to the presentation web page. I clear the cache of the classloader and i return to the applet. I have the following exception :
Exception in thread “AWT-EventQueue-6” java.lang.UnsatisfiedLinkError: Native Library ############.jogl_ext\www_vlsolutions_com_lib_\jogl.dll already loaded in another classloader
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at net.java.games.jogl.applets.JOGLAppletLauncher$3.run(JOGLAppletLauncher.java:277)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

I have this problem on two differents xp computers. It works again when I close and restart firefox.

The another problem is on the time for loading the applet. After a first run, are the jogls jars cached for futher runs (some days after). If not, the wheight for the applets is high (min 1.5 Mo for the jogls jars).

Mathlamenace

Thanks !

The child applet doesn’t have to be signed (in the demo, it isn’t), unless it needs special property permissions (like opening a server socket).

Thanks for reporting this error, I wasn’t aware of this classloader issue and you seem to have an old jogl.jar in your jre.
I think I will just add a try/catch around the native loading and avoid crashing if these case are encoutered.

The applet is cached, and loading the full 1.5megs should only occur at first time, unless the applet cache has been cleared in between. Unfortunately it is not possible to share this download with other web sites… it’s not as good as JNLP extensions !

Lilian

Tanks for the answer,

Ok, I aggree with you. Then in this case, the user needs to accept two certificates, the first one from sun for jogl, and the second one for the applet.

Indeed, the first exception was due to the jogl.jar in the JRE. But, to my mind, the second is due to a wrong unlinking of jogl.dll (i am sorry for my poor english, i hope it is understandable) when clearing the cache of applet. But adding a try/catch (as for os x in your code) may be sufficient, I think.

:).
Is your code planned to be added in the jogl.jar for avoiding signing applet problems ?

Mathlamenace

Well I’m not part of the jogl team but I’ve signed the contributor agreement… so the answer should be yes.

I’ll let Ken Russel confirm this once the code is stabilized, as it is not yet the case… so it’s too early to be 100% sure…

About unloadind the dll, I don’t think it’s possible so I’d rather fix the Exception.

About double signing : it’s an option, but in that case you should just sign the jogl.jar with your own certificate, so the user will only have to agree once.

Lilian

Ken and others that want to help…

I’m now trying to load the natives from the applet (like last week) but I want to enforce security.
(This is to avoid having them in the archive tag and downloading them all when only one is needed).

so here’s my problem :

I want to read the META-INF contents of the jogl.jar used by the applet.
I need this to compare the signature used by jogl.jar with the one of the native lib jar (to verifiy the contents haven’t been infected).

I can’t rely on JarInputStream and getCodeBase() + “/jogl.jar”, as the jogl.jar used by the applet might be in a subdirectory of the codebase : potential hacking

I can’t use the java.class.path system property as it points to the local cache and the jar file names are modified during the download process…

I can’t load the files with ClassLoader.getResourceAsStream() as the classloader seems to find the first entry in the classpath matching the name, and doesn’t look into the downloaded jars.

Right now I’m a bit confused… ?!? Any help is welcome !

Lilian

You’re trying to find the certificates signing jogl.jar, correct? You should be able to do something like

GLDrawableFactory.class.getProtectionDomain().getCodeSource().getCertificates();

Does that solve the problem?

Thank you that made it…

But I’ve found another problem : when comparing the jogl.jar certificates with the ones of the JarEntry of the native dll, everything works as expected with java 1.4.2, but not with 1.5.0_04/05 : here’s the related bug id :

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6348368

the jarEntry.getCertificates() returns always null, instead of the array of certificates as expected. It’s not possible to verify the integrity on this file.

This is a showstopper for option 2, unless someone finds a workaround for that one. >:(

Lilian

[edit]
if we choose option 1, I just wanted to add that jogl.jar with pack200 compression is only 280 kbytes, so download size for 1.5 applets is low when the server is properly configured (total jogl download size is just 340 kb for windows users if we use pack200 and auto-detect windows on server side to skip unnecessary native jars from other systems).

I’ve had problems using JarInputStream before and have found saving the jar file to the local disk and using JarFile to be much more robust. Here is a modified version of Apache’s test case which works on 1.5.


import java.net.*;
import java.util.jar.*;
import java.security.cert.*;

public class cert15f
{
  public static void main(String[] args)
    throws Exception
  {
    java.io.File file = new java.io.File(args[0]);
    JarFile jar = new JarFile(file);
		
    for (java.util.Enumeration e = jar.entries(); e.hasMoreElements();) {
      JarEntry je = (JarEntry) e.nextElement();
      java.io.InputStream jis = jar.getInputStream(je);

      // need to read the data to see the certs.
      byte[] data = new byte[1024];
      for (; jis.read(data) != -1;)
        ;
      Certificate[] certs = je.getCertificates();
      System.out.println("Entry: " + je.getName());
      if (certs == null)
        {
          System.out.println("  no certificates");
          continue;
        }
      System.out.println(certs.length + " certificates");
      for (int i = 0; i < certs.length; i++)
        {
          System.out.println("  " + certs[i].toString());
        }
    }
  }
}

Ken, you’re full of resources !

I’m going back to the project and testing this option !

Lilian

And here it is ! :slight_smile:

Now it’s in the hands of the JOGL team to verify the source code and promote it into the jogl.jar !!

demo and source code

Lilian

Updated again (bux fixes and improvements)

I’ve added the applet into the jogl.jar, to see how it will look like. Some first thoughts :

  • The download progress bar from the java plug-in is limited to the first jar (jogl.jar) which in this case is the most important jar (but with a game with more contents, this will not be the case).

  • Then the applet hangs until the game.jar is downloaded. I haven’t found a means to have an indefinite progress bar, it just hangs until the classloader has finished its job.

  • I’ve added an option to show an image while installing the natives and game jar, but I hope the users won’t think the game is broken (in older JRE releases, there was a small dialog with a progress bar that was shown in such situation, it was much better).

So for a typical java game, we’ll have :

  • the default java plugin progress bar during the download of jogl.jar
  • custom progress bar during native jar download
  • applet freeze during game jars download
  • the game begins…

Does anybody knows a means of loading the game jars without freezing the applet ? That would be the “final touch”. I’ve tried referencing the sub applet class from the EDT or in a background thread, and it hangs in both cases !!

Lilian

Hi Lilian,

Nice work! I hope this will give applets the boost they need to be able to compete with shockwave3d and alike!

Note you can also use a custom animated gif that tells the user the applet is downloading.
http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/special_attributes.html

Another way of loading (large) resource files is by downloading the files runtime over an URLConnection with setUseCache enabled. A limitation is that it only caches files with a .jar or .class extension. You can make a zip containing all your images, sound etc and rename it to either .class or .jar. (for jar files you should use URL url = new URL (“jar:” + jarname + “!/”))
Another limitation of this technique is that you can’t monitor progress with caching enabled.

The advantage you have is that you gain more control over what to display as your applet is already up & running without waiting for the JVM archive jars to load…

Now I think of it, it might be possible to overcome the disability to monitor download progress with setUseCache enabled… You can implement your own protocol handler: http://java.sun.com/developer/onlineTraining/protocolhandlers/

What probably happens with setUseCache(true) is the handler streaming the resource to a file upon urlconnection.getInputStream(), it first downloads the whole resource into this file (in the plugincache) and then handles the stream over in one go. Maybe we could override the standard handler and enable reading the progress for the resource->file stream.

Thijs

Thanks !

About the animated image : it replaces the default java cup, so it would work only for the jogl.jar download.

I’ve found this link : http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/applet_caching.html

It seems it should be possible to specify a “preload” tag on jar files, and in that case our problem would be solved.

I’ll try that option soon :slight_smile:

Lilian