Mercurial > hg > openjdk > jdk8u > jdk
changeset 13264:fde7fd2a2fd2 jdk8u192-b05
Merge
author | aefimov |
---|---|
date | Fri, 03 Aug 2018 19:50:58 +0100 |
parents | 5d8ea4165d26 (current diff) 676618f2eb22 (diff) |
children | bd0ccb0d6710 e222c45022e7 |
files | .hgtags src/share/classes/sun/security/ssl/ClientHandshaker.java src/share/classes/sun/security/ssl/SSLEngineImpl.java src/share/classes/sun/security/ssl/SSLSocketImpl.java src/share/classes/sun/security/ssl/ServerHandshaker.java src/share/classes/sun/security/tools/keytool/Main.java src/share/classes/sun/security/util/SignatureFileVerifier.java src/windows/native/sun/security/mscapi/security.cpp src/windows/native/sun/windows/awt_Component.cpp test/sun/security/tools/jarsigner/warnings.sh |
diffstat | 50 files changed, 1749 insertions(+), 536 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Wed Aug 01 03:36:32 2018 -0700 +++ b/.hgtags Fri Aug 03 19:50:58 2018 +0100 @@ -857,6 +857,13 @@ 95df717479b19f5ea244afc67434827f2f851287 jdk8u162-b11 ddae5cb11d6c04130b8002b852bc7f80e0c8bcd2 jdk8u162-b12 8e40acfcc41a631f5922824712d4336742652eac jdk8u162-b31 +c00bdbbd9a77150f565298af9c305d7e6863eb59 jdk8u162-b32 +70a653814e61a5552312345308b85330fa8f27bc jdk8u162-b33 +f1f949ac13549c6fb3766279848539b124ad835e jdk8u162-b34 +b3de2b1e82fb2427cd40bb230aa26d9b7d8fb09c jdk8u162-b35 +e03fff22900242d92a97839a9c095bb106bdc68f jdk8u162-b36 +19696e8204b0e77e0f10af106c384b7ba6dd5bda jdk8u162-b37 +305c40e81a6fd59699036d4c35d8994f8501f116 jdk8u162-b38 b6195815c4bbbf275f1aefd337d805eb66f2b5b8 jdk8u171-b00 f1792a59f1fa20e47fe5d4561754012440564bec jdk8u171-b01 cac020298633fc736f5e21afddf00145665ef0a7 jdk8u171-b02 @@ -875,6 +882,8 @@ db8272cb8c99eea536a66c4c368c4bf2bf013a81 jdk8u172-b02 bd24ee3a9a0494121fd1d96c308b9738f585001b jdk8u172-b03 cf952b84daa1e74403a4d1df541c0ecca830717d jdk8u172-b04 +e7e27f446209924f66a4bf86738f3e5f2fbbef5f jdk8u181-b00 +a8746b41e23a1deda3d0f41ed2eca3d3a4cc74de jdk8u191-b00 076daed81c0a851f6d13fac538834ac465cdc122 jdk8u172-b05 94491d0dc59590535339a2ffae510166bb16f34c jdk8u172-b06 7e9eeb74e84beb6d8a6f562441eb7dd0ab0befa9 jdk8u172-b07 @@ -885,6 +894,16 @@ d902fae6241006af3c4cfc4ce82ebcb3efb9d725 jdk8u181-b01 baac18e216fb47b4cfa04169b3c3de58d667de7c jdk8u181-b02 d237c59d14e1c1fb1f750e9cdabcea6e711f4d34 jdk8u181-b03 +f3185b46a35b82727f39d52ac7fad7c4c78ddcdd jdk8u172-b31 +0939503b7477ba081484c54f26f177f9a66d92e4 jdk8u172-b32 +f4b138a6c95cf17f6138598fe04a90dfe1086bf4 jdk8u172-b33 +93b4d31ee70576a45a87607e2f5474d90ba31653 jdk8u172-b34 +6b4e239c74929b86b46113e92fe36d355157e235 jdk8u172-b35 +010852525831e0e88f622167d615438b82002e1f jdk8u172-b36 +9ac2466ffdbb1b9d9005b50aa633a5986617a002 jdk8u172-b37 +d902fae6241006af3c4cfc4ce82ebcb3efb9d725 jdk8u181-b01 +baac18e216fb47b4cfa04169b3c3de58d667de7c jdk8u181-b02 +d237c59d14e1c1fb1f750e9cdabcea6e711f4d34 jdk8u181-b03 6eeca4fb7748e8bdca4afbd6785b04376b1d44cc jdk8u181-b04 f34c24087b0e6f52391f491d6c3a608616d1db2c jdk8u181-b05 076f5fd6258846fce7010a598de2c7583628bb1e jdk8u181-b06 @@ -895,6 +914,10 @@ 112f3576f12e24d5e35d8d31782698e7d9a8fa52 jdk8u181-b11 22e01e7c5c39bfa3f5e2d18be76c7bf0dc71033a jdk8u181-b12 0cb452d66676bc1b3824bea4a0c16ac76e58b070 jdk8u181-b13 +b01c6e5aa43c784fc66465b56227ddd9aa29eee6 jdk8u191-b01 +2db6890a956723ac347b573217d91bbbedbb0528 jdk8u191-b02 +89e2889d02d2f5dabdeda7f60cf80a8df3100eb4 jdk8u191-b03 +94e4769c6d69241f9eb7164a85fc91fc83faab5c jdk8u191-b04 51b6cc7fbd98a87c6cdb5c70b7dbe25bb10e0dd7 jdk8u182-b00 bead1ed7344f2911f5bed83639cf5160596561ef jdk8u192-b00 444b4528c8ecdd39b5923820fa2ed6d583808b5e jdk8u192-b01
--- a/src/share/classes/com/sun/media/sound/DLSSoundbank.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/com/sun/media/sound/DLSSoundbank.java Fri Aug 03 19:50:58 2018 +0100 @@ -548,7 +548,7 @@ long count = riff.readUnsignedInt(); if (size - 8 != 0) - riff.skipBytes(size - 8); + riff.skip(size - 8); for (int i = 0; i < count; i++) { DLSModulator modulator = new DLSModulator(); @@ -568,7 +568,7 @@ long count = riff.readUnsignedInt(); if (size - 8 != 0) - riff.skipBytes(size - 8); + riff.skip(size - 8); for (int i = 0; i < count; i++) { DLSModulator modulator = new DLSModulator(); @@ -661,7 +661,7 @@ long loops = riff.readInt(); if (size > 20) - riff.skipBytes(size - 20); + riff.skip(size - 20); for (int i = 0; i < loops; i++) { DLSSampleLoop loop = new DLSSampleLoop(); @@ -671,7 +671,7 @@ loop.length = riff.readUnsignedInt(); sampleOptions.loops.add(loop); if (size2 > 16) - riff.skipBytes(size2 - 16); + riff.skip(size2 - 16); } }
--- a/src/share/classes/com/sun/media/sound/RIFFReader.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/com/sun/media/sound/RIFFReader.java Fri Aug 03 19:50:58 2018 +0100 @@ -172,49 +172,41 @@ } } - public final long skipBytes(long n) throws IOException { - if (n < 0) + @Override + public long skip(final long n) throws IOException { + if (n <= 0 || avail == 0) { return 0; - long skipped = 0; - while (skipped != n) { - long s = skip(n - skipped); - if (s < 0) - break; - if (s == 0) + } + // will not skip more than + long remaining = Math.min(n, avail); + while (remaining > 0) { + // Some input streams like FileInputStream can return more bytes, + // when EOF is reached. + long ret = Math.min(stream.skip(remaining), remaining); + if (ret == 0) { + // EOF or not? we need to check. Thread.yield(); - skipped += s; + if (stream.read() == -1) { + avail = 0; + break; + } + ret = 1; + } + remaining -= ret; + avail -= ret; + filepointer += ret; } - return skipped; + return n - remaining; } - public long skip(long n) throws IOException { - if (avail == 0) - return -1; - if (n > avail) { - long len = stream.skip(avail); - if (len != -1) - filepointer += len; - avail = 0; - return len; - } else { - long ret = stream.skip(n); - if (ret == -1) { - avail = 0; - return -1; - } - avail -= ret; - filepointer += ret; - return ret; - } - } - + @Override public int available() { return (int)avail; } public void finish() throws IOException { if (avail != 0) { - skipBytes(avail); + skip(avail); } } @@ -337,6 +329,7 @@ return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24); } + @Override public void close() throws IOException { finish(); if (this == root)
--- a/src/share/classes/com/sun/naming/internal/VersionHelper12.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/com/sun/naming/internal/VersionHelper12.java Fri Aug 03 19:50:58 2018 +0100 @@ -62,6 +62,25 @@ } /** + * Determines whether classes may be loaded from an arbitrary URL code base. + */ + private static final String TRUST_URL_CODEBASE_PROPERTY = + "com.sun.jndi.ldap.object.trustURLCodebase"; + private static final String trustURLCodebase = + AccessController.doPrivileged( + new PrivilegedAction<String>() { + public String run() { + try { + return System.getProperty(TRUST_URL_CODEBASE_PROPERTY, + "false"); + } catch (SecurityException e) { + return "false"; + } + } + } + ); + + /** * Package private. * * This internal method is used with Thread Context Class Loader (TCCL), @@ -79,12 +98,15 @@ */ public Class<?> loadClass(String className, String codebase) throws ClassNotFoundException, MalformedURLException { + if ("true".equalsIgnoreCase(trustURLCodebase)) { + ClassLoader parent = getContextClassLoader(); + ClassLoader cl = + URLClassLoader.newInstance(getUrlArray(codebase), parent); - ClassLoader parent = getContextClassLoader(); - ClassLoader cl = - URLClassLoader.newInstance(getUrlArray(codebase), parent); - - return loadClass(className, cl); + return loadClass(className, cl); + } else { + return null; + } } String getJndiProperty(final int i) {
--- a/src/share/classes/java/net/InetAddress.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/java/net/InetAddress.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.io.ObjectStreamException; import java.io.ObjectStreamField; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; @@ -1602,8 +1603,11 @@ } GetField gf = s.readFields(); String host = (String)gf.get("hostName", null); - int address= gf.get("address", 0); - int family= gf.get("family", 0); + int address = gf.get("address", 0); + int family = gf.get("family", 0); + if (family != IPv4 && family != IPv6) { + throw new InvalidObjectException("invalid address family type: " + family); + } InetAddressHolder h = new InetAddressHolder(host, address, family); UNSAFE.putObject(this, FIELDS_OFFSET, h); }
--- a/src/share/classes/java/net/NetworkInterface.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/java/net/NetworkInterface.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -319,8 +319,20 @@ if (addr == null) { throw new NullPointerException(); } - if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) { - throw new IllegalArgumentException ("invalid address type"); + if (addr instanceof Inet4Address) { + Inet4Address inet4Address = (Inet4Address) addr; + if (inet4Address.holder.family != InetAddress.IPv4) { + throw new IllegalArgumentException("invalid family type: " + + inet4Address.holder.family); + } + } else if (addr instanceof Inet6Address) { + Inet6Address inet6Address = (Inet6Address) addr; + if (inet6Address.holder.family != InetAddress.IPv6) { + throw new IllegalArgumentException("invalid family type: " + + inet6Address.holder.family); + } + } else { + throw new IllegalArgumentException("invalid address type: " + addr); } return getByInetAddress0(addr); }
--- a/src/share/classes/java/net/URLClassLoader.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/java/net/URLClassLoader.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ import java.util.jar.JarFile; import java.util.jar.Manifest; import sun.misc.Resource; +import sun.misc.SharedSecrets; import sun.misc.URLClassPath; import sun.net.www.ParseUtil; import sun.security.util.SecurityConstants; @@ -486,13 +487,13 @@ protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException { - String path = name.replace('.', '/').concat("/"); String specTitle = null, specVersion = null, specVendor = null; String implTitle = null, implVersion = null, implVendor = null; String sealed = null; URL sealBase = null; - Attributes attr = man.getAttributes(path); + Attributes attr = SharedSecrets.javaUtilJarAccess() + .getTrustedAttributes(man, name.replace('.', '/').concat("/")); if (attr != null) { specTitle = attr.getValue(Name.SPECIFICATION_TITLE); specVersion = attr.getValue(Name.SPECIFICATION_VERSION); @@ -536,10 +537,12 @@ /* * Returns true if the specified package name is sealed according to the * given manifest. + * + * @throws SecurityException if the package name is untrusted in the manifest */ private boolean isSealed(String name, Manifest man) { - String path = name.replace('.', '/').concat("/"); - Attributes attr = man.getAttributes(path); + Attributes attr = SharedSecrets.javaUtilJarAccess() + .getTrustedAttributes(man, name.replace('.', '/').concat("/")); String sealed = null; if (attr != null) { sealed = attr.getValue(Name.SEALED);
--- a/src/share/classes/java/util/jar/JarFile.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/java/util/jar/JarFile.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -191,10 +191,10 @@ if (manEntry != null) { if (verify) { byte[] b = getBytes(manEntry); - man = new Manifest(new ByteArrayInputStream(b)); if (!jvInitialized) { jv = new JarVerifier(b); } + man = new Manifest(jv, new ByteArrayInputStream(b)); } else { man = new Manifest(super.getInputStream(manEntry)); }
--- a/src/share/classes/java/util/jar/JarVerifier.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/java/util/jar/JarVerifier.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -879,4 +879,24 @@ static CodeSource getUnsignedCS(URL url) { return new VerifierCodeSource(null, url, (java.security.cert.Certificate[]) null); } + + /** + * Returns whether the name is trusted. Used by + * {@link Manifest#getTrustedAttributes(String)}. + */ + boolean isTrustedManifestEntry(String name) { + // How many signers? MANIFEST.MF is always verified + CodeSigner[] forMan = verifiedSigners.get(JarFile.MANIFEST_NAME); + if (forMan == null) { + return true; + } + // Check sigFileSigners first, because we are mainly dealing with + // non-file entries which will stay in sigFileSigners forever. + CodeSigner[] forName = sigFileSigners.get(name); + if (forName == null) { + forName = verifiedSigners.get(name); + } + // Returns trusted if all signers sign the entry + return forName != null && forName.length == forMan.length; + } }
--- a/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,4 +60,9 @@ public List<Object> getManifestDigests(JarFile jar) { return jar.getManifestDigests(); } + + public Attributes getTrustedAttributes(Manifest man, String name) { + return man.getTrustedAttributes(name); + } + }
--- a/src/share/classes/java/util/jar/Manifest.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/java/util/jar/Manifest.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,15 +48,19 @@ */ public class Manifest implements Cloneable { // manifest main attributes - private Attributes attr = new Attributes(); + private final Attributes attr = new Attributes(); // manifest entries - private Map<String, Attributes> entries = new HashMap<>(); + private final Map<String, Attributes> entries = new HashMap<>(); + + // associated JarVerifier, not null when called by JarFile::getManifest. + private final JarVerifier jv; /** * Constructs a new, empty Manifest. */ public Manifest() { + jv = null; } /** @@ -66,7 +70,16 @@ * @throws IOException if an I/O error has occurred */ public Manifest(InputStream is) throws IOException { + this(null, is); + } + + /** + * Constructs a new Manifest from the specified input stream + * and associates it with a JarVerifier. + */ + Manifest(JarVerifier jv, InputStream is) throws IOException { read(is); + this.jv = jv; } /** @@ -77,6 +90,7 @@ public Manifest(Manifest man) { attr.putAll(man.getMainAttributes()); entries.putAll(man.getEntries()); + jv = man.jv; } /** @@ -127,6 +141,23 @@ } /** + * Returns the Attributes for the specified entry name, if trusted. + * + * @param name entry name + * @return returns the same result as {@link #getAttributes(String)} + * @throws SecurityException if the associated jar is signed but this entry + * has been modified after signing (i.e. the section in the manifest + * does not exist in SF files of all signers). + */ + Attributes getTrustedAttributes(String name) { + Attributes result = getAttributes(name); + if (result != null && jv != null && ! jv.isTrustedManifestEntry(name)) { + throw new SecurityException("Untrusted manifest entry: " + name); + } + return result; + } + + /** * Clears the main Attributes as well as the entries in this Manifest. */ public void clear() {
--- a/src/share/classes/javax/crypto/Cipher.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/javax/crypto/Cipher.java Fri Aug 03 19:50:58 2018 +0100 @@ -2703,7 +2703,7 @@ // Input sanity check if ((src == null) || (offset < 0) || (len < 0) - || ((len + offset) > src.length)) { + || (len > (src.length - offset))) { throw new IllegalArgumentException("Bad arguments"); }
--- a/src/share/classes/javax/crypto/CipherInputStream.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/javax/crypto/CipherInputStream.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,13 @@ * that are not thrown by its ancestor classes. In particular, the * <code>skip</code> method skips, and the <code>available</code> * method counts only data that have been processed by the encapsulated Cipher. + * This class may catch BadPaddingException and other exceptions thrown by + * failed integrity checks during decryption. These exceptions are not + * re-thrown, so the client may not be informed that integrity checks + * failed. Because of this behavior, this class may not be suitable + * for use with decryption in an authenticated mode of operation (e.g. GCM). + * Applications that require authenticated encryption can use the Cipher API + * directly as an alternative to using this class. * * <p> It is crucial for a programmer using this class not to use * methods that are not defined or overriden in this class (such as a
--- a/src/share/classes/javax/crypto/spec/GCMParameterSpec.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/javax/crypto/spec/GCMParameterSpec.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,7 +120,7 @@ // Input sanity check if ((src == null) ||(len < 0) || (offset < 0) - || ((len + offset) > src.length)) { + || (len > (src.length - offset))) { throw new IllegalArgumentException("Invalid buffer arguments"); }
--- a/src/share/classes/sun/misc/JavaUtilJarAccess.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/misc/JavaUtilJarAccess.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,10 @@ import java.security.CodeSource; import java.util.Enumeration; import java.util.List; +import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.jar.Manifest; public interface JavaUtilJarAccess { public boolean jarFileHasClassPathAttribute(JarFile jar) throws IOException; @@ -41,4 +43,5 @@ public Enumeration<JarEntry> entries2(JarFile jar); public void setEagerValidation(JarFile jar, boolean eager); public List<Object> getManifestDigests(JarFile jar); + public Attributes getTrustedAttributes(Manifest man, String name); }
--- a/src/share/classes/sun/misc/URLClassPath.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/misc/URLClassPath.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.util.jar.Attributes.Name; import java.net.JarURLConnection; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; @@ -69,6 +70,8 @@ private static final boolean DEBUG_LOOKUP_CACHE; private static final boolean DISABLE_JAR_CHECKING; private static final boolean DISABLE_ACC_CHECKING; + private static final boolean DISABLE_CP_URL_CHECK; + private static final boolean DEBUG_CP_URL_CHECK; static { JAVA_VERSION = java.security.AccessController.doPrivileged( @@ -84,6 +87,13 @@ p = AccessController.doPrivileged( new GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions")); DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false; + + // This property will be removed in a later release + p = AccessController.doPrivileged( + new GetPropertyAction("jdk.net.URLClassPath.disableClassPathURLCheck")); + + DISABLE_CP_URL_CHECK = p != null ? p.equals("true") || p.isEmpty() : false; + DEBUG_CP_URL_CHECK = "debug".equals(p); } /* The original search path of URLs. */ @@ -1217,11 +1227,51 @@ int i = 0; while (st.hasMoreTokens()) { String path = st.nextToken(); - urls[i] = new URL(base, path); - i++; + URL url = DISABLE_CP_URL_CHECK ? new URL(base, path) : safeResolve(base, path); + if (url != null) { + urls[i] = url; + i++; + } + } + if (i == 0) { + urls = null; + } else if (i != urls.length) { + // Truncate nulls from end of array + urls = Arrays.copyOf(urls, i); } return urls; } + + /* + * Return a URL for the given path resolved against the base URL, or + * null if the resulting URL is invalid. + */ + static URL safeResolve(URL base, String path) { + String child = path.replace(File.separatorChar, '/'); + try { + if (!URI.create(child).isAbsolute()) { + URL url = new URL(base, child); + if (base.getProtocol().equalsIgnoreCase("file")) { + return url; + } else { + String bp = base.getPath(); + String urlp = url.getPath(); + int pos = bp.lastIndexOf('/'); + if (pos == -1) { + pos = bp.length() - 1; + } + if (urlp.regionMatches(0, bp, 0, pos + 1) + && urlp.indexOf("..", pos) == -1) { + return url; + } + } + } + } catch (MalformedURLException | IllegalArgumentException e) {} + if (DEBUG_CP_URL_CHECK) { + System.err.println("Class-Path entry: \"" + path + "\" ignored in JAR file " + base); + } + return null; + } } /*
--- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2686,6 +2686,8 @@ // doesn't know about proxy. useProxyResponseCode = true; } else { + final URL prevURL = url; + // maintain previous headers, just change the name // of the file we're getting url = locUrl; @@ -2714,6 +2716,14 @@ poster = null; if (!checkReuseConnection()) connect(); + + if (!sameDestination(prevURL, url)) { + // Ensures pre-redirect user-set cookie will not be reset. + // CookieHandler, if any, will be queried to determine + // cookies for redirected URL, if any. + userCookies = null; + userCookies2 = null; + } } else { if (!checkReuseConnection()) connect(); @@ -2736,11 +2746,52 @@ } requests.set("Host", host); } + + if (!sameDestination(prevURL, url)) { + // Redirecting to a different destination will drop any + // security-sensitive headers, regardless of whether + // they are user-set or not. CookieHandler, if any, will be + // queried to determine cookies for redirected URL, if any. + userCookies = null; + userCookies2 = null; + requests.remove("Cookie"); + requests.remove("Cookie2"); + requests.remove("Authorization"); + + // check for preemptive authorization + AuthenticationInfo sauth = + AuthenticationInfo.getServerAuth(url); + if (sauth != null && sauth.supportsPreemptiveAuthorization() ) { + // Sets "Authorization" + requests.setIfNotSet(sauth.getHeaderName(), sauth.getHeaderValue(url,method)); + currentServerCredentials = sauth; + } + } } } return true; } + /* Returns true iff the given URLs have the same host and effective port. */ + private static boolean sameDestination(URL firstURL, URL secondURL) { + assert firstURL.getProtocol().equalsIgnoreCase(secondURL.getProtocol()): + "protocols not equal: " + firstURL + " - " + secondURL; + + if (!firstURL.getHost().equalsIgnoreCase(secondURL.getHost())) + return false; + + int firstPort = firstURL.getPort(); + if (firstPort == -1) + firstPort = firstURL.getDefaultPort(); + int secondPort = secondURL.getPort(); + if (secondPort == -1) + secondPort = secondURL.getDefaultPort(); + if (firstPort != secondPort) + return false; + + return true; + } + /* dummy byte buffer for reading off socket prior to closing */ byte[] cdata = new byte [128];
--- a/src/share/classes/sun/security/ssl/ClientHandshaker.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/security/ssl/ClientHandshaker.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -719,7 +719,8 @@ session = new SSLSessionImpl(protocolVersion, cipherSuite, getLocalSupportedSignAlgs(), mesg.sessionId, getHostSE(), getPortSE(), - (extendedMasterSecretExt != null)); + (extendedMasterSecretExt != null), + getEndpointIdentificationAlgorithmSE()); session.setRequestedServerNames(requestedServerNames); setHandshakeSessionSE(session); if (debug != null && Debug.isOn("handshake")) { @@ -1391,6 +1392,24 @@ } } + // ensure that the endpoint identification algorithm matches the + // one in the session + String identityAlg = getEndpointIdentificationAlgorithmSE(); + if (session != null && identityAlg != null) { + + String sessionIdentityAlg = + session.getEndpointIdentificationAlgorithm(); + if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + + if (debug != null && Debug.isOn("session")) { + System.out.println("%% can't resume, endpoint id" + + " algorithm does not match, requested: " + + identityAlg + ", cached: " + sessionIdentityAlg); + } + session = null; + } + } + if (session != null) { if (debug != null) { if (Debug.isOn("handshake") || Debug.isOn("session")) {
--- a/src/share/classes/sun/security/ssl/SSLSessionImpl.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/security/ssl/SSLSessionImpl.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,6 +115,10 @@ private Principal peerPrincipal; private Principal localPrincipal; + // The endpoint identification algorithm used to check certificates + // in this session. + private final String endpointIdentificationAlgorithm; + /* * Is the session currently re-established with a session-resumption * abbreviated initial handshake? @@ -146,7 +150,7 @@ */ private SSLSessionImpl() { this(ProtocolVersion.NONE, CipherSuite.C_NULL, null, - new SessionId(false, null), null, -1, false); + new SessionId(false, null), null, -1, false, null); } /* @@ -157,10 +161,10 @@ SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite, Collection<SignatureAndHashAlgorithm> algorithms, SecureRandom generator, String host, int port, - boolean useExtendedMasterSecret) { + boolean useExtendedMasterSecret, String endpointIdAlgorithm) { this(protocolVersion, cipherSuite, algorithms, new SessionId(defaultRejoinable, generator), host, port, - useExtendedMasterSecret); + useExtendedMasterSecret, endpointIdAlgorithm); } /* @@ -169,7 +173,8 @@ SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite, Collection<SignatureAndHashAlgorithm> algorithms, SessionId id, String host, int port, - boolean useExtendedMasterSecret) { + boolean useExtendedMasterSecret, + String endpointIdAlgorithm){ this.protocolVersion = protocolVersion; sessionId = id; peerCerts = null; @@ -182,6 +187,7 @@ localSupportedSignAlgs = SignatureAndHashAlgorithm.getAlgorithmNames(algorithms); this.useExtendedMasterSecret = useExtendedMasterSecret; + this.endpointIdentificationAlgorithm = endpointIdAlgorithm; if (debug != null && Debug.isOn("session")) { System.out.println("%% Initialized: " + this); @@ -247,6 +253,10 @@ localPrincipal = principal; } + String getEndpointIdentificationAlgorithm() { + return this.endpointIdentificationAlgorithm; + } + /** * Returns true iff this session may be resumed ... sessions are * usually resumable. Security policies may suggest otherwise,
--- a/src/share/classes/sun/security/ssl/ServerHandshaker.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -698,6 +698,25 @@ } } + // ensure that the endpoint identification algorithm matches the + // one in the session + String identityAlg = getEndpointIdentificationAlgorithmSE(); + if (resumingSession && identityAlg != null) { + + String sessionIdentityAlg = + previous.getEndpointIdentificationAlgorithm(); + if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + + if (debug != null && Debug.isOn("session")) { + System.out.println("%% can't resume, endpoint id" + + " algorithm does not match, requested: " + + identityAlg + ", cached: " + + sessionIdentityAlg); + } + resumingSession = false; + } + } + if (resumingSession) { CipherSuite suite = previous.getSuite(); // verify that the ciphersuite from the cached session @@ -769,7 +788,8 @@ sslContext.getSecureRandom(), getHostAddressSE(), getPortSE(), (requestedToUseEMS && - (protocolVersion.v >= ProtocolVersion.TLS10.v))); + (protocolVersion.v >= ProtocolVersion.TLS10.v)), + getEndpointIdentificationAlgorithmSE()); if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (peerSupportedSignAlgs != null) {
--- a/src/share/classes/sun/security/tools/KeyStoreUtil.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/security/tools/KeyStoreUtil.java Fri Aug 03 19:50:58 2018 +0100 @@ -35,6 +35,7 @@ import java.security.KeyStore; +import java.security.cert.X509Certificate; import java.text.Collator; import java.util.Locale; @@ -59,6 +60,25 @@ }; /** + * Returns true if the certificate is self-signed, false otherwise. + */ + public static boolean isSelfSigned(X509Certificate cert) { + return signedBy(cert, cert); + } + + public static boolean signedBy(X509Certificate end, X509Certificate ca) { + if (!ca.getSubjectX500Principal().equals(end.getIssuerX500Principal())) { + return false; + } + try { + end.verify(ca.getPublicKey()); + return true; + } catch (Exception e) { + return false; + } + } + + /** * Returns true if KeyStore has a password. This is true except for * MSCAPI KeyStores */
--- a/src/share/classes/sun/security/tools/jarsigner/Main.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/security/tools/jarsigner/Main.java Fri Aug 03 19:50:58 2018 +0100 @@ -26,6 +26,8 @@ package sun.security.tools.jarsigner; import java.io.*; +import java.security.cert.CertPathValidatorException; +import java.security.cert.PKIXBuilderParameters; import java.util.*; import java.util.zip.*; import java.util.jar.*; @@ -46,11 +48,9 @@ import java.net.URL; import java.net.URLClassLoader; import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateNotYetValidException; -import java.security.cert.PKIXParameters; import java.security.cert.TrustAnchor; import java.util.Map.Entry; import sun.security.pkcs.PKCS7; @@ -58,6 +58,8 @@ import sun.security.timestamp.TimestampToken; import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; +import sun.security.validator.Validator; +import sun.security.validator.ValidatorException; import sun.security.x509.*; import sun.security.util.*; import java.util.Base64; @@ -173,22 +175,34 @@ private boolean noTimestamp = false; private Date expireDate = new Date(0L); // used in noTimestamp warning - // Severe warnings + // Severe warnings. + + // jarsigner used to check signer cert chain validity and key usages + // itself and set various warnings. Later CertPath validation is + // added but chainNotValidated is only flagged when no other existing + // warnings are set. TSA cert chain check is added separately and + // only tsaChainNotValidated is set, i.e. has no affect on hasExpiredCert, + // notYetValidCert, or any badXyzUsage. + + private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg private boolean hasExpiredCert = false; private boolean notYetValidCert = false; private boolean chainNotValidated = false; + private boolean tsaChainNotValidated = false; private boolean notSignedByAlias = false; private boolean aliasNotInStore = false; private boolean hasUnsignedEntry = false; private boolean badKeyUsage = false; private boolean badExtendedKeyUsage = false; private boolean badNetscapeCertType = false; + private boolean signerSelfSigned = false; + + private Throwable chainNotValidatedReason = null; + private Throwable tsaChainNotValidatedReason = null; private boolean seeWeak = false; - CertificateFactory certificateFactory; - CertPathValidator validator; - PKIXParameters pkixParameters; + PKIXBuilderParameters pkixParameters; public void run(String args[]) { try { @@ -275,7 +289,8 @@ if (strict) { int exitCode = 0; - if (chainNotValidated || hasExpiredCert || notYetValidCert) { + if (weakAlg != 0 || chainNotValidated + || hasExpiredCert || notYetValidCert || signerSelfSigned) { exitCode |= 4; } if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) { @@ -287,6 +302,9 @@ if (notSignedByAlias || aliasNotInStore) { exitCode |= 32; } + if (tsaChainNotValidated) { + exitCode |= 64; + } if (exitCode != 0) { System.exit(exitCode); } @@ -807,6 +825,9 @@ System.out.println(rb.getString("no.manifest.")); } + // If there is a time stamp block inside the PKCS7 block file + boolean hasTimestampBlock = false; + // Even if the verbose option is not specified, all out strings // must be generated so seeWeak can be updated. if (!digestMap.isEmpty() @@ -835,6 +856,7 @@ PublicKey key = signer.getPublicKey(); PKCS7 tsToken = si.getTsToken(); if (tsToken != null) { + hasTimestampBlock = true; SignerInfo tsSi = tsToken.getSignerInfos()[0]; X509Certificate tsSigner = tsSi.getCertificate(tsToken); byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); @@ -890,6 +912,12 @@ } System.out.println(); + // If signer is a trusted cert or private entry in user's own + // keystore, it can be self-signed. + if (!aliasNotInStore) { + signerSelfSigned = false; + } + if (!anySigned) { if (seeWeak) { if (verbose != null) { @@ -910,8 +938,8 @@ boolean errorAppeared = false; if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || notYetValidCert || chainNotValidated || hasExpiredCert || - hasUnsignedEntry || - aliasNotInStore || notSignedByAlias) { + hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) || + aliasNotInStore || notSignedByAlias || tsaChainNotValidated) { if (strict) { System.out.println(rb.getString("jar.verified.with.signer.errors.")); @@ -925,6 +953,12 @@ warningAppeared = true; } + if (weakAlg != 0) { + // In fact, jarsigner verification did not catch this + // since it has not read the JarFile content itself. + // Everything is done with JarFile API. + } + if (badKeyUsage) { System.out.println( rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); @@ -954,8 +988,15 @@ } if (chainNotValidated) { - System.out.println( - rb.getString("This.jar.contains.entries.whose.certificate.chain.is.not.validated.")); + System.out.println(String.format( + rb.getString("This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"), + chainNotValidatedReason.getLocalizedMessage())); + } + + if (tsaChainNotValidated) { + System.out.println(String.format( + rb.getString("This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"), + tsaChainNotValidatedReason.getLocalizedMessage())); } if (notSignedByAlias) { @@ -966,6 +1007,11 @@ if (aliasNotInStore) { System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.")); } + + if (signerSelfSigned) { + System.out.println(rb.getString( + "This.jar.contains.entries.whose.signer.certificate.is.self.signed.")); + } } else { System.out.println(rb.getString("jar.verified.")); } @@ -980,8 +1026,15 @@ "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.")); } if (noTimestamp) { - System.out.println( - String.format(rb.getString("no.timestamp.verifying"), expireDate)); + if (hasTimestampBlock) { + // JarSigner API has not seen the timestamp, + // might have ignored it due to weak alg, etc. + System.out.println( + String.format(rb.getString("bad.timestamp.verifying"), expireDate)); + } else { + System.out.println( + String.format(rb.getString("no.timestamp.verifying"), expireDate)); + } } } if (warningAppeared || errorAppeared) { @@ -1032,16 +1085,23 @@ private static MessageFormat expiredTimeForm = null; private static MessageFormat expiringTimeForm = null; - /* - * Display some details about a certificate: + /** + * Returns a string about a certificate: * * [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"] * [<validity-period> | <expiry-warning>] + * [<key-usage-warning>] * - * Note: no newline character at the end + * Note: no newline character at the end. + * + * When isTsCert is true, this method sets global flags like hasExpiredCert, + * notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType. + * + * @param isTsCert true if c is in the TSA cert chain, false otherwise. + * @param checkUsage true to check code signer keyUsage */ - String printCert(String tab, Certificate c, boolean checkValidityPeriod, - Date timestamp, boolean checkUsage) { + String printCert(boolean isTsCert, String tab, Certificate c, + Date timestamp, boolean checkUsage) throws Exception { StringBuilder certStr = new StringBuilder(); String space = rb.getString("SPACE"); @@ -1061,7 +1121,7 @@ certStr.append(space).append(alias); } - if (checkValidityPeriod && x509Cert != null) { + if (x509Cert != null) { certStr.append("\n").append(tab).append("["); Date notAfter = x509Cert.getNotAfter(); @@ -1074,7 +1134,7 @@ x509Cert.checkValidity(); // test if cert will expire within six months if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) { - hasExpiringCert = true; + if (!isTsCert) hasExpiringCert = true; if (expiringTimeForm == null) { expiringTimeForm = new MessageFormat( rb.getString("certificate.will.expire.on")); @@ -1095,7 +1155,7 @@ certStr.append(validityTimeForm.format(source)); } } catch (CertificateExpiredException cee) { - hasExpiredCert = true; + if (!isTsCert) hasExpiredCert = true; if (expiredTimeForm == null) { expiredTimeForm = new MessageFormat( @@ -1105,7 +1165,7 @@ certStr.append(expiredTimeForm.format(source)); } catch (CertificateNotYetValidException cnyve) { - notYetValidCert = true; + if (!isTsCert) notYetValidCert = true; if (notYetTimeForm == null) { notYetTimeForm = new MessageFormat( @@ -1218,7 +1278,25 @@ } void signJar(String jarName, String alias, String[] args) - throws Exception { + throws Exception { + + DisabledAlgorithmConstraints dac = + new DisabledAlgorithmConstraints( + DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); + + if (digestalg != null && !dac.permits( + Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), digestalg, null)) { + weakAlg |= 1; + } + if (tSADigestAlg != null && !dac.permits( + Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), tSADigestAlg, null)) { + weakAlg |= 4; + } + if (sigalg != null && !dac.permits( + Collections.singleton(CryptoPrimitive.SIGNATURE), sigalg, null)) { + weakAlg |= 2; + } + boolean aliasUsed = false; X509Certificate tsaCert = null; @@ -1494,7 +1572,7 @@ tsaURI); } System.out.println(rb.getString("TSA.certificate.") + - printCert("", tsaCert, false, null, false)); + printCert(true, "", tsaCert, null, false)); } if (signingMechanism != null) { System.out.println( @@ -1557,6 +1635,30 @@ } } + // The JarSigner API always accepts the timestamp received. + // We need to extract the certs from the signed jar to + // validate it. + if (!noTimestamp) { + try (JarFile check = new JarFile(signedJarFile)) { + PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry( + "META-INF/" + sigfile + "." + privateKey.getAlgorithm()))); + SignerInfo si = p7.getSignerInfos()[0]; + PKCS7 tsToken = si.getTsToken(); + SignerInfo tsSi = tsToken.getSignerInfos()[0]; + try { + validateCertChain(Validator.VAR_TSA_SERVER, + tsSi.getCertificateChain(tsToken), null); + } catch (Exception e) { + tsaChainNotValidated = true; + tsaChainNotValidatedReason = e; + } + } catch (Exception e) { + if (debug) { + e.printStackTrace(); + } + } + } + // no IOException thrown in the follow try clause, so disable // the try clause. // try { @@ -1586,8 +1688,10 @@ } boolean warningAppeared = false; - if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || - notYetValidCert || chainNotValidated || hasExpiredCert) { + if (weakAlg != 0 || badKeyUsage || badExtendedKeyUsage + || badNetscapeCertType || notYetValidCert + || chainNotValidated || tsaChainNotValidated + || hasExpiredCert || signerSelfSigned) { if (strict) { System.out.println(rb.getString("jar.signed.with.signer.errors.")); System.out.println(); @@ -1623,8 +1727,37 @@ } if (chainNotValidated) { + System.out.println(String.format( + rb.getString("The.signer.s.certificate.chain.is.invalid.reason.1"), + chainNotValidatedReason.getLocalizedMessage())); + } + + if (tsaChainNotValidated) { + System.out.println(String.format( + rb.getString("The.tsa.certificate.chain.is.invalid.reason.1"), + tsaChainNotValidatedReason.getLocalizedMessage())); + } + + if (signerSelfSigned) { System.out.println( - rb.getString("The.signer.s.certificate.chain.is.not.validated.")); + rb.getString("The.signer.s.certificate.is.self.signed.")); + } + + if ((weakAlg & 1) == 1) { + System.out.println(String.format( + rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."), + digestalg, "-digestalg")); + } + + if ((weakAlg & 2) == 2) { + System.out.println(String.format( + rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."), + sigalg, "-sigalg")); + } + if ((weakAlg & 4) == 4) { + System.out.println(String.format( + rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."), + tSADigestAlg, "-tsadigestalg")); } } else { System.out.println(rb.getString("jar.signed.")); @@ -1700,18 +1833,18 @@ /** * Returns a string of singer info, with a newline at the end */ - private String signerInfo(CodeSigner signer, String tab) { + private String signerInfo(CodeSigner signer, String tab) throws Exception { if (cacheForSignerInfo.containsKey(signer)) { return cacheForSignerInfo.get(signer); } - StringBuffer s = new StringBuffer(); + StringBuilder sb = new StringBuilder(); List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates(); // display the signature timestamp, if present Date timestamp; Timestamp ts = signer.getTimestamp(); if (ts != null) { - s.append(printTimestamp(tab, ts)); - s.append('\n'); + sb.append(printTimestamp(tab, ts)); + sb.append('\n'); timestamp = ts.getTimestamp(); } else { timestamp = null; @@ -1720,28 +1853,41 @@ // display the certificate(s). The first one is end-entity cert and // its KeyUsage should be checked. boolean first = true; + sb.append(tab).append(rb.getString("...Signer")).append('\n'); for (Certificate c : certs) { - s.append(printCert(tab, c, true, timestamp, first)); - s.append('\n'); + sb.append(printCert(false, tab, c, timestamp, first)); + sb.append('\n'); first = false; } try { - validateCertChain(certs); + validateCertChain(Validator.VAR_CODE_SIGNING, certs, ts); } catch (Exception e) { - if (debug) { - e.printStackTrace(); + chainNotValidated = true; + chainNotValidatedReason = e; + sb.append(tab).append(rb.getString(".Invalid.certificate.chain.")) + .append(e.getLocalizedMessage()).append("]\n"); + } + if (ts != null) { + sb.append(tab).append(rb.getString("...TSA")).append('\n'); + for (Certificate c : ts.getSignerCertPath().getCertificates()) { + sb.append(printCert(true, tab, c, timestamp, false)); + sb.append('\n'); } - if (e.getCause() != null && - (e.getCause() instanceof CertificateExpiredException || - e.getCause() instanceof CertificateNotYetValidException)) { - // No more warning, we alreay have hasExpiredCert or notYetValidCert - } else { - chainNotValidated = true; - s.append(tab + rb.getString(".CertPath.not.validated.") + - e.getLocalizedMessage() + "]\n"); // TODO + try { + validateCertChain(Validator.VAR_TSA_SERVER, + ts.getSignerCertPath().getCertificates(), null); + } catch (Exception e) { + tsaChainNotValidated = true; + tsaChainNotValidatedReason = e; + sb.append(tab).append(rb.getString(".Invalid.TSA.certificate.chain.")) + .append(e.getLocalizedMessage()).append("]\n"); } } - String result = s.toString(); + if (certs.size() == 1 + && KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) { + signerSelfSigned = true; + } + String result = sb.toString(); cacheForSignerInfo.put(signer, result); return result; } @@ -1793,9 +1939,6 @@ } try { - - certificateFactory = CertificateFactory.getInstance("X.509"); - validator = CertPathValidator.getInstance("PKIX"); Set<TrustAnchor> tas = new HashSet<>(); try { KeyStore caks = KeyStoreUtil.getCacertsKeyStore(); @@ -1871,7 +2014,7 @@ } } finally { try { - pkixParameters = new PKIXParameters(tas); + pkixParameters = new PKIXBuilderParameters(tas, null); pkixParameters.setRevocationEnabled(false); } catch (InvalidAlgorithmParameterException ex) { // Only if tas is empty @@ -1987,7 +2130,7 @@ } } - void getAliasInfo(String alias) { + void getAliasInfo(String alias) throws Exception { Key key = null; @@ -2033,21 +2176,18 @@ // We don't meant to print anything, the next call // checks validity and keyUsage etc - printCert("", certChain[0], true, null, true); + printCert(false, "", certChain[0], null, true); try { - validateCertChain(Arrays.asList(certChain)); + validateCertChain(Validator.VAR_CODE_SIGNING, + Arrays.asList(certChain), null); } catch (Exception e) { - if (debug) { - e.printStackTrace(); - } - if (e.getCause() != null && - (e.getCause() instanceof CertificateExpiredException || - e.getCause() instanceof CertificateNotYetValidException)) { - // No more warning, we alreay have hasExpiredCert or notYetValidCert - } else { - chainNotValidated = true; - } + chainNotValidated = true; + chainNotValidatedReason = e; + } + + if (KeyStoreUtil.isSelfSigned(certChain[0])) { + signerSelfSigned = true; } try { @@ -2101,19 +2241,55 @@ System.exit(1); } - void validateCertChain(List<? extends Certificate> certs) throws Exception { - int cpLen = 0; - out: for (; cpLen<certs.size(); cpLen++) { - for (TrustAnchor ta: pkixParameters.getTrustAnchors()) { - if (ta.getTrustedCert().equals(certs.get(cpLen))) { - break out; + /** + * Validates a cert chain. + * + * @param parameter this might be a timestamp + */ + void validateCertChain(String variant, List<? extends Certificate> certs, + Object parameter) + throws Exception { + try { + Validator.getInstance(Validator.TYPE_PKIX, + variant, + pkixParameters) + .validate(certs.toArray(new X509Certificate[certs.size()]), + null, parameter); + } catch (Exception e) { + if (debug) { + e.printStackTrace(); + } + + // Exception might be dismissed if another warning flag + // is already set by printCert. This is only done for + // code signing certs. + + if (variant.equals(Validator.VAR_CODE_SIGNING) && + e instanceof ValidatorException) { + // Throw cause if it's CertPathValidatorException, + if (e.getCause() != null && + e.getCause() instanceof CertPathValidatorException) { + e = (Exception) e.getCause(); + Throwable t = e.getCause(); + if ((t instanceof CertificateExpiredException && + hasExpiredCert) || + (t instanceof CertificateNotYetValidException && + notYetValidCert)) { + // we already have hasExpiredCert and notYetValidCert + return; + } + } + if (e instanceof ValidatorException) { + ValidatorException ve = (ValidatorException)e; + if (ve.getErrorType() == ValidatorException.T_EE_EXTENSIONS && + (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType)) { + // We already have badKeyUsage, badExtendedKeyUsage + // and badNetscapeCertType + return; + } } } - } - if (cpLen > 0) { - CertPath cp = certificateFactory.generateCertPath( - (cpLen == certs.size())? certs: certs.subList(0, cpLen)); - validator.validate(cp, pkixParameters); + throw e; } }
--- a/src/share/classes/sun/security/tools/jarsigner/Resources.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/security/tools/jarsigner/Resources.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -199,7 +199,8 @@ {"certificate.is.not.valid.until", "certificate is not valid until {0}"}, {"certificate.will.expire.on", "certificate will expire on {0}"}, - {".CertPath.not.validated.", "[CertPath not validated: "}, + {".Invalid.certificate.chain.", "[Invalid certificate chain: "}, + {".Invalid.TSA.certificate.chain.", "[Invalid TSA certificate chain: "}, {"requesting.a.signature.timestamp", "requesting a signature timestamp"}, {"TSA.location.", "TSA location: "}, @@ -216,6 +217,8 @@ {"entry.was.signed.on", "entry was signed on {0}"}, {"Warning.", "Warning: "}, {"Error.", "Error: "}, + {"...Signer", ">>> Signer"}, + {"...TSA", ">>> TSA"}, {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.", "This jar contains unsigned entries which have not been integrity-checked. "}, {"This.jar.contains.entries.whose.signer.certificate.has.expired.", @@ -224,6 +227,8 @@ "This jar contains entries whose signer certificate will expire within six months. "}, {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.", "This jar contains entries whose signer certificate is not yet valid. "}, + {"This.jar.contains.entries.whose.signer.certificate.is.self.signed.", + "This jar contains entries whose signer certificate is self-signed."}, {"Re.run.with.the.verbose.option.for.more.details.", "Re-run with the -verbose option for more details."}, {"Re.run.with.the.verbose.and.certs.options.for.more.details.", @@ -248,14 +253,24 @@ "This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."}, {".{0}.extension.does.not.support.code.signing.", "[{0} extension does not support code signing]"}, - {"The.signer.s.certificate.chain.is.not.validated.", - "The signer's certificate chain is not validated."}, - {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.", - "This jar contains entries whose certificate chain is not validated."}, + {"The.signer.s.certificate.chain.is.invalid.reason.1", + "The signer's certificate chain is invalid. Reason: %s"}, + {"The.tsa.certificate.chain.is.invalid.reason.1", + "The TSA certificate chain is invalid. Reason: %s"}, + {"The.signer.s.certificate.is.self.signed.", + "The signer's certificate is self-signed."}, + {"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.", + "The %1$s algorithm specified for the %2$s option is considered a security risk."}, + {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1", + "This jar contains entries whose certificate chain is invalid. Reason: %s"}, + {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1", + "This jar contains entries whose TSA certificate chain is invalid. Reason: %s"}, {"no.timestamp.signing", "No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."}, {"no.timestamp.verifying", "This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."}, + {"bad.timestamp.verifying", + "This jar contains signatures that include an invalid timestamp. Without a valid timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td).\nRerun jarsigner with -J-Djava.security.debug=jar for more information."}, {"Unknown.password.type.", "Unknown password type: "}, {"Cannot.find.environment.variable.", "Cannot find environment variable: "},
--- a/src/share/classes/sun/security/tools/keytool/Main.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/security/tools/keytool/Main.java Fri Aug 03 19:50:58 2018 +0100 @@ -1352,7 +1352,7 @@ for (Certificate ca: keyStore.getCertificateChain(alias)) { if (ca instanceof X509Certificate) { X509Certificate xca = (X509Certificate)ca; - if (!isSelfSigned(xca)) { + if (!KeyStoreUtil.isSelfSigned(xca)) { dumpCert(xca, out); } } @@ -2869,7 +2869,7 @@ // if certificate is self-signed, make sure it verifies boolean selfSigned = false; - if (isSelfSigned(cert)) { + if (KeyStoreUtil.isSelfSigned(cert)) { cert.verify(cert.getPublicKey()); selfSigned = true; } @@ -3173,25 +3173,6 @@ } /** - * Returns true if the certificate is self-signed, false otherwise. - */ - private boolean isSelfSigned(X509Certificate cert) { - return signedBy(cert, cert); - } - - private boolean signedBy(X509Certificate end, X509Certificate ca) { - if (!ca.getSubjectDN().equals(end.getIssuerDN())) { - return false; - } - try { - end.verify(ca.getPublicKey()); - return true; - } catch (Exception e) { - return false; - } - } - - /** * Locates a signer for a given certificate from a given keystore and * returns the signer's certificate. * @param cert the certificate whose signer is searched, not null @@ -3531,7 +3512,7 @@ // find a cert in the reply who signs thisCert int j; for (j=i; j<replyCerts.length; j++) { - if (signedBy(thisCert, (X509Certificate)replyCerts[j])) { + if (KeyStoreUtil.signedBy(thisCert, (X509Certificate)replyCerts[j])) { tmpCert = replyCerts[i]; replyCerts[i] = replyCerts[j]; replyCerts[j] = tmpCert; @@ -3689,7 +3670,7 @@ private boolean buildChain(Pair<String,X509Certificate> certToVerify, Vector<Pair<String,X509Certificate>> chain, Hashtable<Principal, Vector<Pair<String,X509Certificate>>> certs) { - if (isSelfSigned(certToVerify.snd)) { + if (KeyStoreUtil.isSelfSigned(certToVerify.snd)) { // reached self-signed root cert; // no verification needed because it's trusted. chain.addElement(certToVerify);
--- a/src/share/classes/sun/security/util/SignatureFileVerifier.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/share/classes/sun/security/util/SignatureFileVerifier.java Fri Aug 03 19:50:58 2018 +0100 @@ -719,7 +719,8 @@ if (signers == null) { signers = new ArrayList<>(); } - // Append the new code signer + // Append the new code signer. If timestamp is invalid, this + // jar will be treated as unsigned. signers.add(new CodeSigner(certChain, info.getTimestamp())); if (debug != null) {
--- a/src/solaris/native/java/net/NetworkInterface.c Wed Aug 01 03:36:32 2018 -0700 +++ b/src/solaris/native/java/net/NetworkInterface.c Fri Aug 03 19:50:58 2018 +0100 @@ -335,10 +335,18 @@ jobject obj = NULL; jboolean match = JNI_FALSE; #if defined(AF_INET6) - int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6; + int family = getInetAddress_family(env, iaObj); JNU_CHECK_EXCEPTION_RETURN(env, NULL); + + if (family == IPv4) { + family = AF_INET; + } else if (family == IPv6) { + family = AF_INET6; + } else { + return NULL; // Invalid family + } #else - int family = AF_INET; + int family = AF_INET; #endif ifs = enumInterfaces(env); if (ifs == NULL) { @@ -357,7 +365,9 @@ int address1 = htonl( ((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr); int address2 = getInetAddress_addr(env, iaObj); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } if (address1 == address2) { match = JNI_TRUE; break; @@ -402,6 +412,7 @@ obj = createNetworkInterface(env, curr); } +cleanup: // release the interface list freeif(ifs);
--- a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -677,7 +677,7 @@ } try { - return invoke(new Callable<File[]>() { + File[] files = invoke(new Callable<File[]>() { public File[] call() throws InterruptedException { if (!isDirectory()) { return null; @@ -732,6 +732,9 @@ : list.toArray(new ShellFolder[list.size()]); } }, InterruptedException.class); + + return Win32ShellFolderManager2.checkFiles(files); + } catch (InterruptedException e) { return new File[0]; }
--- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed Aug 01 03:36:32 2018 -0700 +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -379,21 +379,30 @@ return null; } - private File checkFile(File file) { + private static File checkFile(File file) { SecurityManager sm = System.getSecurityManager(); return (sm == null || file == null) ? file : checkFile(file, sm); } - private File checkFile(File file, SecurityManager sm) { + private static File checkFile(File file, SecurityManager sm) { try { sm.checkRead(file.getPath()); + + if (file instanceof Win32ShellFolder2) { + Win32ShellFolder2 f = (Win32ShellFolder2)file; + if (f.isLink()) { + Win32ShellFolder2 link = (Win32ShellFolder2)f.getLinkLocation(); + if (link != null) + sm.checkRead(link.getPath()); + } + } return file; } catch (SecurityException se) { return null; } } - private File[] checkFiles(File[] files) { + static File[] checkFiles(File[] files) { SecurityManager sm = System.getSecurityManager(); if (sm == null || files == null || files.length == 0) { return files; @@ -401,7 +410,7 @@ return checkFiles(Arrays.stream(files), sm); } - private File[] checkFiles(List<File> files) { + private static File[] checkFiles(List<File> files) { SecurityManager sm = System.getSecurityManager(); if (sm == null || files.isEmpty()) { return files.toArray(new File[files.size()]); @@ -409,7 +418,7 @@ return checkFiles(files.stream(), sm); } - private File[] checkFiles(Stream<File> filesStream, SecurityManager sm) { + private static File[] checkFiles(Stream<File> filesStream, SecurityManager sm) { return filesStream.filter((file) -> checkFile(file, sm) != null) .toArray(File[]::new); }
--- a/src/windows/native/java/net/NetworkInterface.c Wed Aug 01 03:36:32 2018 -0700 +++ b/src/windows/native/java/net/NetworkInterface.c Fri Aug 03 19:50:58 2018 +0100 @@ -287,6 +287,7 @@ if (curr->name == NULL || curr->displayName == NULL) { if (curr->name) free(curr->name); if (curr->displayName) free(curr->displayName); + free(curr); curr = NULL; } } @@ -593,7 +594,10 @@ /* default ctor will set family to AF_INET */ setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + free_netaddr(netaddrP); + return NULL; + } if (addrs->mask != -1) { ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { @@ -607,7 +611,10 @@ return NULL; } setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + free_netaddr(netaddrP); + return NULL; + } (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); @@ -618,6 +625,7 @@ if (iaObj) { int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); if (ret == JNI_FALSE) { + free_netaddr(netaddrP); return NULL; }
--- a/src/windows/native/java/net/NetworkInterface_winXP.c Wed Aug 01 03:36:32 2018 -0700 +++ b/src/windows/native/java/net/NetworkInterface_winXP.c Fri Aug 03 19:50:58 2018 +0100 @@ -488,8 +488,9 @@ jobjectArray addrArr, bindsArr, childArr; netaddr *addrs; jint addr_index; - int netaddrCount=ifs->naddrs; - netaddr *netaddrP=ifs->addrs; + int netaddrCount = ifs->naddrs; + netaddr *netaddrP = ifs->addrs; + netaddr *netaddrPToFree = NULL; jint bind_index; /* @@ -520,21 +521,23 @@ * Note that 0 is a valid number of addresses. */ if (netaddrCount < 0) { - netaddrCount = enumAddresses_win(env, ifs, &netaddrP); + netaddrCount = enumAddresses_win(env, ifs, &netaddrPToFree); if (netaddrCount == -1) { return NULL; } + netaddrP = netaddrPToFree; } addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL); if (addrArr == NULL) { + free_netaddr(netaddrPToFree); return NULL; } bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL); if (bindsArr == NULL) { - free_netaddr(netaddrP); - return NULL; + free_netaddr(netaddrPToFree); + return NULL; } addrs = netaddrP; @@ -546,26 +549,32 @@ if (addrs->addr.him.sa_family == AF_INET) { iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); if (iaObj == NULL) { + free_netaddr(netaddrPToFree); return NULL; } /* default ctor will set family to AF_INET */ setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); - - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + free_netaddr(netaddrPToFree); + return NULL; + } ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { - free_netaddr(netaddrP); - return NULL; + free_netaddr(netaddrPToFree); + return NULL; } (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID); if (ia2Obj == NULL) { - free_netaddr(netaddrP); - return NULL; + free_netaddr(netaddrPToFree); + return NULL; } setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); - JNU_CHECK_EXCEPTION_RETURN(env, NULL); + if ((*env)->ExceptionCheck(env)) { + free_netaddr(netaddrPToFree); + return NULL; + } (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); @@ -574,10 +583,12 @@ int ret; iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID); if (iaObj == NULL) { + free_netaddr(netaddrPToFree); return NULL; } ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); if (ret == JNI_FALSE) { + free_netaddr(netaddrPToFree); return NULL; } scope = addrs->addr.him6.sin6_scope_id; @@ -587,8 +598,8 @@ } ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { - free_netaddr(netaddrP); - return NULL; + free_netaddr(netaddrPToFree); + return NULL; } (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); @@ -601,6 +612,8 @@ (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr); + free_netaddr(netaddrPToFree); + /* * Windows doesn't have virtual interfaces, so child array * is always empty. @@ -640,7 +653,7 @@ } /* if found create a NetworkInterface */ - if (curr != NULL) {; + if (curr != NULL) { netifObj = createNetworkInterfaceXP(env, curr); } @@ -767,6 +780,7 @@ /* allocate a NetworkInterface array */ netIFArr = (*env)->NewObjectArray(env, count, cls, NULL); if (netIFArr == NULL) { + free_netif(ifList); return NULL; } @@ -781,6 +795,7 @@ netifObj = createNetworkInterfaceXP(env, curr); if (netifObj == NULL) { + free_netif(ifList); return NULL; }
--- a/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c Wed Aug 01 03:36:32 2018 -0700 +++ b/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c Fri Aug 03 19:50:58 2018 +0100 @@ -445,7 +445,6 @@ "Protocol family not supported"); return; } - JNU_CHECK_EXCEPTION(env); if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); return;
--- a/src/windows/native/sun/security/mscapi/security.cpp Wed Aug 01 03:36:32 2018 -0700 +++ b/src/windows/native/sun/security/mscapi/security.cpp Fri Aug 03 19:50:58 2018 +0100 @@ -183,7 +183,6 @@ { HCRYPTPROV hCryptProv = NULL; - BYTE* pbData = NULL; jbyte* reseedBytes = NULL; jbyte* seedBytes = NULL; jbyteArray result = NULL; @@ -227,28 +226,17 @@ result = NULL; - } else if (length > 0) { + } else { - pbData = new (env) BYTE[length]; - if (pbData == NULL) { - __leave; + if (length > 0) { + seed = env->NewByteArray(length); + if (seed == NULL) { + __leave; + } + } else { + length = env->GetArrayLength(seed); } - if (::CryptGenRandom( - hCryptProv, - length, - pbData) == FALSE) { - - ThrowException(env, PROVIDER_EXCEPTION, GetLastError()); - __leave; - } - - result = env->NewByteArray(length); - env->SetByteArrayRegion(result, 0, length, (jbyte*) pbData); - - } else { // length == 0 - - length = env->GetArrayLength(seed); if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) { __leave; } @@ -273,9 +261,6 @@ if (reseedBytes) env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT); - if (pbData) - delete [] pbData; - if (seedBytes) env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig
--- a/test/javax/sound/midi/Gervill/RiffReaderWriter/Skip.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/javax/sound/midi/Gervill/RiffReaderWriter/Skip.java Fri Aug 03 19:50:58 2018 +0100 @@ -27,9 +27,8 @@ import java.io.File; import java.io.FileInputStream; -import javax.sound.sampled.*; - -import com.sun.media.sound.*; +import com.sun.media.sound.RIFFReader; +import com.sun.media.sound.RIFFWriter; public class Skip { @@ -40,6 +39,11 @@ } public static void main(String[] args) throws Exception { + test(false); + test(true); + } + + private static void test(boolean customStream) throws Exception { RIFFWriter writer = null; RIFFReader reader = null; File tempfile = File.createTempFile("test",".riff"); @@ -51,7 +55,17 @@ chunk.write((byte)44); writer.close(); writer = null; - FileInputStream fis = new FileInputStream(tempfile); + final FileInputStream fis; + if (customStream) { + fis = new FileInputStream(tempfile); + } else { + fis = new FileInputStream(tempfile) { + @Override + public long skip(long n) { + return 0; + } + }; + } reader = new RIFFReader(fis); RIFFReader readchunk = reader.nextChunk(); reader.skip(1);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lib/testlibrary/jdk/testlibrary/InMemoryJavaCompiler.java Fri Aug 03 19:50:58 2018 +0100 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import java.net.URI; +import java.util.Arrays; + +import javax.tools.ForwardingJavaFileManager; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.FileObject; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +/** + * {@code InMemoryJavaCompiler} can be used for compiling a {@link + * CharSequence} to a {@code byte[]}. + * + * The compiler will not use the file system at all, instead using a {@link + * ByteArrayOutputStream} for storing the byte code. For the source code, any + * kind of {@link CharSequence} can be used, e.g. {@link String}, {@link + * StringBuffer} or {@link StringBuilder}. + * + * The {@code InMemoryCompiler} can easily be used together with a {@code + * ByteClassLoader} to easily compile and load source code in a {@link String}: + * + * <pre> + * {@code + * import com.oracle.java.testlibrary.InMemoryJavaCompiler; + * import com.oracle.java.testlibrary.ByteClassLoader; + * + * class Example { + * public static void main(String[] args) { + * String className = "Foo"; + * String sourceCode = "public class " + className + " {" + + * " public void bar() {" + + * " System.out.println("Hello from bar!");" + + * " }" + + * "}"; + * byte[] byteCode = InMemoryJavaCompiler.compile(className, sourceCode); + * Class fooClass = ByteClassLoader.load(className, byteCode); + * } + * } + * } + * </pre> + */ +public class InMemoryJavaCompiler { + private static class MemoryJavaFileObject extends SimpleJavaFileObject { + private final String className; + private final CharSequence sourceCode; + private final ByteArrayOutputStream byteCode; + + public MemoryJavaFileObject(String className, CharSequence sourceCode) { + super(URI.create("string:///" + className.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); + this.className = className; + this.sourceCode = sourceCode; + this.byteCode = new ByteArrayOutputStream(); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return sourceCode; + } + + @Override + public OutputStream openOutputStream() throws IOException { + return byteCode; + } + + public byte[] getByteCode() { + return byteCode.toByteArray(); + } + + public String getClassName() { + return className; + } + } + + private static class FileManagerWrapper extends ForwardingJavaFileManager { + private MemoryJavaFileObject file; + + public FileManagerWrapper(MemoryJavaFileObject file) { + super(getCompiler().getStandardFileManager(null, null, null)); + this.file = file; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, + Kind kind, FileObject sibling) + throws IOException { + if (!file.getClassName().equals(className)) { + throw new IOException("Expected class with name " + file.getClassName() + + ", but got " + className); + } + return file; + } + } + + /** + * Compiles the class with the given name and source code. + * + * @param className The name of the class + * @param sourceCode The source code for the class with name {@code className} + * @throws RuntimeException if the compilation did not succeed + * @return The resulting byte code from the compilation + */ + public static byte[] compile(String className, CharSequence sourceCode) { + MemoryJavaFileObject file = new MemoryJavaFileObject(className, sourceCode); + CompilationTask task = getCompilationTask(file); + + if(!task.call()) { + throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode); + } + + return file.getByteCode(); + } + + private static JavaCompiler getCompiler() { + return ToolProvider.getSystemJavaCompiler(); + } + + private static CompilationTask getCompilationTask(MemoryJavaFileObject file) { + return getCompiler().getTask(null, new FileManagerWrapper(file), null, null, null, Arrays.asList(file)); + } +}
--- a/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,16 +23,21 @@ package jdk.testlibrary; +import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -45,6 +50,72 @@ public final class JarUtils { /** + * Creates a JAR file. + * + * Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...} + * + * The input files are resolved against the given directory. Any input + * files that are directories are processed recursively. + */ + public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... file) + throws IOException + { + // create the target directory + Path parent = jarfile.getParent(); + if (parent != null) + Files.createDirectories(parent); + + List<Path> entries = new ArrayList<>(); + for (Path entry : file) { + Files.find(dir.resolve(entry), Integer.MAX_VALUE, + (p, attrs) -> attrs.isRegularFile()) + .map(e -> dir.relativize(e)) + .forEach(entries::add); + } + + try (OutputStream out = Files.newOutputStream(jarfile); + JarOutputStream jos = new JarOutputStream(out)) + { + if (man != null) { + JarEntry je = new JarEntry(JarFile.MANIFEST_NAME); + jos.putNextEntry(je); + man.write(jos); + jos.closeEntry(); + } + + for (Path entry : entries) { + String name = toJarEntryName(entry); + jos.putNextEntry(new JarEntry(name)); + Files.copy(dir.resolve(entry), jos); + jos.closeEntry(); + } + } + } + + /** + * Creates a JAR file. + * + * Equivalent to {@code jar cf <jarfile> -C <dir> file...} + * + * The input files are resolved against the given directory. Any input + * files that are directories are processed recursively. + */ + public static void createJarFile(Path jarfile, Path dir, Path... file) + throws IOException + { + createJarFile(jarfile, null, dir, file); + } + + /** + * Creates a JAR file from the contents of a directory. + * + * Equivalent to {@code jar cf <jarfile> -C <dir> .} + */ + public static void createJarFile(Path jarfile, Path dir) throws IOException { + createJarFile(jarfile, dir, Paths.get(".")); + } + + /** * Create jar file with specified files. If a specified file does not exist, * a new jar entry will be created with the file name itself as the content. */ @@ -126,6 +197,11 @@ changes = new HashMap<>(changes); System.out.printf("Creating %s from %s...\n", dest, src); + + if (dest.equals(src)) { + throw new IOException("src and dest cannot be the same"); + } + try (JarOutputStream jos = new JarOutputStream( new FileOutputStream(dest))) { @@ -153,6 +229,24 @@ System.out.println(); } + /** + * Update the Manifest inside a jar. + * + * @param src the original jar file name + * @param dest the new jar file name + * @param man the Manifest + * + * @throws IOException + */ + public static void updateManifest(String src, String dest, Manifest man) + throws IOException { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + man.write(bout); + Map<String, Object> map = new HashMap<>(); + map.put(JarFile.MANIFEST_NAME, bout.toByteArray()); + updateJar(src, dest, map); + } + private static void updateEntry(JarOutputStream jos, String name, Object content) throws IOException { if (content instanceof Boolean) { @@ -172,4 +266,14 @@ } } } + + /** + * Map a file path to the equivalent name in a JAR file + */ + private static String toJarEntryName(Path file) { + Path normalized = file.normalize(); + return normalized.subpath(0, normalized.getNameCount()) // drop root + .toString() + .replace(File.separatorChar, '/'); + } }
--- a/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java Fri Aug 03 19:50:58 2018 +0100 @@ -39,7 +39,7 @@ private final String stdout; private final String stderr; - private final int exitValue; + private final int exitValue; // useless now. output contains exit value. /** * Create an OutputAnalyzer, a utility class for verifying output and exit
--- a/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.PrintStream; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; @@ -353,9 +354,31 @@ * @return The output from the process. */ public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Throwable { + return executeProcess(pb, null); + } + + /** + * Executes a process, pipe some text into its STDIN, waits for it + * to finish and returns the process output. The process will have exited + * before this method returns. + * @param pb The ProcessBuilder to execute. + * @param input The text to pipe into STDIN. Can be null. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input) + throws Throwable { OutputAnalyzer output = null; + Process p = null; try { - output = new OutputAnalyzer(pb.start()); + p = pb.start(); + if (input != null) { + try (OutputStream os = p.getOutputStream(); + PrintStream ps = new PrintStream(os)) { + ps.print(input); + ps.flush(); + } + } + output = new OutputAnalyzer(p); return output; } catch (Throwable t) { System.out.println("executeProcess() failed: " + t);
--- a/test/lib/testlibrary/jdk/testlibrary/SecurityTools.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/lib/testlibrary/jdk/testlibrary/SecurityTools.java Fri Aug 03 19:50:58 2018 +0100 @@ -49,10 +49,7 @@ launcher.addToolArg(arg); } } - String[] cmds = launcher.getCommand(); - String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" ")); - System.out.println("Command line: [" + cmdLine + "]"); - return new ProcessBuilder(cmds); + return new ProcessBuilder(launcher.getCommand()); } // keytool @@ -69,7 +66,7 @@ pb.redirectInput(ProcessBuilder.Redirect.from(new File(RESPONSE_FILE))); try { - return ProcessTools.executeProcess(pb); + return execute(pb); } catch (Throwable t) { throw new RuntimeException("keytool failure: " + t); } finally { @@ -101,11 +98,20 @@ public static OutputAnalyzer jarsigner(List<String> args) throws Exception { + return execute(getProcessBuilder("jarsigner", args)); + } + + private static OutputAnalyzer execute(ProcessBuilder pb) throws Exception { try { - return ProcessTools.executeProcess( - getProcessBuilder("jarsigner", args)); + OutputAnalyzer oa = ProcessTools.executeCommand(pb); + System.out.println("Exit value: " + oa.getExitValue()); + return oa; } catch (Throwable t) { - throw new RuntimeException("jarsigner error: " + t); + if (t instanceof Exception) { + throw (Exception) t; + } else { + throw new Exception(t); + } } }
--- a/test/sun/rmi/transport/tcp/DisableRMIOverHttp/DisableRMIOverHTTPTest.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/sun/rmi/transport/tcp/DisableRMIOverHttp/DisableRMIOverHTTPTest.java Fri Aug 03 19:50:58 2018 +0100 @@ -22,7 +22,7 @@ */ /* @test - * @bug 8193833 + * @bug 8158963 * * @summary Disable RMI over HTTP by default *
--- a/test/sun/security/tools/jarsigner/TimestampCheck.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/sun/security/tools/jarsigner/TimestampCheck.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,8 @@ */ import com.sun.net.httpserver.*; + +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -36,16 +38,18 @@ import java.security.PrivateKey; import java.security.Signature; import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.List; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; import sun.misc.IOUtils; -import jdk.testlibrary.*; +import jdk.testlibrary.SecurityTools; +import jdk.testlibrary.OutputAnalyzer; import jdk.testlibrary.JarUtils; import sun.security.pkcs.ContentInfo; import sun.security.pkcs.PKCS7; @@ -58,9 +62,12 @@ import sun.security.x509.AlgorithmId; import sun.security.x509.X500Name; +import jdk.testlibrary.Utils; + /* * @test * @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8169688 8171121 + * 8180289 * @summary checking response of timestamp * @modules java.base/sun.security.pkcs * java.base/sun.security.timestamp @@ -68,7 +75,7 @@ * java.base/sun.security.util * java.base/sun.security.tools.keytool * @library /lib/testlibrary - * @run main/timeout=600 TimestampCheck + * @run main/othervm/timeout=600 TimestampCheck */ public class TimestampCheck { @@ -114,12 +121,12 @@ */ byte[] sign(byte[] input, String path) throws Exception { DerValue value = new DerValue(input); - System.err.println("\nIncoming Request\n==================="); - System.err.println("Version: " + value.data.getInteger()); + System.out.println("\nIncoming Request\n==================="); + System.out.println("Version: " + value.data.getInteger()); DerValue messageImprint = value.data.getDerValue(); AlgorithmId aid = AlgorithmId.parse( messageImprint.data.getDerValue()); - System.err.println("AlgorithmId: " + aid); + System.out.println("AlgorithmId: " + aid); ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId); BigInteger nonce = null; @@ -127,25 +134,24 @@ DerValue v = value.data.getDerValue(); if (v.tag == DerValue.tag_Integer) { nonce = v.getBigInteger(); - System.err.println("nonce: " + nonce); + System.out.println("nonce: " + nonce); } else if (v.tag == DerValue.tag_Boolean) { - System.err.println("certReq: " + v.getBoolean()); + System.out.println("certReq: " + v.getBoolean()); } else if (v.tag == DerValue.tag_ObjectId) { policyId = v.getOID(); - System.err.println("PolicyID: " + policyId); + System.out.println("PolicyID: " + policyId); } } - System.err.println("\nResponse\n==================="); + System.out.println("\nResponse\n==================="); FileInputStream is = new FileInputStream(keystore); KeyStore ks = KeyStore.getInstance("JCEKS"); ks.load(is, "changeit".toCharArray()); is.close(); - String alias = "ts"; - if (path.startsWith("bad") || path.equals("weak")) { - alias = "ts" + path; - } + // If path starts with "ts", use the TSA it points to. + // Otherwise, always use "ts". + String alias = path.startsWith("ts") ? path : "ts"; if (path.equals("diffpolicy")) { policyId = new ObjectIdentifier(defaultPolicyId); @@ -192,8 +198,11 @@ tst.putInteger(1); - Calendar cal = Calendar.getInstance(); - tst.putGeneralizedTime(cal.getTime()); + Instant instant = Instant.now(); + if (path.equals("tsold")) { + instant = instant.minus(20, ChronoUnit.DAYS); + } + tst.putGeneralizedTime(Date.from(instant)); if (path.equals("diffnonce")) { tst.putInteger(1234); @@ -220,10 +229,10 @@ "1.2.840.113549.1.9.16.1.4"), new DerValue(tstInfo2.toByteArray())); - System.err.println("Signing..."); - System.err.println(new X500Name(signer + System.out.println("Signing..."); + System.out.println(new X500Name(signer .getIssuerX500Principal().getName())); - System.err.println(signer.getSerialNumber()); + System.out.println(signer.getSerialNumber()); SignerInfo signerInfo = new SignerInfo( new X500Name(signer.getIssuerX500Principal().getName()), @@ -296,24 +305,52 @@ prepare(); - try (Handler tsa = Handler.init(0, "tsks");) { + try (Handler tsa = Handler.init(0, "ks");) { tsa.start(); int port = tsa.getPort(); host = "http://localhost:" + port + "/"; if (args.length == 0) { // Run this test - sign("none") + + sign("normal") + .shouldNotContain("Warning") + .shouldHaveExitValue(0); + + verify("normal.jar") + .shouldNotContain("Warning") + .shouldHaveExitValue(0); + + // Simulate signing at a previous date: + // 1. tsold will create a timestamp of 20 days ago. + // 2. oldsigner expired 10 days ago. + // jarsigner will show a warning at signing. + signVerbose("tsold", "unsigned.jar", "tsold.jar", "oldsigner") + .shouldHaveExitValue(4); + + // It verifies perfectly. + verify("tsold.jar", "-verbose", "-certs") + .shouldNotContain("Warning") + .shouldHaveExitValue(0); + + signVerbose(null, "unsigned.jar", "none.jar", "signer") .shouldContain("is not timestamped") .shouldHaveExitValue(0); - sign("badku") - .shouldHaveExitValue(0); + signVerbose(null, "unsigned.jar", "badku.jar", "badku") + .shouldHaveExitValue(8); checkBadKU("badku.jar"); - sign("normal") - .shouldNotContain("is not timestamped") - .shouldHaveExitValue(0); + // 8180289: unvalidated TSA cert chain + sign("tsnoca") + .shouldContain("TSA certificate chain is invalid") + .shouldHaveExitValue(64); + + verify("tsnoca.jar", "-verbose", "-certs") + .shouldHaveExitValue(64) + .shouldContain("jar verified") + .shouldContain("Invalid TSA certificate chain") + .shouldContain("TSA certificate chain is invalid"); sign("nononce") .shouldHaveExitValue(1); @@ -325,11 +362,11 @@ .shouldHaveExitValue(1); sign("fullchain") .shouldHaveExitValue(0); // Success, 6543440 solved. - sign("bad1") + sign("tsbad1") .shouldHaveExitValue(1); - sign("bad2") + sign("tsbad2") .shouldHaveExitValue(1); - sign("bad3") + sign("tsbad3") .shouldHaveExitValue(1); sign("nocert") .shouldHaveExitValue(1); @@ -341,119 +378,171 @@ sign("diffpolicy", "-tsapolicyid", "1.2.3") .shouldHaveExitValue(1); - sign("tsaalg", "-tsadigestalg", "SHA") + sign("sha1alg", "-tsadigestalg", "SHA") .shouldHaveExitValue(0); - checkTimestamp("tsaalg.jar", defaultPolicyId, "SHA-1"); + checkTimestamp("sha1alg.jar", defaultPolicyId, "SHA-1"); - sign("weak", "-digestalg", "MD5", + sign("tsweak", "-digestalg", "MD5", "-sigalg", "MD5withRSA", "-tsadigestalg", "MD5") - .shouldHaveExitValue(0); - checkWeak("weak.jar"); + .shouldHaveExitValue(68); + checkWeak("tsweak.jar"); + + signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer") + .shouldHaveExitValue(64) + .shouldContain("TSA certificate chain is invalid"); - signWithAliasAndTsa("halfWeak", "old.jar", "old", "-digestalg", "MD5") - .shouldHaveExitValue(0); + // Weak timestamp is an error and jar treated unsigned + verify("tsweak2.jar", "-verbose") + .shouldHaveExitValue(16) + .shouldContain("treated as unsigned") + .shouldMatch("Timestamp.*512.*weak"); + + signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer", + "-digestalg", "MD5") + .shouldHaveExitValue(4); checkHalfWeak("halfWeak.jar"); // sign with DSA key - signWithAliasAndTsa("sign1", "old.jar", "dsakey") + signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey") .shouldHaveExitValue(0); // sign with RSAkeysize < 1024 - signWithAliasAndTsa("sign2", "sign1.jar", "weakkeysize") - .shouldHaveExitValue(0); + signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize") + .shouldHaveExitValue(4); checkMultiple("sign2.jar"); // When .SF or .RSA is missing or invalid checkMissingOrInvalidFiles("normal.jar"); + + if (Files.exists(Paths.get("ts2.cert"))) { + checkInvalidTsaCertKeyUsage(); + } } else { // Run as a standalone server - System.err.println("Press Enter to quit server"); + System.out.println("Press Enter to quit server"); System.in.read(); } } } + private static void checkInvalidTsaCertKeyUsage() throws Exception { + + // Hack: Rewrite the TSA cert inside normal.jar into ts2.jar. + + // Both the cert and the serial number must be rewritten. + byte[] tsCert = Files.readAllBytes(Paths.get("ts.cert")); + byte[] ts2Cert = Files.readAllBytes(Paths.get("ts2.cert")); + byte[] tsSerial = getCert(tsCert) + .getSerialNumber().toByteArray(); + byte[] ts2Serial = getCert(ts2Cert) + .getSerialNumber().toByteArray(); + + byte[] oldBlock; + try (JarFile normal = new JarFile("normal.jar")) { + oldBlock = Utils.readAllBytes(normal.getInputStream( + normal.getJarEntry("META-INF/SIGNER.RSA"))); + } + + JarUtils.updateJar("normal.jar", "ts2.jar", + mapOf("META-INF/SIGNER.RSA", + updateBytes(updateBytes(oldBlock, tsCert, ts2Cert), + tsSerial, ts2Serial))); + + verify("ts2.jar", "-verbose", "-certs") + .shouldHaveExitValue(64) + .shouldContain("jar verified") + .shouldContain("Invalid TSA certificate chain: Extended key usage does not permit use for TSA server"); + } + + public static X509Certificate getCert(byte[] data) + throws CertificateException, IOException { + return (X509Certificate) + CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(data)); + } + + private static byte[] updateBytes(byte[] old, byte[] from, byte[] to) { + int pos = 0; + while (true) { + if (pos + from.length > old.length) { + return null; + } + if (Arrays.equals(Arrays.copyOfRange(old, pos, pos+from.length), from)) { + byte[] result = old.clone(); + System.arraycopy(to, 0, result, pos, from.length); + return result; + } + pos++; + } + } + private static void checkMissingOrInvalidFiles(String s) throws Throwable { - JarUtils.updateJar(s, "1.jar", "-", "META-INF/OLD.SF"); + + JarUtils.updateJar(s, "1.jar", mapOf("META-INF/SIGNER.SF", Boolean.FALSE)); verify("1.jar", "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") - .shouldContain("Missing signature-related file META-INF/OLD.SF"); - JarUtils.updateJar(s, "2.jar", "-", "META-INF/OLD.RSA"); + .shouldContain("Missing signature-related file META-INF/SIGNER.SF"); + JarUtils.updateJar(s, "2.jar", mapOf("META-INF/SIGNER.RSA", Boolean.FALSE)); verify("2.jar", "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") - .shouldContain("Missing block file for signature-related file META-INF/OLD.SF"); - JarUtils.updateJar(s, "3.jar", "META-INF/OLD.SF"); + .shouldContain("Missing block file for signature-related file META-INF/SIGNER.SF"); + JarUtils.updateJar(s, "3.jar", mapOf("META-INF/SIGNER.SF", "dummy")); verify("3.jar", "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") - .shouldContain("Unparsable signature-related file META-INF/OLD.SF"); - JarUtils.updateJar(s, "4.jar", "META-INF/OLD.RSA"); + .shouldContain("Unparsable signature-related file META-INF/SIGNER.SF"); + JarUtils.updateJar(s, "4.jar", mapOf("META-INF/SIGNER.RSA", "dummy")); verify("4.jar", "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") - .shouldContain("Unparsable signature-related file META-INF/OLD.RSA"); + .shouldContain("Unparsable signature-related file META-INF/SIGNER.RSA"); } static OutputAnalyzer jarsigner(List<String> extra) - throws Throwable { - JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner") - .addVMArg("-Duser.language=en") - .addVMArg("-Duser.country=US") - .addToolArg("-keystore") - .addToolArg("tsks") - .addToolArg("-storepass") - .addToolArg("changeit"); - for (String s : extra) { - if (s.startsWith("-J")) { - launcher.addVMArg(s.substring(2)); - } else { - launcher.addToolArg(s); - } - } - System.err.println("COMMAND: "); - for (String cmd : launcher.getCommand()) { - System.err.print(cmd + " "); - } - System.err.println(); - return ProcessTools.executeCommand(launcher.getCommand()); + throws Exception { + List<String> args = new ArrayList<>( + listOf("-keystore", "ks", "-storepass", "changeit")); + args.addAll(extra); + return SecurityTools.jarsigner(args); } static OutputAnalyzer verify(String file, String... extra) - throws Throwable { + throws Exception { List<String> args = new ArrayList<>(); args.add("-verify"); + args.add("-strict"); args.add(file); args.addAll(Arrays.asList(extra)); return jarsigner(args); } - static void checkBadKU(String file) throws Throwable { + static void checkBadKU(String file) throws Exception { System.err.println("BadKU: " + file); verify(file) - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldContain("re-run jarsigner with debug enabled"); verify(file, "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("Signed by") .shouldContain("treated as unsigned") .shouldContain("re-run jarsigner with debug enabled"); verify(file, "-J-Djava.security.debug=jar") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("SignatureException: Key usage restricted") .shouldContain("treated as unsigned") .shouldContain("re-run jarsigner with debug enabled"); } - static void checkWeak(String file) throws Throwable { + static void checkWeak(String file) throws Exception { verify(file) - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldMatch("weak algorithm that is now disabled.") .shouldMatch("Re-run jarsigner with the -verbose option for more details"); verify(file, "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldMatch("weak algorithm that is now disabled by") .shouldMatch("Digest algorithm: .*weak") @@ -462,18 +551,18 @@ .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak") .shouldMatch("Timestamp signature algorithm: .*key.*weak"); verify(file, "-J-Djava.security.debug=jar") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldMatch("SignatureException:.*disabled"); } - static void checkHalfWeak(String file) throws Throwable { + static void checkHalfWeak(String file) throws Exception { verify(file) - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldMatch("weak algorithm that is now disabled.") .shouldMatch("Re-run jarsigner with the -verbose option for more details"); verify(file, "-verbose") - .shouldHaveExitValue(0) + .shouldHaveExitValue(16) .shouldContain("treated as unsigned") .shouldMatch("weak algorithm that is now disabled by") .shouldMatch("Digest algorithm: .*weak") @@ -483,7 +572,7 @@ .shouldNotMatch("Timestamp signature algorithm: .*key.*weak"); } - static void checkMultiple(String file) throws Throwable { + static void checkMultiple(String file) throws Exception { verify(file) .shouldHaveExitValue(0) .shouldContain("jar verified"); @@ -500,7 +589,7 @@ static void checkTimestamp(String file, String policyId, String digestAlg) throws Exception { try (JarFile jf = new JarFile(file)) { - JarEntry je = jf.getJarEntry("META-INF/OLD.RSA"); + JarEntry je = jf.getJarEntry("META-INF/SIGNER.RSA"); try (InputStream is = jf.getInputStream(je)) { byte[] content = IOUtils.readFully(is, -1, true); PKCS7 p7 = new PKCS7(content); @@ -526,26 +615,38 @@ static int which = 0; /** + * Sign with a TSA path. Always use alias "signer" to sign "unsigned.jar". + * The signed jar name is always path.jar. + * * @param extra more args given to jarsigner */ static OutputAnalyzer sign(String path, String... extra) - throws Throwable { - String alias = path.equals("badku") ? "badku" : "old"; - return signWithAliasAndTsa(path, "old.jar", alias, extra); + throws Exception { + return signVerbose( + path, + "unsigned.jar", + path + ".jar", + "signer", + extra); } - static OutputAnalyzer signWithAliasAndTsa (String path, String jar, - String alias, String...extra) throws Throwable { + static OutputAnalyzer signVerbose( + String path, // TSA URL path + String oldJar, + String newJar, + String alias, // signer + String...extra) throws Exception { which++; - System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra)); + System.out.println("\n>> Test #" + which); List<String> args = new ArrayList<>(); - args.add("-J-Djava.security.egd=file:/dev/./urandom"); + args.add("-strict"); + args.add("-verbose"); args.add("-debug"); args.add("-signedjar"); - args.add(path + ".jar"); - args.add(jar); + args.add(newJar); + args.add(oldJar); args.add(alias); - if (!path.equals("none") && !path.equals("badku")) { + if (path != null) { args.add("-tsa"); args.add(host + path); } @@ -554,24 +655,54 @@ } static void prepare() throws Exception { - jdk.testlibrary.JarUtils.createJar("old.jar", "A"); - Files.deleteIfExists(Paths.get("tsks")); - keytool("-alias ca -genkeypair -ext bc -dname CN=CA"); - keytool("-alias old -genkeypair -dname CN=old"); + JarUtils.createJar("unsigned.jar", "A"); + Files.deleteIfExists(Paths.get("ks")); + keytool("-alias signer -genkeypair -ext bc -dname CN=signer"); + keytool("-alias oldsigner -genkeypair -dname CN=oldsigner"); keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey"); keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize"); keytool("-alias badku -genkeypair -dname CN=badku"); keytool("-alias ts -genkeypair -dname CN=ts"); - keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1"); + keytool("-alias tsold -genkeypair -dname CN=tsold"); + keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsweak"); keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1"); keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2"); keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3"); + keytool("-alias tsnoca -genkeypair -dname CN=tsnoca"); - gencert("old"); + // tsnoca's issuer will be removed from keystore later + keytool("-alias ca -genkeypair -ext bc -dname CN=CA"); + gencert("tsnoca", "-ext eku:critical=ts"); + keytool("-delete -alias ca"); + keytool("-alias ca -genkeypair -ext bc -dname CN=CA -startdate -40d"); + + gencert("signer"); + gencert("oldsigner", "-startdate -30d -validity 20"); gencert("dsakey"); gencert("weakkeysize"); gencert("badku", "-ext ku:critical=keyAgreement"); gencert("ts", "-ext eku:critical=ts"); + + + for (int i = 0; i < 5; i++) { + // Issue another cert for "ts" with a different EKU. + // Length might be different because serial number is + // random. Try several times until a cert with the same + // length is generated so we can substitute ts.cert + // embedded in the PKCS7 block with ts2.cert. + // If cannot create one, related test will be ignored. + keytool("-gencert -alias ca -infile ts.req -outfile ts2.cert " + + "-ext eku:critical=1.3.6.1.5.5.7.3.9"); + if (Files.size(Paths.get("ts.cert")) != Files.size(Paths.get("ts2.cert"))) { + Files.delete(Paths.get("ts2.cert")); + System.out.println("Warning: cannot create same length"); + } else { + break; + } + } + + gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 45"); + gencert("tsweak", "-ext eku:critical=ts"); gencert("tsbad1"); gencert("tsbad2", "-ext eku=ts"); @@ -590,8 +721,16 @@ } static void keytool(String cmd) throws Exception { - cmd = "-keystore tsks -storepass changeit -keypass changeit " + + cmd = "-keystore ks -storepass changeit -keypass changeit " + "-keyalg rsa -validity 200 " + cmd; sun.security.tools.keytool.Main.main(cmd.split(" ")); } + + static <K,V> Map<K,V> mapOf(K k1, V v1) { + return Collections.singletonMap(k1, v1); + } + + static <E> List<E> listOf(E... elements) { + return Arrays.asList(elements); + } }
--- a/test/sun/security/tools/jarsigner/TsacertOptionTest.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/sun/security/tools/jarsigner/TsacertOptionTest.java Fri Aug 03 19:50:58 2018 +0100 @@ -46,6 +46,7 @@ + ".txt"; private static final String PASSWORD = "changeit"; private static final String KEYSTORE = "ks.jks"; + private static final String CA_KEY_ALIAS = "ca"; private static final String SIGNING_KEY_ALIAS = "sign_alias"; private static final String TSA_KEY_ALIAS = "ts"; private static final String KEY_ALG = "RSA"; @@ -73,20 +74,52 @@ // look for free network port for TSA service int port = jdk.testlibrary.Utils.getFreePort(); - String host = jdk.testlibrary.Utils.getHostname(); + String host = "127.0.0.1"; String tsaUrl = "http://" + host + ":" + port; // create key pair for jar signing ProcessTools.executeCommand(KEYTOOL, "-genkey", + "-alias", CA_KEY_ALIAS, + "-keyalg", KEY_ALG, + "-keysize", Integer.toString(KEY_SIZE), + "-keystore", KEYSTORE, + "-storepass", PASSWORD, + "-keypass", PASSWORD, + "-dname", "CN=CA", + "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0); + ProcessTools.executeCommand(KEYTOOL, + "-genkey", "-alias", SIGNING_KEY_ALIAS, "-keyalg", KEY_ALG, "-keysize", Integer.toString(KEY_SIZE), "-keystore", KEYSTORE, "-storepass", PASSWORD, "-keypass", PASSWORD, - "-dname", "CN=Test", - "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0); + "-dname", "CN=Test").shouldHaveExitValue(0); + ProcessTools.executeCommand(KEYTOOL, + "-certreq", + "-alias", SIGNING_KEY_ALIAS, + "-keystore", KEYSTORE, + "-storepass", PASSWORD, + "-keypass", PASSWORD, + "-file", "certreq").shouldHaveExitValue(0); + ProcessTools.executeCommand(KEYTOOL, + "-gencert", + "-alias", CA_KEY_ALIAS, + "-keystore", KEYSTORE, + "-storepass", PASSWORD, + "-keypass", PASSWORD, + "-validity", Integer.toString(VALIDITY), + "-infile", "certreq", + "-outfile", "cert").shouldHaveExitValue(0); + ProcessTools.executeCommand(KEYTOOL, + "-importcert", + "-alias", SIGNING_KEY_ALIAS, + "-keystore", KEYSTORE, + "-storepass", PASSWORD, + "-keypass", PASSWORD, + "-file", "cert").shouldHaveExitValue(0); // create key pair for TSA service // SubjectInfoAccess extension contains URL to TSA service
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/tools/jarsigner/Warning.java Fri Aug 03 19:50:58 2018 +0100 @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.testlibrary.JDKToolLauncher; +import jdk.testlibrary.JarUtils; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; + +/** + * @test + * @bug 8024302 8026037 8130132 + * @summary warnings, errors and -strict + * @library /lib/testlibrary + */ +public class Warning { + + public static void main(String[] args) throws Throwable { + + Files.deleteIfExists(Paths.get("ks")); + + newCert("ca", "-validity 365000"); + + recreateJar(); + + newCert("a"); + run("jarsigner", "a.jar a") + .shouldContain("is self-signed"); + run("jarsigner", "a.jar a -strict") + .shouldContain("is self-signed") + .shouldHaveExitValue(4); + // Trusted entry can be self-signed without a warning + run("jarsigner", "-verify a.jar") + .shouldNotContain("is self-signed") + .shouldNotContain("not signed by alias in this keystore"); + run("keytool", "-delete -alias a"); + // otherwise a warning will be shown + run("jarsigner", "-verify a.jar") + .shouldContain("is self-signed") + .shouldContain("not signed by alias in this keystore"); + + recreateJar(); + + newCert("b"); + issueCert("b"); + run("jarsigner", "a.jar b") + .shouldNotContain("is self-signed"); + run("jarsigner", "-verify a.jar") + .shouldNotContain("is self-signed"); + + run("jarsigner", "a.jar b -digestalg MD5") + .shouldContain("-digestalg option is considered a security risk."); + run("jarsigner", "a.jar b -digestalg MD5 -strict") + .shouldHaveExitValue(4) + .shouldContain("-digestalg option is considered a security risk."); + run("jarsigner", "a.jar b -sigalg MD5withRSA") + .shouldContain("-sigalg option is considered a security risk"); + + issueCert("b", "-sigalg MD5withRSA"); + run("jarsigner", "a.jar b") + .shouldMatch("chain is invalid. Reason:.*MD5withRSA"); + + recreateJar(); + + newCert("c", "-keysize 512"); + issueCert("c"); + run("jarsigner", "a.jar c") + .shouldContain("chain is invalid. " + + "Reason: Algorithm constraints check failed"); + + recreateJar(); + + newCert("s1"); issueCert("s1", "-startdate 2000/01/01 -validity 36525"); + run("jarsigner", "a.jar s1") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp").shouldContain("2100-01-01") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s1 -strict") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp").shouldContain("2100-01-01") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s1 -verify") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp").shouldContain("2100-01-01") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s1 -verify -strict") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp").shouldContain("2100-01-01") + .shouldNotContain("with signer errors"); + + recreateJar(); + + newCert("s2"); issueCert("s2", "-validity 100"); + run("jarsigner", "a.jar s2") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp") + .shouldContain("will expire") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s2 -strict") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp") + .shouldContain("will expire") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s2 -verify") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp") + .shouldContain("will expire") + .shouldNotContain("with signer errors"); + run("jarsigner", "a.jar s2 -verify -strict") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("Error:") + .shouldContain("timestamp") + .shouldContain("will expire") + .shouldNotContain("with signer errors"); + + recreateJar(); + + newCert("s3"); issueCert("s3", "-startdate -200d -validity 100"); + run("jarsigner", "a.jar s3") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldContain("has expired") + .shouldNotContain("with signer errors") + .shouldNotContain("Error:"); + run("jarsigner", "a.jar s3 -strict") + .shouldHaveExitValue(4) + .shouldContain("with signer errors") + .shouldMatch("(?s).*Error:.*has expired.*Warning:.*"); + run("jarsigner", "a.jar s3 -verify") + .shouldHaveExitValue(0) + .shouldContain("Warning:") + .shouldNotContain("with signer errors") + .shouldNotContain("Error:"); + run("jarsigner", "a.jar s3 -verify -strict") + .shouldHaveExitValue(4) + .shouldContain("with signer errors") + .shouldMatch("(?s).*Error:.*has expired.*Warning:.*"); + } + + // Creates a new jar without signature + static void recreateJar() throws Exception { + JarUtils.createJar("a.jar", "ks"); + } + + // Creates a self-signed cert for alias with zero or more -genkey options + static void newCert(String alias, String... more) throws Throwable { + String args = "-genkeypair -alias " + alias + " -dname CN=" + alias; + for (String s: more) { + args += " " + s; + } + run("keytool", args).shouldHaveExitValue(0); + } + + // Asks ca to issue a cert to alias with zero or more -gencert options + static void issueCert(String alias, String...more) throws Throwable { + String req = run("keytool", "-certreq -alias " + alias) + .shouldHaveExitValue(0).getStdout(); + String args = "-gencert -alias ca -rfc"; + for (String s: more) { + args += " " + s; + } + String cert = run("keytool", args, req) + .shouldHaveExitValue(0).getStdout(); + run("keytool", "-import -alias " + alias, cert).shouldHaveExitValue(0); + } + + // Runs a java tool with command line arguments + static OutputAnalyzer run(String command, String args) + throws Throwable { + return run(command, args, null); + } + + // Runs a java tool with command line arguments and an optional input block + static OutputAnalyzer run(String command, String args, String input) + throws Throwable { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(command); + launcher.addVMArg("-Duser.language=en").addVMArg("-Duser.country=US"); + switch (command) { + case "keytool": + for (String s: new String[] { + "-keystore", "ks", "-storepass", "changeit", + "-storetype", "jks", + "-keypass", "changeit", "-keyalg", "rsa", "-debug"}) { + launcher.addToolArg(s); + } + break; + case "jarsigner": + for (String s: new String[] { + "-keystore", "ks", "-storepass", "changeit", + "-storetype", "jks"}) { + launcher.addToolArg(s); + } + break; + } + for (String arg: args.split(" ")) { + launcher.addToolArg(arg); + } + String[] cmd = launcher.getCommand(); + ProcessBuilder pb = new ProcessBuilder(cmd); + OutputAnalyzer out = ProcessTools.executeProcess(pb, input); + System.out.println("======================"); + System.out.println(Arrays.toString(cmd)); + String msg = " stdout: [" + out.getStdout() + "];\n" + + " stderr: [" + out.getStderr() + "]\n" + + " exitValue = " + out.getExitValue() + "\n"; + System.out.println(msg); + return out; + } +} +
--- a/test/sun/security/tools/jarsigner/checkusage.sh Wed Aug 01 03:36:32 2018 -0700 +++ b/test/sun/security/tools/jarsigner/checkusage.sh Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -91,7 +91,7 @@ #[ $RESULT = 0 ] || exit 2 # Test 3: When no keystore is specified, the error is only -# "chain not validated" +# "chain invalid" $JARSIGNER -strict -verify a.jar RESULT=$? @@ -99,7 +99,7 @@ #[ $RESULT = 4 ] || exit 3 # Test 4: When unrelated keystore is specified, the error is -# "chain not validated" and "not alias in keystore" +# "chain invalid" and "not alias in keystore" $JARSIGNER -keystore unrelated.jks -strict -verify a.jar RESULT=$?
--- a/test/sun/security/tools/jarsigner/concise_jarsigner.sh Wed Aug 01 03:36:32 2018 -0700 +++ b/test/sun/security/tools/jarsigner/concise_jarsigner.sh Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,10 @@ # # @test -# @bug 6802846 +# @bug 6802846 8172529 # @summary jarsigner needs enhanced cert validation(options) # -# @run shell concise_jarsigner.sh +# @run shell/timeout=240 concise_jarsigner.sh # if [ "${TESTJAVA}" = "" ] ; then @@ -47,12 +47,15 @@ # Choose 1024-bit RSA to make sure it runs fine and fast on all platforms. In # fact, every keyalg/keysize combination is OK for this test. -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore js.jks -keyalg rsa -keysize 1024" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner -JAVAC=$TESTJAVA${FS}bin${FS}javac +TESTTOOLVMOPTS="$TESTTOOLVMOPTS -J-Duser.language=en -J-Duser.country=US" -rm js.jks +KS=js.ks +KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa -keysize 1024" +JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}" +JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -debug" +JAVAC="$TESTJAVA${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}" + +rm $KS echo class A1 {} > A1.java echo class A2 {} > A2.java @@ -68,14 +71,14 @@ # First part: output format # ========================================================== -$KT -genkeypair -alias a1 -dname CN=a1 -validity 365 -$KT -genkeypair -alias a2 -dname CN=a2 -validity 365 +$KT -genkeypair -alias a1 -dname CN=a1 -validity 366 +$KT -genkeypair -alias a2 -dname CN=a2 -validity 366 # a.jar includes 8 unsigned, 2 signed by a1 and a2, 2 signed by a3 $JAR cvf a.jar A1.class A2.class -$JARSIGNER -keystore js.jks -storepass changeit a.jar a1 +$JARSIGNER -keystore $KS -storepass changeit a.jar a1 $JAR uvf a.jar A3.class A4.class -$JARSIGNER -keystore js.jks -storepass changeit a.jar a2 +$JARSIGNER -keystore $KS -storepass changeit a.jar a2 $JAR uvf a.jar A5.class A6.class # Verify OK @@ -87,15 +90,15 @@ [ $? = 20 ] || exit $LINENO # 16(hasUnsignedEntry) -$JARSIGNER -verify a.jar -strict -keystore js.jks +$JARSIGNER -verify a.jar -strict -keystore $KS -storepass changeit [ $? = 16 ] || exit $LINENO # 16(hasUnsignedEntry)+32(notSignedByAlias) -$JARSIGNER -verify a.jar a1 -strict -keystore js.jks +$JARSIGNER -verify a.jar a1 -strict -keystore $KS -storepass changeit [ $? = 48 ] || exit $LINENO # 16(hasUnsignedEntry) -$JARSIGNER -verify a.jar a1 a2 -strict -keystore js.jks +$JARSIGNER -verify a.jar a1 a2 -strict -keystore $KS -storepass changeit [ $? = 16 ] || exit $LINENO # 12 entries all together @@ -135,43 +138,52 @@ [ $LINES = 4 ] || exit $LINENO # ========================================================== -# Second part: exit code 2, 4, 8 +# Second part: exit code 2, 4, 8. # 16 and 32 already covered in the first part # ========================================================== -$KT -genkeypair -alias expired -dname CN=expired -startdate -10m -$KT -genkeypair -alias notyetvalid -dname CN=notyetvalid -startdate +1m -$KT -genkeypair -alias badku -dname CN=badku -ext KU=cRLSign -validity 365 -$KT -genkeypair -alias badeku -dname CN=badeku -ext EKU=sa -validity 365 -$KT -genkeypair -alias goodku -dname CN=goodku -ext KU=dig -validity 365 -$KT -genkeypair -alias goodeku -dname CN=goodeku -ext EKU=codesign -validity 365 +$KT -genkeypair -alias ca -dname CN=ca -ext bc -validity 365 +$KT -genkeypair -alias expired -dname CN=expired +$KT -certreq -alias expired | $KT -gencert -alias ca -startdate -10m | $KT -import -alias expired +$KT -genkeypair -alias notyetvalid -dname CN=notyetvalid +$KT -certreq -alias notyetvalid | $KT -gencert -alias ca -startdate +1m | $KT -import -alias notyetvalid +$KT -genkeypair -alias badku -dname CN=badku +$KT -certreq -alias badku | $KT -gencert -alias ca -ext KU=cRLSign -validity 365 | $KT -import -alias badku +$KT -genkeypair -alias badeku -dname CN=badeku +$KT -certreq -alias badeku | $KT -gencert -alias ca -ext EKU=sa -validity 365 | $KT -import -alias badeku +$KT -genkeypair -alias goodku -dname CN=goodku +$KT -certreq -alias goodku | $KT -gencert -alias ca -ext KU=dig -validity 365 | $KT -import -alias goodku +$KT -genkeypair -alias goodeku -dname CN=goodeku +$KT -certreq -alias goodeku | $KT -gencert -alias ca -ext EKU=codesign -validity 365 | $KT -import -alias goodeku -# badchain signed by ca, but ca is removed later -$KT -genkeypair -alias badchain -dname CN=badchain -validity 365 -$KT -genkeypair -alias ca -dname CN=ca -ext bc -validity 365 -$KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \ - $KT -importcert -alias badchain -$KT -delete -alias ca +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar expired +[ $? = 4 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar notyetvalid [ $? = 4 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar notyetvalid -[ $? = 4 ] || exit $LINENO +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badku +[ $? = 8 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badku +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badeku [ $? = 8 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badeku -[ $? = 8 ] || exit $LINENO +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodku +[ $? = 0 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodku +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodeku [ $? = 0 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodeku -[ $? = 0 ] || exit $LINENO +# badchain signed by ca1, but ca1 is removed later +$KT -genkeypair -alias badchain -dname CN=badchain -validity 365 +$KT -genkeypair -alias ca1 -dname CN=ca1 -ext bc -validity 365 +$KT -certreq -alias badchain | $KT -gencert -alias ca1 -validity 365 | \ + $KT -importcert -alias badchain +# save ca1.cert for easy replay +$KT -exportcert -file ca1.cert -alias ca1 +$KT -delete -alias ca1 -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badchain +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badchain [ $? = 4 ] || exit $LINENO $JARSIGNER -verify a.jar @@ -181,23 +193,55 @@ # Third part: -certchain test # ========================================================== -# altchain signed by ca2, but ca2 is removed later +# altchain signed by ca2 $KT -genkeypair -alias altchain -dname CN=altchain -validity 365 $KT -genkeypair -alias ca2 -dname CN=ca2 -ext bc -validity 365 $KT -certreq -alias altchain | $KT -gencert -alias ca2 -validity 365 -rfc > certchain $KT -exportcert -alias ca2 -rfc >> certchain -$KT -delete -alias ca2 -# Now altchain is still self-signed -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar altchain +# Self-signed cert does not work +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar altchain +[ $? = 4 ] || exit $LINENO + +# -certchain works +$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain [ $? = 0 ] || exit $LINENO -# If -certchain is used, then it's bad -$JARSIGNER -strict -keystore js.jks -storepass changeit -certchain certchain a.jar altchain +# if ca2 is removed, -certchain still work because altchain is a self-signed entry and +# it is trusted by jarsigner +# save ca2.cert for easy replay +$KT -exportcert -file ca2.cert -alias ca2 +$KT -delete -alias ca2 +$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain +[ $? = 0 ] || exit $LINENO + +# if cert is imported, -certchain won't work because this certificate entry is not trusted +$KT -importcert -file certchain -alias altchain -noprompt +$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain [ $? = 4 ] || exit $LINENO $JARSIGNER -verify a.jar [ $? = 0 ] || exit $LINENO +# ========================================================== +# 8172529 +# ========================================================== + +$KT -genkeypair -alias ee -dname CN=ee +$KT -genkeypair -alias caone -dname CN=caone +$KT -genkeypair -alias catwo -dname CN=catwo + +$KT -certreq -alias ee | $KT -gencert -alias catwo -rfc > ee.cert +$KT -certreq -alias catwo | $KT -gencert -alias caone -sigalg MD5withRSA -rfc > catwo.cert + +# This certchain contains a cross-signed weak catwo.cert +cat ee.cert catwo.cert | $KT -importcert -alias ee + +$JAR cvf a.jar A1.class +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar ee +[ $? = 0 ] || exit $LINENO +$JARSIGNER -strict -keystore $KS -storepass changeit -verify a.jar +[ $? = 0 ] || exit $LINENO + echo OK exit 0
--- a/test/sun/security/tools/jarsigner/ec.sh Wed Aug 01 03:36:32 2018 -0700 +++ b/test/sun/security/tools/jarsigner/ec.sh Fri Aug 03 19:50:58 2018 +0100 @@ -53,11 +53,20 @@ echo A > A $JAR cvf $JFILE A -$KT -alias a -dname CN=a -keyalg ec -genkey -validity 300 || exit 11 -$KT -alias b -dname CN=b -keyalg ec -genkey -validity 300 || exit 12 +$KT -alias ca -dname CN=ca -keyalg ec -genkey -validity 300 || exit 11 + +$KT -alias a -dname CN=a -keyalg ec -genkey || exit 11 +$KT -alias a -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias a || exit 111 + +$KT -alias b -dname CN=b -keyalg ec -genkey || exit 12 +$KT -alias b -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias b || exit 121 + # Ensure that key length is sufficient for the intended hash (SHA512withECDSA) -$KT -alias c -dname CN=c -keyalg ec -genkey -validity 300 -keysize 521 || exit 13 +$KT -alias c -dname CN=c -keyalg ec -genkey -keysize 521 || exit 13 +$KT -alias c -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias c || exit 131 + $KT -alias x -dname CN=x -keyalg ec -genkey -validity 300 || exit 14 +$KT -alias x -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias x || exit 141 $JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 21 $JARSIGNER -keystore $KS -storepass changeit $JFILE b -debug -strict -sigalg SHA1withECDSA || exit 22
--- a/test/sun/security/tools/jarsigner/onlymanifest.sh Wed Aug 01 03:36:32 2018 -0700 +++ b/test/sun/security/tools/jarsigner/onlymanifest.sh Fri Aug 03 19:50:58 2018 +0100 @@ -57,12 +57,14 @@ echo "Key: Value" > manifest $JAR cvfm $JFILE manifest -$KT -alias a -dname CN=a -genkey -validity 300 || exit 1 -$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 2 +$KT -alias ca -dname CN=ca -genkey -validity 300 || exit 1 +$KT -alias a -dname CN=a -genkey -validity 300 || exit 2 +$KT -alias a -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias a || exit 3 +$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 4 $JARSIGNER -keystore $KS -storepass changeit -verify $JFILE a -debug -strict \ - > onlymanifest.out || exit 3 + > onlymanifest.out || exit 5 -grep unsigned onlymanifest.out && exit 4 +grep unsigned onlymanifest.out && exit 6 exit 0
--- a/test/sun/security/tools/jarsigner/warnings.sh Wed Aug 01 03:36:32 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code 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 -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 8024302 -# @bug 8026037 -# @summary Clarify jar verifications -# - -if [ "${TESTJAVA}" = "" ] ; then - JAVAC_CMD=`which javac` - TESTJAVA=`dirname $JAVAC_CMD`/.. -fi - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Windows_* ) - FS="\\" - ;; - * ) - FS="/" - ;; -esac - -KS=warnings.jks -JFILE=warnings.jar - -KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \ - -keystore $KS" -JAR=$TESTJAVA${FS}bin${FS}jar -JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit" - -rm $KS 2> /dev/null - -LANG=C -export LANG - -echo 12345 > file - -ERR="" - -# Normal signer expiring on 2100-01-01 -$KT -alias s1 -dname CN=s1 -genkey -startdate 2000/01/01 -validity 36525 || ERR="$ERR keytool s1," -# Cert expiring soon, informational warning -$KT -alias s2 -dname CN=s2 -genkey -validity 100 || ERR="$ERR keytool s2," -# Cert expired, severe warning -$KT -alias s3 -dname CN=s3 -genkey -startdate -200d -validity 100 || ERR="$ERR keytool s3," - -# noTimestamp is informatiional warning and includes a date -$JAR cvf $JFILE file -$JARSIGNER $JFILE s1 > output1 || ERR="$ERR jarsigner s1," -$JARSIGNER -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict," -$JARSIGNER -verify $JFILE s1 >> output1 || ERR="$ERR jarsigner s1," -$JARSIGNER -verify -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict," - -cat output1 | grep Warning || ERR="$ERR s1 warning," -cat output1 | grep Error && ERR="$ERR s1 error," -cat output1 | grep timestamp | grep 2100-01-01 || ERR="$ERR s1 timestamp," -cat output1 | grep "with signer errors" && ERR="$ERR s1 err," - -# hasExpiringCert is informatiional warning -$JAR cvf $JFILE file -$JARSIGNER $JFILE s2 > output2 || ERR="$ERR jarsigner s2," -$JARSIGNER -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict," -$JARSIGNER -verify $JFILE s2 >> output2 || ERR="$ERR jarsigner s2," -$JARSIGNER -verify -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict," - -cat output2 | grep Warning || ERR="$ERR s2 warning," -cat output2 | grep Error && ERR="$ERR s2 error," -cat output2 | grep timestamp || ERR="$ERR s2 timestamp," -cat output2 | grep "will expire" || ERR="$ERR s2 expiring," -cat output2 | grep "with signer errors" && ERR="$ERR s2 err," - -# hasExpiredCert is severe warning -$JAR cvf $JFILE file -$JARSIGNER $JFILE s3 > output3 || ERR="$ERR jarsigner s3," -$JARSIGNER -strict $JFILE s3 > output3s && ERR="$ERR jarsigner s3 strict," -$JARSIGNER -verify $JFILE s3 >> output3 || ERR="$ERR jarsigner s3," -$JARSIGNER -verify -strict $JFILE s3 >> output3s && ERR="$ERR jarsigner s3 strict," - -# warning without -strict -cat output3 | grep Warning || ERR="$ERR s3 warning," -cat output3 | grep Error && ERR="$ERR s3 error," -cat output3 | grep "with signer errors" && ERR="$ERR s3 err," - -# error with -strict -cat output3s | grep Warning || ERR="$ERR s3s warning," -cat output3s | grep Error || ERR="$ERR s3s error," -cat output3s | grep "with signer errors" || ERR="$ERR s3 err," - -if [ "$ERR" = "" ]; then - exit 0 -else - echo "ERR is $ERR" - exit 1 -fi - -
--- a/test/sun/security/tools/jarsigner/warnings/Test.java Wed Aug 01 03:36:32 2018 -0700 +++ b/test/sun/security/tools/jarsigner/warnings/Test.java Fri Aug 03 19:50:58 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING = "This jar contains entries " - + "whose certificate chain is not validated."; + + "whose certificate chain is invalid."; static final String ALIAS_NOT_IN_STORE_VERIFYING_WARNING = "This jar contains signed entries " @@ -95,7 +95,7 @@ + "doesn't allow code signing."; static final String CHAIN_NOT_VALIDATED_SIGNING_WARNING - = "The signer's certificate chain is not validated."; + = "The signer's certificate chain is invalid."; static final String HAS_EXPIRING_CERT_SIGNING_WARNING = "The signer certificate will expire within six months.";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/tools/jarsigner/weaksize.sh Fri Aug 03 19:50:58 2018 +0100 @@ -0,0 +1,60 @@ +# +# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code 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 +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8044755 +# @summary Add a test for algorithm constraints check in jarsigner +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# The sigalg used is MD2withRSA, which is obsolete. + +KT="$TESTJAVA/bin/keytool ${TESTTOOLVMOPTS} -keystore ks + -storepass changeit -keypass changeit + -keyalg rsa -sigalg MD2withRSA -debug" +JS="$TESTJAVA/bin/jarsigner ${TESTTOOLVMOPTS} -keystore ks + -storepass changeit -strict -debug" +JAR="$TESTJAVA/bin/jar ${TESTTOOLVMOPTS}" + +rm ks 2> /dev/null + +$KT -genkeypair -alias ca -dname CN=CA -ext bc +$KT -genkeypair -alias signer -dname CN=Signer + +$KT -certreq -alias signer | \ + $KT -gencert -alias ca -ext ku=dS -rfc | \ + $KT -importcert -alias signer + +$JAR cvf a.jar ks + +# We always trust a TrustedCertificateEntry +$JS a.jar ca | grep "chain is invalid" && exit 1 + +# An end-entity cert must follow algorithm constraints +$JS a.jar signer | grep "chain is invalid" || exit 2 + +exit 0