changeset in /hg/icedtea: Security patches for netx+plugin.
Andrew John Hughes
ahughes at redhat.com
Wed Aug 5 07:19:55 PDT 2009
changeset 77ea95965bad in /hg/icedtea
details: http://icedtea.classpath.org/hg/icedtea?cmd=changeset;node=77ea95965bad
description:
Security patches for netx+plugin.
2009-08-05 Lillian Angel <langel at redhat.com>
* plugin/icedtea/netscape/javascript/JSObject.java: Security patch
applied to disallow the ability to run unsigned code as
signed under some cases.
* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java:
Likewise.
* netx/net/sourceforge/jnlp/SecurityDesc.java: Likewise.
* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Likewise.
* plugin/icedtea/netscape/javascript/JSObjectCreatePermission.java:
Likewise.
* netx/netscape/javascript/JSObjectCreatePermission.java: Likewise.
diffstat:
7 files changed, 360 insertions(+), 180 deletions(-)
ChangeLog | 13
netx/net/sourceforge/jnlp/SecurityDesc.java | 24
netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java | 366 +++++-----
netx/netscape/javascript/JSObjectCreatePermission.java | 47 +
plugin/icedtea/netscape/javascript/JSObject.java | 37 -
plugin/icedtea/netscape/javascript/JSObjectCreatePermission.java | 47 +
plugin/icedtea/sun/applet/PluginAppletSecurityContext.java | 6
diffs (truncated from 826 to 500 lines):
diff -r adadd58eff31 -r 77ea95965bad ChangeLog
--- a/ChangeLog Wed Aug 05 15:02:51 2009 +0100
+++ b/ChangeLog Wed Aug 05 15:22:13 2009 +0100
@@ -1,3 +1,16 @@ 2009-08-04 Andrew John Hughes <ahughes
+2009-08-05 Lillian Angel <langel at redhat.com>
+
+ * plugin/icedtea/netscape/javascript/JSObject.java: Security patch
+ applied to disallow the ability to run unsigned code as
+ signed under some cases.
+ * plugin/icedtea/sun/applet/PluginAppletSecurityContext.java:
+ Likewise.
+ * netx/net/sourceforge/jnlp/SecurityDesc.java: Likewise.
+ * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Likewise.
+ * plugin/icedtea/netscape/javascript/JSObjectCreatePermission.java:
+ Likewise.
+ * netx/netscape/javascript/JSObjectCreatePermission.java: Likewise.
+
2009-08-04 Andrew John Hughes <ahughes at redhat.com>
* Makefile.am:
diff -r adadd58eff31 -r 77ea95965bad netx/net/sourceforge/jnlp/SecurityDesc.java
--- a/netx/net/sourceforge/jnlp/SecurityDesc.java Wed Aug 05 15:02:51 2009 +0100
+++ b/netx/net/sourceforge/jnlp/SecurityDesc.java Wed Aug 05 15:22:13 2009 +0100
@@ -166,6 +166,30 @@ public class SecurityDesc {
return permissions;
}
+
+ /**
+ * Returns a PermissionCollection containing the sandbox permissions
+ */
+ public PermissionCollection getSandBoxPermissions() {
+
+ Permissions permissions = new Permissions();
+
+ for (int i=0; i < sandboxPermissions.length; i++)
+ permissions.add(sandboxPermissions[i]);
+
+ if (downloadHost != null)
+ permissions.add(new SocketPermission(downloadHost,
+ "connect, accept"));
+
+ // properties
+ PropertyDesc props[] = file.getResources().getProperties();
+ for (int i=0; i < props.length; i++) {
+ // should only allow jnlp.* properties if in sandbox?
+ permissions.add(new PropertyPermission(props[i].getKey(), "read,write"));
+ }
+
+ return permissions;
+ }
}
diff -r adadd58eff31 -r 77ea95965bad netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Wed Aug 05 15:02:51 2009 +0100
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Wed Aug 05 15:22:13 2009 +0100
@@ -1,15 +1,15 @@
-//
+//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
-//
+//
// This library 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
// Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@@ -66,7 +66,7 @@ import sun.misc.JarIndex;
* security context when the classloader was created.
*
* @author <a href="mailto:jmaxwell at users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
- * @version $Revision: 1.20 $
+ * @version $Revision: 1.20 $
*/
public class JNLPClassLoader extends URLClassLoader {
@@ -115,29 +115,29 @@ public class JNLPClassLoader extends URL
/** the security section */
private SecurityDesc security;
-
+
/** Permissions granted by the user during runtime. */
private ArrayList<Permission> runtimePermissions = new ArrayList<Permission>();
/** all jars not yet part of classloader or active */
private List available = new ArrayList();
- /** all of the jar files that were verified */
- private ArrayList<String> verifiedJars = null;
-
- /** all of the jar files that were not verified */
- private ArrayList<String> unverifiedJars = null;
-
- /** the jarsigner tool to verify our jars */
- private JarSigner js = null;
-
- private boolean signing = false;
-
- /** ArrayList containing jar indexes for various jars available to this classloader */
- private ArrayList<JarIndex> jarIndexes = new ArrayList<JarIndex>();
-
- /** File entries in the jar files available to this classloader */
- private TreeSet jarEntries = new TreeSet();
+ /** all of the jar files that were verified */
+ private ArrayList<String> verifiedJars = null;
+
+ /** all of the jar files that were not verified */
+ private ArrayList<String> unverifiedJars = null;
+
+ /** the jarsigner tool to verify our jars */
+ private JarSigner js = null;
+
+ private boolean signing = false;
+
+ /** ArrayList containing jar indexes for various jars available to this classloader */
+ private ArrayList<JarIndex> jarIndexes = new ArrayList<JarIndex>();
+
+ /** File entries in the jar files available to this classloader */
+ private TreeSet jarEntries = new TreeSet();
/**
* Create a new JNLPClassLoader from the specified file.
@@ -167,41 +167,41 @@ public class JNLPClassLoader extends URL
}
private void setSecurity() {
- /**
- * When we're trying to load an applet, file.getSecurity() will return
- * null since there is no jnlp file to specify permissions. We
- * determine security settings here, after trying to verify jars.
- */
- if (file instanceof PluginBridge) {
- if (signing == true) {
- this.security = new SecurityDesc(file,
- SecurityDesc.ALL_PERMISSIONS,
- file.getCodeBase().getHost());
- } else {
- this.security = new SecurityDesc(file,
- SecurityDesc.SANDBOX_PERMISSIONS,
- file.getCodeBase().getHost());
- }
- } else { //regular jnlp file
-
- /**
- * If the application is signed, then we set the SecurityDesc to the
- * <security> tag in the jnlp file. Note that if an application is
- * signed, but there is no <security> tag in the jnlp file, the
- * application will get sandbox permissions.
- * If the application is unsigned, we ignore the <security> tag and
- * use a sandbox instead.
- */
- if (signing == true) {
- this.security = file.getSecurity();
- } else {
- this.security = new SecurityDesc(file,
- SecurityDesc.SANDBOX_PERMISSIONS,
- file.getCodeBase().getHost());
- }
- }
- }
-
+ /**
+ * When we're trying to load an applet, file.getSecurity() will return
+ * null since there is no jnlp file to specify permissions. We
+ * determine security settings here, after trying to verify jars.
+ */
+ if (file instanceof PluginBridge) {
+ if (signing == true) {
+ this.security = new SecurityDesc(file,
+ SecurityDesc.ALL_PERMISSIONS,
+ file.getCodeBase().getHost());
+ } else {
+ this.security = new SecurityDesc(file,
+ SecurityDesc.SANDBOX_PERMISSIONS,
+ file.getCodeBase().getHost());
+ }
+ } else { //regular jnlp file
+
+ /**
+ * If the application is signed, then we set the SecurityDesc to the
+ * <security> tag in the jnlp file. Note that if an application is
+ * signed, but there is no <security> tag in the jnlp file, the
+ * application will get sandbox permissions.
+ * If the application is unsigned, we ignore the <security> tag and
+ * use a sandbox instead.
+ */
+ if (signing == true) {
+ this.security = file.getSecurity();
+ } else {
+ this.security = new SecurityDesc(file,
+ SecurityDesc.SANDBOX_PERMISSIONS,
+ file.getCodeBase().getHost());
+ }
+ }
+ }
+
/**
* Returns a JNLP classloader for the specified JNLP file.
*
@@ -215,12 +215,12 @@ public class JNLPClassLoader extends URL
if (location != null)
loader = (JNLPClassLoader) urlToLoader.get(location);
- try {
- if (loader == null)
- loader = new JNLPClassLoader(file, policy);
- } catch (LaunchException e) {
- throw e;
- }
+ try {
+ if (loader == null)
+ loader = new JNLPClassLoader(file, policy);
+ } catch (LaunchException e) {
+ throw e;
+ }
if (file.getInformation().isSharingAllowed())
urlToLoader.put(location, loader);
@@ -230,7 +230,7 @@ public class JNLPClassLoader extends URL
/**
* Returns a JNLP classloader for the JNLP file at the specified
- * location.
+ * location.
*
* @param location the file's location
* @param version the file's version
@@ -256,17 +256,17 @@ public class JNLPClassLoader extends URL
loaderList.add(this);
- //if (ext != null) {
- for (int i=0; i < ext.length; i++) {
- try {
- JNLPClassLoader loader = getInstance(ext[i].getLocation(), ext[i].getVersion(), updatePolicy);
- loaderList.add(loader);
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- //}
+ //if (ext != null) {
+ for (int i=0; i < ext.length; i++) {
+ try {
+ JNLPClassLoader loader = getInstance(ext[i].getLocation(), ext[i].getVersion(), updatePolicy);
+ loaderList.add(loader);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ //}
loaders = (JNLPClassLoader[]) loaderList.toArray(new JNLPClassLoader[ loaderList.size()]);
}
@@ -283,10 +283,10 @@ public class JNLPClassLoader extends URL
jars[i].getVersion());
if (JNLPRuntime.isDebug()) {
- if (p == null)
- System.out.println("Unable to add permission for " + jars[i].getLocation());
- else
- System.out.println("Permission added: " + p.toString());
+ if (p == null)
+ System.out.println("Unable to add permission for " + jars[i].getLocation());
+ else
+ System.out.println("Permission added: " + p.toString());
}
if (p != null)
resourcePermissions.add(p);
@@ -299,14 +299,14 @@ public class JNLPClassLoader extends URL
*/
void initializeResources() throws LaunchException {
JARDesc jars[] = resources.getJARs();
- if (jars == null || jars.length == 0)
- return;
- /*
- if (jars == null || jars.length == 0) {
- throw new LaunchException(null, null, R("LSFatal"),
- R("LCInit"), R("LFatalVerification"), "No jars!");
- }
- */
+ if (jars == null || jars.length == 0)
+ return;
+ /*
+ if (jars == null || jars.length == 0) {
+ throw new LaunchException(null, null, R("LSFatal"),
+ R("LCInit"), R("LFatalVerification"), "No jars!");
+ }
+ */
List initialJars = new ArrayList();
for (int i=0; i < jars.length; i++) {
@@ -317,7 +317,7 @@ public class JNLPClassLoader extends URL
initialJars.add(jars[i]); // regardless of part
tracker.addResource(jars[i].getLocation(),
- jars[i].getVersion(),
+ jars[i].getVersion(),
jars[i].isCacheable() ? JNLPRuntime.getDefaultUpdatePolicy() : UpdatePolicy.FORCE
);
}
@@ -325,42 +325,42 @@ public class JNLPClassLoader extends URL
if (strict)
fillInPartJars(initialJars); // add in each initial part's lazy jars
- if (JNLPRuntime.isVerifying()) {
-
- JarSigner js;
- waitForJars(initialJars); //download the jars first.
-
- try {
- js = verifyJars(initialJars);
- } catch (Exception e) {
- //we caught an Exception from the JarSigner class.
- //Note: one of these exceptions could be from not being able
- //to read the cacerts or trusted.certs files.
- e.printStackTrace();
- throw new LaunchException(null, null, R("LSFatal"),
- R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo"));
- }
-
- //Case when at least one jar has some signing
- if (js.anyJarsSigned()){
- signing = true;
-
- //user does not trust this publisher
- if (!js.getAlreadyTrustPublisher()) {
- checkTrustWithUser(js);
- } else {
- /**
- * If the user trusts this publisher (i.e. the publisher's certificate
- * is in the user's trusted.certs file), we do not show any dialogs.
- */
- }
- } else {
-
- signing = false;
- //otherwise this jar is simply unsigned -- make sure to ask
- //for permission on certain actions
- }
- }
+ if (JNLPRuntime.isVerifying()) {
+
+ JarSigner js;
+ waitForJars(initialJars); //download the jars first.
+
+ try {
+ js = verifyJars(initialJars);
+ } catch (Exception e) {
+ //we caught an Exception from the JarSigner class.
+ //Note: one of these exceptions could be from not being able
+ //to read the cacerts or trusted.certs files.
+ e.printStackTrace();
+ throw new LaunchException(null, null, R("LSFatal"),
+ R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo"));
+ }
+
+ //Case when at least one jar has some signing
+ if (js.anyJarsSigned()){
+ signing = true;
+
+ //user does not trust this publisher
+ if (!js.getAlreadyTrustPublisher()) {
+ checkTrustWithUser(js);
+ } else {
+ /**
+ * If the user trusts this publisher (i.e. the publisher's certificate
+ * is in the user's trusted.certs file), we do not show any dialogs.
+ */
+ }
+ } else {
+
+ signing = false;
+ //otherwise this jar is simply unsigned -- make sure to ask
+ //for permission on certain actions
+ }
+ }
activateJars(initialJars);
}
@@ -370,7 +370,7 @@ public class JNLPClassLoader extends URL
boolean b = SecurityWarningDialog.showCertWarningDialog(
SecurityWarningDialog.AccessType.UNVERIFIED, file, js);
if (!b)
- throw new LaunchException(null, null, R("LSFatal"),
+ throw new LaunchException(null, null, R("LSFatal"),
R("LCLaunching"), R("LNotVerified"), "");
} else if (js.getRootInCacerts()) { //root cert is in cacerts
boolean b = false;
@@ -435,11 +435,29 @@ public class JNLPClassLoader extends URL
// access w/o security dialog once we actually check certificates.
// copy security permissions from SecurityDesc element
- if (security != null) {
- Enumeration e = security.getPermissions().elements();
- while (e.hasMoreElements())
- result.add((Permission) e.nextElement());
- }
+ if (security != null) {
+ // Security desc. is used only to track security settings for the
+ // application. However, an application may comprise of multiple
+ // jars, and as such, security must be evaluated on a per jar basis.
+
+ // set default perms
+ PermissionCollection permissions = security.getSandBoxPermissions();
+
+ // If more than default is needed, evaluate based on codesource
+ if (security.getSecurityType().equals(SecurityDesc.ALL_PERMISSIONS) ||
+ security.getSecurityType().equals(SecurityDesc.J2EE_PERMISSIONS)) {
+
+ if (cs.getCodeSigners() != null) {
+ permissions = security.getPermissions();
+ }
+ }
+
+ Enumeration<Permission> e = permissions.elements();
+ while (e.hasMoreElements())
+ result.add(e.nextElement());
+ }
+
+
// add in permission to read the cached JAR files
for (int i=0; i < resourcePermissions.size(); i++)
@@ -447,15 +465,15 @@ public class JNLPClassLoader extends URL
// add in the permissions that the user granted.
for (int i=0; i < runtimePermissions.size(); i++)
- result.add(runtimePermissions.get(i));
+ result.add(runtimePermissions.get(i));
return result;
}
protected void addPermission(Permission p) {
- runtimePermissions.add(p);
- }
-
+ runtimePermissions.add(p);
+ }
+
/**
* Adds to the specified list of JARS any other JARs that need
* to be loaded at the same time as the JARs specified (ie, are
@@ -501,25 +519,25 @@ public class JNLPClassLoader extends URL
URL location = jar.getLocation(); // non-cacheable, use source location
if (localFile != null) {
location = localFile.toURL(); // cached file
-
- // This is really not the best way.. but we need some way for
- // PluginAppletViewer::getCachedImageRef() to check if the image
- // is available locally, and it cannot use getResources() because
- // that prefetches the resource, which confuses MediaTracker.waitForAll()
- // which does a wait(), waiting for notification (presumably
+
+ // This is really not the best way.. but we need some way for
+ // PluginAppletViewer::getCachedImageRef() to check if the image
+ // is available locally, and it cannot use getResources() because
+ // that prefetches the resource, which confuses MediaTracker.waitForAll()
+ // which does a wait(), waiting for notification (presumably
// thrown after a resource is fetched). This bug manifests itself
// particularly when using The FileManager applet from Webmin.
-
+
JarFile jarFile = new JarFile(localFile);
Enumeration e = jarFile.entries();
while (e.hasMoreElements()) {
-
+
JarEntry je = (JarEntry) e.nextElement();
-
- // another jar in my jar? it is more likely than you think
+
+ // another jar in my jar? it is more likely than you think
if (je.getName().endsWith(".jar")) {
- // We need to extract that jar so that it can be loaded
- // (inline loading with "jar:..!/..." path will not work
+ // We need to extract that jar so that it can be loaded
+ // (inline loading with "jar:..!/..." path will not work
// with standard classloader methods)
String extractedJarLocation = localFile.getParent() + "/" + je.getName();
@@ -564,7 +582,7 @@ public class JNLPClassLoader extends URL
addURL(location);
- // there is currently no mechanism to cache files per
+ // there is currently no mechanism to cache files per
More information about the distro-pkg-dev
mailing list