changeset 938:d133c4ebfe24

Methods validating manifests' attributes moved to separate class.
author Jiri Vanek <jvanek@redhat.com>
date Thu, 20 Mar 2014 16:29:46 +0100
parents 15bbdf43c1e7
children cea32875903d
files ChangeLog netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java netx/net/sourceforge/jnlp/runtime/ManifestsAttributesValidator.java netx/net/sourceforge/jnlp/util/UrlUtils.java
diffstat 4 files changed, 274 insertions(+), 193 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Mar 14 10:50:15 2014 -0400
+++ b/ChangeLog	Thu Mar 20 16:29:46 2014 +0100
@@ -1,3 +1,15 @@
+2014-03-20  Jiri Vanek  <jvanek@redhat.com>
+
+	Methods validating manifests' attributes moved to separate class.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Cleaned imports.
+	At (init) methods (checkCodebaseAttribute), (checkPermissionsAttribute) and 
+	(checkApplicationLibraryAllowableCodebaseAttribute) moved to
+	ManifestsAttributesValidator. (guessCodeBase) generalized in UrlUtils.
+	* netx/net/sourceforge/jnlp/runtime/ManifestsAttributesValidator.java:
+	new class. Contains logic to validate manifests'attributes.
+	* netx/net/sourceforge/jnlp/util/UrlUtils.java: added method (guessCodeBase)
+	as generalization of JNLPClassLoader's guessCodeBase method.
+
 2014-03-14  Andrew Azores  <aazores@redhat.com>
 
 	Added new PartiallySigned Dialog to replace NotAllSignedWarningPane.
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Fri Mar 14 10:50:15 2014 -0400
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Thu Mar 20 16:29:46 2014 +0100
@@ -64,7 +64,6 @@
 import net.sourceforge.jnlp.ExtensionDesc;
 import net.sourceforge.jnlp.JARDesc;
 import net.sourceforge.jnlp.JNLPFile;
-import net.sourceforge.jnlp.JNLPFile.ManifestBoolean;
 import net.sourceforge.jnlp.JNLPMatcher;
 import net.sourceforge.jnlp.JNLPMatcherException;
 import net.sourceforge.jnlp.LaunchDesc;
@@ -84,12 +83,8 @@
 import net.sourceforge.jnlp.security.AppVerifier;
 import net.sourceforge.jnlp.security.JNLPAppVerifier;
 import net.sourceforge.jnlp.security.PluginAppVerifier;
-import net.sourceforge.jnlp.security.SecurityDialogs;
-import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel;
-import net.sourceforge.jnlp.security.appletextendedsecurity.AppletStartupSecuritySettings;
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletTrustConfirmation;
 import net.sourceforge.jnlp.tools.JarCertVerifier;
-import net.sourceforge.jnlp.util.ClasspathMatcher.ClasspathMatchers;
 import net.sourceforge.jnlp.util.JarFile;
 import net.sourceforge.jnlp.util.StreamUtils;
 import net.sourceforge.jnlp.util.UrlUtils;
@@ -288,12 +283,11 @@
         initializePermissions();
 
         setSecurity();
-        
-        checkCodebaseAttribute();
-        
-        checkPermissionsAttribute();
-        
-        checkApplicationLibraryAllowableCodebaseAttribute();
+
+        ManifestsAttributesValidator mav = new ManifestsAttributesValidator(security, file, signing);
+        mav.checkCodebaseAttribute();
+        mav.checkPermissionsAttribute();
+        mav.checkApplicationLibraryAllowableCodebaseAttribute();
         
         installShutdownHooks();
         
@@ -319,7 +313,7 @@
     }
 
     private void setSecurity() throws LaunchException {
-        URL codebase = guessCodeBase();
+        URL codebase = UrlUtils.guessCodeBase(file);
         this.security = securityDelegate.getClassLoaderSecurity(codebase.getHost());
     }
 
@@ -2246,52 +2240,9 @@
         return mainClass;
     }
     
-    private URL guessCodeBase() {
-        if (file.getCodeBase() != null) {
-            return file.getCodeBase();
-        } else {
-            //Fixme: codebase should be the codebase of the Main Jar not
-            //the location. Although, it still works in the current state.
-            return file.getResources().getMainJAR().getLocation();
-        }
-    }
-
-    /**
-     * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#codebase
-     */
-    private void checkCodebaseAttribute() throws LaunchException {
-        if (file.getCodeBase() == null || file.getCodeBase().getProtocol().equals("file")) {
-            OutputController.getLogger().log(OutputController.Level.WARNING_ALL, Translator.R("CBCheckFile"));
-            return;
-        }
-        final Object securityType = security.getSecurityType();
-        final URL codebase = guessCodeBase();
-        final ClasspathMatchers codebaseAtt = file.getManifestsAttributes().getCodebase();
-        if (codebaseAtt == null) {
-            OutputController.getLogger().log(OutputController.Level.WARNING_ALL, Translator.R("CBCheckNoEntry"));
-            return;
-        }
-        if (securityType.equals(SecurityDesc.SANDBOX_PERMISSIONS)) {
-            if (codebaseAtt.matches(codebase)) {
-                OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Translator.R("CBCheckUnsignedPass"));
-            } else {
-                OutputController.getLogger().log(OutputController.Level.ERROR_ALL, Translator.R("CBCheckUnsignedFail"));
-            }
-        } else {
-            if (codebaseAtt.matches(codebase)) {
-                OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Translator.R("CBCheckOkSignedOk"));
-            } else {
-                if (file instanceof PluginBridge) {
-                    throw new LaunchException(Translator.R("CBCheckSignedAppletDontMatchException", file.getManifestsAttributes().getCodebase().toString(), codebase));
-                } else {
-                    OutputController.getLogger().log(OutputController.Level.ERROR_ALL, Translator.R("CBCheckSignedFail"));
-                }
-            }
-        }
-
-    }
-
-    /**
+
+
+   /**
      * SecurityDelegate, in real usage, relies on having a "parent" JNLPClassLoader instance.
      * However, JNLPClassLoaders are very large, heavyweight, difficult-to-mock objects, which
      * means that unit testing on anything that uses a SecurityDelegate can become very difficult.
@@ -2321,96 +2272,6 @@
         public boolean getRunInSandbox();
     }
 
-    private void checkApplicationLibraryAllowableCodebaseAttribute() throws LaunchException {
-        if (signing == SigningState.NONE){
-            return; /*when app is not signed at all, then skip this check*/
-        } 
-        //conditions
-        URL codebase = file.getCodeBase();
-        URL documentBase = null;
-        if (file instanceof PluginBridge) {
-            documentBase = ((PluginBridge) file).getSourceLocation();
-        }
-        if (documentBase == null) {
-            documentBase = file.getCodeBase();
-        }
-
-        //cases
-        Set<URL> usedUrls = new HashSet<URL>();
-        URL sourceLocation = file.getSourceLocation();
-        ResourcesDesc[] resourcesDescs = file.getResourcesDescs();
-        if (sourceLocation != null) {
-            usedUrls.add(UrlUtils.removeFileName(sourceLocation));
-        }
-        for (ResourcesDesc resourcesDesc: resourcesDescs) {
-            ExtensionDesc[] ex = resourcesDesc.getExtensions();
-            if (ex != null) {
-                for ( ExtensionDesc extensionDesc: ex) {
-                    if (extensionDesc != null) {
-                        usedUrls.add(UrlUtils.removeFileName(extensionDesc.getLocation()));
-                    }
-                }
-            }
-            JARDesc[] jars = resourcesDesc.getJARs();
-            if (jars != null) {
-                for (JARDesc jarDesc: jars) {
-                    if (jarDesc != null) {
-                        usedUrls.add(UrlUtils.removeFileName(jarDesc.getLocation()));
-                    }
-                }
-            }
-            JNLPFile jnlp = resourcesDesc.getJNLPFile();
-            if (jnlp != null) {
-                usedUrls.add(UrlUtils.removeFileName(jnlp.getSourceLocation()));
-            }
-
-        }
-        OutputController.getLogger().log("Found alaca URLs to be verified");
-        for (URL url : usedUrls) {
-            OutputController.getLogger().log(" - " + url.toExternalForm());
-        }
-        if (usedUrls.isEmpty()) {
-            //I hope this is the case, when the resources is/are
-            //only codebase classes. Then it should be safe to return.
-            OutputController.getLogger().log("The application is not using any url resources, skipping Application-Library-Allowable-Codebase Attribute check.");
-            return;
-        }
-
-        if (usedUrls.size() == 1) {
-            if (UrlUtils.equalsIgnoreLastSlash(usedUrls.toArray(new URL[0])[0], codebase)
-                    && UrlUtils.equalsIgnoreLastSlash(usedUrls.toArray(new URL[0])[0], documentBase)) {
-                //all resoources are from codebase or document base. it is ok to proceeed.
-                OutputController.getLogger().log("All applications resources (" + usedUrls.toArray(new URL[0])[0] + ") are from codebas/documentbase " + codebase + "/" + documentBase + ", skipping Application-Library-Allowable-Codebase Attribute check.");
-                return;
-            }
-        }
-        ClasspathMatchers att = file.getManifestsAttributes().getApplicationLibraryAllowableCodebase();
-
-        if (att == null) {
-            boolean a = SecurityDialogs.showMissingALACAttributePanel(file.getTitle(), documentBase, usedUrls);
-            if (!a) {
-                throw new LaunchException("The application uses non-codebase resources, has no Application-Library-Allowable-Codebase Attribute, and was blocked from running by the user");
-            } else {
-                OutputController.getLogger().log("The application uses non-codebase resources, has no Application-Library-Allowable-Codebase Attribute, and was allowed to run by the user");
-                return;
-            }
-        } else {
-            for (URL foundUrl : usedUrls) {
-                if (!att.matches(foundUrl)) {
-                    throw new LaunchException("The resource from " + foundUrl + " does not match the  location in Application-Library-Allowable-Codebase Attribute " + att + ". Blocking the application from running.");
-                } else {
-                    OutputController.getLogger().log("The resource from " + foundUrl + " does  match the  location in Application-Library-Allowable-Codebase Attribute " + att + ". Continuing.");
-                }
-            }
-        }
-        boolean a = SecurityDialogs.showMatchingALACAttributePanel(file.getTitle(), documentBase, usedUrls);
-        if (!a) {
-            throw new LaunchException("The application uses non-codebase resources, which do match its Application-Library-Allowable-Codebase Attribute, but was blocked from running by the user." );
-        } else {
-            OutputController.getLogger().log("The application uses non-codebase resources, which do match its Application-Library-Allowable-Codebase Attribute, and was allowed to run by the user." );
-        }
-    }
-
     /**
      * Handles security decision logic for the JNLPClassLoader, eg which permission level to assign
      * to JARs.
@@ -2547,51 +2408,6 @@
 
     }
     
-    /**
-     * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/manifest.html#permissions
-     */
-    public void checkPermissionsAttribute() throws LaunchException {
-        final ManifestBoolean permissions = file.getManifestsAttributes().isSandboxForced();
-        AppletSecurityLevel level = AppletStartupSecuritySettings.getInstance().getSecurityLevel();
-        if (level == AppletSecurityLevel.ALLOW_UNSIGNED) {
-            OutputController.getLogger().log(OutputController.Level.WARNING_ALL, "Although 'permissions' attribute of this application is '" + file.getManifestsAttributes().permissionsToString() + "' Your Extended applets security is at 'low', continuing");
-            return;
-        }
-        switch (permissions) {
-            case UNDEFINED: {
-                if (level == AppletSecurityLevel.DENY_UNSIGNED) {
-                    throw new LaunchException("Your Extended applets security is at 'Very high', and this application is missing the 'permissions' attribute in manifest. This is fatal");
-                }
-                if (level == AppletSecurityLevel.ASK_UNSIGNED) {
-                    boolean a = SecurityDialogs.showMissingPermissionsAttributeDialogue(file.getTitle(), file.getCodeBase());
-                    if (!a) {
-                        throw new LaunchException("Your Extended applets security is at 'high' and  this applicationis missing the 'permissions' attribute in manifest. And you have refused to run it.");
-                    } else {
-                        OutputController.getLogger().log("Your Extended applets security is at 'high' and  this applicationis missing the 'permissions' attribute in manifest. And you have allowed to run it.");
-                    }
-                }
-                //default for missing is sandbox
-                if (!SecurityDesc.SANDBOX_PERMISSIONS.equals(security.getSecurityType())) {
-                    throw new LaunchException("The 'permissions' attribute is not specified, and application is requesting permissions. This is fatal");
-                }
-                break;
-            }
-            case TRUE: {
-                if (SecurityDesc.SANDBOX_PERMISSIONS.equals(security.getSecurityType())) {
-                    OutputController.getLogger().log("The permissions attribute of this application is " + file.getManifestsAttributes().permissionsToString() + "' and security is '" + security.getSecurityType() + "'. Thats correct");
-                } else {
-                    throw new LaunchException("The 'permissions' attribute is '" + file.getManifestsAttributes().permissionsToString() + "' but  security is '" + security.getSecurityType() + "'. This is fatal");
-                }
-            }
-            case FALSE: {
-                if (SecurityDesc.SANDBOX_PERMISSIONS.equals(security.getSecurityType())) {
-                    throw new LaunchException("The 'permissions' attribute is '" + file.getManifestsAttributes().permissionsToString() + "' but  security is' " + security.getSecurityType() + "'. This is fatal");
-                } else {
-                    OutputController.getLogger().log("The permissions attribute of this application is '" + file.getManifestsAttributes().permissionsToString() + "' and security is '" + security.getSecurityType() + "'. Thats correct");
-                }
-            }
-        }
-    }
 
     /*
      * Helper class to expose protected URLClassLoader methods.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/runtime/ManifestsAttributesValidator.java	Thu Mar 20 16:29:46 2014 +0100
@@ -0,0 +1,242 @@
+/* 
+Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+package net.sourceforge.jnlp.runtime;
+
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
+import net.sourceforge.jnlp.ExtensionDesc;
+import net.sourceforge.jnlp.JARDesc;
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.JNLPFile.ManifestBoolean;
+import net.sourceforge.jnlp.LaunchException;
+import net.sourceforge.jnlp.PluginBridge;
+import net.sourceforge.jnlp.ResourcesDesc;
+import net.sourceforge.jnlp.SecurityDesc;
+import net.sourceforge.jnlp.runtime.JNLPClassLoader.SigningState;
+import net.sourceforge.jnlp.security.SecurityDialogs;
+import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel;
+import net.sourceforge.jnlp.security.appletextendedsecurity.AppletStartupSecuritySettings;
+import net.sourceforge.jnlp.util.ClasspathMatcher.ClasspathMatchers;
+import net.sourceforge.jnlp.util.UrlUtils;
+import net.sourceforge.jnlp.util.logging.OutputController;
+
+public class ManifestsAttributesValidator {
+
+    private final SecurityDesc security;
+    private final JNLPFile file;
+    private final SigningState signing;
+
+    public ManifestsAttributesValidator(SecurityDesc security, JNLPFile file, SigningState signing) {
+        this.security = security;
+        this.file = file;
+        this.signing = signing;
+    }
+    
+    
+
+    /**
+     * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#codebase
+     */
+    void checkCodebaseAttribute() throws LaunchException {
+        if (file.getCodeBase() == null || file.getCodeBase().getProtocol().equals("file")) {
+            OutputController.getLogger().log(OutputController.Level.WARNING_ALL, Translator.R("CBCheckFile"));
+            return;
+        }
+        final Object securityType = security.getSecurityType();
+        final URL codebase = UrlUtils.guessCodeBase(file);
+        final ClasspathMatchers codebaseAtt = file.getManifestsAttributes().getCodebase();
+        if (codebaseAtt == null) {
+            OutputController.getLogger().log(OutputController.Level.WARNING_ALL, Translator.R("CBCheckNoEntry"));
+            return;
+        }
+        if (securityType.equals(SecurityDesc.SANDBOX_PERMISSIONS)) {
+            if (codebaseAtt.matches(codebase)) {
+                OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Translator.R("CBCheckUnsignedPass"));
+            } else {
+                OutputController.getLogger().log(OutputController.Level.ERROR_ALL, Translator.R("CBCheckUnsignedFail"));
+            }
+        } else {
+            if (codebaseAtt.matches(codebase)) {
+                OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Translator.R("CBCheckOkSignedOk"));
+            } else {
+                if (file instanceof PluginBridge) {
+                    throw new LaunchException(Translator.R("CBCheckSignedAppletDontMatchException", file.getManifestsAttributes().getCodebase().toString(), codebase));
+                } else {
+                    OutputController.getLogger().log(OutputController.Level.ERROR_ALL, Translator.R("CBCheckSignedFail"));
+                }
+            }
+        }
+
+    }
+
+    /**
+     * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/manifest.html#permissions
+     */
+    void checkPermissionsAttribute() throws LaunchException {
+        final ManifestBoolean permissions = file.getManifestsAttributes().isSandboxForced();
+        AppletSecurityLevel level = AppletStartupSecuritySettings.getInstance().getSecurityLevel();
+        if (level == AppletSecurityLevel.ALLOW_UNSIGNED) {
+            OutputController.getLogger().log(OutputController.Level.WARNING_ALL, "Although 'permissions' attribute of this application is '" + file.getManifestsAttributes().permissionsToString() + "' Your Extended applets security is at 'low', continuing");
+            return;
+        }
+        switch (permissions) {
+            case UNDEFINED: {
+                if (level == AppletSecurityLevel.DENY_UNSIGNED) {
+                    throw new LaunchException("Your Extended applets security is at 'Very high', and this application is missing the 'permissions' attribute in manifest. This is fatal");
+                }
+                if (level == AppletSecurityLevel.ASK_UNSIGNED) {
+                    boolean a = SecurityDialogs.showMissingPermissionsAttributeDialogue(file.getTitle(), file.getCodeBase());
+                    if (!a) {
+                        throw new LaunchException("Your Extended applets security is at 'high' and  this applicationis missing the 'permissions' attribute in manifest. And you have refused to run it.");
+                    } else {
+                        OutputController.getLogger().log("Your Extended applets security is at 'high' and  this applicationis missing the 'permissions' attribute in manifest. And you have allowed to run it.");
+                    }
+                }
+                //default for missing is sandbox
+                if (!SecurityDesc.SANDBOX_PERMISSIONS.equals(security.getSecurityType())) {
+                    throw new LaunchException("The 'permissions' attribute is not specified, and application is requesting permissions. This is fatal");
+                }
+                break;
+            }
+            case TRUE: {
+                if (SecurityDesc.SANDBOX_PERMISSIONS.equals(security.getSecurityType())) {
+                    OutputController.getLogger().log("The permissions attribute of this application is " + file.getManifestsAttributes().permissionsToString() + "' and security is '" + security.getSecurityType() + "'. Thats correct");
+                } else {
+                    throw new LaunchException("The 'permissions' attribute is '" + file.getManifestsAttributes().permissionsToString() + "' but  security is '" + security.getSecurityType() + "'. This is fatal");
+                }
+            }
+            case FALSE: {
+                if (SecurityDesc.SANDBOX_PERMISSIONS.equals(security.getSecurityType())) {
+                    throw new LaunchException("The 'permissions' attribute is '" + file.getManifestsAttributes().permissionsToString() + "' but  security is' " + security.getSecurityType() + "'. This is fatal");
+                } else {
+                    OutputController.getLogger().log("The permissions attribute of this application is '" + file.getManifestsAttributes().permissionsToString() + "' and security is '" + security.getSecurityType() + "'. Thats correct");
+                }
+            }
+        }
+    }
+
+    void checkApplicationLibraryAllowableCodebaseAttribute() throws LaunchException {
+        if (signing == SigningState.NONE) {
+            return; /*when app is not signed at all, then skip this check*/
+        }
+        //conditions
+        URL codebase = file.getCodeBase();
+        URL documentBase = null;
+        if (file instanceof PluginBridge) {
+            documentBase = ((PluginBridge) file).getSourceLocation();
+        }
+        if (documentBase == null) {
+            documentBase = file.getCodeBase();
+        }
+
+        //cases
+        Set<URL> usedUrls = new HashSet<URL>();
+        URL sourceLocation = file.getSourceLocation();
+        ResourcesDesc[] resourcesDescs = file.getResourcesDescs();
+        if (sourceLocation != null) {
+            usedUrls.add(UrlUtils.removeFileName(sourceLocation));
+        }
+        for (ResourcesDesc resourcesDesc : resourcesDescs) {
+            ExtensionDesc[] ex = resourcesDesc.getExtensions();
+            if (ex != null) {
+                for (ExtensionDesc extensionDesc : ex) {
+                    if (extensionDesc != null) {
+                        usedUrls.add(UrlUtils.removeFileName(extensionDesc.getLocation()));
+                    }
+                }
+            }
+            JARDesc[] jars = resourcesDesc.getJARs();
+            if (jars != null) {
+                for (JARDesc jarDesc : jars) {
+                    if (jarDesc != null) {
+                        usedUrls.add(UrlUtils.removeFileName(jarDesc.getLocation()));
+                    }
+                }
+            }
+            JNLPFile jnlp = resourcesDesc.getJNLPFile();
+            if (jnlp != null) {
+                usedUrls.add(UrlUtils.removeFileName(jnlp.getSourceLocation()));
+            }
+
+        }
+        OutputController.getLogger().log("Found alaca URLs to be verified");
+        for (URL url : usedUrls) {
+            OutputController.getLogger().log(" - " + url.toExternalForm());
+        }
+        if (usedUrls.isEmpty()) {
+            //I hope this is the case, when the resources is/are
+            //only codebase classes. Then it should be safe to return.
+            OutputController.getLogger().log("The application is not using any url resources, skipping Application-Library-Allowable-Codebase Attribute check.");
+            return;
+        }
+
+        if (usedUrls.size() == 1) {
+            if (UrlUtils.equalsIgnoreLastSlash(usedUrls.toArray(new URL[0])[0], codebase)
+                    && UrlUtils.equalsIgnoreLastSlash(usedUrls.toArray(new URL[0])[0], documentBase)) {
+                //all resoources are from codebase or document base. it is ok to proceeed.
+                OutputController.getLogger().log("All applications resources (" + usedUrls.toArray(new URL[0])[0] + ") are from codebas/documentbase " + codebase + "/" + documentBase + ", skipping Application-Library-Allowable-Codebase Attribute check.");
+                return;
+            }
+        }
+        ClasspathMatchers att = file.getManifestsAttributes().getApplicationLibraryAllowableCodebase();
+
+        if (att == null) {
+            boolean a = SecurityDialogs.showMissingALACAttributePanel(file.getTitle(), documentBase, usedUrls);
+            if (!a) {
+                throw new LaunchException("The application uses non-codebase resources, has no Application-Library-Allowable-Codebase Attribute, and was blocked from running by the user");
+            } else {
+                OutputController.getLogger().log("The application uses non-codebase resources, has no Application-Library-Allowable-Codebase Attribute, and was allowed to run by the user");
+                return;
+            }
+        } else {
+            for (URL foundUrl : usedUrls) {
+                if (!att.matches(foundUrl)) {
+                    throw new LaunchException("The resource from " + foundUrl + " does not match the  location in Application-Library-Allowable-Codebase Attribute " + att + ". Blocking the application from running.");
+                } else {
+                    OutputController.getLogger().log("The resource from " + foundUrl + " does  match the  location in Application-Library-Allowable-Codebase Attribute " + att + ". Continuing.");
+                }
+            }
+        }
+        boolean a = SecurityDialogs.showMatchingALACAttributePanel(file.getTitle(), documentBase, usedUrls);
+        if (!a) {
+            throw new LaunchException("The application uses non-codebase resources, which do match its Application-Library-Allowable-Codebase Attribute, but was blocked from running by the user.");
+        } else {
+            OutputController.getLogger().log("The application uses non-codebase resources, which do match its Application-Library-Allowable-Codebase Attribute, and was allowed to run by the user.");
+        }
+    }
+}
--- a/netx/net/sourceforge/jnlp/util/UrlUtils.java	Fri Mar 14 10:50:15 2014 -0400
+++ b/netx/net/sourceforge/jnlp/util/UrlUtils.java	Thu Mar 20 16:29:46 2014 +0100
@@ -46,6 +46,7 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLDecoder;
+import net.sourceforge.jnlp.JNLPFile;
 
 public class UrlUtils {
     private static final String UTF8 = "utf-8";
@@ -258,4 +259,14 @@
             throw new RuntimeException(ex);
         }
     }
+
+     public static URL guessCodeBase(JNLPFile file) {
+        if (file.getCodeBase() != null) {
+            return file.getCodeBase();
+        } else {
+            //Fixme: codebase should be the codebase of the Main Jar not
+            //the location. Although, it still works in the current state.
+            return file.getResources().getMainJAR().getLocation();
+        }
+    }
 }