diff --git a/.hgtags b/.hgtags index 5ae6d87986003f772b1914ed17c35f569f748a47..2609a22a2802f665a425016753fbc0b7ce010341 100644 --- a/.hgtags +++ b/.hgtags @@ -871,4 +871,5 @@ ac700f67341a20ddae093c319da1c65e41edcacd jdk8u171-b04 db8272cb8c99eea536a66c4c368c4bf2bf013a81 jdk8u172-b02 bd24ee3a9a0494121fd1d96c308b9738f585001b jdk8u172-b03 cf952b84daa1e74403a4d1df541c0ecca830717d jdk8u172-b04 +e7e27f446209924f66a4bf86738f3e5f2fbbef5f jdk8u181-b00 076daed81c0a851f6d13fac538834ac465cdc122 jdk8u172-b05 diff --git a/src/share/classes/com/sun/crypto/provider/JceKeyStore.java b/src/share/classes/com/sun/crypto/provider/JceKeyStore.java index 50fa3b73d29d4e45881573234feeedc13e400bad..d47f5a9c9fd48347e7bbc07d0c10a74f4731442f 100644 --- a/src/share/classes/com/sun/crypto/provider/JceKeyStore.java +++ b/src/share/classes/com/sun/crypto/provider/JceKeyStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -929,8 +929,10 @@ public final class JceKeyStore extends KeyStoreSpi { // First run a custom filter long nestedDepth = info.depth(); if ((nestedDepth == 1 && - info.serialClass() != SealedObjectForKeyProtector.class) || - nestedDepth > MAX_NESTED_DEPTH) { + info.serialClass() != SealedObjectForKeyProtector.class) || + (nestedDepth > MAX_NESTED_DEPTH && + info.serialClass() != null && + info.serialClass() != Object.class)) { return Status.REJECTED; } diff --git a/src/share/classes/com/sun/crypto/provider/KeyProtector.java b/src/share/classes/com/sun/crypto/provider/KeyProtector.java index 823d7bdb8d1fe44a675dbcafc06e8f9687396250..7f9d0b2ee0f54d9d3c539ce9b32222bee2b32856 100644 --- a/src/share/classes/com/sun/crypto/provider/KeyProtector.java +++ b/src/share/classes/com/sun/crypto/provider/KeyProtector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -26,8 +26,6 @@ package com.sun.crypto.provider; import java.io.IOException; -import java.io.Serializable; -import java.security.Security; import java.security.Key; import java.security.PrivateKey; import java.security.Provider; @@ -35,7 +33,6 @@ import java.security.KeyFactory; import java.security.MessageDigest; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.UnrecoverableKeyException; import java.security.AlgorithmParameters; import java.security.spec.InvalidParameterSpecException; @@ -44,7 +41,6 @@ import java.security.spec.PKCS8EncodedKeySpec; import javax.crypto.Cipher; import javax.crypto.CipherSpi; import javax.crypto.SecretKey; -import javax.crypto.IllegalBlockSizeException; import javax.crypto.SealedObject; import javax.crypto.spec.*; import sun.security.x509.AlgorithmId; @@ -347,7 +343,7 @@ final class KeyProtector { SunJCE.getInstance(), "PBEWithMD5AndTripleDES"); cipher.init(Cipher.DECRYPT_MODE, skey, params); - return (Key)soForKeyProtector.getObject(cipher); + return soForKeyProtector.getKey(cipher); } catch (NoSuchAlgorithmException ex) { // Note: this catch needed to be here because of the // later catch of GeneralSecurityException diff --git a/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java b/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java index d88e7668c208a3475e89eb321db3b4896a7d2512..c95770e91d22f7b7c6e407a9f0ca112adfb30c11 100644 --- a/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java +++ b/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -25,6 +25,9 @@ package com.sun.crypto.provider; +import sun.misc.ObjectInputFilter; +import sun.misc.SharedSecrets; + import java.io.*; import java.security.*; import javax.crypto.*; @@ -33,6 +36,16 @@ final class SealedObjectForKeyProtector extends SealedObject { static final long serialVersionUID = -3650226485480866989L; + /** + * The InputStreamFilter for a Key object inside this SealedObject. It can + * be either provided as a {@link Security} property or a system property + * (when provided as latter, it shadows the former). If the result of this + * filter is {@link sun.misc.ObjectInputFilter.Status.UNDECIDED}, the system + * level filter defined by jdk.serialFilter will be consulted. The value + * of this property uses the same format of jdk.serialFilter. + */ + private static final String KEY_SERIAL_FILTER = "jceks.key.serialFilter"; + SealedObjectForKeyProtector(Serializable object, Cipher c) throws IOException, IllegalBlockSizeException { super(object, c); @@ -59,4 +72,88 @@ final class SealedObjectForKeyProtector extends SealedObject { } return params; } + + final Key getKey(Cipher c) + throws IOException, ClassNotFoundException, IllegalBlockSizeException, + BadPaddingException { + + try (ObjectInputStream ois = SharedSecrets.getJavaxCryptoSealedObjectAccess() + .getExtObjectInputStream(this, c)) { + AccessController.doPrivileged( + (PrivilegedAction) () -> { + ObjectInputFilter.Config.setObjectInputFilter(ois, + DeserializationChecker.ONE_FILTER); + return null; + }); + try { + @SuppressWarnings("unchecked") + Key t = (Key) ois.readObject(); + return t; + } catch (InvalidClassException ice) { + String msg = ice.getMessage(); + if (msg.contains("REJECTED")) { + throw new IOException("Rejected by the" + + " jceks.key.serialFilter or jdk.serialFilter" + + " property", ice); + } else { + throw ice; + } + } + } + } + + /** + * The filter for the content of a SealedObjectForKeyProtector. + * + * First, the jceks.key.serialFilter will be consulted. If the result + * is UNDECIDED, the system level jdk.serialFilter will be consulted. + */ + private static class DeserializationChecker implements ObjectInputFilter { + + private static final ObjectInputFilter ONE_FILTER; + + static { + String prop = AccessController.doPrivileged( + (PrivilegedAction) () -> { + String tmp = System.getProperty(KEY_SERIAL_FILTER); + if (tmp != null) { + return tmp; + } else { + return Security.getProperty(KEY_SERIAL_FILTER); + } + }); + ONE_FILTER = new DeserializationChecker(prop == null ? null + : ObjectInputFilter.Config.createFilter(prop)); + } + + private final ObjectInputFilter base; + + private DeserializationChecker(ObjectInputFilter base) { + this.base = base; + } + + @Override + public ObjectInputFilter.Status checkInput( + ObjectInputFilter.FilterInfo info) { + + if (info.serialClass() == Object.class) { + return Status.UNDECIDED; + } + + if (base != null) { + Status result = base.checkInput(info); + if (result != Status.UNDECIDED) { + return result; + } + } + + ObjectInputFilter defaultFilter = + ObjectInputFilter.Config.getSerialFilter(); + if (defaultFilter != null) { + return defaultFilter.checkInput(info); + } + + return Status.UNDECIDED; + } + } } diff --git a/src/share/classes/java/awt/Desktop.java b/src/share/classes/java/awt/Desktop.java index a9b947dfa25253189bd65168ba145e1e9a1aadc6..577ffdde0c2d7333681e708aa69056e65aa7031e 100644 --- a/src/share/classes/java/awt/Desktop.java +++ b/src/share/classes/java/awt/Desktop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -202,15 +202,11 @@ public class Desktop { * @throws NullPointerException if file is null * @throws IllegalArgumentException if file doesn't exist */ - private static void checkFileValidation(File file){ - if (file == null) throw new NullPointerException("File must not be null"); - + private static void checkFileValidation(File file) { if (!file.exists()) { throw new IllegalArgumentException("The file: " + file.getPath() + " doesn't exist."); } - - file.canRead(); } /** @@ -264,6 +260,7 @@ public class Desktop { * @see java.awt.AWTPermission */ public void open(File file) throws IOException { + file = new File(file.getPath()); checkAWTPermission(); checkExec(); checkActionSupport(Action.OPEN); @@ -295,6 +292,7 @@ public class Desktop { * @see java.awt.AWTPermission */ public void edit(File file) throws IOException { + file = new File(file.getPath()); checkAWTPermission(); checkExec(); checkActionSupport(Action.EDIT); @@ -325,6 +323,7 @@ public class Desktop { * allowed to create a subprocess */ public void print(File file) throws IOException { + file = new File(file.getPath()); checkExec(); SecurityManager sm = System.getSecurityManager(); if (sm != null) { diff --git a/src/share/classes/java/io/ObjectInputStream.java b/src/share/classes/java/io/ObjectInputStream.java index fa1832ddcea96652f9abe52abaf17cb9684726a9..410b2ee1b3dc2a9852d76cf2573013dd216dee5f 100644 --- a/src/share/classes/java/io/ObjectInputStream.java +++ b/src/share/classes/java/io/ObjectInputStream.java @@ -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 @@ -245,7 +245,7 @@ public class ObjectInputStream static { /* Setup access so sun.misc can invoke package private functions. */ - sun.misc.SharedSecrets.setJavaOISAccess(new JavaOISAccess() { + JavaOISAccess javaOISAccess = new JavaOISAccess() { public void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter) { stream.setInternalObjectInputFilter(filter); } @@ -259,7 +259,11 @@ public class ObjectInputStream { stream.checkArray(arrayType, arrayLength); } - }); + }; + + sun.misc.SharedSecrets.setJavaOISAccess(javaOISAccess); + + sun.corba.SharedSecrets.setJavaOISAccess(javaOISAccess); } /* diff --git a/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java index db888250c10471047e20a09799a0eb9918f283a9..d124a3ea9e5934508a11135e724244481feb0e83 100644 --- a/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -48,6 +48,7 @@ import java.util.Queue; import java.util.SortedSet; import java.util.Spliterator; import java.util.function.Consumer; +import sun.misc.SharedSecrets; /** * An unbounded {@linkplain BlockingQueue blocking queue} that uses @@ -940,7 +941,9 @@ public class PriorityBlockingQueue extends AbstractQueue throws java.io.IOException, ClassNotFoundException { try { s.defaultReadObject(); - this.queue = new Object[q.size()]; + int sz = q.size(); + SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, sz); + this.queue = new Object[sz]; comparator = q.comparator(); addAll(q); } finally { diff --git a/src/share/classes/javax/crypto/SealedObject.java b/src/share/classes/javax/crypto/SealedObject.java index 5c548323c08c5f7adf30593ed54246dbed33da24..cdf9bd346510adbe696895102764fa127bfda969 100644 --- a/src/share/classes/javax/crypto/SealedObject.java +++ b/src/share/classes/javax/crypto/SealedObject.java @@ -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 @@ -25,6 +25,8 @@ package javax.crypto; +import sun.misc.SharedSecrets; + import java.io.*; import java.security.AlgorithmParameters; import java.security.Key; @@ -287,17 +289,7 @@ public class SealedObject implements Serializable { throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException { - /* - * Unseal the object - */ - byte[] content = c.doFinal(this.encryptedContent); - - /* - * De-serialize it - */ - // creating a stream pipe-line, from b to a - ByteArrayInputStream b = new ByteArrayInputStream(content); - ObjectInput a = new extObjectInputStream(b); + ObjectInput a = getExtObjectInputStream(c); try { Object obj = a.readObject(); return obj; @@ -417,17 +409,7 @@ public class SealedObject implements Serializable { throw new RuntimeException(iape.getMessage()); } - /* - * Unseal the object - */ - byte[] content = c.doFinal(this.encryptedContent); - - /* - * De-serialize it - */ - // creating a stream pipe-line, from b to a - ByteArrayInputStream b = new ByteArrayInputStream(content); - ObjectInput a = new extObjectInputStream(b); + ObjectInput a = getExtObjectInputStream(c); try { Object obj = a.readObject(); return obj; @@ -450,6 +432,19 @@ public class SealedObject implements Serializable { if (encodedParams != null) encodedParams = encodedParams.clone(); } + + // This method is also called inside SealedObjectForKeyProtector.java. + private ObjectInputStream getExtObjectInputStream(Cipher c) + throws BadPaddingException, IllegalBlockSizeException, IOException { + + byte[] content = c.doFinal(this.encryptedContent); + ByteArrayInputStream b = new ByteArrayInputStream(content); + return new extObjectInputStream(b); + } + + static { + SharedSecrets.setJavaxCryptoSealedObjectAccess((obj,c) -> obj.getExtObjectInputStream(c)); + } } final class extObjectInputStream extends ObjectInputStream { diff --git a/src/share/classes/com/sun/crypto/provider/ai.java b/src/share/classes/sun/misc/JavaxCryptoSealedObjectAccess.java similarity index 56% rename from src/share/classes/com/sun/crypto/provider/ai.java rename to src/share/classes/sun/misc/JavaxCryptoSealedObjectAccess.java index 853307396ff3a1bc359b92012f3aa997327de126..664ec05fb79a65b352b239463dc70aaf57e2558c 100644 --- a/src/share/classes/com/sun/crypto/provider/ai.java +++ b/src/share/classes/sun/misc/JavaxCryptoSealedObjectAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -22,43 +22,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package sun.misc; -package com.sun.crypto.provider; - -import java.io.IOException; -import java.io.Serializable; -import java.io.ObjectStreamException; -import java.security.AlgorithmParameters; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; +import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.SealedObject; -import javax.crypto.spec.*; - -/** - * This class is introduced to workaround a problem in - * the SunJCE provider shipped in JCE 1.2.1: the class - * SealedObjectForKeyProtector was obfuscated due to a mistake. - * - * In order to retrieve secret keys in a JCEKS KeyStore written - * by the SunJCE provider in JCE 1.2.1, this class will be used. - * - * @author Valerie Peng - * - * - * @see JceKeyStore - */ - -final class ai extends javax.crypto.SealedObject { - - static final long serialVersionUID = -7051502576727967444L; - - ai(SealedObject so) { - super(so); - } +import java.io.IOException; +import java.io.ObjectInputStream; - Object readResolve() throws ObjectStreamException { - return new SealedObjectForKeyProtector(this); - } +public interface JavaxCryptoSealedObjectAccess { + ObjectInputStream getExtObjectInputStream( + SealedObject sealed, Cipher cipher) + throws BadPaddingException, IllegalBlockSizeException, IOException; } diff --git a/src/share/classes/sun/misc/SharedSecrets.java b/src/share/classes/sun/misc/SharedSecrets.java index 18accf8ebe31fb807bcbc81e22798abeeeb59ed1..5f8ee1b4a287af6ab7cac462ce07099b1fd5a482 100644 --- a/src/share/classes/sun/misc/SharedSecrets.java +++ b/src/share/classes/sun/misc/SharedSecrets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, 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 @@ -25,7 +25,7 @@ package sun.misc; -import java.io.ObjectInputStream; +import javax.crypto.SealedObject; import java.util.jar.JarFile; import java.io.Console; import java.io.FileDescriptor; @@ -58,6 +58,7 @@ public class SharedSecrets { private static JavaUtilZipFileAccess javaUtilZipFileAccess; private static JavaAWTAccess javaAWTAccess; private static JavaOISAccess javaOISAccess; + private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -199,4 +200,15 @@ public class SharedSecrets { } return javaAWTAccess; } + + public static void setJavaxCryptoSealedObjectAccess(JavaxCryptoSealedObjectAccess jcsoa) { + javaxCryptoSealedObjectAccess = jcsoa; + } + + public static JavaxCryptoSealedObjectAccess getJavaxCryptoSealedObjectAccess() { + if (javaxCryptoSealedObjectAccess == null) { + unsafe.ensureClassInitialized(SealedObject.class); + } + return javaxCryptoSealedObjectAccess; + } } diff --git a/src/share/classes/sun/security/tools/KeyStoreUtil.java b/src/share/classes/sun/security/tools/KeyStoreUtil.java index 6407b88cb8221d07ba6c3c02d6f51f4183598423..2ce57232013400e1eb419ae4982c4fa7fbbbd2f6 100644 --- a/src/share/classes/sun/security/tools/KeyStoreUtil.java +++ b/src/share/classes/sun/security/tools/KeyStoreUtil.java @@ -35,6 +35,7 @@ import java.net.URL; import java.security.KeyStore; +import java.security.cert.X509Certificate; import java.text.Collator; import java.util.Locale; @@ -58,6 +59,25 @@ public class KeyStoreUtil { collator.setStrength(Collator.PRIMARY); }; + /** + * 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 diff --git a/src/share/classes/sun/security/tools/jarsigner/Main.java b/src/share/classes/sun/security/tools/jarsigner/Main.java index 0d22d7d82fd93cb21347cec890c1edbc34a5e521..57dc512e64606d4fdf2a757feb82713080083c27 100644 --- a/src/share/classes/sun/security/tools/jarsigner/Main.java +++ b/src/share/classes/sun/security/tools/jarsigner/Main.java @@ -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.SocketTimeoutException; 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.pkcs.SignerInfo; 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 @@ public class Main { 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 @@ public class Main { 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 @@ public class Main { if (notSignedByAlias || aliasNotInStore) { exitCode |= 32; } + if (tsaChainNotValidated) { + exitCode |= 64; + } if (exitCode != 0) { System.exit(exitCode); } @@ -807,6 +825,9 @@ public class Main { 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 @@ public class Main { 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 @@ public class Main { } 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 @@ public class Main { 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 @@ public class Main { 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 @@ public class Main { } 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 @@ public class Main { 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 @@ public class Main { "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 @@ public class Main { private static MessageFormat expiredTimeForm = null; private static MessageFormat expiringTimeForm = null; - /* - * Display some details about a certificate: + /** + * Returns a string about a certificate: * * [] [", " ] [" (" ")"] * [ | ] + * [] + * + * 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 @@ public class Main { 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 @@ public class Main { 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 @@ public class Main { certStr.append(validityTimeForm.format(source)); } } catch (CertificateExpiredException cee) { - hasExpiredCert = true; + if (!isTsCert) hasExpiredCert = true; if (expiredTimeForm == null) { expiredTimeForm = new MessageFormat( @@ -1105,7 +1165,7 @@ public class Main { certStr.append(expiredTimeForm.format(source)); } catch (CertificateNotYetValidException cnyve) { - notYetValidCert = true; + if (!isTsCert) notYetValidCert = true; if (notYetTimeForm == null) { notYetTimeForm = new MessageFormat( @@ -1218,7 +1278,25 @@ public class Main { } 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 @@ public class Main { 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 @@ public class Main { } } + // 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 @@ public class Main { } 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 @@ public class Main { } 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 @@ public class Main { /** * 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 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 @@ public class Main { // 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 @@ public class Main { } try { - - certificateFactory = CertificateFactory.getInstance("X.509"); - validator = CertPathValidator.getInstance("PKIX"); Set tas = new HashSet<>(); try { KeyStore caks = KeyStoreUtil.getCacertsKeyStore(); @@ -1871,7 +2014,7 @@ public class Main { } } 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 @@ public class Main { } } - void getAliasInfo(String alias) { + void getAliasInfo(String alias) throws Exception { Key key = null; @@ -2033,21 +2176,18 @@ public class Main { // 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 @@ public class Main { System.exit(1); } - void validateCertChain(List certs) throws Exception { - int cpLen = 0; - out: for (; cpLen 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; } } diff --git a/src/share/classes/sun/security/tools/jarsigner/Resources.java b/src/share/classes/sun/security/tools/jarsigner/Resources.java index bff9dd718d5f68b71ccd930f6e209066a0af0597..7a6ea5cbeb6e171f5fff20cd20c0332121f2fa00 100644 --- a/src/share/classes/sun/security/tools/jarsigner/Resources.java +++ b/src/share/classes/sun/security/tools/jarsigner/Resources.java @@ -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 @@ public class Resources extends java.util.ListResourceBundle { {"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 @@ public class Resources extends java.util.ListResourceBundle { {"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 @@ public class Resources extends java.util.ListResourceBundle { "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 @@ public class Resources extends java.util.ListResourceBundle { "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: "}, diff --git a/src/share/classes/sun/security/tools/keytool/Main.java b/src/share/classes/sun/security/tools/keytool/Main.java index 0730f4ff6995a88335161c7ca8d046620860fa1e..0c626b5664130ce44ab56a66bd88b2a103e57766 100644 --- a/src/share/classes/sun/security/tools/keytool/Main.java +++ b/src/share/classes/sun/security/tools/keytool/Main.java @@ -1352,7 +1352,7 @@ public final class Main { for (Certificate ca: keyStore.getCertificateChain(alias)) { if (ca instanceof X509Certificate) { X509Certificate xca = (X509Certificate)ca; - if (!isSelfSigned(xca)) { + if (!KeyStoreUtil.isSelfSigned(xca)) { dumpCert(xca, out); } } @@ -2857,7 +2857,7 @@ public final class Main { // 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; } @@ -3160,25 +3160,6 @@ public final class Main { } } - /** - * 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. @@ -3519,7 +3500,7 @@ public final class Main { // find a cert in the reply who signs thisCert int j; for (j=i; j certToVerify, Vector> chain, Hashtable>> 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); diff --git a/src/share/classes/sun/security/util/SignatureFileVerifier.java b/src/share/classes/sun/security/util/SignatureFileVerifier.java index 0663f0573ae35823427a3abbc503151bb292a354..ee5c28832172bf3dc0bffc67840144a73e4456d4 100644 --- a/src/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/src/share/classes/sun/security/util/SignatureFileVerifier.java @@ -718,7 +718,8 @@ public class SignatureFileVerifier { 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) { diff --git a/src/share/lib/security/java.security-aix b/src/share/lib/security/java.security-aix index 7cb04ba23f5bdf48564cc9cfc4a3d21fbd3f41b2..5a6b9f3fecc2e75109808f26ddaf345b771bdde2 100644 --- a/src/share/lib/security/java.security-aix +++ b/src/share/lib/security/java.security-aix @@ -860,6 +860,9 @@ jdk.xml.dsig.secureValidationPolicy=\ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -955,3 +958,20 @@ jdk.xml.dsig.secureValidationPolicy=\ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!* diff --git a/src/share/lib/security/java.security-linux b/src/share/lib/security/java.security-linux index 2b9336c6f71b3ab4aae8b500fc1b1490115beb9a..455eb977e7364cd4c7f6a946a7f07e7718b70d48 100644 --- a/src/share/lib/security/java.security-linux +++ b/src/share/lib/security/java.security-linux @@ -861,6 +861,9 @@ jdk.xml.dsig.secureValidationPolicy=\ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -961,3 +964,20 @@ jdk.xml.dsig.secureValidationPolicy=\ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!* diff --git a/src/share/lib/security/java.security-macosx b/src/share/lib/security/java.security-macosx index 5850b8a8c1129b75862088784b7cfd62944f3712..6891bfbf1e68196c76ccb8b68ca957562842ac6e 100644 --- a/src/share/lib/security/java.security-macosx +++ b/src/share/lib/security/java.security-macosx @@ -864,6 +864,9 @@ jdk.xml.dsig.secureValidationPolicy=\ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -959,3 +962,20 @@ jdk.xml.dsig.secureValidationPolicy=\ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!* diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris index 16feb7a3b8ba8e880a2c532103bfdb74f32124c5..5dcb58444688a66b2414b4699eb0ef19bbbc614f 100644 --- a/src/share/lib/security/java.security-solaris +++ b/src/share/lib/security/java.security-solaris @@ -863,6 +863,9 @@ jdk.xml.dsig.secureValidationPolicy=\ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -958,3 +961,20 @@ jdk.xml.dsig.secureValidationPolicy=\ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!* diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows index 375c8b2b13b768b1a807e5318c2075763fa8b3e9..724b6967aadb1585a78ae6623d8ee9d397c978dc 100644 --- a/src/share/lib/security/java.security-windows +++ b/src/share/lib/security/java.security-windows @@ -864,6 +864,9 @@ jdk.xml.dsig.secureValidationPolicy=\ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the sequence of patterns. @@ -959,3 +962,20 @@ jdk.xml.dsig.secureValidationPolicy=\ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\ + java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!* diff --git a/src/share/native/common/jni_util.h b/src/share/native/common/jni_util.h index 7655eab639666cd138143f444bd8f9eebc22429f..1356c8a35a5e076d118f8651b73a9f35e4883413 100644 --- a/src/share/native/common/jni_util.h +++ b/src/share/native/common/jni_util.h @@ -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 @@ -297,6 +297,22 @@ JNU_NotifyAll(JNIEnv *env, jobject object); } \ } while (0) \ +#define CHECK_NULL_THROW_NPE(env, x, msg) \ + do { \ + if ((x) == NULL) { \ + JNU_ThrowNullPointerException((env), (msg));\ + return; \ + } \ + } while(0) \ + +#define CHECK_NULL_THROW_NPE_RETURN(env, x, msg, z)\ + do { \ + if ((x) == NULL) { \ + JNU_ThrowNullPointerException((env), (msg));\ + return (z); \ + } \ + } while(0) \ + #define CHECK_NULL_RETURN(x, y) \ do { \ if ((x) == NULL) { \ diff --git a/src/share/native/java/net/net_util.c b/src/share/native/java/net/net_util.c index 2194e2e6ef4a0a955825f52285a441882ddfd04d..b1b8223a633170eb2ff15f906915674bbcb99505 100644 --- a/src/share/native/java/net/net_util.c +++ b/src/share/native/java/net/net_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -168,32 +168,38 @@ int setInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *address) { void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) { jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID); + CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null"); (*env)->SetIntField(env, holder, iac_addressID, address); } void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) { jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID); + CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null"); (*env)->SetIntField(env, holder, iac_familyID, family); } void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) { jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID); + CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null"); (*env)->SetObjectField(env, holder, iac_hostNameID, host); (*env)->SetObjectField(env, holder, iac_origHostNameID, host); } int getInetAddress_addr(JNIEnv *env, jobject iaObj) { jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID); + CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", -1); return (*env)->GetIntField(env, holder, iac_addressID); } int getInetAddress_family(JNIEnv *env, jobject iaObj) { jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID); + CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", -1); return (*env)->GetIntField(env, holder, iac_familyID); } jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) { jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID); + CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", NULL); return (*env)->GetObjectField(env, holder, iac_hostNameID); } @@ -215,7 +221,9 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { CHECK_NULL_RETURN(iaObj, NULL); address = NET_IPv4MappedToIPv4(caddr); setInetAddress_addr(env, iaObj, address); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); setInetAddress_family(env, iaObj, IPv4); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); } else { jint scope; int ret; @@ -224,6 +232,7 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr)); CHECK_NULL_RETURN(ret, NULL); setInetAddress_family(env, iaObj, IPv6); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); scope = getScopeID(him); setInet6Address_scopeid(env, iaObj, scope); } @@ -235,7 +244,9 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); CHECK_NULL_RETURN(iaObj, NULL); setInetAddress_family(env, iaObj, IPv4); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr)); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); *port = ntohs(him4->sin_port); } return iaObj; @@ -248,6 +259,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) #ifdef AF_INET6 family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6; + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); if (him->sa_family == AF_INET6) { #ifdef WIN32 struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him; @@ -263,6 +275,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) } addrNew = NET_IPv4MappedToIPv4(caddrNew); addrCur = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); if (addrNew == addrCur) { return JNI_TRUE; } else { @@ -294,6 +307,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) } addrNew = ntohl(him4->sin_addr.s_addr); addrCur = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); if (addrNew == addrCur) { return JNI_TRUE; } else { diff --git a/src/solaris/native/java/net/Inet4AddressImpl.c b/src/solaris/native/java/net/Inet4AddressImpl.c index ec4f97dfae11ccc5eeff6da0f1bc4e2f30c64b21..426a2b2588f2fac03522847feb192a383c460b7f 100644 --- a/src/solaris/native/java/net/Inet4AddressImpl.c +++ b/src/solaris/native/java/net/Inet4AddressImpl.c @@ -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 @@ -236,7 +236,11 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, goto cleanupAndReturn; } setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)(iterator->ai_addr))->sin_addr.s_addr)); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; setInetAddress_hostName(env, iaObj, name); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; (*env)->SetObjectArrayElement(env, ret, retLen - i -1, iaObj); i++; iterator = iterator->ai_next; @@ -479,7 +483,11 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, goto cleanupAndReturn; } setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr)); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; setInetAddress_hostName(env, iaObj, host); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; (*env)->SetObjectArrayElement(env, ret, i++, iaObj); iterator = iterator->ai_next; } diff --git a/src/solaris/native/java/net/Inet6AddressImpl.c b/src/solaris/native/java/net/Inet6AddressImpl.c index e29a25daf52801e50baae5cc1eccb30c304ef32c..46b2e5c357a1b9e2bc74d3f89c94154d9e875d90 100644 --- a/src/solaris/native/java/net/Inet6AddressImpl.c +++ b/src/solaris/native/java/net/Inet6AddressImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, 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 @@ -221,6 +221,8 @@ lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6) return NULL; } setInetAddress_hostName(env, o, name); + if ((*env)->ExceptionCheck(env)) + goto done; (*env)->SetObjectArrayElement(env, result, index, o); (*env)->DeleteLocalRef(env, o); } @@ -411,7 +413,11 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, goto cleanupAndReturn; } setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr)); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; setInetAddress_hostName(env, iaObj, host); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj); inetIndex++; } else if (iterator->ai_family == AF_INET6) { @@ -433,6 +439,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, setInet6Address_scopeid(env, iaObj, scope); } setInetAddress_hostName(env, iaObj, host); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj); inet6Index++; } diff --git a/src/solaris/native/java/net/NetworkInterface.c b/src/solaris/native/java/net/NetworkInterface.c index 9db36ae05d942ae0b0ff8fcfe6e67cf27fc8faed..843278159042768ac9052e6addf5504df08bf651 100644 --- a/src/solaris/native/java/net/NetworkInterface.c +++ b/src/solaris/native/java/net/NetworkInterface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, 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 @@ -332,14 +332,14 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 (JNIEnv *env, jclass cls, jobject iaObj) { netif *ifs, *curr; + jobject obj = NULL; + jboolean match = JNI_FALSE; #if defined(AF_INET6) int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6; + JNU_CHECK_EXCEPTION_RETURN(env, NULL); #else int family = AF_INET; #endif - jobject obj = NULL; - jboolean match = JNI_FALSE; - ifs = enumInterfaces(env); if (ifs == NULL) { return NULL; @@ -357,7 +357,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 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 (address1 == address2) { match = JNI_TRUE; break; @@ -703,6 +703,7 @@ static jobject createNetworkInterface(JNIEnv *env, netif *ifs) { if (iaObj) { setInetAddress_addr(env, iaObj, htonl( ((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr)); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); } else { return NULL; } @@ -715,6 +716,7 @@ static jobject createNetworkInterface(JNIEnv *env, netif *ifs) { if (ia2Obj) { setInetAddress_addr(env, ia2Obj, htonl( ((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr)); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj); } else { return NULL; diff --git a/src/solaris/native/java/net/PlainDatagramSocketImpl.c b/src/solaris/native/java/net/PlainDatagramSocketImpl.c index c48d1153ce42061c55881355276c8e8f209a18b3..a53c28931f130f3b41ee54588693baa8363cf3ad 100644 --- a/src/solaris/native/java/net/PlainDatagramSocketImpl.c +++ b/src/solaris/native/java/net/PlainDatagramSocketImpl.c @@ -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 @@ -569,12 +569,15 @@ Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port); #ifdef AF_INET6 family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6; + JNU_CHECK_EXCEPTION_RETURN(env, -1); #else family = AF_INET; #endif if (family == AF_INET) { /* this API can't handle IPV6 addresses */ int address = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, -1); setInetAddress_addr(env, addressObj, address); + JNU_CHECK_EXCEPTION_RETURN(env, -1); } return port; } @@ -1078,6 +1081,7 @@ static void mcast_set_if_by_if_v4(JNIEnv *env, jobject this, int fd, jobject val struct in_addr in; jobjectArray addrArray; jsize len; + jint family; jobject addr; int i; @@ -1107,8 +1111,12 @@ static void mcast_set_if_by_if_v4(JNIEnv *env, jobject this, int fd, jobject val */ for (i = 0; i < len; i++) { addr = (*env)->GetObjectArrayElement(env, addrArray, i); - if (getInetAddress_family(env, addr) == IPv4) { + family = getInetAddress_family(env, addr); + JNU_CHECK_EXCEPTION(env); + if (family == IPv4) { + JNU_CHECK_EXCEPTION(env); in.s_addr = htonl(getInetAddress_addr(env, addr)); + JNU_CHECK_EXCEPTION(env); break; } } @@ -1162,6 +1170,7 @@ static void mcast_set_if_by_addr_v4(JNIEnv *env, jobject this, int fd, jobject v in.s_addr = htonl( getInetAddress_addr(env, value) ); + JNU_CHECK_EXCEPTION(env); if (JVM_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&in, sizeof(in)) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", @@ -1528,6 +1537,7 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, jint opt) { CHECK_NULL_RETURN(addr, NULL); setInetAddress_addr(env, addr, ntohl(in.s_addr)); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); /* * For IP_MULTICAST_IF return InetAddress @@ -1968,6 +1978,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this, jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); jint fd; + jint family; jint ipv6_join_leave; if (IS_NULL(fdObj)) { @@ -1989,7 +2000,10 @@ static void mcast_join_leave(JNIEnv *env, jobject this, ipv6_join_leave = ipv6_available(); #ifdef __linux__ - if (getInetAddress_family(env, iaObj) == IPv4) { + family = getInetAddress_family(env, iaObj); + JNU_CHECK_EXCEPTION(env); + if (family == IPv4) { + JNU_CHECK_EXCEPTION(env); ipv6_join_leave = JNI_FALSE; } #endif @@ -2037,6 +2051,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this, } mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj)); + JNU_CHECK_EXCEPTION(env); mname.imr_address.s_addr = 0; mname.imr_ifindex = (*env)->GetIntField(env, niObj, ni_indexID); mname_len = sizeof(struct ip_mreqn); @@ -2055,10 +2070,13 @@ static void mcast_join_leave(JNIEnv *env, jobject this, addr = (*env)->GetObjectArrayElement(env, addrArray, 0); mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj)); + JNU_CHECK_EXCEPTION(env); #ifdef __linux__ mname.imr_address.s_addr = htonl(getInetAddress_addr(env, addr)); + JNU_CHECK_EXCEPTION(env); #else mname.imr_interface.s_addr = htonl(getInetAddress_addr(env, addr)); + JNU_CHECK_EXCEPTION(env); #endif mname_len = sizeof(struct ip_mreq); } @@ -2094,6 +2112,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this, } mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj)); + JNU_CHECK_EXCEPTION(env); mname.imr_address.s_addr = 0 ; mname.imr_ifindex = index; mname_len = sizeof(struct ip_mreqn); @@ -2116,6 +2135,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this, mname.imr_interface.s_addr = in.s_addr; #endif mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj)); + JNU_CHECK_EXCEPTION(env); mname_len = sizeof(struct ip_mreq); } } @@ -2181,10 +2201,12 @@ static void mcast_join_leave(JNIEnv *env, jobject this, jint family; jint address; family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6; + JNU_CHECK_EXCEPTION(env); if (family == AF_INET) { /* will convert to IPv4-mapped address */ memset((char *) caddr, 0, 16); address = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION(env); caddr[10] = 0xff; caddr[11] = 0xff; diff --git a/src/solaris/native/java/net/net_util_md.c b/src/solaris/native/java/net/net_util_md.c index eae347cf10a8fdf52c2bca97d0bb7b372ad8bc22..7436d5214b93f94551f3f7238d12d5d3378d820f 100644 --- a/src/solaris/native/java/net/net_util_md.c +++ b/src/solaris/native/java/net/net_util_md.c @@ -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 @@ -786,6 +786,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr int *len, jboolean v4MappedAddress) { jint family; family = getInetAddress_family(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, -1); #ifdef AF_INET6 /* needs work. 1. family 2. clean up him6 etc deallocate memory */ if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) { @@ -797,6 +798,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr if (family == IPv4) { /* will convert to IPv4-mapped address */ memset((char *) caddr, 0, 16); address = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, -1); if (address == INADDR_ANY) { /* we would always prefer IPv6 wildcard address caddr[10] = 0xff; @@ -905,6 +907,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr } memset((char *) him4, 0, sizeof(struct sockaddr_in)); address = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, -1); him4->sin_port = htons((short) port); him4->sin_addr.s_addr = (uint32_t) htonl(address); him4->sin_family = AF_INET; diff --git a/src/windows/native/java/net/Inet4AddressImpl.c b/src/windows/native/java/net/Inet4AddressImpl.c index 9e7097ec91020d8e9f210f7b90f6165f069ee167..eaeb1f0bccfc0f0703cd82e37de5c378215d79ca 100644 --- a/src/windows/native/java/net/Inet4AddressImpl.c +++ b/src/windows/native/java/net/Inet4AddressImpl.c @@ -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 @@ -195,6 +195,8 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, goto cleanupAndReturn; } setInetAddress_addr(env, iaObj, ntohl(address)); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; (*env)->SetObjectArrayElement(env, ret, 0, iaObj); JNU_ReleaseStringPlatformChars(env, host, hostname); return ret; @@ -228,7 +230,11 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, goto cleanupAndReturn; } setInetAddress_addr(env, iaObj, ntohl((*addrp)->s_addr)); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; setInetAddress_hostName(env, iaObj, host); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; (*env)->SetObjectArrayElement(env, ret, i, iaObj); addrp++; i++; diff --git a/src/windows/native/java/net/Inet6AddressImpl.c b/src/windows/native/java/net/Inet6AddressImpl.c index 0ebd0613b6a133c2d1576745e4a6a2783e8d605c..bf3df11c0695136d8932c886fb5748524be412f2 100644 --- a/src/windows/native/java/net/Inet6AddressImpl.c +++ b/src/windows/native/java/net/Inet6AddressImpl.c @@ -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 @@ -219,7 +219,11 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, goto cleanupAndReturn; } setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr)); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; setInetAddress_hostName(env, iaObj, host); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj); inetIndex ++; } else if (iterator->ai_family == AF_INET6) { @@ -240,6 +244,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, setInet6Address_scopeid(env, iaObj, scope); } setInetAddress_hostName(env, iaObj, host); + if ((*env)->ExceptionCheck(env)) + goto cleanupAndReturn; (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj); inet6Index ++; } diff --git a/src/windows/native/java/net/NetworkInterface.c b/src/windows/native/java/net/NetworkInterface.c index 4dc22a08c0f44b625754e2072949e6286324dd96..6b2d05f5233ba111f52b4c05c20de0d13faf2801 100644 --- a/src/windows/native/java/net/NetworkInterface.c +++ b/src/windows/native/java/net/NetworkInterface.c @@ -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 @@ -593,6 +593,7 @@ jobject createNetworkInterface /* 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 (addrs->mask != -1) { ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { @@ -606,6 +607,7 @@ jobject createNetworkInterface return NULL; } setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); @@ -761,8 +763,9 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 (JNIEnv *env, jclass cls, jobject iaObj) { netif *ifList, *curr; - jint addr = getInetAddress_addr(env, iaObj); jobject netifObj = NULL; + jint addr = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack if (ipv6_available()) { diff --git a/src/windows/native/java/net/NetworkInterface_winXP.c b/src/windows/native/java/net/NetworkInterface_winXP.c index d4d8c510039a32a697d03e1486cc2c914d5365a0..9f6ba398a29276434a8c88ca4f53b81a40c8171f 100644 --- a/src/windows/native/java/net/NetworkInterface_winXP.c +++ b/src/windows/native/java/net/NetworkInterface_winXP.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, 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 @@ -552,6 +552,7 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { free_netaddr(netaddrP); @@ -564,6 +565,7 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) return NULL; } setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); diff --git a/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c b/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c index e7f1f58f1d5c8ba0fa502471dd3eaefc22bc713e..2b683aaab02af7440498881fcd53b80e13faa018 100644 --- a/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c +++ b/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c @@ -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 @@ -439,12 +439,13 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, memset((char *)&lcladdr, 0, sizeof(lcladdr)); family = getInetAddress_family(env, addressObj); + JNU_CHECK_EXCEPTION(env); if (family == IPv6 && !ipv6_supported) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "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; @@ -459,6 +460,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, return; } else { address = getInetAddress_addr(env, addressObj); + JNU_CHECK_EXCEPTION(env); } if (NET_InetAddressToSockaddr(env, addressObj, port, (struct sockaddr *)&lcladdr, &lcladdrlen, JNI_FALSE) != 0) { @@ -562,8 +564,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject thi } addr = getInetAddress_addr(env, address); - + JNU_CHECK_EXCEPTION(env); family = getInetAddress_family(env, address); + JNU_CHECK_EXCEPTION(env); if (family == IPv6 && !ipv6_supported) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family not supported"); @@ -681,6 +684,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this, } family = getInetAddress_family(env, iaObj); + JNU_CHECK_EXCEPTION(env); if (family == IPv4) { fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); } else { @@ -731,6 +735,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this, * Check is not necessary on these OSes */ if (connected) { address = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION(env); } else { address = ntohl(rmtaddr.him4.sin_addr.s_addr); } @@ -841,6 +846,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, return -1; } else { address = getInetAddress_addr(env, addressObj); + JNU_CHECK_EXCEPTION_RETURN(env, -1); /* We only handle IPv4 for now. Will support IPv6 once its in the os */ family = AF_INET; } @@ -923,7 +929,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, return 0; } setInetAddress_addr(env, addressObj, ntohl(remote_addr.sin_addr.s_addr)); + JNU_CHECK_EXCEPTION_RETURN(env, -1); setInetAddress_family(env, addressObj, IPv4); + JNU_CHECK_EXCEPTION_RETURN(env, -1); /* return port */ return ntohs(remote_addr.sin_port); @@ -1630,6 +1638,7 @@ static int getInetAddrFromIf (JNIEnv *env, int family, jobject nif, jobject *iad int fam; addr = (*env)->GetObjectArrayElement(env, addrArray, i); fam = getInetAddress_family(env, addr); + JNU_CHECK_EXCEPTION_RETURN(env, -1); if (fam == family) { *iaddr = addr; return 0; @@ -1648,6 +1657,7 @@ static int getInet4AddrFromIf (JNIEnv *env, jobject nif, struct in_addr *iaddr) } iaddr->s_addr = htonl(getInetAddress_addr(env, addr)); + JNU_CHECK_EXCEPTION_RETURN(env, -1); return 0; } @@ -1752,6 +1762,7 @@ static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, struct in_addr in; in.s_addr = htonl(getInetAddress_addr(env, value)); + JNU_CHECK_EXCEPTION(env); if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&in, sizeof(in)) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", @@ -1993,7 +2004,7 @@ static jobject getIPv4NetworkInterface (JNIEnv *env, jobject this, int fd, jint CHECK_NULL_RETURN(addr, NULL); setInetAddress_addr(env, addr, ntohl(in.s_addr)); - + JNU_CHECK_EXCEPTION_RETURN(env, NULL); /* * For IP_MULTICAST_IF return InetAddress */ diff --git a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c index 6e7ea71e6b6f7f5215867d9a28f6ed577e5fc5a2..bf7c047f88edcfa4e2fb3c2cfdd5bb5478eb4dc3 100644 --- a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c +++ b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c @@ -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 @@ -414,6 +414,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); family = getInetAddress_family(env, iaObj); + JNU_CHECK_EXCEPTION(env); if (family == IPv6 && !ipv6_supported) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", @@ -731,7 +732,9 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this, } setInetAddress_addr(env, socketAddressObj, ntohl(him.him4.sin_addr.s_addr)); + JNU_CHECK_EXCEPTION(env); setInetAddress_family(env, socketAddressObj, IPv4); + JNU_CHECK_EXCEPTION(env); (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); } else { /* AF_INET6 -> Inet6Address */ @@ -758,6 +761,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this, } setInet6Address_ipaddress(env, socketAddressObj, (const char *)&him.him6.sin6_addr); setInetAddress_family(env, socketAddressObj, IPv6); + JNU_CHECK_EXCEPTION(env); setInet6Address_scopeid(env, socketAddressObj, him.him6.sin6_scope_id); } diff --git a/src/windows/native/java/net/net_util_md.c b/src/windows/native/java/net/net_util_md.c index 7d990bff9e9c9fab7f3988825eda758a4f7c192d..4721e036826ad30d4573958e4a39ae685cef4704 100644 --- a/src/windows/native/java/net/net_util_md.c +++ b/src/windows/native/java/net/net_util_md.c @@ -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 @@ -875,6 +875,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr int *len, jboolean v4MappedAddress) { jint family, iafam; iafam = getInetAddress_family(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, -1); family = (iafam == IPv4)? AF_INET : AF_INET6; if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) { struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him; @@ -885,6 +886,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr if (family == AF_INET) { /* will convert to IPv4-mapped address */ memset((char *) caddr, 0, 16); address = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, -1); if (address == INADDR_ANY) { /* we would always prefer IPv6 wildcard address caddr[10] = 0xff; @@ -923,6 +925,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr } memset((char *) him4, 0, sizeof(struct sockaddr_in)); address = getInetAddress_addr(env, iaObj); + JNU_CHECK_EXCEPTION_RETURN(env, -1); him4->sin_port = htons((short) port); him4->sin_addr.s_addr = (u_long) htonl(address); him4->sin_family = AF_INET; diff --git a/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java b/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java index 77312208d11c540cdef0d048c8284421077a8ddc..77b4cdbd56ad1282d010f73e7b730116bae6c9d1 100644 --- a/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java +++ b/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java @@ -39,7 +39,7 @@ public final class OutputAnalyzer { 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 diff --git a/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java index 5050e15dff5207cf762f33b5d7db9a631d814811..5edbefcdfcf5ce71da9607c512d0b35014c2d7f0 100644 --- a/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java +++ b/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java @@ -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 @@ package jdk.testlibrary; 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 @@ public final class ProcessTools { * @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); diff --git a/test/lib/testlibrary/jdk/testlibrary/SecurityTools.java b/test/lib/testlibrary/jdk/testlibrary/SecurityTools.java index 6eca88d2601da36c92cdebc4f2b1185567befc7b..71a4b852deb0a21faf654035962eec5baaa63e08 100644 --- a/test/lib/testlibrary/jdk/testlibrary/SecurityTools.java +++ b/test/lib/testlibrary/jdk/testlibrary/SecurityTools.java @@ -49,10 +49,7 @@ public class SecurityTools { 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 @@ public class SecurityTools { 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 class SecurityTools { public static OutputAnalyzer jarsigner(List 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); + } } } diff --git a/test/sun/security/tools/jarsigner/TimestampCheck.java b/test/sun/security/tools/jarsigner/TimestampCheck.java index 2d4760283722405787fe16b465965a77258a36de..ab11a8d58d249cff355cb4890611dc8e4950e172 100644 --- a/test/sun/security/tools/jarsigner/TimestampCheck.java +++ b/test/sun/security/tools/jarsigner/TimestampCheck.java @@ -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.KeyStore; 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.util.ObjectIdentifier; 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 @@ import sun.security.x509.X500Name; * 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 @@ public class TimestampCheck { */ 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 @@ public class TimestampCheck { 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 @@ public class TimestampCheck { 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 @@ public class TimestampCheck { "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,25 +305,53 @@ public class TimestampCheck { 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") - .shouldContain("is not timestamped") + + sign("normal") + .shouldNotContain("Warning") .shouldHaveExitValue(0); - sign("badku") + verify("normal.jar") + .shouldNotContain("Warning") .shouldHaveExitValue(0); - checkBadKU("badku.jar"); - sign("normal") - .shouldNotContain("is not timestamped") + // 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); + + signVerbose(null, "unsigned.jar", "badku.jar", "badku") + .shouldHaveExitValue(8); + checkBadKU("badku.jar"); + + // 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); sign("diffnonce") @@ -325,11 +362,11 @@ public class TimestampCheck { .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 @@ public class TimestampCheck { 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"); - - signWithAliasAndTsa("halfWeak", "old.jar", "old", "-digestalg", "MD5") - .shouldHaveExitValue(0); + .shouldHaveExitValue(68); + checkWeak("tsweak.jar"); + + signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer") + .shouldHaveExitValue(64) + .shouldContain("TSA certificate chain is invalid"); + + // 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 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 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 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 @@ public class TimestampCheck { .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 @@ public class TimestampCheck { .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 @@ public class TimestampCheck { 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 @@ public class TimestampCheck { 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 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 @@ public class TimestampCheck { } 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"); + + // 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("old"); + 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 @@ public class TimestampCheck { } 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 Map mapOf(K k1, V v1) { + return Collections.singletonMap(k1, v1); + } + + static List listOf(E... elements) { + return Arrays.asList(elements); + } } diff --git a/test/sun/security/tools/jarsigner/TsacertOptionTest.java b/test/sun/security/tools/jarsigner/TsacertOptionTest.java index 811ffd9c221fdf2877c857f17d1b77df30ee30ea..96116e1efde853f0759117812ae5ddc83b065b98 100644 --- a/test/sun/security/tools/jarsigner/TsacertOptionTest.java +++ b/test/sun/security/tools/jarsigner/TsacertOptionTest.java @@ -46,6 +46,7 @@ public class TsacertOptionTest { + ".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 @@ public class TsacertOptionTest { // 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", SIGNING_KEY_ALIAS, + "-alias", CA_KEY_ALIAS, "-keyalg", KEY_ALG, "-keysize", Integer.toString(KEY_SIZE), "-keystore", KEYSTORE, "-storepass", PASSWORD, "-keypass", PASSWORD, - "-dname", "CN=Test", + "-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").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 diff --git a/test/sun/security/tools/jarsigner/Warning.java b/test/sun/security/tools/jarsigner/Warning.java new file mode 100644 index 0000000000000000000000000000000000000000..095d2053438b502b5d4f5bc3d9051faf153ebb31 --- /dev/null +++ b/test/sun/security/tools/jarsigner/Warning.java @@ -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; + } +} + diff --git a/test/sun/security/tools/jarsigner/checkusage.sh b/test/sun/security/tools/jarsigner/checkusage.sh index ff2d1c53f38a0d04d2ca9c4639c15e7285fd2de0..5debcc0bc7fcfbe5a3c1a61cc7634e47b57d47ff 100644 --- a/test/sun/security/tools/jarsigner/checkusage.sh +++ b/test/sun/security/tools/jarsigner/checkusage.sh @@ -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 @@ echo $RESULT #[ $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 @@ echo $RESULT #[ $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=$? diff --git a/test/sun/security/tools/jarsigner/concise_jarsigner.sh b/test/sun/security/tools/jarsigner/concise_jarsigner.sh index 34e7b3240c624c79b2a4a086e8cbe995a17a7b29..b9ec9e8323229e146fe33a387748a4e6e930feef 100644 --- a/test/sun/security/tools/jarsigner/concise_jarsigner.sh +++ b/test/sun/security/tools/jarsigner/concise_jarsigner.sh @@ -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 @@ esac # 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 @@ YEAR=`date +%Y` # 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 @@ $JARSIGNER -verify a.jar -strict [ $? = 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=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l` [ $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 - -# 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 js.jks -storepass changeit a.jar expired +$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 + +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar expired [ $? = 4 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar notyetvalid +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar notyetvalid [ $? = 4 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badku +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badku [ $? = 8 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badeku +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badeku [ $? = 8 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodku +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodku [ $? = 0 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodeku +$JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodeku [ $? = 0 ] || exit $LINENO -$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badchain +# 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 $KS -storepass changeit a.jar badchain [ $? = 4 ] || exit $LINENO $JARSIGNER -verify a.jar @@ -181,23 +193,55 @@ $JARSIGNER -verify a.jar # 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 diff --git a/test/sun/security/tools/jarsigner/ec.sh b/test/sun/security/tools/jarsigner/ec.sh index fc66bbc8f9e2daba5f189c53db0947b38531bfbe..442e854635e67bd038b18f6d22b53a467030eb95 100644 --- a/test/sun/security/tools/jarsigner/ec.sh +++ b/test/sun/security/tools/jarsigner/ec.sh @@ -53,11 +53,20 @@ rm $KS $JFILE 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 diff --git a/test/sun/security/tools/jarsigner/onlymanifest.sh b/test/sun/security/tools/jarsigner/onlymanifest.sh index 37551a86fac3787c98527a95a02ce83433e29ff7..bbc90a1b3a889a067aedbbecdc6c09a6579db418 100644 --- a/test/sun/security/tools/jarsigner/onlymanifest.sh +++ b/test/sun/security/tools/jarsigner/onlymanifest.sh @@ -57,12 +57,14 @@ rm $KS $JFILE 2> /dev/null 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 diff --git a/test/sun/security/tools/jarsigner/warnings.sh b/test/sun/security/tools/jarsigner/warnings.sh deleted file mode 100644 index fbe745585ae33e08a30723c091945b91bb4021f1..0000000000000000000000000000000000000000 --- a/test/sun/security/tools/jarsigner/warnings.sh +++ /dev/null @@ -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 - - diff --git a/test/sun/security/tools/jarsigner/warnings/Test.java b/test/sun/security/tools/jarsigner/warnings/Test.java index 999789a5e7404754fb185365b3349956007f72d0..5688d6126cfe4a367bf4657f06b0a06ef96ab64f 100644 --- a/test/sun/security/tools/jarsigner/warnings/Test.java +++ b/test/sun/security/tools/jarsigner/warnings/Test.java @@ -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 @@ public abstract class Test { 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 @@ public abstract class Test { + "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."; diff --git a/test/sun/security/tools/jarsigner/weaksize.sh b/test/sun/security/tools/jarsigner/weaksize.sh new file mode 100644 index 0000000000000000000000000000000000000000..28aad3dce69deae4d975099f726416506c59d720 --- /dev/null +++ b/test/sun/security/tools/jarsigner/weaksize.sh @@ -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