# HG changeset patch # User Jiri Vanek # Date 1444299109 -7200 # Node ID 2b1af623e3a8b3e8f1a543c6aa00abdfa73396df # Parent cbc3174bed987ef58d2bbeb6fa8cbe8a87675fbe All connection restrictions now consider also port diff -r cbc3174bed98 -r 2b1af623e3a8 ChangeLog --- a/ChangeLog Fri Oct 02 15:35:30 2015 +0200 +++ b/ChangeLog Thu Oct 08 12:11:49 2015 +0200 @@ -1,3 +1,20 @@ +2015-10-07 Jiri Vanek + + All connection restrictions now consider also port + * NEWS: mentioned restriction about ports + * netx/net/sourceforge/jnlp/SecurityDesc.java: downloadHost redeclared to URL + and made final. All set/gets adapted + * netx/net/sourceforge/jnlp/Parser.java: (base) passes url to SecurityDesc + * netx/net/sourceforge/jnlp/PluginBridge.java: (PluginBridge) same + * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: same + * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java: (getApplet) + (getApplets) same + * netx/net/sourceforge/jnlp/util/UrlUtils.java: added methods sanitizePort and + getPort, which always returns port. If no port goes in, default port is going + out. Added getHostAndPort which returns host also with port. + * tests/netx/unit/net/sourceforge/jnlp/SecurityDescTest.java: adapted to new api + * tests/netx/unit/net/sourceforge/jnlp/util/UrlUtilsTest.java: tested new methods + 2015-10-02 Jiri Vanek Fixed possible segfault during files on and debug on diff -r cbc3174bed98 -r 2b1af623e3a8 NEWS --- a/NEWS Fri Oct 02 15:35:30 2015 +0200 +++ b/NEWS Thu Oct 08 12:11:49 2015 +0200 @@ -9,6 +9,7 @@ CVE-XXXX-YYYY: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=XXXX-YYYY New in release 1.6.2 (YYYY-MM-DD): +* all connection restrictions now consider also port New in release 1.6.1 (2015-09-11): * Enabled Entry-Point attribute check diff -r cbc3174bed98 -r 2b1af623e3a8 netx/net/sourceforge/jnlp/Parser.java --- a/netx/net/sourceforge/jnlp/Parser.java Fri Oct 02 15:35:30 2015 +0200 +++ b/netx/net/sourceforge/jnlp/Parser.java Thu Oct 08 12:11:49 2015 +0200 @@ -622,7 +622,7 @@ } if (base != null) { - return new SecurityDesc(file, requestedPermissionLevel, type, base.getHost()); + return new SecurityDesc(file, requestedPermissionLevel, type, base); } else { return new SecurityDesc(file, requestedPermissionLevel, type, null); } diff -r cbc3174bed98 -r 2b1af623e3a8 netx/net/sourceforge/jnlp/PluginBridge.java --- a/netx/net/sourceforge/jnlp/PluginBridge.java Fri Oct 02 15:35:30 2015 +0200 +++ b/netx/net/sourceforge/jnlp/PluginBridge.java Thu Oct 08 12:11:49 2015 +0200 @@ -224,7 +224,7 @@ if (main.endsWith(".class")) //single class file only security = new SecurityDesc(this, SecurityDesc.SANDBOX_PERMISSIONS, - codebase.getHost()); + codebase); else security = null; diff -r cbc3174bed98 -r 2b1af623e3a8 netx/net/sourceforge/jnlp/SecurityDesc.java --- a/netx/net/sourceforge/jnlp/SecurityDesc.java Fri Oct 02 15:35:30 2015 +0200 +++ b/netx/net/sourceforge/jnlp/SecurityDesc.java Thu Oct 08 12:11:49 2015 +0200 @@ -22,6 +22,7 @@ import java.net.SocketPermission; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.security.AllPermission; import java.security.CodeSource; import java.security.Permission; @@ -33,6 +34,7 @@ import net.sourceforge.jnlp.config.DeploymentConfiguration; import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.util.UrlUtils; import net.sourceforge.jnlp.util.logging.OutputController; /** @@ -132,7 +134,7 @@ private Object type; /** the download host */ - private String downloadHost; + final private URL downloadHost; /** whether sandbox applications should get the show window without banner permission */ private final boolean grantAwtPermissions; @@ -256,7 +258,7 @@ * @param type the type of security * @param downloadHost the download host (can always connect to) */ - public SecurityDesc(JNLPFile file, RequestedPermissionLevel requestedPermissionLevel, Object type, String downloadHost) { + public SecurityDesc(JNLPFile file, RequestedPermissionLevel requestedPermissionLevel, Object type, URL downloadHost) { if (file == null) { throw new NullJnlpFileException(); } @@ -278,7 +280,7 @@ * @param type the type of security * @param downloadHost the download host (can always connect to) */ - public SecurityDesc(JNLPFile file, Object type, String downloadHost) { + public SecurityDesc(JNLPFile file, Object type, URL downloadHost) { this(file, RequestedPermissionLevel.NONE, type, downloadHost); } @@ -375,9 +377,10 @@ } } - if (downloadHost != null && downloadHost.length() > 0) - permissions.add(new SocketPermission(downloadHost, - "connect, accept")); + if (downloadHost != null && downloadHost.getHost().length() > 0) { + permissions.add(new SocketPermission(UrlUtils.getHostAndPort(downloadHost), + "connect, accept")); + } final Collection urlPermissions = getUrlPermissions(); for (final Permission permission : urlPermissions) { diff -r cbc3174bed98 -r 2b1af623e3a8 netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Fri Oct 02 15:35:30 2015 +0200 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Thu Oct 08 12:11:49 2015 +0200 @@ -318,7 +318,7 @@ private void setSecurity() throws LaunchException { URL codebase = UrlUtils.guessCodeBase(file); - this.security = securityDelegate.getClassLoaderSecurity(codebase.getHost()); + this.security = securityDelegate.getClassLoaderSecurity(codebase); } /** @@ -754,7 +754,7 @@ validJars.add(jarDesc); final URL codebase = getJnlpFileCodebase(); - final SecurityDesc jarSecurity = securityDelegate.getCodebaseSecurityDesc(jarDesc, codebase.getHost()); + final SecurityDesc jarSecurity = securityDelegate.getCodebaseSecurityDesc(jarDesc, codebase); if (jarSecurity.getSecurityType().equals(SecurityDesc.SANDBOX_PERMISSIONS)) { containsUnsignedJar = true; } else { @@ -778,7 +778,7 @@ for (JARDesc jarDesc : validJars) { final URL codebase = getJnlpFileCodebase(); - final SecurityDesc jarSecurity = securityDelegate.getCodebaseSecurityDesc(jarDesc, codebase.getHost()); + final SecurityDesc jarSecurity = securityDelegate.getCodebaseSecurityDesc(jarDesc, codebase); jarLocationSecurityMap.put(jarDesc.getLocation(), jarSecurity); } @@ -1188,7 +1188,7 @@ // Class from host X should be allowed to connect to host X if (cs.getLocation() != null && cs.getLocation().getHost().length() > 0) - result.add(new SocketPermission(cs.getLocation().getHost(), + result.add(new SocketPermission(UrlUtils.getHostAndPort(cs.getLocation()), "connect, accept")); return result; @@ -1302,7 +1302,7 @@ codebase = file.getResources().getMainJAR().getLocation(); } - final SecurityDesc jarSecurity = securityDelegate.getJarPermissions(codebase.getHost()); + final SecurityDesc jarSecurity = securityDelegate.getJarPermissions(codebase); try { URL fileURL = new URL("file://" + extractedJarLocation); @@ -1630,7 +1630,7 @@ checkTrustWithUser(); - final SecurityDesc security = securityDelegate.getJarPermissions(file.getCodeBase().getHost()); + final SecurityDesc security = securityDelegate.getJarPermissions(file.getCodeBase()); jarLocationSecurityMap.put(remoteURL, security); @@ -2249,7 +2249,7 @@ // Permissions for all remote hosting urls synchronized (jarLocationSecurityMap) { for (URL u : jarLocationSecurityMap.keySet()) { - permissions.add(new SocketPermission(u.getHost(), + permissions.add(new SocketPermission(UrlUtils.getHostAndPort(u), "connect, accept")); } } @@ -2257,7 +2257,7 @@ // Permissions for codebase urls (if there is a loader) if (codeBaseLoader != null) { for (URL u : codeBaseLoader.getURLs()) { - permissions.add(new SocketPermission(u.getHost(), + permissions.add(new SocketPermission(UrlUtils.getHostAndPort(u), "connect, accept")); } } @@ -2290,11 +2290,11 @@ public boolean userPromptedForSandbox(); - public SecurityDesc getCodebaseSecurityDesc(final JARDesc jarDesc, final String codebaseHost); - - public SecurityDesc getClassLoaderSecurity(final String codebaseHost) throws LaunchException; - - public SecurityDesc getJarPermissions(final String codebaseHost); + public SecurityDesc getCodebaseSecurityDesc(final JARDesc jarDesc, final URL codebaseHost); + + public SecurityDesc getClassLoaderSecurity(final URL codebaseHost) throws LaunchException; + + public SecurityDesc getJarPermissions(final URL codebaseHost); public void promptUserOnPartialSigning() throws LaunchException; @@ -2331,7 +2331,7 @@ } @Override - public SecurityDesc getCodebaseSecurityDesc(final JARDesc jarDesc, final String codebaseHost) { + public SecurityDesc getCodebaseSecurityDesc(final JARDesc jarDesc, final URL codebaseHost) { if (runInSandbox) { return new SecurityDesc(classLoader.file, SecurityDesc.SANDBOX_PERMISSIONS, @@ -2361,7 +2361,7 @@ } @Override - public SecurityDesc getClassLoaderSecurity(final String codebaseHost) throws LaunchException { + public SecurityDesc getClassLoaderSecurity(final URL codebaseHost) throws LaunchException { if (isPluginApplet()) { if (!runInSandbox && classLoader.getSigning()) { return new SecurityDesc(classLoader.file, @@ -2403,7 +2403,7 @@ } @Override - public SecurityDesc getJarPermissions(final String codebaseHost) { + public SecurityDesc getJarPermissions(final URL codebaseHost) { if (!runInSandbox && classLoader.jcv.isFullySigned()) { // Already trust application, nested jar should be given return new SecurityDesc(classLoader.file, diff -r cbc3174bed98 -r 2b1af623e3a8 netx/net/sourceforge/jnlp/util/UrlUtils.java --- a/netx/net/sourceforge/jnlp/util/UrlUtils.java Fri Oct 02 15:35:30 2015 +0200 +++ b/netx/net/sourceforge/jnlp/util/UrlUtils.java Thu Oct 08 12:11:49 2015 +0200 @@ -332,7 +332,19 @@ } } + public static int getSanitizedPort(final URL u) { + if (u.getPort() < 0) { + return u.getDefaultPort(); + } + return u.getPort(); + } + public static int getPort(final URL url) { + return getSanitizedPort(url); + } + public static String getHostAndPort(final URL url) { + return url.getHost() + ":" + getSanitizedPort(url); + } } diff -r cbc3174bed98 -r 2b1af623e3a8 plugin/icedteanp/java/sun/applet/PluginAppletViewer.java --- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java Fri Oct 02 15:35:30 2015 +0200 +++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java Thu Oct 08 12:11:49 2015 +0200 @@ -113,6 +113,7 @@ import net.sourceforge.jnlp.splashscreen.SplashController; import net.sourceforge.jnlp.splashscreen.SplashPanel; import net.sourceforge.jnlp.splashscreen.SplashUtils; +import net.sourceforge.jnlp.util.UrlUtils; import net.sourceforge.jnlp.util.logging.OutputController; import sun.awt.AppContext; import sun.awt.SunToolkit; @@ -887,7 +888,7 @@ public Applet getApplet(String name) { name = name.toLowerCase(); SocketPermission panelSp = - new SocketPermission(panel.getCodeBase().getHost(), "connect"); + new SocketPermission(UrlUtils.getHostAndPort(panel.getCodeBase()), "connect"); synchronized(appletPanels) { for (Enumeration e = appletPanels.elements(); e.hasMoreElements();) { AppletPanel p = e.nextElement(); @@ -899,7 +900,7 @@ p.getDocumentBase().equals(panel.getDocumentBase())) { SocketPermission sp = - new SocketPermission(p.getCodeBase().getHost(), "connect"); + new SocketPermission(UrlUtils.getHostAndPort(p.getCodeBase()), "connect"); if (panelSp.implies(sp)) { return p.applet; @@ -918,7 +919,7 @@ public Enumeration getApplets() { Vector v = new Vector(); SocketPermission panelSp = - new SocketPermission(panel.getCodeBase().getHost(), "connect"); + new SocketPermission(UrlUtils.getHostAndPort(panel.getCodeBase()), "connect"); synchronized(appletPanels) { for (Enumeration e = appletPanels.elements(); e.hasMoreElements();) { @@ -926,7 +927,7 @@ if (p.getDocumentBase().equals(panel.getDocumentBase())) { SocketPermission sp = - new SocketPermission(p.getCodeBase().getHost(), "connect"); + new SocketPermission(UrlUtils.getHostAndPort(p.getCodeBase()), "connect"); if (panelSp.implies(sp)) { v.addElement(p.applet); } diff -r cbc3174bed98 -r 2b1af623e3a8 tests/netx/unit/net/sourceforge/jnlp/SecurityDescTest.java --- a/tests/netx/unit/net/sourceforge/jnlp/SecurityDescTest.java Fri Oct 02 15:35:30 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/SecurityDescTest.java Thu Oct 08 12:11:49 2015 +0200 @@ -48,7 +48,7 @@ public void testNotNullJnlpFile() throws Exception { Throwable t = null; try { - new SecurityDesc(new DummyJNLPFile(), SecurityDesc.SANDBOX_PERMISSIONS, "hey!"); + new SecurityDesc(new DummyJNLPFile(), SecurityDesc.SANDBOX_PERMISSIONS, null); } catch (Exception ex) { t = ex; } @@ -57,7 +57,7 @@ @Test(expected = NullPointerException.class) public void testNullJnlpFile() throws Exception { - new SecurityDesc(null, SecurityDesc.SANDBOX_PERMISSIONS, "hey!"); + new SecurityDesc(null, SecurityDesc.SANDBOX_PERMISSIONS, null); } @Test diff -r cbc3174bed98 -r 2b1af623e3a8 tests/netx/unit/net/sourceforge/jnlp/util/UrlUtilsTest.java --- a/tests/netx/unit/net/sourceforge/jnlp/util/UrlUtilsTest.java Fri Oct 02 15:35:30 2015 +0200 +++ b/tests/netx/unit/net/sourceforge/jnlp/util/UrlUtilsTest.java Thu Oct 08 12:11:49 2015 +0200 @@ -42,6 +42,7 @@ import static org.junit.Assert.assertTrue; import java.io.File; +import java.net.MalformedURLException; import java.net.URL; import net.sourceforge.jnlp.annotations.KnownToFail; import org.junit.Assert; @@ -325,5 +326,36 @@ Assert.assertFalse(UrlUtils.compareNullableStrings("BBB", "aaa", false)); } + + @Test + public void sanitizePortTest() throws MalformedURLException { + Assert.assertEquals(0, UrlUtils.getSanitizedPort(new URL("http://aaa.cz:0"))); + Assert.assertEquals(1, UrlUtils.getSanitizedPort(new URL("https://aaa.cz:1"))); + Assert.assertEquals(100, UrlUtils.getSanitizedPort(new URL("ftp://aaa.cz:100"))); + //Assert.assertEquals(1001, UrlUtils.getSanitizedPort(new URL("ssh://aaa.cz:1001"))); unknown protocol :( + //Assert.assertEquals(22, UrlUtils.getSanitizedPort(new URL("ssh://aaa.cz"))); + Assert.assertEquals(80, UrlUtils.getSanitizedPort(new URL("http://aaa.cz"))); + Assert.assertEquals(443, UrlUtils.getSanitizedPort(new URL("https://aaa.cz"))); + Assert.assertEquals(21, UrlUtils.getSanitizedPort(new URL("ftp://aaa.cz"))); + + } + + public void getPortTest() throws MalformedURLException { + Assert.assertEquals(1, UrlUtils.getPort(new URL("http://aa.bb:1"))); + Assert.assertEquals(10, UrlUtils.getPort(new URL("http://aa.bb:10/aa"))); + Assert.assertEquals(1000, UrlUtils.getPort(new URL("http://aa.bb:1000/aa.fs"))); + Assert.assertEquals(443, UrlUtils.getPort(new URL("https://aa.bb/aa.fs"))); + Assert.assertEquals(80, UrlUtils.getPort(new URL("http://aa.bb"))); + Assert.assertEquals(80, UrlUtils.getPort(new URL("http://aa.bb:80/a/b/c"))); + } + + public void getHostAndPortTest() throws MalformedURLException { + Assert.assertEquals("aa.bb:2", UrlUtils.getHostAndPort(new URL("http://aa.bb:2"))); + Assert.assertEquals("aa.bb:12", UrlUtils.getHostAndPort(new URL("http://aa.bb:12/aa"))); + Assert.assertEquals("aa.bb:1002", UrlUtils.getHostAndPort(new URL("http://aa.bb:1002/aa.fs"))); + Assert.assertEquals("aa.bb:443", UrlUtils.getHostAndPort(new URL("https://aa.bb/aa.fs"))); + Assert.assertEquals("aa.bb:80", UrlUtils.getHostAndPort(new URL("http://aa.bb"))); + Assert.assertEquals("aa.bb:80", UrlUtils.getHostAndPort(new URL("http://aa.bb:80/a/b/c"))); + } }