# HG changeset patch # User mullan # Date 1338412786 14400 # Node ID 9ffbd4e4341375b8013bf85b9d9c160298adf6d0 # Parent 5fe35861f07e9fd2c7ae936b6ed0ef84a4c973ac 6854712: Revocation checking enhancements (JEP-124) 6637288: Add OCSP support to PKIX CertPathBuilder implementation 7126011: ReverseBuilder.getMatchingCACerts may throws NPE Reviewed-by: xuelei diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/java/security/cert/CertPathBuilder.java --- a/jdk/src/share/classes/java/security/cert/CertPathBuilder.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/java/security/cert/CertPathBuilder.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -45,15 +45,28 @@ * one of the static <code>getInstance</code> methods, passing in the * algorithm name of the <code>CertPathBuilder</code> desired and optionally * the name of the provider desired. - * <p> - * Once a <code>CertPathBuilder</code> object has been created, certification + * + * <p>Once a <code>CertPathBuilder</code> object has been created, certification * paths can be constructed by calling the {@link #build build} method and * passing it an algorithm-specific set of parameters. If successful, the * result (including the <code>CertPath</code> that was built) is returned * in an object that implements the <code>CertPathBuilderResult</code> * interface. * - * <p> Every implementation of the Java platform is required to support the + * <p>The {@link #getRevocationChecker} method allows an application to specify + * additional algorithm-specific parameters and options used by the + * {@code CertPathBuilder} when checking the revocation status of certificates. + * Here is an example demonstrating how it is used with the PKIX algorithm: + * + * <pre> + * CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX"); + * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker(); + * rc.setOptions(EnumSet.of(Option.PREFER_CRLS)); + * params.addCertPathChecker(rc); + * CertPathBuilderResult cpbr = cpb.build(params); + * </pre> + * + * <p>Every implementation of the Java platform is required to support the * following standard <code>CertPathBuilder</code> algorithm: * <ul> * <li><tt>PKIX</tt></li> @@ -96,10 +109,9 @@ * </pre> */ private static final String CPB_TYPE = "certpathbuilder.type"; - private static final Debug debug = Debug.getInstance("certpath"); - private CertPathBuilderSpi builderSpi; - private Provider provider; - private String algorithm; + private final CertPathBuilderSpi builderSpi; + private final Provider provider; + private final String algorithm; /** * Creates a <code>CertPathBuilder</code> object of the given algorithm, @@ -290,15 +302,30 @@ * if no such property exists. */ public final static String getDefaultType() { - String cpbtype; - cpbtype = AccessController.doPrivileged(new PrivilegedAction<String>() { - public String run() { - return Security.getProperty(CPB_TYPE); - } - }); - if (cpbtype == null) { - cpbtype = "PKIX"; - } - return cpbtype; + String cpbtype = + AccessController.doPrivileged(new PrivilegedAction<String>() { + public String run() { + return Security.getProperty(CPB_TYPE); + } + }); + return (cpbtype == null) ? "PKIX" : cpbtype; + } + + /** + * Returns a {@code CertPathChecker} that the encapsulated + * {@code CertPathBuilderSpi} implementation uses to check the revocation + * status of certificates. A PKIX implementation returns objects of + * type {@code PKIXRevocationChecker}. + * + * <p>The primary purpose of this method is to allow callers to specify + * additional input parameters and options specific to revocation checking. + * See the class description for an example. + * + * @throws UnsupportedOperationException if the service provider does not + * support this method + * @since 1.8 + */ + public final CertPathChecker getRevocationChecker() { + return builderSpi.engineGetRevocationChecker(); } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java --- a/jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -72,4 +72,25 @@ */ public abstract CertPathBuilderResult engineBuild(CertPathParameters params) throws CertPathBuilderException, InvalidAlgorithmParameterException; + + /** + * Returns a {@code CertPathChecker} that this implementation uses to + * check the revocation status of certificates. A PKIX implementation + * returns objects of type {@code PKIXRevocationChecker}. + * + * <p>The primary purpose of this method is to allow callers to specify + * additional input parameters and options specific to revocation checking. + * See the class description of {@code CertPathBuilder} for an example. + * + * <p>This method was added to version 1.8 of the Java Platform Standard + * Edition. In order to maintain backwards compatibility with existing + * service providers, this method cannot be abstract and by default throws + * an {@code UnsupportedOperationException}. + * + * @throws UnsupportedOperationException if this method is not supported + * @since 1.8 + */ + public CertPathChecker engineGetRevocationChecker() { + throw new UnsupportedOperationException(); + } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/java/security/cert/CertPathChecker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/security/cert/CertPathChecker.java Wed May 30 17:19:46 2012 -0400 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.security.cert; + +/** + * <p>Performs one or more checks on each {@code Certificate} of a + * {@code CertPath}. + * + * <p>A {@code CertPathChecker} implementation is typically created to extend + * a certification path validation algorithm. For example, an implementation + * may check for and process a critical private extension of each certificate + * in a certification path. + * + * @since 1.8 + */ +public interface CertPathChecker { + + /** + * Initializes the internal state of this {@code CertPathChecker}. + * + * <p>The {@code forward} flag specifies the order that certificates will + * be passed to the {@link #check check} method (forward or reverse). + * + * @param forward the order that certificates are presented to the + * {@code check} method. If {@code true}, certificates are + * presented from target to trust anchor (forward); if + * {@code false}, from trust anchor to target (reverse). + * @throws CertPathValidatorException if this {@code CertPathChecker} is + * unable to check certificates in the specified order + */ + void init(boolean forward) throws CertPathValidatorException; + + /** + * Indicates if forward checking is supported. Forward checking refers + * to the ability of the {@code CertPathChecker} to perform its checks + * when certificates are presented to the {@code check} method in the + * forward direction (from target to trust anchor). + * + * @return {@code true} if forward checking is supported, {@code false} + * otherwise + */ + boolean isForwardCheckingSupported(); + + /** + * Performs the check(s) on the specified certificate using its internal + * state. The certificates are presented in the order specified by the + * {@code init} method. + * + * @param cert the {@code Certificate} to be checked + * @throws CertPathValidatorException if the specified certificate does + * not pass the check + */ + void check(Certificate cert) throws CertPathValidatorException; +} diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/java/security/cert/CertPathValidator.java --- a/jdk/src/share/classes/java/security/cert/CertPathValidator.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/java/security/cert/CertPathValidator.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -46,15 +46,29 @@ * call one of the static <code>getInstance</code> methods, passing in the * algorithm name of the <code>CertPathValidator</code> desired and * optionally the name of the provider desired. - * <p> - * Once a <code>CertPathValidator</code> object has been created, it can + * + * <p>Once a <code>CertPathValidator</code> object has been created, it can * be used to validate certification paths by calling the {@link #validate * validate} method and passing it the <code>CertPath</code> to be validated * and an algorithm-specific set of parameters. If successful, the result is * returned in an object that implements the * <code>CertPathValidatorResult</code> interface. * - * <p> Every implementation of the Java platform is required to support the + * <p>The {@link #getRevocationChecker} method allows an application to specify + * additional algorithm-specific parameters and options used by the + * {@code CertPathValidator} when checking the revocation status of + * certificates. Here is an example demonstrating how it is used with the PKIX + * algorithm: + * + * <pre> + * CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); + * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpv.getRevocationChecker(); + * rc.setOptions(EnumSet.of(Option.SOFT_FAIL)); + * params.addCertPathChecker(rc); + * CertPathValidatorResult cpvr = cpv.validate(path, params); + * </pre> + * + * <p>Every implementation of the Java platform is required to support the * following standard <code>CertPathValidator</code> algorithm: * <ul> * <li><tt>PKIX</tt></li> @@ -96,10 +110,9 @@ * </pre> */ private static final String CPV_TYPE = "certpathvalidator.type"; - private static final Debug debug = Debug.getInstance("certpath"); - private CertPathValidatorSpi validatorSpi; - private Provider provider; - private String algorithm; + private final CertPathValidatorSpi validatorSpi; + private final Provider provider; + private final String algorithm; /** * Creates a <code>CertPathValidator</code> object of the given algorithm, @@ -301,15 +314,30 @@ * if no such property exists. */ public final static String getDefaultType() { - String cpvtype; - cpvtype = AccessController.doPrivileged(new PrivilegedAction<String>() { - public String run() { - return Security.getProperty(CPV_TYPE); - } - }); - if (cpvtype == null) { - cpvtype = "PKIX"; - } - return cpvtype; + String cpvtype = + AccessController.doPrivileged(new PrivilegedAction<String>() { + public String run() { + return Security.getProperty(CPV_TYPE); + } + }); + return (cpvtype == null) ? "PKIX" : cpvtype; + } + + /** + * Returns a {@code CertPathChecker} that the encapsulated + * {@code CertPathValidatorSpi} implementation uses to check the revocation + * status of certificates. A PKIX implementation returns objects of + * type {@code PKIXRevocationChecker}. + * + * <p>The primary purpose of this method is to allow callers to specify + * additional input parameters and options specific to revocation checking. + * See the class description for an example. + * + * @throws UnsupportedOperationException if the service provider does not + * support this method + * @since 1.8 + */ + public final CertPathChecker getRevocationChecker() { + return validatorSpi.engineGetRevocationChecker(); } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java --- a/jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -82,4 +82,25 @@ public abstract CertPathValidatorResult engineValidate(CertPath certPath, CertPathParameters params) throws CertPathValidatorException, InvalidAlgorithmParameterException; + + /** + * Returns a {@code CertPathChecker} that this implementation uses to + * check the revocation status of certificates. A PKIX implementation + * returns objects of type {@code PKIXRevocationChecker}. + * + * <p>The primary purpose of this method is to allow callers to specify + * additional input parameters and options specific to revocation checking. + * See the class description of {@code CertPathValidator} for an example. + * + * <p>This method was added to version 1.8 of the Java Platform Standard + * Edition. In order to maintain backwards compatibility with existing + * service providers, this method cannot be abstract and by default throws + * an {@code UnsupportedOperationException}. + * + * @throws UnsupportedOperationException if this method is not supported + * @since 1.8 + */ + public CertPathChecker engineGetRevocationChecker() { + throw new UnsupportedOperationException(); + } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java --- a/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -87,7 +87,8 @@ * @author Yassir Elley * @author Sean Mullan */ -public abstract class PKIXCertPathChecker implements Cloneable { +public abstract class PKIXCertPathChecker + implements CertPathChecker, Cloneable { /** * Default constructor. @@ -111,6 +112,7 @@ * the specified order; it should never be thrown if the forward flag * is false since reverse checking must be supported */ + @Override public abstract void init(boolean forward) throws CertPathValidatorException; @@ -123,6 +125,7 @@ * @return <code>true</code> if forward checking is supported, * <code>false</code> otherwise */ + @Override public abstract boolean isForwardCheckingSupported(); /** @@ -163,6 +166,17 @@ throws CertPathValidatorException; /** + * {@inheritDoc} + * + * <p>This implementation calls + * {@code check(cert, java.util.Collections.<String>emptySet())}. + */ + @Override + public void check(Certificate cert) throws CertPathValidatorException { + check(cert, java.util.Collections.<String>emptySet()); + } + + /** * Returns a clone of this object. Calls the <code>Object.clone()</code> * method. * All subclasses which maintain state must support and @@ -170,6 +184,7 @@ * * @return a copy of this <code>PKIXCertPathChecker</code> */ + @Override public Object clone() { try { return super.clone(); diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java Wed May 30 17:19:46 2012 -0400 @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.security.cert; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * A {@code PKIXCertPathChecker} for checking the revocation status of + * certificates with the PKIX algorithm. + * + * <p>A {@code PKIXRevocationChecker} checks the revocation status of + * certificates with the Online Certificate Status Protocol (OCSP) or + * Certificate Revocation Lists (CRLs). OCSP is described in RFC 2560 and + * is a network protocol for determining the status of a certificate. A CRL + * is a time-stamped list identifying revoked certificates, and RFC 5280 + * describes an algorithm for determining the revocation status of certificates + * using CRLs. + * + * <p>Each {@code PKIXRevocationChecker} must be able to check the revocation + * status of certificates with OCSP and CRLs. By default, OCSP is the + * preferred mechanism for checking revocation status, with CRLs as the + * fallback mechanism. However, this preference can be switched to CRLs with + * the {@link Option.PREFER_CRLS} option. + * + * <p>A {@code PKIXRevocationChecker} is obtained by calling the + * {@link CertPathValidator#getRevocationChecker getRevocationChecker} method + * of a PKIX {@code CertPathValidator}. Additional parameters and options + * specific to revocation can be set (by calling {@link #setOCSPResponder} + * method for instance). The {@code PKIXRevocationChecker} is added to + * a {@code PKIXParameters} object using the + * {@link PKIXParameters#addCertPathChecker addCertPathChecker} + * or {@link PKIXParameters#setCertPathCheckers setCertPathCheckers} method, + * and then the {@code PKIXParameters} is passed along with the {@code CertPath} + * to be validated to the {@link CertPathValidator#validate validate} method + * of a PKIX {@code CertPathValidator}. When supplying a revocation checker in + * this manner, do not enable the default revocation checking mechanism (by + * calling {@link PKIXParameters#setRevocationEnabled}. + * + * <p>Note that when a {@code PKIXRevocationChecker} is added to + * {@code PKIXParameters}, it clones the {@code PKIXRevocationChecker}; + * thus any subsequent modifications to the {@code PKIXRevocationChecker} + * have no effect. + * + * <p>Any parameter that is not set (or is set to {@code null}) will be set to + * the default value for that parameter. + * + * <p><b>Concurrent Access</b> + * + * <p>Unless otherwise specified, the methods defined in this class are not + * thread-safe. Multiple threads that need to access a single object + * concurrently should synchronize amongst themselves and provide the + * necessary locking. Multiple threads each manipulating separate objects + * need not synchronize. + * + * @since 1.8 + */ +public abstract class PKIXRevocationChecker extends PKIXCertPathChecker { + private URI ocspResponder; + private X509Certificate ocspResponderCert; + private List<Extension> ocspExtensions = Collections.<Extension>emptyList(); + private Map<X509Certificate, byte[]> ocspStapled = Collections.emptyMap(); + private Set<Option> options = Collections.emptySet(); + + protected PKIXRevocationChecker() {} + + /** + * Sets the URI that identifies the location of the OCSP responder. This + * overrides the {@code ocsp.responderURL} security property and any + * responder specified in a certificate's Authority Information Access + * Extension, as defined in RFC 5280. + * + * @param uri the responder URI + */ + public void setOCSPResponder(URI uri) { + this.ocspResponder = uri; + } + + /** + * Gets the URI that identifies the location of the OCSP responder. This + * overrides the {@code ocsp.responderURL} security property. If this + * parameter or the {@code ocsp.responderURL} property is not set, the + * location is determined from the certificate's Authority Information + * Access Extension, as defined in RFC 5280. + * + * @return the responder URI, or {@code null} if not set + */ + public URI getOCSPResponder() { + return ocspResponder; + } + + /** + * Sets the OCSP responder's certificate. This overrides the + * {@code ocsp.responderCertSubjectName}, + * {@code ocsp.responderCertIssuerName}, + * and {@code ocsp.responderCertSerialNumber} security properties. + * + * @param cert the responder's certificate + */ + public void setOCSPResponderCert(X509Certificate cert) { + this.ocspResponderCert = cert; + } + + /** + * Gets the OCSP responder's certificate. This overrides the + * {@code ocsp.responderCertSubjectName}, + * {@code ocsp.responderCertIssuerName}, + * and {@code ocsp.responderCertSerialNumber} security properties. If this + * parameter or the aforementioned properties are not set, then the + * responder's certificate is determined as specified in RFC 2560. + * + * @return the responder's certificate, or {@code null} if not set + */ + public X509Certificate getOCSPResponderCert() { + return ocspResponderCert; + } + + // request extensions; single extensions not supported + /** + * Sets the optional OCSP request extensions. + * + * @param extensions a list of extensions. The list is copied to protect + * against subsequent modification. + */ + public void setOCSPExtensions(List<Extension> extensions) + { + this.ocspExtensions = (extensions == null) + ? Collections.<Extension>emptyList() + : new ArrayList<Extension>(extensions); + } + + /** + * Gets the optional OCSP request extensions. + * + * @return an unmodifiable list of extensions. Returns an empty list if no + * extensions have been specified. + */ + public List<Extension> getOCSPExtensions() { + return Collections.unmodifiableList(ocspExtensions); + } + + /** + * Sets the stapled OCSP responses. These responses are used to determine + * the revocation status of the specified certificates when OCSP is used. + * + * @param responses a map of stapled OCSP responses. Each key is an + * {@code X509Certificate} that maps to the corresponding + * DER-encoded OCSP response for that certificate. A deep copy of + * the map is performed to protect against subsequent modification. + */ + public void setOCSPStapledResponses(Map<X509Certificate, byte[]> responses) + { + if (responses == null) { + this.ocspStapled = Collections.<X509Certificate, byte[]>emptyMap(); + } else { + Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size()); + for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) { + copy.put(e.getKey(), e.getValue().clone()); + } + this.ocspStapled = copy; + } + } + + /** + * Gets the stapled OCSP responses. These responses are used to determine + * the revocation status of the specified certificates when OCSP is used. + * + * @return a map of stapled OCSP responses. Each key is an + * {@code X509Certificate} that maps to the corresponding + * DER-encoded OCSP response for that certificate. A deep copy of + * the map is returned to protect against subsequent modification. + * Returns an empty map if no responses have been specified. + */ + public Map<X509Certificate, byte[]> getOCSPStapledResponses() { + Map<X509Certificate, byte[]> copy = new HashMap<>(ocspStapled.size()); + for (Map.Entry<X509Certificate, byte[]> e : ocspStapled.entrySet()) { + copy.put(e.getKey(), e.getValue().clone()); + } + return copy; + } + + /** + * Sets the revocation options. + * + * @param options a set of revocation options. The set is copied to protect + * against subsequent modification. + */ + public void setOptions(Set<Option> options) { + this.options = (options == null) + ? Collections.<Option>emptySet() + : new HashSet<Option>(options); + } + + /** + * Gets the revocation options. + * + * @return an unmodifiable set of revocation options, or an empty set if + * none are specified + */ + public Set<Option> getOptions() { + return Collections.unmodifiableSet(options); + } + + @Override + public Object clone() { + PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone(); + copy.ocspExtensions = new ArrayList<>(ocspExtensions); + copy.ocspStapled = new HashMap<>(ocspStapled); + // deep-copy the encoded stapled responses, since they are mutable + for (Map.Entry<X509Certificate, byte[]> entry : + copy.ocspStapled.entrySet()) + { + byte[] encoded = entry.getValue(); + entry.setValue(encoded.clone()); + } + copy.options = new HashSet<>(options); + return copy; + } + + /** + * Various revocation options that can be specified for the revocation + * checking mechanism. + */ + public enum Option { + /** + * Only check the revocation status of end-entity certificates. + */ + ONLY_END_ENTITY, + /** + * Prefer CRLs to OSCP. The default behavior is to prefer OCSP. Each + * PKIX implementation should document further details of their + * specific preference rules and fallback policies. + */ + PREFER_CRLS, + /** + * Ignore network failures. The default behavior is to consider it a + * failure if the revocation status of a certificate cannot be obtained + * due to a network error. This option applies to both OCSP and CRLs. + */ + SOFT_FAIL + } +} diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/java/security/cert/package.html --- a/jdk/src/share/classes/java/security/cert/package.html Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/java/security/cert/package.html Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ <!-- - Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 1998, 2012, 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 @@ -38,8 +38,10 @@ <li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture (JCA) Reference Guide</b></a> - <li>RFC 3280: Internet X.509 Public Key Infrastructure Certificate and + <li>RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile + <li>RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate + Status Protocol - OCSP <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html"> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture Standard Algorithm Name @@ -50,8 +52,8 @@ For information about X.509 certificates and CRLs, please see: <ul> - <li><a href="http://www.ietf.org/rfc/rfc3280.txt"> - http://www.ietf.org/rfc/rfc3280.txt</a> + <li><a href="http://www.ietf.org/rfc/rfc5280.txt"> + http://www.ietf.org/rfc/rfc5280.txt</a> <li><a href= "{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html"> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java --- a/jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -24,13 +24,11 @@ */ package sun.security.provider.certpath; - import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; - /** * An AdjacencyList is used to store the history of certification paths * attempted in constructing a path from an initiator to a target. The @@ -123,124 +121,117 @@ * at the start. */ private boolean buildList(List<List<Vertex>> theList, int index, - BuildStep follow) { + BuildStep follow) { // Each time this method is called, we're examining a new list // from the global list. So, we have to start by getting the list // that contains the set of Vertexes we're considering. List<Vertex> l = theList.get(index); - try { - // we're interested in the case where all indexes are -1... - boolean allNegOne = true; - // ...and in the case where every entry has a Throwable - boolean allXcps = true; + // we're interested in the case where all indexes are -1... + boolean allNegOne = true; + // ...and in the case where every entry has a Throwable + boolean allXcps = true; + + for (Vertex v : l) { + if (v.getIndex() != -1) { + // count an empty list the same as an index of -1...this + // is to patch a bug somewhere in the builder + if (theList.get(v.getIndex()).size() != 0) + allNegOne = false; + } else { + if (v.getThrowable() == null) + allXcps = false; + } + // every entry, regardless of the final use for it, is always + // entered as a possible step before we take any actions + mStepList.add(new BuildStep(v, BuildStep.POSSIBLE)); + } + + if (allNegOne) { + // There are two cases that we could be looking at here. We + // may need to back up, or the build may have succeeded at + // this point. This is based on whether or not any + // exceptions were found in the list. + if (allXcps) { + // we need to go back...see if this is the last one + if (follow == null) + mStepList.add(new BuildStep(null, BuildStep.FAIL)); + else + mStepList.add(new BuildStep(follow.getVertex(), + BuildStep.BACK)); + + return false; + } else { + // we succeeded...now the only question is which is the + // successful step? If there's only one entry without + // a throwable, then that's the successful step. Otherwise, + // we'll have to make some guesses... + List<Vertex> possibles = new ArrayList<>(); + for (Vertex v : l) { + if (v.getThrowable() == null) + possibles.add(v); + } + + if (possibles.size() == 1) { + // real easy...we've found the final Vertex + mStepList.add(new BuildStep(possibles.get(0), + BuildStep.SUCCEED)); + } else { + // ok...at this point, there is more than one Cert + // which might be the succeed step...how do we know + // which it is? I'm going to assume that our builder + // algorithm is good enough to know which is the + // correct one, and put it first...but a FIXME goes + // here anyway, and we should be comparing to the + // target/initiator Cert... + mStepList.add(new BuildStep(possibles.get(0), + BuildStep.SUCCEED)); + } + + return true; + } + } else { + // There's at least one thing that we can try before we give + // up and go back. Run through the list now, and enter a new + // BuildStep for each path that we try to follow. If none of + // the paths we try produce a successful end, we're going to + // have to back out ourselves. + boolean success = false; for (Vertex v : l) { + + // Note that we'll only find a SUCCEED case when we're + // looking at the last possible path, so we don't need to + // consider success in the while loop + if (v.getIndex() != -1) { - // count an empty list the same as an index of -1...this - // is to patch a bug somewhere in the builder - if (theList.get(v.getIndex()).size() != 0) - allNegOne = false; + if (theList.get(v.getIndex()).size() != 0) { + // If the entry we're looking at doesn't have an + // index of -1, and doesn't lead to an empty list, + // then it's something we follow! + BuildStep bs = new BuildStep(v, BuildStep.FOLLOW); + mStepList.add(bs); + success = buildList(theList, v.getIndex(), bs); + } } - else - if (v.getThrowable() == null) - allXcps = false; - - // every entry, regardless of the final use for it, is always - // entered as a possible step before we take any actions - mStepList.add(new BuildStep(v, BuildStep.POSSIBLE)); } - if (allNegOne) { - // There are two cases that we could be looking at here. We - // may need to back up, or the build may have succeeded at - // this point. This is based on whether or not any - // exceptions were found in the list. - if (allXcps) { - // we need to go back...see if this is the last one - if (follow == null) - mStepList.add(new BuildStep(null, BuildStep.FAIL)); - else - mStepList.add(new BuildStep(follow.getVertex(), - BuildStep.BACK)); - - return false; - } else { - // we succeeded...now the only question is which is the - // successful step? If there's only one entry without - // a throwable, then that's the successful step. Otherwise, - // we'll have to make some guesses... - List<Vertex> possibles = new ArrayList<Vertex>(); - for (Vertex v : l) { - if (v.getThrowable() == null) - possibles.add(v); - } - - if (possibles.size() == 1) { - // real easy...we've found the final Vertex - mStepList.add(new BuildStep(possibles.get(0), - BuildStep.SUCCEED)); - } else { - // ok...at this point, there is more than one Cert - // which might be the succeed step...how do we know - // which it is? I'm going to assume that our builder - // algorithm is good enough to know which is the - // correct one, and put it first...but a FIXME goes - // here anyway, and we should be comparing to the - // target/initiator Cert... - mStepList.add(new BuildStep(possibles.get(0), - BuildStep.SUCCEED)); - } + if (success) { + // We're already finished! + return true; + } else { + // We failed, and we've exhausted all the paths that we + // could take. The only choice is to back ourselves out. + if (follow == null) + mStepList.add(new BuildStep(null, BuildStep.FAIL)); + else + mStepList.add(new BuildStep(follow.getVertex(), + BuildStep.BACK)); - return true; - } - } else { - // There's at least one thing that we can try before we give - // up and go back. Run through the list now, and enter a new - // BuildStep for each path that we try to follow. If none of - // the paths we try produce a successful end, we're going to - // have to back out ourselves. - boolean success = false; - - for (Vertex v : l) { - - // Note that we'll only find a SUCCEED case when we're - // looking at the last possible path, so we don't need to - // consider success in the while loop - - if (v.getIndex() != -1) { - if (theList.get(v.getIndex()).size() != 0) { - // If the entry we're looking at doesn't have an - // index of -1, and doesn't lead to an empty list, - // then it's something we follow! - BuildStep bs = new BuildStep(v, BuildStep.FOLLOW); - mStepList.add(bs); - success = buildList(theList, v.getIndex(), bs); - } - } - } - - if (success) { - // We're already finished! - return true; - } else { - // We failed, and we've exhausted all the paths that we - // could take. The only choice is to back ourselves out. - if (follow == null) - mStepList.add(new BuildStep(null, BuildStep.FAIL)); - else - mStepList.add(new BuildStep(follow.getVertex(), - BuildStep.BACK)); - - return false; - } + return false; } } - catch (Exception e) {} - - // we'll never get here, but you know java... - return false; } /** @@ -248,23 +239,20 @@ * * @return String representation */ + @Override public String toString() { - String out = "[\n"; + StringBuilder sb = new StringBuilder("[\n"); int i = 0; for (List<Vertex> l : mOrigList) { - out = out + "LinkedList[" + i++ + "]:\n"; + sb.append("LinkedList[").append(i++).append("]:\n"); for (Vertex step : l) { - try { - out = out + step.toString(); - out = out + "\n"; - } - catch (Exception e) { out = out + "No Such Element\n"; } + sb.append(step.toString()).append("\n"); } } - out = out + "]\n"; + sb.append("]\n"); - return out; + return sb.toString(); } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java --- a/jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -62,7 +62,7 @@ private static final Debug debug = Debug.getInstance("certpath"); private final PublicKey trustedPubKey; private final X500Principal caName; - private final Date testDate; + private final Date date; private final String sigProvider; private final boolean sigOnly; private X500Principal prevSubject; @@ -73,14 +73,13 @@ * * @param anchor the anchor selected to validate the target certificate * @param testDate the time for which the validity of the certificate - * should be determined + * should be determined * @param sigProvider the name of the signature provider * @param sigOnly true if only signature checking is to be done; * if false, all checks are done */ - BasicChecker(TrustAnchor anchor, Date testDate, String sigProvider, - boolean sigOnly) throws CertPathValidatorException - { + BasicChecker(TrustAnchor anchor, Date date, String sigProvider, + boolean sigOnly) { if (anchor.getTrustedCert() != null) { this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); this.caName = anchor.getTrustedCert().getSubjectX500Principal(); @@ -88,16 +87,16 @@ this.trustedPubKey = anchor.getCAPublicKey(); this.caName = anchor.getCA(); } - this.testDate = testDate; + this.date = date; this.sigProvider = sigProvider; this.sigOnly = sigOnly; - init(false); } /** * Initializes the internal state of the checker from parameters * specified in the constructor. */ + @Override public void init(boolean forward) throws CertPathValidatorException { if (!forward) { prevPubKey = trustedPubKey; @@ -108,10 +107,12 @@ } } + @Override public boolean isForwardCheckingSupported() { return false; } + @Override public Set<String> getSupportedExtensions() { return null; } @@ -124,33 +125,31 @@ * @param cert the Certificate * @param unresolvedCritExts a Collection of the unresolved critical * extensions - * @exception CertPathValidatorException Exception thrown if certificate - * does not verify. + * @throws CertPathValidatorException if certificate does not verify */ + @Override public void check(Certificate cert, Collection<String> unresolvedCritExts) throws CertPathValidatorException { - X509Certificate currCert = (X509Certificate) cert; + X509Certificate currCert = (X509Certificate)cert; if (!sigOnly) { - verifyTimestamp(currCert, testDate); - verifyNameChaining(currCert, prevSubject); + verifyTimestamp(currCert); + verifyNameChaining(currCert); } - verifySignature(currCert, prevPubKey, sigProvider); + verifySignature(currCert); updateState(currCert); } /** - * Verifies the signature on the certificate using the previous public key - * @param cert the Certificate - * @param prevPubKey the previous PublicKey - * @param sigProvider a String containing the signature provider - * @exception CertPathValidatorException Exception thrown if certificate - * does not verify. + * Verifies the signature on the certificate using the previous public key. + * + * @param cert the X509Certificate + * @throws CertPathValidatorException if certificate does not verify */ - private void verifySignature(X509Certificate cert, PublicKey prevPubKey, - String sigProvider) throws CertPathValidatorException + private void verifySignature(X509Certificate cert) + throws CertPathValidatorException { String msg = "signature"; if (debug != null) @@ -162,7 +161,7 @@ throw new CertPathValidatorException (msg + " check failed", e, null, -1, BasicReason.INVALID_SIGNATURE); - } catch (Exception e) { + } catch (GeneralSecurityException e) { throw new CertPathValidatorException(msg + " check failed", e); } @@ -173,7 +172,7 @@ /** * Internal method to verify the timestamp on a certificate */ - private void verifyTimestamp(X509Certificate cert, Date date) + private void verifyTimestamp(X509Certificate cert) throws CertPathValidatorException { String msg = "timestamp"; @@ -197,8 +196,8 @@ /** * Internal method to check that cert has a valid DN to be next in a chain */ - private void verifyNameChaining(X509Certificate cert, - X500Principal prevSubject) throws CertPathValidatorException + private void verifyNameChaining(X509Certificate cert) + throws CertPathValidatorException { if (prevSubject != null) { @@ -207,8 +206,8 @@ debug.println("---checking " + msg + "..."); X500Principal currIssuer = cert.getIssuerX500Principal(); + // reject null or empty issuer DNs - if (X500Name.asX500Name(currIssuer).isEmpty()) { throw new CertPathValidatorException (msg + " check failed: " + diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java --- a/jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,6 @@ package sun.security.provider.certpath; -import sun.security.util.Debug; import java.security.cert.X509Certificate; /** @@ -39,7 +38,6 @@ */ public class BuildStep { - private static final Debug debug = Debug.getInstance("certpath"); private Vertex vertex; private X509Certificate cert; private Throwable throwable; @@ -86,7 +84,7 @@ public BuildStep(Vertex vtx, int res) { vertex = vtx; if (vertex != null) { - cert = (X509Certificate)vertex.getCertificate(); + cert = vertex.getCertificate(); throwable = vertex.getThrowable(); } result = res; @@ -117,7 +115,7 @@ * @returns String form of issuer name or null, if no certificate. */ public String getIssuerName() { - return (cert == null ? null : cert.getIssuerX500Principal().toString()); + return getIssuerName(null); } /** @@ -142,7 +140,7 @@ * @returns String form of subject name or null, if no certificate. */ public String getSubjectName() { - return (cert == null ? null : cert.getSubjectX500Principal().toString()); + return getSubjectName(null); } /** @@ -191,21 +189,21 @@ public String resultToString(int res) { String resultString = ""; switch (res) { - case BuildStep.POSSIBLE: + case POSSIBLE: resultString = "Certificate to be tried.\n"; break; - case BuildStep.BACK: + case BACK: resultString = "Certificate backed out since path does not " + "satisfy build requirements.\n"; break; - case BuildStep.FOLLOW: + case FOLLOW: resultString = "Certificate satisfies conditions.\n"; break; - case BuildStep.FAIL: + case FAIL: resultString = "Certificate backed out since path does not " + "satisfy conditions.\n"; break; - case BuildStep.SUCCEED: + case SUCCEED: resultString = "Certificate satisfies conditions.\n"; break; default: @@ -220,6 +218,7 @@ * * @returns String */ + @Override public String toString() { String out = "Internal Error\n"; switch (result) { @@ -273,8 +272,6 @@ * @returns String */ public String fullToString() { - String out = resultToString(getResult()); - out = out + vertex.toString(); - return out; + return resultToString(getResult()) + vertex.toString(); } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/Builder.java --- a/jdk/src/share/classes/sun/security/provider/certpath/Builder.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/Builder.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -31,9 +31,8 @@ import java.security.cert.*; import java.util.*; -import javax.security.auth.x500.X500Principal; - import sun.security.action.GetBooleanAction; +import sun.security.provider.certpath.PKIX.BuilderParams; import sun.security.util.Debug; import sun.security.x509.GeneralNames; import sun.security.x509.GeneralNameInterface; @@ -56,9 +55,7 @@ private static final Debug debug = Debug.getInstance("certpath"); private Set<String> matchingPolicies; - final PKIXBuilderParameters buildParams; - final X500Principal targetSubjectDN; - final Date date; + final BuilderParams buildParams; final X509CertSelector targetCertConstraints; /** @@ -74,14 +71,10 @@ * * @param params the parameter set used to build a certification path */ - Builder(PKIXBuilderParameters buildParams, X500Principal targetSubjectDN) { + Builder(BuilderParams buildParams) { this.buildParams = buildParams; - this.targetSubjectDN = targetSubjectDN; - // Initialize date if not specified - Date paramsDate = buildParams.getDate(); - this.date = paramsDate != null ? paramsDate : new Date(); this.targetCertConstraints = - (X509CertSelector) buildParams.getTargetCertConstraints(); + (X509CertSelector)buildParams.targetCertConstraints(); } /** @@ -104,7 +97,8 @@ * @param certPathList the certPathList generated thus far */ abstract void verifyCert(X509Certificate cert, State currentState, - List<X509Certificate> certPathList) throws GeneralSecurityException; + List<X509Certificate> certPathList) + throws GeneralSecurityException; /** * Verifies whether the input certificate completes the path. @@ -123,7 +117,7 @@ * @param certPathList the certification path list */ abstract void addCertToPath(X509Certificate cert, - LinkedList<X509Certificate> certPathList); + LinkedList<X509Certificate> certPathList); /** * Removes final certificate from the certPathList @@ -147,7 +141,8 @@ * is a grandparent, etc. */ static int distance(GeneralNameInterface base, - GeneralNameInterface test, int incomparable) { + GeneralNameInterface test, int incomparable) + { switch (base.constrains(test)) { case GeneralNameInterface.NAME_DIFF_TYPE: if (debug != null) { @@ -192,7 +187,8 @@ * some number of down hops. */ static int hops(GeneralNameInterface base, GeneralNameInterface test, - int incomparable) { + int incomparable) + { int baseRtest = base.constrains(test); switch (baseRtest) { case GeneralNameInterface.NAME_DIFF_TYPE: @@ -282,9 +278,9 @@ * @throws IOException if certificate does not get closer */ static int targetDistance(NameConstraintsExtension constraints, - X509Certificate cert, GeneralNameInterface target) - throws IOException { - + X509Certificate cert, GeneralNameInterface target) + throws IOException + { /* ensure that certificate satisfies existing name constraints */ if (constraints != null && !constraints.verify(cert)) { throw new IOException("certificate does not satisfy existing name " @@ -295,7 +291,7 @@ try { certImpl = X509CertImpl.toImpl(cert); } catch (CertificateException e) { - throw (IOException)new IOException("Invalid certificate").initCause(e); + throw new IOException("Invalid certificate", e); } /* see if certificate subject matches target */ X500Name subject = X500Name.asX500Name(certImpl.getSubjectX500Principal()); @@ -398,13 +394,13 @@ */ Set<String> getMatchingPolicies() { if (matchingPolicies != null) { - Set<String> initialPolicies = buildParams.getInitialPolicies(); + Set<String> initialPolicies = buildParams.initialPolicies(); if ((!initialPolicies.isEmpty()) && (!initialPolicies.contains(PolicyChecker.ANY_POLICY)) && - (buildParams.isPolicyMappingInhibited())) + (buildParams.policyMappingInhibited())) { - initialPolicies.add(PolicyChecker.ANY_POLICY); - matchingPolicies = initialPolicies; + matchingPolicies = new HashSet<>(initialPolicies); + matchingPolicies.add(PolicyChecker.ANY_POLICY); } else { // we just return an empty set to make sure that there is // at least a certificate policies extension in the cert @@ -429,13 +425,15 @@ * Returns true iff resultCerts changed (a cert was added to the collection) */ boolean addMatchingCerts(X509CertSelector selector, - Collection<CertStore> certStores, - Collection<X509Certificate> resultCerts, boolean checkAll) { + Collection<CertStore> certStores, + Collection<X509Certificate> resultCerts, + boolean checkAll) + { X509Certificate targetCert = selector.getCertificate(); if (targetCert != null) { // no need to search CertStores if (selector.match(targetCert) && !X509CertImpl.isSelfSigned - (targetCert, buildParams.getSigProvider())) { + (targetCert, buildParams.sigProvider())) { if (debug != null) { debug.println("Builder.addMatchingCerts: adding target cert"); } @@ -450,7 +448,7 @@ store.getCertificates(selector); for (Certificate cert : certs) { if (!X509CertImpl.isSelfSigned - ((X509Certificate)cert, buildParams.getSigProvider())) { + ((X509Certificate)cert, buildParams.sigProvider())) { if (resultCerts.add((X509Certificate)cert)) { add = true; } @@ -471,16 +469,4 @@ } return add; } - - /** - * Returns true if CertStore is local. Currently, returns true if - * type is Collection or if it has been initialized with - * CollectionCertStoreParameters. A new API method should be added - * to CertStore that returns local or remote. - */ - static boolean isLocalCertStore(CertStore certStore) { - return (certStore.getType().equals("Collection") || - certStore.getCertStoreParameters() instanceof - CollectionCertStoreParameters); - } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java --- a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2012, 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 @@ -83,9 +83,8 @@ = (CertStoreHelper)c.newInstance(); cache.put(type, csh); return csh; - } catch (InstantiationException e) { - throw new AssertionError(e); - } catch (IllegalAccessException e) { + } catch (InstantiationException | + IllegalAccessException e) { throw new AssertionError(e); } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java --- a/jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -31,7 +31,6 @@ import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.HashSet; -import java.util.Iterator; import java.security.cert.CertSelector; import java.security.cert.CertStore; import java.security.cert.CertStoreException; @@ -114,6 +113,7 @@ * match the specified selector * @throws CertStoreException if an exception occurs */ + @Override public Collection<Certificate> engineGetCertificates (CertSelector selector) throws CertStoreException { if (coll == null) { @@ -122,18 +122,15 @@ // Tolerate a few ConcurrentModificationExceptions for (int c = 0; c < 10; c++) { try { - HashSet<Certificate> result = new HashSet<Certificate>(); - Iterator<?> i = coll.iterator(); + HashSet<Certificate> result = new HashSet<>(); if (selector != null) { - while (i.hasNext()) { - Object o = i.next(); + for (Object o : coll) { if ((o instanceof Certificate) && selector.match((Certificate) o)) result.add((Certificate)o); } } else { - while (i.hasNext()) { - Object o = i.next(); + for (Object o : coll) { if (o instanceof Certificate) result.add((Certificate)o); } @@ -157,6 +154,7 @@ * match the specified selector * @throws CertStoreException if an exception occurs */ + @Override public Collection<CRL> engineGetCRLs(CRLSelector selector) throws CertStoreException { @@ -166,22 +164,19 @@ // Tolerate a few ConcurrentModificationExceptions for (int c = 0; c < 10; c++) { try { - HashSet<CRL> result = new HashSet<CRL>(); - Iterator<?> i = coll.iterator(); + HashSet<CRL> result = new HashSet<>(); if (selector != null) { - while (i.hasNext()) { - Object o = i.next(); + for (Object o : coll) { if ((o instanceof CRL) && selector.match((CRL) o)) result.add((CRL)o); } } else { - while (i.hasNext()) { - Object o = i.next(); + for (Object o : coll) { if (o instanceof CRL) result.add((CRL)o); } } - return(result); + return result; } catch (ConcurrentModificationException e) { } } throw new ConcurrentModificationException("Too many " diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,19 +25,20 @@ package sun.security.provider.certpath; -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import java.util.HashSet; import java.io.IOException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; -import java.security.cert.X509Certificate; import java.security.cert.PKIXCertPathChecker; import java.security.cert.PKIXReason; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + import sun.security.util.Debug; -import sun.security.x509.PKIXExtensions; +import static sun.security.x509.PKIXExtensions.*; import sun.security.x509.NameConstraintsExtension; import sun.security.x509.X509CertImpl; @@ -66,13 +67,12 @@ * Creates a ConstraintsChecker. * * @param certPathLength the length of the certification path - * @throws CertPathValidatorException if the checker cannot be initialized */ - ConstraintsChecker(int certPathLength) throws CertPathValidatorException { + ConstraintsChecker(int certPathLength) { this.certPathLength = certPathLength; - init(false); } + @Override public void init(boolean forward) throws CertPathValidatorException { if (!forward) { i = 0; @@ -84,15 +84,17 @@ } } + @Override public boolean isForwardCheckingSupported() { return false; } + @Override public Set<String> getSupportedExtensions() { if (supportedExts == null) { - supportedExts = new HashSet<String>(); - supportedExts.add(PKIXExtensions.BasicConstraints_Id.toString()); - supportedExts.add(PKIXExtensions.NameConstraints_Id.toString()); + supportedExts = new HashSet<String>(2); + supportedExts.add(BasicConstraints_Id.toString()); + supportedExts.add(NameConstraints_Id.toString()); supportedExts = Collections.unmodifiableSet(supportedExts); } return supportedExts; @@ -104,14 +106,15 @@ * * @param cert the <code>Certificate</code> to be checked * @param unresCritExts a <code>Collection</code> of OID strings - * representing the current set of unresolved critical extensions + * representing the current set of unresolved critical extensions * @throws CertPathValidatorException if the specified certificate - * does not pass the check + * does not pass the check */ + @Override public void check(Certificate cert, Collection<String> unresCritExts) throws CertPathValidatorException { - X509Certificate currCert = (X509Certificate) cert; + X509Certificate currCert = (X509Certificate)cert; i++; // MUST run NC check second, since it depends on BC check to @@ -120,8 +123,8 @@ verifyNameConstraints(currCert); if (unresCritExts != null && !unresCritExts.isEmpty()) { - unresCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString()); - unresCritExts.remove(PKIXExtensions.NameConstraints_Id.toString()); + unresCritExts.remove(BasicConstraints_Id.toString()); + unresCritExts.remove(NameConstraints_Id.toString()); } } @@ -166,9 +169,9 @@ /** * Helper to fold sets of name constraints together */ - static NameConstraintsExtension - mergeNameConstraints(X509Certificate currCert, - NameConstraintsExtension prevNC) throws CertPathValidatorException + static NameConstraintsExtension mergeNameConstraints( + X509Certificate currCert, NameConstraintsExtension prevNC) + throws CertPathValidatorException { X509CertImpl currCertImpl; try { @@ -197,7 +200,7 @@ // Make sure we do a clone here, because we're probably // going to modify this object later and we don't want to // be sharing it with a Certificate object! - return (NameConstraintsExtension) newConstraints.clone(); + return (NameConstraintsExtension)newConstraints.clone(); } } else { try { diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java --- a/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java Mon Jan 23 04:44:16 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,785 +0,0 @@ -/* - * Copyright (c) 2000, 2011, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.security.provider.certpath; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.HashSet; -import java.util.Set; -import java.util.Iterator; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.cert.*; -import java.security.cert.CertPathValidatorException.BasicReason; -import java.security.interfaces.DSAPublicKey; -import sun.security.util.Debug; -import sun.security.x509.AccessDescription; -import sun.security.x509.AuthorityInfoAccessExtension; -import sun.security.x509.CRLDistributionPointsExtension; -import sun.security.x509.DistributionPoint; -import sun.security.x509.GeneralName; -import sun.security.x509.GeneralNames; -import sun.security.x509.PKIXExtensions; -import sun.security.x509.X500Name; -import sun.security.x509.X509CertImpl; -import sun.security.x509.X509CRLEntryImpl; - -/** - * CrlRevocationChecker is a <code>PKIXCertPathChecker</code> that checks - * revocation status information on a PKIX certificate using CRLs obtained - * from one or more <code>CertStores</code>. This is based on section 6.3 - * of RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt). - * - * @since 1.4 - * @author Seth Proctor - * @author Steve Hanna - */ -class CrlRevocationChecker extends PKIXCertPathChecker { - - private static final Debug debug = Debug.getInstance("certpath"); - private final TrustAnchor mAnchor; - private final List<CertStore> mStores; - private final String mSigProvider; - private final Date mCurrentTime; - private PublicKey mPrevPubKey; - private boolean mCRLSignFlag; - private HashSet<X509CRL> mPossibleCRLs; - private HashSet<X509CRL> mApprovedCRLs; - private final PKIXParameters mParams; - private static final boolean [] mCrlSignUsage = - { false, false, false, false, false, false, true }; - private static final boolean[] ALL_REASONS = - {true, true, true, true, true, true, true, true, true}; - private boolean mOnlyEECert = false; - - // Maximum clock skew in milliseconds (15 minutes) allowed when checking - // validity of CRLs - private static final long MAX_CLOCK_SKEW = 900000; - - /** - * Creates a <code>CrlRevocationChecker</code>. - * - * @param anchor anchor selected to validate the target certificate - * @param params <code>PKIXParameters</code> to be used for - * finding certificates and CRLs, etc. - */ - CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params) - throws CertPathValidatorException - { - this(anchor, params, null); - } - - /** - * Creates a <code>CrlRevocationChecker</code>, allowing - * extra certificates to be supplied beyond those contained - * in the <code>PKIXParameters</code>. - * - * @param anchor anchor selected to validate the target certificate - * @param params <code>PKIXParameters</code> to be used for - * finding certificates and CRLs, etc. - * @param certs a <code>Collection</code> of certificates - * that may be useful, beyond those available - * through <code>params</code> (<code>null</code> - * if none) - */ - CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params, - Collection<X509Certificate> certs) throws CertPathValidatorException - { - this(anchor, params, certs, false); - } - - CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params, - Collection<X509Certificate> certs, boolean onlyEECert) - throws CertPathValidatorException { - mAnchor = anchor; - mParams = params; - mStores = new ArrayList<CertStore>(params.getCertStores()); - mSigProvider = params.getSigProvider(); - if (certs != null) { - try { - mStores.add(CertStore.getInstance("Collection", - new CollectionCertStoreParameters(certs))); - } catch (Exception e) { - // should never occur but not necessarily fatal, so log it, - // ignore and continue - if (debug != null) { - debug.println("CrlRevocationChecker: " + - "error creating Collection CertStore: " + e); - } - } - } - Date testDate = params.getDate(); - mCurrentTime = (testDate != null ? testDate : new Date()); - mOnlyEECert = onlyEECert; - init(false); - } - - /** - * Initializes the internal state of the checker from parameters - * specified in the constructor - */ - public void init(boolean forward) throws CertPathValidatorException - { - if (!forward) { - if (mAnchor != null) { - if (mAnchor.getCAPublicKey() != null) { - mPrevPubKey = mAnchor.getCAPublicKey(); - } else { - mPrevPubKey = mAnchor.getTrustedCert().getPublicKey(); - } - } else { - mPrevPubKey = null; - } - mCRLSignFlag = true; - } else { - throw new CertPathValidatorException("forward checking " - + "not supported"); - } - } - - public boolean isForwardCheckingSupported() { - return false; - } - - public Set<String> getSupportedExtensions() { - return null; - } - - /** - * Performs the revocation status check on the certificate using - * its internal state. - * - * @param cert the Certificate - * @param unresolvedCritExts a Collection of the unresolved critical - * extensions - * @exception CertPathValidatorException Exception thrown if - * certificate does not verify - */ - public void check(Certificate cert, Collection<String> unresolvedCritExts) - throws CertPathValidatorException - { - X509Certificate currCert = (X509Certificate) cert; - verifyRevocationStatus(currCert, mPrevPubKey, mCRLSignFlag, true); - - // Make new public key if parameters are missing - PublicKey cKey = currCert.getPublicKey(); - if (cKey instanceof DSAPublicKey && - ((DSAPublicKey)cKey).getParams() == null) { - // cKey needs to inherit DSA parameters from prev key - cKey = BasicChecker.makeInheritedParamsKey(cKey, mPrevPubKey); - } - mPrevPubKey = cKey; - mCRLSignFlag = certCanSignCrl(currCert); - } - - /** - * Performs the revocation status check on the certificate using - * the provided state variables, as well as the constant internal - * data. - * - * @param currCert the Certificate - * @param prevKey the previous PublicKey in the chain - * @param signFlag a boolean as returned from the last call, or true - * if this is the first cert in the chain - * @return a boolean specifying if the cert is allowed to vouch for the - * validity of a CRL for the next iteration - * @exception CertPathValidatorException Exception thrown if - * certificate does not verify. - */ - public boolean check(X509Certificate currCert, PublicKey prevKey, - boolean signFlag) throws CertPathValidatorException - { - verifyRevocationStatus(currCert, prevKey, signFlag, true); - return certCanSignCrl(currCert); - } - - /** - * Checks that a cert can be used to verify a CRL. - * - * @param currCert an X509Certificate to check - * @return a boolean specifying if the cert is allowed to vouch for the - * validity of a CRL - */ - static boolean certCanSignCrl(X509Certificate currCert) { - // if the cert doesn't include the key usage ext, or - // the key usage ext asserts cRLSigning, return true, - // otherwise return false. - boolean[] kbools = currCert.getKeyUsage(); - if (kbools != null) { - return kbools[6]; - } - return false; - } - - /** - * Internal method to start the verification of a cert - */ - private void verifyRevocationStatus(X509Certificate currCert, - PublicKey prevKey, boolean signFlag, boolean allowSeparateKey) - throws CertPathValidatorException - { - verifyRevocationStatus(currCert, prevKey, signFlag, - allowSeparateKey, null, mParams.getTrustAnchors()); - } - - /** - * Internal method to start the verification of a cert - * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s> - * whose revocation status depends on the - * non-revoked status of this cert. To avoid - * circular dependencies, we assume they're - * revoked while checking the revocation - * status of this cert. - * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s - */ - private void verifyRevocationStatus(X509Certificate currCert, - PublicKey prevKey, boolean signFlag, boolean allowSeparateKey, - Set<X509Certificate> stackedCerts, - Set<TrustAnchor> trustAnchors) throws CertPathValidatorException { - - String msg = "revocation status"; - if (debug != null) { - debug.println("CrlRevocationChecker.verifyRevocationStatus()" + - " ---checking " + msg + "..."); - } - - if (mOnlyEECert && currCert.getBasicConstraints() != -1) { - if (debug != null) { - debug.println("Skipping revocation check, not end entity cert"); - } - return; - } - - // reject circular dependencies - RFC 3280 is not explicit on how - // to handle this, so we feel it is safest to reject them until - // the issue is resolved in the PKIX WG. - if ((stackedCerts != null) && stackedCerts.contains(currCert)) { - if (debug != null) { - debug.println("CrlRevocationChecker.verifyRevocationStatus()" + - " circular dependency"); - } - throw new CertPathValidatorException - ("Could not determine revocation status", null, null, -1, - BasicReason.UNDETERMINED_REVOCATION_STATUS); - } - - // init the state for this run - mPossibleCRLs = new HashSet<X509CRL>(); - mApprovedCRLs = new HashSet<X509CRL>(); - boolean[] reasonsMask = new boolean[9]; - - try { - X509CRLSelector sel = new X509CRLSelector(); - sel.setCertificateChecking(currCert); - CertPathHelper.setDateAndTime(sel, mCurrentTime, MAX_CLOCK_SKEW); - - for (CertStore mStore : mStores) { - for (java.security.cert.CRL crl : mStore.getCRLs(sel)) { - mPossibleCRLs.add((X509CRL)crl); - } - } - DistributionPointFetcher store = - DistributionPointFetcher.getInstance(); - // all CRLs returned by the DP Fetcher have also been verified - mApprovedCRLs.addAll(store.getCRLs(sel, signFlag, prevKey, - mSigProvider, mStores, reasonsMask, trustAnchors, - mParams.getDate())); - } catch (Exception e) { - if (debug != null) { - debug.println("CrlRevocationChecker.verifyRevocationStatus() " - + "unexpected exception: " + e.getMessage()); - } - throw new CertPathValidatorException(e); - } - - if (debug != null) { - debug.println("CrlRevocationChecker.verifyRevocationStatus() " + - "crls.size() = " + mPossibleCRLs.size()); - } - if (!mPossibleCRLs.isEmpty()) { - // Now that we have a list of possible CRLs, see which ones can - // be approved - mApprovedCRLs.addAll(verifyPossibleCRLs(mPossibleCRLs, currCert, - signFlag, prevKey, reasonsMask, trustAnchors)); - } - if (debug != null) { - debug.println("CrlRevocationChecker.verifyRevocationStatus() " + - "approved crls.size() = " + mApprovedCRLs.size()); - } - - // make sure that we have at least one CRL that _could_ cover - // the certificate in question and all reasons are covered - if (mApprovedCRLs.isEmpty() || - !Arrays.equals(reasonsMask, ALL_REASONS)) { - if (allowSeparateKey) { - verifyWithSeparateSigningKey(currCert, prevKey, signFlag, - stackedCerts); - return; - } else { - throw new CertPathValidatorException - ("Could not determine revocation status", null, null, -1, - BasicReason.UNDETERMINED_REVOCATION_STATUS); - } - } - - // See if the cert is in the set of approved crls. - if (debug != null) { - BigInteger sn = currCert.getSerialNumber(); - debug.println("CrlRevocationChecker.verifyRevocationStatus() " + - "starting the final sweep..."); - debug.println("CrlRevocationChecker.verifyRevocationStatus" + - " cert SN: " + sn.toString()); - } - - CRLReason reasonCode = CRLReason.UNSPECIFIED; - X509CRLEntryImpl entry = null; - for (X509CRL crl : mApprovedCRLs) { - X509CRLEntry e = crl.getRevokedCertificate(currCert); - if (e != null) { - try { - entry = X509CRLEntryImpl.toImpl(e); - } catch (CRLException ce) { - throw new CertPathValidatorException(ce); - } - if (debug != null) { - debug.println("CrlRevocationChecker.verifyRevocationStatus" - + " CRL entry: " + entry.toString()); - } - - /* - * Abort CRL validation and throw exception if there are any - * unrecognized critical CRL entry extensions (see section - * 5.3 of RFC 3280). - */ - Set<String> unresCritExts = entry.getCriticalExtensionOIDs(); - if (unresCritExts != null && !unresCritExts.isEmpty()) { - /* remove any that we will process */ - unresCritExts.remove - (PKIXExtensions.ReasonCode_Id.toString()); - unresCritExts.remove - (PKIXExtensions.CertificateIssuer_Id.toString()); - if (!unresCritExts.isEmpty()) { - if (debug != null) { - debug.println("Unrecognized " - + "critical extension(s) in revoked CRL entry: " - + unresCritExts); - } - throw new CertPathValidatorException - ("Could not determine revocation status", null, null, - -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); - } - } - - reasonCode = entry.getRevocationReason(); - if (reasonCode == null) { - reasonCode = CRLReason.UNSPECIFIED; - } - Throwable t = new CertificateRevokedException - (entry.getRevocationDate(), reasonCode, - crl.getIssuerX500Principal(), entry.getExtensions()); - throw new CertPathValidatorException(t.getMessage(), t, - null, -1, BasicReason.REVOKED); - } - } - } - - /** - * We have a cert whose revocation status couldn't be verified by - * a CRL issued by the cert that issued the CRL. See if we can - * find a valid CRL issued by a separate key that can verify the - * revocation status of this certificate. - * <p> - * Note that this does not provide support for indirect CRLs, - * only CRLs signed with a different key (but the same issuer - * name) as the certificate being checked. - * - * @param currCert the <code>X509Certificate</code> to be checked - * @param prevKey the <code>PublicKey</code> that failed - * @param signFlag <code>true</code> if that key was trusted to sign CRLs - * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s> - * whose revocation status depends on the - * non-revoked status of this cert. To avoid - * circular dependencies, we assume they're - * revoked while checking the revocation - * status of this cert. - * @throws CertPathValidatorException if the cert's revocation status - * cannot be verified successfully with another key - */ - private void verifyWithSeparateSigningKey(X509Certificate currCert, - PublicKey prevKey, boolean signFlag, Set<X509Certificate> stackedCerts) - throws CertPathValidatorException { - String msg = "revocation status"; - if (debug != null) { - debug.println( - "CrlRevocationChecker.verifyWithSeparateSigningKey()" + - " ---checking " + msg + "..."); - } - - // reject circular dependencies - RFC 3280 is not explicit on how - // to handle this, so we feel it is safest to reject them until - // the issue is resolved in the PKIX WG. - if ((stackedCerts != null) && stackedCerts.contains(currCert)) { - if (debug != null) { - debug.println( - "CrlRevocationChecker.verifyWithSeparateSigningKey()" + - " circular dependency"); - } - throw new CertPathValidatorException - ("Could not determine revocation status", null, null, - -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); - } - - // If prevKey wasn't trusted, maybe we just didn't have the right - // path to it. Don't rule that key out. - if (!signFlag) { - prevKey = null; - } - - // Try to find another key that might be able to sign - // CRLs vouching for this cert. - buildToNewKey(currCert, prevKey, stackedCerts); - } - - /** - * Tries to find a CertPath that establishes a key that can be - * used to verify the revocation status of a given certificate. - * Ignores keys that have previously been tried. Throws a - * CertPathValidatorException if no such key could be found. - * - * @param currCert the <code>X509Certificate</code> to be checked - * @param prevKey the <code>PublicKey</code> of the certificate whose key - * cannot be used to vouch for the CRL and should be ignored - * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s> - * whose revocation status depends on the - * establishment of this path. - * @throws CertPathValidatorException on failure - */ - private void buildToNewKey(X509Certificate currCert, - PublicKey prevKey, Set<X509Certificate> stackedCerts) - throws CertPathValidatorException { - - if (debug != null) { - debug.println("CrlRevocationChecker.buildToNewKey()" + - " starting work"); - } - Set<PublicKey> badKeys = new HashSet<PublicKey>(); - if (prevKey != null) { - badKeys.add(prevKey); - } - X509CertSelector certSel = new RejectKeySelector(badKeys); - certSel.setSubject(currCert.getIssuerX500Principal()); - certSel.setKeyUsage(mCrlSignUsage); - - Set<TrustAnchor> newAnchors = - (mAnchor == null ? mParams.getTrustAnchors() : - Collections.singleton(mAnchor)); - - PKIXBuilderParameters builderParams; - if (mParams instanceof PKIXBuilderParameters) { - builderParams = (PKIXBuilderParameters) mParams.clone(); - builderParams.setTargetCertConstraints(certSel); - // Policy qualifiers must be rejected, since we don't have - // any way to convey them back to the application. - builderParams.setPolicyQualifiersRejected(true); - try { - builderParams.setTrustAnchors(newAnchors); - } catch (InvalidAlgorithmParameterException iape) { - throw new RuntimeException(iape); // should never occur - } - } else { - // It's unfortunate that there's no easy way to make a - // PKIXBuilderParameters object from a PKIXParameters - // object. This might miss some things if parameters - // are added in the future or the validatorParams object - // is a custom class derived from PKIXValidatorParameters. - try { - builderParams = new PKIXBuilderParameters(newAnchors, certSel); - } catch (InvalidAlgorithmParameterException iape) { - throw new RuntimeException(iape); // should never occur - } - builderParams.setInitialPolicies(mParams.getInitialPolicies()); - builderParams.setCertStores(mStores); - builderParams.setExplicitPolicyRequired - (mParams.isExplicitPolicyRequired()); - builderParams.setPolicyMappingInhibited - (mParams.isPolicyMappingInhibited()); - builderParams.setAnyPolicyInhibited(mParams.isAnyPolicyInhibited()); - // Policy qualifiers must be rejected, since we don't have - // any way to convey them back to the application. - // That's the default, so no need to write code. - builderParams.setDate(mParams.getDate()); - builderParams.setCertPathCheckers(mParams.getCertPathCheckers()); - builderParams.setSigProvider(mParams.getSigProvider()); - } - - // Skip revocation during this build to detect circular - // references. But check revocation afterwards, using the - // key (or any other that works). - builderParams.setRevocationEnabled(false); - - // check for AuthorityInformationAccess extension - if (Builder.USE_AIA == true) { - X509CertImpl currCertImpl = null; - try { - currCertImpl = X509CertImpl.toImpl(currCert); - } catch (CertificateException ce) { - // ignore but log it - if (debug != null) { - debug.println("CrlRevocationChecker.buildToNewKey: " + - "error decoding cert: " + ce); - } - } - AuthorityInfoAccessExtension aiaExt = null; - if (currCertImpl != null) { - aiaExt = currCertImpl.getAuthorityInfoAccessExtension(); - } - if (aiaExt != null) { - List<AccessDescription> adList = aiaExt.getAccessDescriptions(); - if (adList != null) { - for (AccessDescription ad : adList) { - CertStore cs = URICertStore.getInstance(ad); - if (cs != null) { - if (debug != null) { - debug.println("adding AIAext CertStore"); - } - builderParams.addCertStore(cs); - } - } - } - } - } - - CertPathBuilder builder = null; - try { - builder = CertPathBuilder.getInstance("PKIX"); - } catch (NoSuchAlgorithmException nsae) { - throw new CertPathValidatorException(nsae); - } - while (true) { - try { - if (debug != null) { - debug.println("CrlRevocationChecker.buildToNewKey()" + - " about to try build ..."); - } - PKIXCertPathBuilderResult cpbr = - (PKIXCertPathBuilderResult) builder.build(builderParams); - - if (debug != null) { - debug.println("CrlRevocationChecker.buildToNewKey()" + - " about to check revocation ..."); - } - // Now check revocation of all certs in path, assuming that - // the stackedCerts are revoked. - if (stackedCerts == null) { - stackedCerts = new HashSet<X509Certificate>(); - } - stackedCerts.add(currCert); - TrustAnchor ta = cpbr.getTrustAnchor(); - PublicKey prevKey2 = ta.getCAPublicKey(); - if (prevKey2 == null) { - prevKey2 = ta.getTrustedCert().getPublicKey(); - } - boolean signFlag = true; - List<? extends Certificate> cpList = - cpbr.getCertPath().getCertificates(); - try { - for (int i = cpList.size()-1; i >= 0; i-- ) { - X509Certificate cert = (X509Certificate) cpList.get(i); - - if (debug != null) { - debug.println("CrlRevocationChecker.buildToNewKey()" - + " index " + i + " checking " + cert); - } - verifyRevocationStatus(cert, prevKey2, signFlag, true, - stackedCerts, newAnchors); - signFlag = certCanSignCrl(cert); - prevKey2 = cert.getPublicKey(); - } - } catch (CertPathValidatorException cpve) { - // ignore it and try to get another key - badKeys.add(cpbr.getPublicKey()); - continue; - } - - if (debug != null) { - debug.println("CrlRevocationChecker.buildToNewKey()" + - " got key " + cpbr.getPublicKey()); - } - // Now check revocation on the current cert using that key. - // If it doesn't check out, try to find a different key. - // And if we can't find a key, then return false. - PublicKey newKey = cpbr.getPublicKey(); - try { - verifyRevocationStatus(currCert, newKey, true, false); - // If that passed, the cert is OK! - return; - } catch (CertPathValidatorException cpve) { - // If it is revoked, rethrow exception - if (cpve.getReason() == BasicReason.REVOKED) { - throw cpve; - } - // Otherwise, ignore the exception and - // try to get another key. - } - badKeys.add(newKey); - } catch (InvalidAlgorithmParameterException iape) { - throw new CertPathValidatorException(iape); - } catch (CertPathBuilderException cpbe) { - throw new CertPathValidatorException - ("Could not determine revocation status", null, null, - -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); - } - } - } - - /* - * This inner class extends the X509CertSelector to add an additional - * check to make sure the subject public key isn't on a particular list. - * This class is used by buildToNewKey() to make sure the builder doesn't - * end up with a CertPath to a public key that has already been rejected. - */ - private static class RejectKeySelector extends X509CertSelector { - private final Set<PublicKey> badKeySet; - - /** - * Creates a new <code>RejectKeySelector</code>. - * - * @param badPublicKeys a <code>Set</code> of - * <code>PublicKey</code>s that - * should be rejected (or <code>null</code> - * if no such check should be done) - */ - RejectKeySelector(Set<PublicKey> badPublicKeys) { - this.badKeySet = badPublicKeys; - } - - /** - * Decides whether a <code>Certificate</code> should be selected. - * - * @param cert the <code>Certificate</code> to be checked - * @return <code>true</code> if the <code>Certificate</code> should be - * selected, <code>false</code> otherwise - */ - public boolean match(Certificate cert) { - if (!super.match(cert)) - return(false); - - if (badKeySet.contains(cert.getPublicKey())) { - if (debug != null) - debug.println("RejectCertSelector.match: bad key"); - return false; - } - - if (debug != null) - debug.println("RejectCertSelector.match: returning true"); - return true; - } - - /** - * Return a printable representation of the <code>CertSelector</code>. - * - * @return a <code>String</code> describing the contents of the - * <code>CertSelector</code> - */ - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("RejectCertSelector: [\n"); - sb.append(super.toString()); - sb.append(badKeySet); - sb.append("]"); - return sb.toString(); - } - } - - /** - * Internal method that verifies a set of possible_crls, - * and sees if each is approved, based on the cert. - * - * @param crls a set of possible CRLs to test for acceptability - * @param cert the certificate whose revocation status is being checked - * @param signFlag <code>true</code> if prevKey was trusted to sign CRLs - * @param prevKey the public key of the issuer of cert - * @param reasonsMask the reason code mask - * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s> - * @return a collection of approved crls (or an empty collection) - */ - private Collection<X509CRL> verifyPossibleCRLs(Set<X509CRL> crls, - X509Certificate cert, boolean signFlag, PublicKey prevKey, - boolean[] reasonsMask, - Set<TrustAnchor> trustAnchors) throws CertPathValidatorException { - - try { - X509CertImpl certImpl = X509CertImpl.toImpl(cert); - if (debug != null) { - debug.println("CRLRevocationChecker.verifyPossibleCRLs: " + - "Checking CRLDPs for " - + certImpl.getSubjectX500Principal()); - } - CRLDistributionPointsExtension ext = - certImpl.getCRLDistributionPointsExtension(); - List<DistributionPoint> points = null; - if (ext == null) { - // assume a DP with reasons and CRLIssuer fields omitted - // and a DP name of the cert issuer. - // TODO add issuerAltName too - X500Name certIssuer = (X500Name)certImpl.getIssuerDN(); - DistributionPoint point = new DistributionPoint - (new GeneralNames().add(new GeneralName(certIssuer)), - null, null); - points = Collections.singletonList(point); - } else { - points = ext.get(CRLDistributionPointsExtension.POINTS); - } - Set<X509CRL> results = new HashSet<X509CRL>(); - DistributionPointFetcher dpf = - DistributionPointFetcher.getInstance(); - for (Iterator<DistributionPoint> t = points.iterator(); - t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) { - DistributionPoint point = t.next(); - for (X509CRL crl : crls) { - if (dpf.verifyCRL(certImpl, point, crl, reasonsMask, - signFlag, prevKey, mSigProvider, - trustAnchors, mStores, mParams.getDate())) { - results.add(crl); - } - } - } - return results; - } catch (Exception e) { - if (debug != null) { - debug.println("Exception while verifying CRL: "+e.getMessage()); - e.printStackTrace(); - } - return Collections.emptySet(); - } - } -} diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java --- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, 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 @@ -27,14 +27,14 @@ import java.io.*; import java.net.URI; -import java.util.*; import java.security.*; import java.security.cert.*; import javax.security.auth.x500.X500Principal; +import java.util.*; -import sun.security.action.GetBooleanAction; import sun.security.util.Debug; import sun.security.util.DerOutputStream; +import static sun.security.x509.PKIXExtensions.*; import sun.security.x509.*; /** @@ -58,44 +58,23 @@ {true, true, true, true, true, true, true, true, true}; /** - * Flag indicating whether support for the CRL distribution point - * extension shall be enabled. Currently disabled by default for - * compatibility and legal reasons. - */ - private final static boolean USE_CRLDP = AccessController.doPrivileged - (new GetBooleanAction("com.sun.security.enableCRLDP")); - - // singleton instance - private static final DistributionPointFetcher INSTANCE = - new DistributionPointFetcher(); - - /** * Private instantiation only. */ private DistributionPointFetcher() {} /** - * Return a DistributionPointFetcher instance. - */ - static DistributionPointFetcher getInstance() { - return INSTANCE; - } - - /** * Return the X509CRLs matching this selector. The selector must be * an X509CRLSelector with certificateChecking set. - * - * If CRLDP support is disabled, this method always returns an - * empty set. */ - Collection<X509CRL> getCRLs(X509CRLSelector selector, boolean signFlag, - PublicKey prevKey, String provider, List<CertStore> certStores, - boolean[] reasonsMask, Set<TrustAnchor> trustAnchors, - Date validity) throws CertStoreException { - - if (USE_CRLDP == false) { - return Collections.emptySet(); - } + static Collection<X509CRL> getCRLs(X509CRLSelector selector, + boolean signFlag, PublicKey prevKey, + String provider, + List<CertStore> certStores, + boolean[] reasonsMask, + Set<TrustAnchor> trustAnchors, + Date validity) + throws CertStoreException + { X509Certificate cert = selector.getCertificateChecking(); if (cert == null) { return Collections.emptySet(); @@ -116,7 +95,7 @@ } List<DistributionPoint> points = ext.get(CRLDistributionPointsExtension.POINTS); - Set<X509CRL> results = new HashSet<X509CRL>(); + Set<X509CRL> results = new HashSet<>(); for (Iterator<DistributionPoint> t = points.iterator(); t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) { DistributionPoint point = t.next(); @@ -129,9 +108,7 @@ debug.println("Returning " + results.size() + " CRLs"); } return results; - } catch (CertificateException e) { - return Collections.emptySet(); - } catch (IOException e) { + } catch (CertificateException | IOException e) { return Collections.emptySet(); } } @@ -140,7 +117,7 @@ * Download CRLs from the given distribution point, verify and return them. * See the top of the class for current limitations. */ - private Collection<X509CRL> getCRLs(X509CRLSelector selector, + private static Collection<X509CRL> getCRLs(X509CRLSelector selector, X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask, boolean signFlag, PublicKey prevKey, String provider, List<CertStore> certStores, Set<TrustAnchor> trustAnchors, @@ -200,7 +177,7 @@ certStores, validity)) { crls.add(crl); } - } catch (Exception e) { + } catch (IOException | CRLException e) { // don't add the CRL if (debug != null) { debug.println("Exception verifying CRL: " + e.getMessage()); @@ -214,7 +191,7 @@ /** * Download CRL from given URI. */ - private X509CRL getCRL(URIName name) { + private static X509CRL getCRL(URIName name) { URI uri = name.getURI(); if (debug != null) { debug.println("Trying to fetch CRL from DP " + uri); @@ -240,7 +217,7 @@ /** * Fetch CRLs from certStores. */ - private Collection<X509CRL> getCRLs(X500Name name, + private static Collection<X509CRL> getCRLs(X500Name name, X500Principal certIssuer, List<CertStore> certStores) { if (debug != null) { @@ -249,7 +226,7 @@ X509CRLSelector xcs = new X509CRLSelector(); xcs.addIssuer(name.asX500Principal()); xcs.addIssuer(certIssuer); - Collection<X509CRL> crls = new ArrayList<X509CRL>(); + Collection<X509CRL> crls = new ArrayList<>(); for (CertStore store : certStores) { try { for (CRL crl : store.getCRLs(xcs)) { @@ -285,7 +262,7 @@ * certification path should be determined * @return true if ok, false if not */ - boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point, + static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point, X509CRL crl, boolean[] reasonsMask, boolean signFlag, PublicKey prevKey, String provider, Set<TrustAnchor> trustAnchors, List<CertStore> certStores, @@ -340,9 +317,9 @@ } else { // in case of self-issued indirect CRL issuer. byte[] certAKID = certImpl.getExtensionValue( - PKIXExtensions.AuthorityKey_Id.toString()); + AuthorityKey_Id.toString()); byte[] crlAKID = crlImpl.getExtensionValue( - PKIXExtensions.AuthorityKey_Id.toString()); + AuthorityKey_Id.toString()); if (certAKID == null || crlAKID == null) { // cannot recognize indirect CRL without AKID @@ -539,7 +516,7 @@ // verify that interim reasons mask includes one or more reasons // not included in the reasons mask boolean oneOrMore = false; - for (int i=0; i < interimReasonsMask.length && !oneOrMore; i++) { + for (int i = 0; i < interimReasonsMask.length && !oneOrMore; i++) { if (!reasonsMask[i] && interimReasonsMask[i]) { oneOrMore = true; } @@ -615,7 +592,7 @@ PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder.build(params); prevKey = result.getPublicKey(); - } catch (Exception e) { + } catch (GeneralSecurityException e) { throw new CRLException(e); } } @@ -633,7 +610,7 @@ // validate the signature on the CRL try { crl.verify(prevKey, provider); - } catch (Exception e) { + } catch (GeneralSecurityException e) { if (debug != null) { debug.println("CRL signature failed to verify"); } @@ -644,22 +621,21 @@ Set<String> unresCritExts = crl.getCriticalExtensionOIDs(); // remove any that we have processed if (unresCritExts != null) { - unresCritExts.remove - (PKIXExtensions.IssuingDistributionPoint_Id.toString()); + unresCritExts.remove(IssuingDistributionPoint_Id.toString()); if (!unresCritExts.isEmpty()) { if (debug != null) { debug.println("Unrecognized critical extension(s) in CRL: " + unresCritExts); - Iterator<String> i = unresCritExts.iterator(); - while (i.hasNext()) - debug.println(i.next()); + for (String ext : unresCritExts) { + debug.println(ext); + } } return false; } } // update reasonsMask - for (int i=0; i < interimReasonsMask.length; i++) { + for (int i = 0; i < interimReasonsMask.length; i++) { if (!reasonsMask[i] && interimReasonsMask[i]) { reasonsMask[i] = true; } @@ -671,9 +647,10 @@ * Append relative name to the issuer name and return a new * GeneralNames object. */ - private GeneralNames getFullNames(X500Name issuer, RDN rdn) - throws IOException { - List<RDN> rdns = new ArrayList<RDN>(issuer.rdns()); + private static GeneralNames getFullNames(X500Name issuer, RDN rdn) + throws IOException + { + List<RDN> rdns = new ArrayList<>(issuer.rdns()); rdns.add(rdn); X500Name fullName = new X500Name(rdns.toArray(new RDN[0])); GeneralNames fullNames = new GeneralNames(); @@ -681,15 +658,16 @@ return fullNames; } - /** Verifies whether a CRL is issued by a certain certificate + /** + * Verifies whether a CRL is issued by a certain certificate * * @param cert the certificate * @param crl the CRL to be verified * @param provider the name of the signature provider */ private static boolean issues(X509CertImpl cert, X509CRLImpl crl, - String provider) throws IOException { - + String provider) throws IOException + { boolean matched = false; AdaptableX509CertSelector issuerSelector = @@ -727,7 +705,7 @@ try { crl.verify(cert.getPublicKey(), provider); matched = true; - } catch (Exception e) { + } catch (GeneralSecurityException e) { matched = false; } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,10 +26,9 @@ package sun.security.provider.certpath; import java.io.IOException; -import java.util.*; - import java.security.GeneralSecurityException; import java.security.InvalidKeyException; +import java.security.PublicKey; import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; import java.security.cert.PKIXReason; @@ -40,12 +39,14 @@ import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.security.cert.X509CertSelector; +import java.util.*; import javax.security.auth.x500.X500Principal; +import sun.security.provider.certpath.PKIX.BuilderParams; import sun.security.util.Debug; import sun.security.x509.AccessDescription; import sun.security.x509.AuthorityInfoAccessExtension; -import sun.security.x509.PKIXExtensions; +import static sun.security.x509.PKIXExtensions.*; import sun.security.x509.PolicyMappingsExtension; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; @@ -72,21 +73,17 @@ TrustAnchor trustAnchor; private Comparator<X509Certificate> comparator; private boolean searchAllCertStores = true; - private boolean onlyEECert = false; /** * Initialize the builder with the input parameters. * * @param params the parameter set used to build a certification path */ - ForwardBuilder(PKIXBuilderParameters buildParams, - X500Principal targetSubjectDN, boolean searchAllCertStores, - boolean onlyEECert) - { - super(buildParams, targetSubjectDN); + ForwardBuilder(BuilderParams buildParams, boolean searchAllCertStores) { + super(buildParams); // populate sets of trusted certificates and subject DNs - trustAnchors = buildParams.getTrustAnchors(); + trustAnchors = buildParams.trustAnchors(); trustedCerts = new HashSet<X509Certificate>(trustAnchors.size()); trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size()); for (TrustAnchor anchor : trustAnchors) { @@ -100,7 +97,6 @@ } comparator = new PKIXCertComparator(trustedSubjectDNs); this.searchAllCertStores = searchAllCertStores; - this.onlyEECert = onlyEECert; } /** @@ -112,8 +108,9 @@ * Must be an instance of <code>ForwardState</code> * @param certStores list of CertStores */ - Collection<X509Certificate> getMatchingCerts - (State currentState, List<CertStore> certStores) + @Override + Collection<X509Certificate> getMatchingCerts(State currentState, + List<CertStore> certStores) throws CertStoreException, CertificateException, IOException { if (debug != null) { @@ -127,7 +124,7 @@ * As each cert is added, it is sorted based on the PKIXCertComparator * algorithm. */ - Set<X509Certificate> certs = new TreeSet<X509Certificate>(comparator); + Set<X509Certificate> certs = new TreeSet<>(comparator); /* * Only look for EE certs if search has just started. @@ -145,9 +142,10 @@ * and requirements specified in the parameters and PKIX state. */ private void getMatchingEECerts(ForwardState currentState, - List<CertStore> certStores, Collection<X509Certificate> eeCerts) - throws IOException { - + List<CertStore> certStores, + Collection<X509Certificate> eeCerts) + throws IOException + { if (debug != null) { debug.println("ForwardBuilder.getMatchingEECerts()..."); } @@ -165,12 +163,12 @@ /* * Match on certificate validity date */ - eeSelector.setCertificateValid(date); + eeSelector.setCertificateValid(buildParams.date()); /* * Policy processing optimizations */ - if (buildParams.isExplicitPolicyRequired()) { + if (buildParams.explicitPolicyRequired()) { eeSelector.setPolicy(getMatchingPolicies()); } /* @@ -188,9 +186,10 @@ * and requirements specified in the parameters and PKIX state. */ private void getMatchingCACerts(ForwardState currentState, - List<CertStore> certStores, Collection<X509Certificate> caCerts) - throws IOException { - + List<CertStore> certStores, + Collection<X509Certificate> caCerts) + throws IOException + { if (debug != null) { debug.println("ForwardBuilder.getMatchingCACerts()..."); } @@ -216,8 +215,8 @@ } if (caTargetSelector == null) { - caTargetSelector = (X509CertSelector) - targetCertConstraints.clone(); + caTargetSelector = + (X509CertSelector) targetCertConstraints.clone(); /* * Since we don't check the validity period of trusted @@ -229,7 +228,7 @@ /* * Policy processing optimizations */ - if (buildParams.isExplicitPolicyRequired()) + if (buildParams.explicitPolicyRequired()) caTargetSelector.setPolicy(getMatchingPolicies()); } @@ -249,7 +248,7 @@ /* * Policy processing optimizations */ - if (buildParams.isExplicitPolicyRequired()) + if (buildParams.explicitPolicyRequired()) caSelector.setPolicy(getMatchingPolicies()); } @@ -278,7 +277,7 @@ * check the validity period */ caSelector.setValidityPeriod(currentState.cert.getNotBefore(), - currentState.cert.getNotAfter()); + currentState.cert.getNotAfter()); sel = caSelector; } @@ -307,7 +306,7 @@ * The trusted certificate matching is completed. We need to match * on certificate validity date. */ - sel.setCertificateValid(date); + sel.setCertificateValid(buildParams.date()); /* * Require CA certs with a pathLenConstraint that allows @@ -323,11 +322,12 @@ * certificate pairs. */ if (currentState.isInitial() || - (buildParams.getMaxPathLength() == -1) || - (buildParams.getMaxPathLength() > currentState.traversedCACerts)) + (buildParams.maxPathLength() == -1) || + (buildParams.maxPathLength() > currentState.traversedCACerts)) { if (addMatchingCerts(sel, certStores, - caCerts, searchAllCertStores) && !searchAllCertStores) { + caCerts, searchAllCertStores) + && !searchAllCertStores) { return; } } @@ -356,7 +356,8 @@ // because of the selector, so the cast is safe @SuppressWarnings("unchecked") private boolean getCerts(AuthorityInfoAccessExtension aiaExt, - Collection<X509Certificate> certs) { + Collection<X509Certificate> certs) + { if (Builder.USE_AIA == false) { return false; } @@ -449,6 +450,7 @@ * @throws ClassCastException if either argument is not of type * X509Certificate */ + @Override public int compare(X509Certificate oCert1, X509Certificate oCert2) { // if certs are the same, return 0 @@ -651,8 +653,10 @@ * @param currentState the current state against which the cert is verified * @param certPathList the certPathList generated thus far */ + @Override void verifyCert(X509Certificate cert, State currentState, - List<X509Certificate> certPathList) throws GeneralSecurityException + List<X509Certificate> certPathList) + throws GeneralSecurityException { if (debug != null) { debug.println("ForwardBuilder.verifyCert(SN: " @@ -683,7 +687,7 @@ debug.println("policyMappingFound = " + policyMappingFound); } if (cert.equals(cpListCert)) { - if ((buildParams.isPolicyMappingInhibited()) || + if ((buildParams.policyMappingInhibited()) || (!policyMappingFound)) { if (debug != null) { debug.println("loop detected!!"); @@ -718,7 +722,7 @@ * all extensions that all user checkers are capable of * processing. */ - for (PKIXCertPathChecker checker : buildParams.getCertPathCheckers()) { + for (PKIXCertPathChecker checker : buildParams.certPathCheckers()) { if (!checker.isForwardCheckingSupported()) { Set<String> supportedExts = checker.getSupportedExtensions(); if (supportedExts != null) { @@ -732,23 +736,15 @@ * to check. If there are any left, throw an exception! */ if (!unresCritExts.isEmpty()) { - unresCritExts.remove( - PKIXExtensions.BasicConstraints_Id.toString()); - unresCritExts.remove( - PKIXExtensions.NameConstraints_Id.toString()); - unresCritExts.remove( - PKIXExtensions.CertificatePolicies_Id.toString()); - unresCritExts.remove( - PKIXExtensions.PolicyMappings_Id.toString()); - unresCritExts.remove( - PKIXExtensions.PolicyConstraints_Id.toString()); - unresCritExts.remove( - PKIXExtensions.InhibitAnyPolicy_Id.toString()); - unresCritExts.remove( - PKIXExtensions.SubjectAlternativeName_Id.toString()); - unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString()); - unresCritExts.remove( - PKIXExtensions.ExtendedKeyUsage_Id.toString()); + unresCritExts.remove(BasicConstraints_Id.toString()); + unresCritExts.remove(NameConstraints_Id.toString()); + unresCritExts.remove(CertificatePolicies_Id.toString()); + unresCritExts.remove(PolicyMappings_Id.toString()); + unresCritExts.remove(PolicyConstraints_Id.toString()); + unresCritExts.remove(InhibitAnyPolicy_Id.toString()); + unresCritExts.remove(SubjectAlternativeName_Id.toString()); + unresCritExts.remove(KeyUsage_Id.toString()); + unresCritExts.remove(ExtendedKeyUsage_Id.toString()); if (!unresCritExts.isEmpty()) throw new CertPathValidatorException @@ -786,31 +782,12 @@ */ /* - * Check revocation for the previous cert - */ - if (buildParams.isRevocationEnabled()) { - - // first off, see if this cert can authorize revocation... - if (CrlRevocationChecker.certCanSignCrl(cert)) { - // And then check to be sure no key requiring key parameters - // has been encountered - if (!currState.keyParamsNeeded()) - // If all that checks out, we can check the - // revocation status of the cert. Otherwise, - // we'll just wait until the end. - currState.crlChecker.check(currState.cert, - cert.getPublicKey(), - true); - } - } - - /* * Check signature only if no key requiring key parameters has been * encountered. */ if (!currState.keyParamsNeeded()) { (currState.cert).verify(cert.getPublicKey(), - buildParams.getSigProvider()); + buildParams.sigProvider()); } } @@ -826,6 +803,7 @@ * @param cert the certificate to test * @return a boolean value indicating whether the cert completes the path. */ + @Override boolean isPathCompleted(X509Certificate cert) { for (TrustAnchor anchor : trustAnchors) { if (anchor.getTrustedCert() != null) { @@ -837,7 +815,7 @@ } } else { X500Principal principal = anchor.getCA(); - java.security.PublicKey publicKey = anchor.getCAPublicKey(); + PublicKey publicKey = anchor.getCAPublicKey(); if (principal != null && publicKey != null && principal.equals(cert.getSubjectX500Principal())) { @@ -856,21 +834,6 @@ } } - /* Check revocation if it is enabled */ - if (buildParams.isRevocationEnabled()) { - try { - CrlRevocationChecker crlChecker = new CrlRevocationChecker - (anchor, buildParams, null, onlyEECert); - crlChecker.check(cert, anchor.getCAPublicKey(), true); - } catch (CertPathValidatorException cpve) { - if (debug != null) { - debug.println("ForwardBuilder.isPathCompleted() cpve"); - cpve.printStackTrace(); - } - continue; - } - } - /* * Check signature */ @@ -879,18 +842,17 @@ // parameters, yet there is no key to inherit the parameters // from. This is probably such a rare case that it is not worth // trying to detect the situation earlier. - cert.verify(anchor.getCAPublicKey(), - buildParams.getSigProvider()); + cert.verify(anchor.getCAPublicKey(), buildParams.sigProvider()); } catch (InvalidKeyException ike) { if (debug != null) { debug.println("ForwardBuilder.isPathCompleted() invalid " - + "DSA key found"); + + "DSA key found"); } continue; - } catch (Exception e){ + } catch (GeneralSecurityException e){ if (debug != null) { debug.println("ForwardBuilder.isPathCompleted() " + - "unexpected exception"); + "unexpected exception"); e.printStackTrace(); } continue; @@ -908,8 +870,10 @@ * @param cert the certificate to be added * @param certPathList the certification path list */ + @Override void addCertToPath(X509Certificate cert, - LinkedList<X509Certificate> certPathList) { + LinkedList<X509Certificate> certPathList) + { certPathList.addFirst(cert); } @@ -917,6 +881,7 @@ * * @param certPathList the certification path list */ + @Override void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) { certPathList.removeFirst(); } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -34,7 +34,6 @@ import java.security.interfaces.DSAPublicKey; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.ListIterator; import javax.security.auth.x500.X500Principal; @@ -76,9 +75,6 @@ /* Flag indicating if state is initial (path is just starting) */ private boolean init = true; - /* the checker used for revocation status */ - public CrlRevocationChecker crlChecker; - /* The list of user-defined checkers that support forward checking */ ArrayList<PKIXCertPathChecker> forwardCheckers; @@ -93,6 +89,7 @@ * * @return boolean flag indicating if the state is initial (just starting) */ + @Override public boolean isInitial() { return init; } @@ -104,6 +101,7 @@ * @return boolean true if key needing to inherit parameters has been * encountered; false otherwise. */ + @Override public boolean keyParamsNeeded() { return keyParamsNeededFlag; } @@ -111,23 +109,18 @@ /** * Display state for debugging purposes */ + @Override public String toString() { - StringBuffer sb = new StringBuffer(); - try { - sb.append("State ["); - sb.append("\n issuerDN of last cert: " + issuerDN); - sb.append("\n traversedCACerts: " + traversedCACerts); - sb.append("\n init: " + String.valueOf(init)); - sb.append("\n keyParamsNeeded: " - + String.valueOf(keyParamsNeededFlag)); - sb.append("\n subjectNamesTraversed: \n" + subjectNamesTraversed); - sb.append("]\n"); - } catch (Exception e) { - if (debug != null) { - debug.println("ForwardState.toString() unexpected exception"); - e.printStackTrace(); - } - } + StringBuilder sb = new StringBuilder(); + sb.append("State ["); + sb.append("\n issuerDN of last cert: ").append(issuerDN); + sb.append("\n traversedCACerts: ").append(traversedCACerts); + sb.append("\n init: ").append(String.valueOf(init)); + sb.append("\n keyParamsNeeded: ").append + (String.valueOf(keyParamsNeededFlag)); + sb.append("\n subjectNamesTraversed: \n").append + (subjectNamesTraversed); + sb.append("]\n"); return sb.toString(); } @@ -147,12 +140,10 @@ * that supports forward checking and initialize the forwardCheckers */ forwardCheckers = new ArrayList<PKIXCertPathChecker>(); - if (certPathCheckers != null) { - for (PKIXCertPathChecker checker : certPathCheckers) { - if (checker.isForwardCheckingSupported()) { - checker.init(true); - forwardCheckers.add(checker); - } + for (PKIXCertPathChecker checker : certPathCheckers) { + if (checker.isForwardCheckingSupported()) { + checker.init(true); + forwardCheckers.add(checker); } } @@ -164,6 +155,7 @@ * * @param cert the certificate which is used to update the state */ + @Override public void updateState(X509Certificate cert) throws CertificateException, IOException, CertPathValidatorException { @@ -208,13 +200,11 @@ if (subjAltNameExt != null) { GeneralNames gNames = subjAltNameExt.get( SubjectAlternativeNameExtension.SUBJECT_NAME); - for (Iterator<GeneralName> t = gNames.iterator(); - t.hasNext(); ) { - GeneralNameInterface gName = t.next().getName(); - subjectNamesTraversed.add(gName); + for (GeneralName gName : gNames.names()) { + subjectNamesTraversed.add(gName.getName()); } } - } catch (Exception e) { + } catch (IOException e) { if (debug != null) { debug.println("ForwardState.updateState() unexpected " + "exception"); @@ -236,6 +226,7 @@ * because some of them will * not have their contents modified by subsequent calls to updateState. */ + @Override @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly public Object clone() { try { diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java --- a/jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, 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 @@ -180,7 +180,7 @@ if (cert.equals(oldEntry)) { return; } - List<X509Certificate> list = new ArrayList<X509Certificate>(2); + List<X509Certificate> list = new ArrayList<>(2); list.add(cert); list.add((X509Certificate)oldEntry); certSubjects.put(subject, list); @@ -206,7 +206,7 @@ if (crl.equals(oldEntry)) { return; } - List<X509CRL> list = new ArrayList<X509CRL>(2); + List<X509CRL> list = new ArrayList<>(2); list.add(crl); list.add((X509CRL)oldEntry); crlIssuers.put(issuer, list); @@ -234,19 +234,20 @@ * match the specified selector * @throws CertStoreException if an exception occurs */ + @Override public Collection<? extends Certificate> engineGetCertificates(CertSelector selector) throws CertStoreException { // no selector means match all if (selector == null) { - Set<Certificate> matches = new HashSet<Certificate>(); + Set<Certificate> matches = new HashSet<>(); matchX509Certs(new X509CertSelector(), matches); matches.addAll(otherCertificates); return matches; } if (selector instanceof X509CertSelector == false) { - Set<Certificate> matches = new HashSet<Certificate>(); + Set<Certificate> matches = new HashSet<>(); matchX509Certs(selector, matches); for (Certificate cert : otherCertificates) { if (selector.match(cert)) { @@ -285,7 +286,7 @@ // See certSubjects javadoc. @SuppressWarnings("unchecked") List<X509Certificate> list = (List<X509Certificate>)entry; - Set<X509Certificate> matches = new HashSet<X509Certificate>(16); + Set<X509Certificate> matches = new HashSet<>(16); for (X509Certificate cert : list) { if (x509Selector.match(cert)) { matches.add(cert); @@ -295,7 +296,7 @@ } } // cannot use index, iterate all - Set<Certificate> matches = new HashSet<Certificate>(16); + Set<Certificate> matches = new HashSet<>(16); matchX509Certs(x509Selector, matches); return matches; } @@ -338,18 +339,19 @@ * match the specified selector * @throws CertStoreException if an exception occurs */ + @Override public Collection<CRL> engineGetCRLs(CRLSelector selector) throws CertStoreException { if (selector == null) { - Set<CRL> matches = new HashSet<CRL>(); + Set<CRL> matches = new HashSet<>(); matchX509CRLs(new X509CRLSelector(), matches); matches.addAll(otherCRLs); return matches; } if (selector instanceof X509CRLSelector == false) { - Set<CRL> matches = new HashSet<CRL>(); + Set<CRL> matches = new HashSet<>(); matchX509CRLs(selector, matches); for (CRL crl : otherCRLs) { if (selector.match(crl)) { @@ -366,7 +368,7 @@ // see if the issuer is specified Collection<X500Principal> issuers = x509Selector.getIssuers(); if (issuers != null) { - HashSet<CRL> matches = new HashSet<CRL>(16); + HashSet<CRL> matches = new HashSet<>(16); for (X500Principal issuer : issuers) { Object entry = crlIssuers.get(issuer); if (entry == null) { @@ -390,7 +392,7 @@ return matches; } // cannot use index, iterate all - Set<CRL> matches = new HashSet<CRL>(16); + Set<CRL> matches = new HashSet<>(16); matchX509CRLs(x509Selector, matches); return matches; } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java --- a/jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ import java.security.cert.PKIXReason; import sun.security.util.Debug; -import sun.security.x509.PKIXExtensions; +import static sun.security.x509.PKIXExtensions.*; /** * KeyChecker is a <code>PKIXCertPathChecker</code> that checks that the @@ -45,33 +45,29 @@ class KeyChecker extends PKIXCertPathChecker { private static final Debug debug = Debug.getInstance("certpath"); - // the index of keyCertSign in the boolean KeyUsage array - private static final int keyCertSign = 5; private final int certPathLen; - private CertSelector targetConstraints; + private final CertSelector targetConstraints; private int remainingCerts; private Set<String> supportedExts; /** - * Default Constructor + * Creates a KeyChecker. * * @param certPathLen allowable cert path length * @param targetCertSel a CertSelector object specifying the constraints * on the target certificate */ - KeyChecker(int certPathLen, CertSelector targetCertSel) - throws CertPathValidatorException - { + KeyChecker(int certPathLen, CertSelector targetCertSel) { this.certPathLen = certPathLen; this.targetConstraints = targetCertSel; - init(false); } /** * Initializes the internal state of the checker from parameters * specified in the constructor */ + @Override public void init(boolean forward) throws CertPathValidatorException { if (!forward) { remainingCerts = certPathLen; @@ -81,16 +77,18 @@ } } - public final boolean isForwardCheckingSupported() { + @Override + public boolean isForwardCheckingSupported() { return false; } + @Override public Set<String> getSupportedExtensions() { if (supportedExts == null) { - supportedExts = new HashSet<String>(); - supportedExts.add(PKIXExtensions.KeyUsage_Id.toString()); - supportedExts.add(PKIXExtensions.ExtendedKeyUsage_Id.toString()); - supportedExts.add(PKIXExtensions.SubjectAlternativeName_Id.toString()); + supportedExts = new HashSet<String>(3); + supportedExts.add(KeyUsage_Id.toString()); + supportedExts.add(ExtendedKeyUsage_Id.toString()); + supportedExts.add(SubjectAlternativeName_Id.toString()); supportedExts = Collections.unmodifiableSet(supportedExts); } return supportedExts; @@ -102,20 +100,20 @@ * * @param cert the Certificate * @param unresolvedCritExts the unresolved critical extensions - * @exception CertPathValidatorException Exception thrown if certificate - * does not verify + * @throws CertPathValidatorException if certificate does not verify */ + @Override public void check(Certificate cert, Collection<String> unresCritExts) throws CertPathValidatorException { - X509Certificate currCert = (X509Certificate) cert; + X509Certificate currCert = (X509Certificate)cert; remainingCerts--; // if final certificate, check that target constraints are satisfied if (remainingCerts == 0) { - if ((targetConstraints != null) && - (targetConstraints.match(currCert) == false)) { + if (targetConstraints != null && + targetConstraints.match(currCert) == false) { throw new CertPathValidatorException("target certificate " + "constraints check failed"); } @@ -126,25 +124,26 @@ // remove the extensions that we have checked if (unresCritExts != null && !unresCritExts.isEmpty()) { - unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString()); - unresCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString()); - unresCritExts.remove( - PKIXExtensions.SubjectAlternativeName_Id.toString()); + unresCritExts.remove(KeyUsage_Id.toString()); + unresCritExts.remove(ExtendedKeyUsage_Id.toString()); + unresCritExts.remove(SubjectAlternativeName_Id.toString()); } } + // the index of keyCertSign in the boolean KeyUsage array + private static final int KEY_CERT_SIGN = 5; /** - * Static method to verify that the key usage and extended key usage - * extension in a CA cert. The key usage extension, if present, must - * assert the keyCertSign bit. The extended key usage extension, if - * present, must include anyExtendedKeyUsage. + * Verifies the key usage extension in a CA cert. + * The key usage extension, if present, must assert the keyCertSign bit. + * The extended key usage extension is not checked (see CR 4776794 for + * more information). */ static void verifyCAKeyUsage(X509Certificate cert) throws CertPathValidatorException { String msg = "CA key usage"; if (debug != null) { debug.println("KeyChecker.verifyCAKeyUsage() ---checking " + msg - + "..."); + + "..."); } boolean[] keyUsageBits = cert.getKeyUsage(); @@ -156,7 +155,7 @@ } // throw an exception if the keyCertSign bit is not set - if (!keyUsageBits[keyCertSign]) { + if (!keyUsageBits[KEY_CERT_SIGN]) { throw new CertPathValidatorException (msg + " check failed: keyCertSign bit is not set", null, null, -1, PKIXReason.INVALID_KEY_USAGE); @@ -164,7 +163,7 @@ if (debug != null) { debug.println("KeyChecker.verifyCAKeyUsage() " + msg - + " verified."); + + " verified."); } } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/OCSP.java --- a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2012, 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 @@ -43,6 +43,7 @@ import static sun.security.provider.certpath.OCSPResponse.*; import sun.security.util.Debug; +import sun.security.util.ObjectIdentifier; import sun.security.x509.AccessDescription; import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.GeneralName; @@ -62,6 +63,9 @@ */ public final class OCSP { + static final ObjectIdentifier NONCE_EXTENSION_OID = + ObjectIdentifier.newInternal(new int[]{ 1, 3, 6, 1, 5, 5, 7, 48, 1, 2}); + private static final Debug debug = Debug.getInstance("certpath"); private static final int CONNECT_TIMEOUT = 15000; // 15 seconds @@ -83,7 +87,7 @@ * encoding the OCSP Request or validating the OCSP Response */ public static RevocationStatus check(X509Certificate cert, - X509Certificate issuerCert) + X509Certificate issuerCert) throws IOException, CertPathValidatorException { CertId certId = null; URI responderURI = null; @@ -95,16 +99,13 @@ ("No OCSP Responder URI in certificate"); } certId = new CertId(issuerCert, certImpl.getSerialNumberObject()); - } catch (CertificateException ce) { + } catch (CertificateException | IOException e) { throw new CertPathValidatorException - ("Exception while encoding OCSPRequest", ce); - } catch (IOException ioe) { - throw new CertPathValidatorException - ("Exception while encoding OCSPRequest", ioe); + ("Exception while encoding OCSPRequest", e); } OCSPResponse ocspResponse = check(Collections.singletonList(certId), - responderURI, issuerCert, null); - return (RevocationStatus) ocspResponse.getSingleResponse(certId); + responderURI, issuerCert, null, Collections.<Extension>emptyList()); + return (RevocationStatus)ocspResponse.getSingleResponse(certId); } /** @@ -123,22 +124,34 @@ * encoding the OCSP Request or validating the OCSP Response */ public static RevocationStatus check(X509Certificate cert, - X509Certificate issuerCert, URI responderURI, X509Certificate - responderCert, Date date) - throws IOException, CertPathValidatorException { + X509Certificate issuerCert, + URI responderURI, + X509Certificate responderCert, + Date date) + throws IOException, CertPathValidatorException + { + return check(cert, issuerCert, responderURI, responderCert, date, + Collections.<Extension>emptyList()); + } + + // Called by com.sun.deploy.security.TrustDecider + public static RevocationStatus check(X509Certificate cert, + X509Certificate issuerCert, + URI responderURI, + X509Certificate responderCert, + Date date, List<Extension> extensions) + throws IOException, CertPathValidatorException + { CertId certId = null; try { X509CertImpl certImpl = X509CertImpl.toImpl(cert); certId = new CertId(issuerCert, certImpl.getSerialNumberObject()); - } catch (CertificateException ce) { + } catch (CertificateException | IOException e) { throw new CertPathValidatorException - ("Exception while encoding OCSPRequest", ce); - } catch (IOException ioe) { - throw new CertPathValidatorException - ("Exception while encoding OCSPRequest", ioe); + ("Exception while encoding OCSPRequest", e); } OCSPResponse ocspResponse = check(Collections.singletonList(certId), - responderURI, responderCert, date); + responderURI, responderCert, date, extensions); return (RevocationStatus) ocspResponse.getSingleResponse(certId); } @@ -157,12 +170,14 @@ * encoding the OCSP Request or validating the OCSP Response */ static OCSPResponse check(List<CertId> certIds, URI responderURI, - X509Certificate responderCert, Date date) - throws IOException, CertPathValidatorException { - + X509Certificate responderCert, Date date, + List<Extension> extensions) + throws IOException, CertPathValidatorException + { byte[] bytes = null; + OCSPRequest request = null; try { - OCSPRequest request = new OCSPRequest(certIds); + request = new OCSPRequest(certIds, extensions); bytes = request.encodeBytes(); } catch (IOException ioe) { throw new CertPathValidatorException @@ -214,6 +229,8 @@ } } response = Arrays.copyOf(response, total); + } catch (IOException ioe) { + throw new NetworkFailureException(ioe); } finally { if (in != null) { try { @@ -233,33 +250,15 @@ OCSPResponse ocspResponse = null; try { - ocspResponse = new OCSPResponse(response, date, responderCert); + ocspResponse = new OCSPResponse(response); } catch (IOException ioe) { // response decoding exception throw new CertPathValidatorException(ioe); } - if (ocspResponse.getResponseStatus() != ResponseStatus.SUCCESSFUL) { - throw new CertPathValidatorException - ("OCSP response error: " + ocspResponse.getResponseStatus()); - } - // Check that the response includes a response for all of the - // certs that were supplied in the request - for (CertId certId : certIds) { - SingleResponse sr = ocspResponse.getSingleResponse(certId); - if (sr == null) { - if (debug != null) { - debug.println("No response found for CertId: " + certId); - } - throw new CertPathValidatorException( - "OCSP response does not include a response for a " + - "certificate supplied in the OCSP request"); - } - if (debug != null) { - debug.println("Status of certificate (with serial number " + - certId.getSerialNumber() + ") is: " + sr.getCertStatus()); - } - } + // verify the response + ocspResponse.verify(certIds, responderCert, date, request.getNonce()); + return ocspResponse; } @@ -271,6 +270,7 @@ * @param cert the certificate * @return the URI of the OCSP Responder, or null if not specified */ + // Called by com.sun.deploy.security.TrustDecider public static URI getResponderURI(X509Certificate cert) { try { return getResponderURI(X509CertImpl.toImpl(cert)); @@ -330,4 +330,12 @@ */ Map<String, Extension> getSingleExtensions(); } + + static class NetworkFailureException extends CertPathValidatorException { + private static final long serialVersionUID = 0l; + + private NetworkFailureException(IOException ioe) { + super(ioe); + } + } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java --- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java Mon Jan 23 04:44:16 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,446 +0,0 @@ -/* - * Copyright (c) 2003, 2011, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.security.provider.certpath; - -import java.math.BigInteger; -import java.util.*; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.Security; -import java.security.cert.*; -import java.security.cert.CertPathValidatorException.BasicReason; -import java.net.URI; -import java.net.URISyntaxException; -import javax.security.auth.x500.X500Principal; - -import static sun.security.provider.certpath.OCSP.*; -import sun.security.util.Debug; -import sun.security.x509.*; - -/** - * OCSPChecker is a <code>PKIXCertPathChecker</code> that uses the - * Online Certificate Status Protocol (OCSP) as specified in RFC 2560 - * <a href="http://www.ietf.org/rfc/rfc2560.txt"> - * http://www.ietf.org/rfc/rfc2560.txt</a>. - * - * @author Ram Marti - */ -class OCSPChecker extends PKIXCertPathChecker { - - static final String OCSP_ENABLE_PROP = "ocsp.enable"; - static final String OCSP_URL_PROP = "ocsp.responderURL"; - static final String OCSP_CERT_SUBJECT_PROP = - "ocsp.responderCertSubjectName"; - static final String OCSP_CERT_ISSUER_PROP = "ocsp.responderCertIssuerName"; - static final String OCSP_CERT_NUMBER_PROP = - "ocsp.responderCertSerialNumber"; - - private static final String HEX_DIGITS = "0123456789ABCDEFabcdef"; - private static final Debug DEBUG = Debug.getInstance("certpath"); - private static final boolean dump = false; - - private int remainingCerts; - - private X509Certificate[] certs; - - private CertPath cp; - - private PKIXParameters pkixParams; - - private boolean onlyEECert = false; - - /** - * Default Constructor - * - * @param certPath the X509 certification path - * @param pkixParams the input PKIX parameter set - * @throws CertPathValidatorException if OCSPChecker can not be created - */ - OCSPChecker(CertPath certPath, PKIXParameters pkixParams) - throws CertPathValidatorException { - this(certPath, pkixParams, false); - } - - OCSPChecker(CertPath certPath, PKIXParameters pkixParams, boolean onlyEECert) - throws CertPathValidatorException { - - this.cp = certPath; - this.pkixParams = pkixParams; - this.onlyEECert = onlyEECert; - List<? extends Certificate> tmp = cp.getCertificates(); - certs = tmp.toArray(new X509Certificate[tmp.size()]); - init(false); - } - - /** - * Initializes the internal state of the checker from parameters - * specified in the constructor - */ - @Override - public void init(boolean forward) throws CertPathValidatorException { - if (!forward) { - remainingCerts = certs.length + 1; - } else { - throw new CertPathValidatorException( - "Forward checking not supported"); - } - } - - @Override public boolean isForwardCheckingSupported() { - return false; - } - - @Override public Set<String> getSupportedExtensions() { - return Collections.<String>emptySet(); - } - - /** - * Sends an OCSPRequest for the certificate to the OCSP Server and - * processes the response back from the OCSP Server. - * - * @param cert the Certificate - * @param unresolvedCritExts the unresolved critical extensions - * @exception CertPathValidatorException Exception is thrown if the - * certificate has been revoked. - */ - @Override - public void check(Certificate cert, Collection<String> unresolvedCritExts) - throws CertPathValidatorException { - - // Decrement the certificate counter - remainingCerts--; - - X509CertImpl currCertImpl = null; - try { - currCertImpl = X509CertImpl.toImpl((X509Certificate)cert); - } catch (CertificateException ce) { - throw new CertPathValidatorException(ce); - } - - if (onlyEECert && currCertImpl.getBasicConstraints() != -1) { - if (DEBUG != null) { - DEBUG.println("Skipping revocation check, not end entity cert"); - } - return; - } - - /* - * OCSP security property values, in the following order: - * 1. ocsp.responderURL - * 2. ocsp.responderCertSubjectName - * 3. ocsp.responderCertIssuerName - * 4. ocsp.responderCertSerialNumber - */ - // should cache these properties to avoid calling every time? - String[] properties = getOCSPProperties(); - - // Check whether OCSP is feasible before seeking cert information - URI uri = getOCSPServerURI(currCertImpl, properties[0]); - - // When responder's subject name is set then the issuer/serial - // properties are ignored - X500Principal responderSubjectName = null; - X500Principal responderIssuerName = null; - BigInteger responderSerialNumber = null; - if (properties[1] != null) { - responderSubjectName = new X500Principal(properties[1]); - } else if (properties[2] != null && properties[3] != null) { - responderIssuerName = new X500Principal(properties[2]); - // remove colon or space separators - String value = stripOutSeparators(properties[3]); - responderSerialNumber = new BigInteger(value, 16); - } else if (properties[2] != null || properties[3] != null) { - throw new CertPathValidatorException( - "Must specify both ocsp.responderCertIssuerName and " + - "ocsp.responderCertSerialNumber properties"); - } - - // If the OCSP responder cert properties are set then the - // identified cert must be located in the trust anchors or - // in the cert stores. - boolean seekResponderCert = false; - if (responderSubjectName != null || responderIssuerName != null) { - seekResponderCert = true; - } - - // Set the issuer certificate to the next cert in the chain - // (unless we're processing the final cert). - X509Certificate issuerCert = null; - boolean seekIssuerCert = true; - X509Certificate responderCert = null; - if (remainingCerts < certs.length) { - issuerCert = certs[remainingCerts]; - seekIssuerCert = false; // done - - // By default, the OCSP responder's cert is the same as the - // issuer of the cert being validated. - if (!seekResponderCert) { - responderCert = issuerCert; - if (DEBUG != null) { - DEBUG.println("Responder's certificate is the same " + - "as the issuer of the certificate being validated"); - } - } - } - - // Check anchor certs for: - // - the issuer cert (of the cert being validated) - // - the OCSP responder's cert - if (seekIssuerCert || seekResponderCert) { - - if (DEBUG != null && seekResponderCert) { - DEBUG.println("Searching trust anchors for responder's " + - "certificate"); - } - - // Extract the anchor certs - Iterator<TrustAnchor> anchors - = pkixParams.getTrustAnchors().iterator(); - if (!anchors.hasNext()) { - throw new CertPathValidatorException( - "Must specify at least one trust anchor"); - } - - X500Principal certIssuerName = - currCertImpl.getIssuerX500Principal(); - while (anchors.hasNext() && (seekIssuerCert || seekResponderCert)) { - - TrustAnchor anchor = anchors.next(); - X509Certificate anchorCert = anchor.getTrustedCert(); - X500Principal anchorSubjectName = - anchorCert.getSubjectX500Principal(); - - if (dump) { - System.out.println("Issuer DN is " + certIssuerName); - System.out.println("Subject DN is " + anchorSubjectName); - } - - // Check if anchor cert is the issuer cert - if (seekIssuerCert && - certIssuerName.equals(anchorSubjectName)) { - - issuerCert = anchorCert; - seekIssuerCert = false; // done - - // By default, the OCSP responder's cert is the same as - // the issuer of the cert being validated. - if (!seekResponderCert && responderCert == null) { - responderCert = anchorCert; - if (DEBUG != null) { - DEBUG.println("Responder's certificate is the" + - " same as the issuer of the certificate " + - "being validated"); - } - } - } - - // Check if anchor cert is the responder cert - if (seekResponderCert) { - // Satisfy the responder subject name property only, or - // satisfy the responder issuer name and serial number - // properties only - if ((responderSubjectName != null && - responderSubjectName.equals(anchorSubjectName)) || - (responderIssuerName != null && - responderSerialNumber != null && - responderIssuerName.equals( - anchorCert.getIssuerX500Principal()) && - responderSerialNumber.equals( - anchorCert.getSerialNumber()))) { - - responderCert = anchorCert; - seekResponderCert = false; // done - } - } - } - if (issuerCert == null) { - throw new CertPathValidatorException( - "No trusted certificate for " + currCertImpl.getIssuerDN()); - } - - // Check cert stores if responder cert has not yet been found - if (seekResponderCert) { - if (DEBUG != null) { - DEBUG.println("Searching cert stores for responder's " + - "certificate"); - } - X509CertSelector filter = null; - if (responderSubjectName != null) { - filter = new X509CertSelector(); - filter.setSubject(responderSubjectName); - } else if (responderIssuerName != null && - responderSerialNumber != null) { - filter = new X509CertSelector(); - filter.setIssuer(responderIssuerName); - filter.setSerialNumber(responderSerialNumber); - } - if (filter != null) { - List<CertStore> certStores = pkixParams.getCertStores(); - for (CertStore certStore : certStores) { - Iterator<? extends Certificate> i = null; - try { - i = certStore.getCertificates(filter).iterator(); - } catch (CertStoreException cse) { - // ignore and try next certStore - if (DEBUG != null) { - DEBUG.println("CertStore exception:" + cse); - } - continue; - } - if (i.hasNext()) { - responderCert = (X509Certificate) i.next(); - seekResponderCert = false; // done - break; - } - } - } - } - } - - // Could not find the certificate identified in the OCSP properties - if (seekResponderCert) { - throw new CertPathValidatorException( - "Cannot find the responder's certificate " + - "(set using the OCSP security properties)."); - } - - // The algorithm constraints of the OCSP trusted responder certificate - // does not need to be checked in this code. The constraints will be - // checked when the responder's certificate is validated. - - CertId certId = null; - OCSPResponse response = null; - try { - certId = new CertId - (issuerCert, currCertImpl.getSerialNumberObject()); - response = OCSP.check(Collections.singletonList(certId), uri, - responderCert, pkixParams.getDate()); - } catch (Exception e) { - if (e instanceof CertPathValidatorException) { - throw (CertPathValidatorException) e; - } else { - // Wrap exceptions in CertPathValidatorException so that - // we can fallback to CRLs, if enabled. - throw new CertPathValidatorException(e); - } - } - - RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId); - RevocationStatus.CertStatus certStatus = rs.getCertStatus(); - if (certStatus == RevocationStatus.CertStatus.REVOKED) { - Throwable t = new CertificateRevokedException( - rs.getRevocationTime(), rs.getRevocationReason(), - responderCert.getSubjectX500Principal(), - rs.getSingleExtensions()); - throw new CertPathValidatorException(t.getMessage(), t, - null, -1, BasicReason.REVOKED); - } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) { - throw new CertPathValidatorException( - "Certificate's revocation status is unknown", null, cp, - remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS); - } - } - - /* - * The OCSP security property values are in the following order: - * 1. ocsp.responderURL - * 2. ocsp.responderCertSubjectName - * 3. ocsp.responderCertIssuerName - * 4. ocsp.responderCertSerialNumber - */ - private static URI getOCSPServerURI(X509CertImpl currCertImpl, - String responderURL) throws CertPathValidatorException { - - if (responderURL != null) { - try { - return new URI(responderURL); - } catch (URISyntaxException e) { - throw new CertPathValidatorException(e); - } - } - - // Examine the certificate's AuthorityInfoAccess extension - AuthorityInfoAccessExtension aia = - currCertImpl.getAuthorityInfoAccessExtension(); - if (aia == null) { - throw new CertPathValidatorException( - "Must specify the location of an OCSP Responder"); - } - - List<AccessDescription> descriptions = aia.getAccessDescriptions(); - for (AccessDescription description : descriptions) { - if (description.getAccessMethod().equals((Object) - AccessDescription.Ad_OCSP_Id)) { - - GeneralName generalName = description.getAccessLocation(); - if (generalName.getType() == GeneralNameInterface.NAME_URI) { - URIName uri = (URIName) generalName.getName(); - return uri.getURI(); - } - } - } - - throw new CertPathValidatorException( - "Cannot find the location of the OCSP Responder"); - } - - /* - * Retrieves the values of the OCSP security properties. - */ - private static String[] getOCSPProperties() { - final String[] properties = new String[4]; - - AccessController.doPrivileged( - new PrivilegedAction<Void>() { - public Void run() { - properties[0] = Security.getProperty(OCSP_URL_PROP); - properties[1] = - Security.getProperty(OCSP_CERT_SUBJECT_PROP); - properties[2] = - Security.getProperty(OCSP_CERT_ISSUER_PROP); - properties[3] = - Security.getProperty(OCSP_CERT_NUMBER_PROP); - return null; - } - }); - - return properties; - } - - /* - * Removes any non-hexadecimal characters from a string. - */ - private static String stripOutSeparators(String value) { - char[] chars = value.toCharArray(); - StringBuilder hexNumber = new StringBuilder(); - for (int i = 0; i < chars.length; i++) { - if (HEX_DIGITS.indexOf(chars[i]) != -1) { - hexNumber.append(chars[i]); - } - } - return hexNumber.toString(); - } -} diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java --- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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,10 @@ package sun.security.provider.certpath; import java.io.IOException; +import java.security.cert.Extension; import java.util.Collections; import java.util.List; + import sun.misc.HexDumpEncoder; import sun.security.util.*; @@ -74,22 +76,29 @@ class OCSPRequest { - private static final Debug debug = Debug.getInstance("certpath"); private static final boolean dump = false; // List of request CertIds private final List<CertId> certIds; + private final List<Extension> extensions; + private byte[] nonce; /* * Constructs an OCSPRequest. This constructor is used * to construct an unsigned OCSP Request for a single user cert. */ OCSPRequest(CertId certId) { - this.certIds = Collections.singletonList(certId); + this(Collections.singletonList(certId)); } OCSPRequest(List<CertId> certIds) { this.certIds = certIds; + this.extensions = Collections.<Extension>emptyList(); + } + + OCSPRequest(List<CertId> certIds, List<Extension> extensions) { + this.certIds = certIds; + this.extensions = extensions; } byte[] encodeBytes() throws IOException { @@ -104,7 +113,20 @@ } tmp.write(DerValue.tag_Sequence, requestsOut); - // No extensions supported + if (!extensions.isEmpty()) { + DerOutputStream extOut = new DerOutputStream(); + for (Extension ext : extensions) { + ext.encode(extOut); + if (ext.getId().equals(OCSP.NONCE_EXTENSION_OID.toString())) { + nonce = ext.getValue(); + } + } + DerOutputStream extsOut = new DerOutputStream(); + extsOut.write(DerValue.tag_Sequence, extOut); + tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, + true, (byte)2), extsOut); + } + DerOutputStream tbsRequest = new DerOutputStream(); tbsRequest.write(DerValue.tag_Sequence, tmp); @@ -126,4 +148,8 @@ List<CertId> getCertIds() { return certIds; } + + byte[] getNonce() { + return nonce; + } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java --- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -33,11 +33,15 @@ import java.security.cert.CRLReason; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.security.auth.x500.X500Principal; + import sun.misc.HexDumpEncoder; import sun.security.x509.*; import sun.security.util.*; @@ -125,13 +129,10 @@ }; private static ResponseStatus[] rsvalues = ResponseStatus.values(); - private static final Debug DEBUG = Debug.getInstance("certpath"); + private static final Debug debug = Debug.getInstance("certpath"); private static final boolean dump = false; private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID = ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1}); - private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID = - ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2}); - private static final int CERT_STATUS_GOOD = 0; private static final int CERT_STATUS_REVOKED = 1; private static final int CERT_STATUS_UNKNOWN = 2; @@ -143,9 +144,6 @@ // Object identifier for the OCSPSigning key purpose private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9"; - private final ResponseStatus responseStatus; - private final Map<CertId, SingleResponse> singleResponseMap; - // Maximum clock skew in milliseconds (15 minutes) allowed when checking // validity of OCSP responses private static final long MAX_CLOCK_SKEW = 900000; @@ -153,14 +151,20 @@ // an array of all of the CRLReasons (used in SingleResponse) private static CRLReason[] values = CRLReason.values(); + private final ResponseStatus responseStatus; + private final Map<CertId, SingleResponse> singleResponseMap; + private final List<X509CertImpl> certs; + private final AlgorithmId sigAlgId; + private final byte[] signature; + private final byte[] tbsResponseData; + private final X500Principal responderName; + private final byte[] responderKey; + private final byte[] responseNonce; + /* * Create an OCSP response from its ASN.1 DER encoding. */ - OCSPResponse(byte[] bytes, Date dateCheckedAgainst, - X509Certificate responderCert) - throws IOException, CertPathValidatorException { - - // OCSPResponse + OCSPResponse(byte[] bytes) throws IOException { if (dump) { HexDumpEncoder hexEnc = new HexDumpEncoder(); System.out.println("OCSPResponse bytes are..."); @@ -181,12 +185,19 @@ // unspecified responseStatus throw new IOException("Unknown OCSPResponse status: " + status); } - if (DEBUG != null) { - DEBUG.println("OCSP response status: " + responseStatus); + if (debug != null) { + debug.println("OCSP response status: " + responseStatus); } if (responseStatus != ResponseStatus.SUCCESSFUL) { // no need to continue, responseBytes are not set. singleResponseMap = Collections.emptyMap(); + certs = Collections.<X509CertImpl>emptyList(); + sigAlgId = null; + signature = null; + tbsResponseData = null; + responderName = null; + responderKey = null; + responseNonce = null; return; } @@ -206,15 +217,15 @@ derIn = tmp.data; ObjectIdentifier responseType = derIn.getOID(); if (responseType.equals((Object)OCSP_BASIC_RESPONSE_OID)) { - if (DEBUG != null) { - DEBUG.println("OCSP response type: basic"); + if (debug != null) { + debug.println("OCSP response type: basic"); } } else { - if (DEBUG != null) { - DEBUG.println("OCSP response type: " + responseType); + if (debug != null) { + debug.println("OCSP response type: " + responseType); } throw new IOException("Unsupported OCSP response type: " + - responseType); + responseType); } // BasicOCSPResponse @@ -229,7 +240,7 @@ DerValue responseData = seqTmp[0]; // Need the DER encoded ResponseData to verify the signature later - byte[] responseDataDer = seqTmp[0].toByteArray(); + tbsResponseData = seqTmp[0].toByteArray(); // tbsResponseData if (responseData.tag != DerValue.tag_Sequence) { @@ -257,12 +268,15 @@ // responderID short tag = (byte)(seq.tag & 0x1f); if (tag == NAME_TAG) { - if (DEBUG != null) { - X500Name responderName = new X500Name(seq.getData()); - DEBUG.println("OCSP Responder name: " + responderName); + responderName = + new X500Principal(new ByteArrayInputStream(seq.toByteArray())); + if (debug != null) { + debug.println("OCSP Responder name: " + responderName); } + responderKey = null; } else if (tag == KEY_TAG) { - // Ignore, for now + responderKey = seq.getOctetString(); + responderName = null; } else { throw new IOException("Bad encoding in responderID element of " + "OCSP response: expected ASN.1 context specific tag 0 or 1"); @@ -270,57 +284,55 @@ // producedAt seq = seqDerIn.getDerValue(); - if (DEBUG != null) { + if (debug != null) { Date producedAtDate = seq.getGeneralizedTime(); - DEBUG.println("OCSP response produced at: " + producedAtDate); + debug.println("OCSP response produced at: " + producedAtDate); } // responses DerValue[] singleResponseDer = seqDerIn.getSequence(1); - singleResponseMap - = new HashMap<CertId, SingleResponse>(singleResponseDer.length); - if (DEBUG != null) { - DEBUG.println("OCSP number of SingleResponses: " - + singleResponseDer.length); + singleResponseMap = new HashMap<>(singleResponseDer.length); + if (debug != null) { + debug.println("OCSP number of SingleResponses: " + + singleResponseDer.length); } for (int i = 0; i < singleResponseDer.length; i++) { - SingleResponse singleResponse - = new SingleResponse(singleResponseDer[i]); + SingleResponse singleResponse = + new SingleResponse(singleResponseDer[i]); singleResponseMap.put(singleResponse.getCertId(), singleResponse); } // responseExtensions + byte[] nonce = null; if (seqDerIn.available() > 0) { seq = seqDerIn.getDerValue(); if (seq.isContextSpecific((byte)1)) { DerValue[] responseExtDer = seq.data.getSequence(3); for (int i = 0; i < responseExtDer.length; i++) { - Extension responseExtension - = new Extension(responseExtDer[i]); - if (DEBUG != null) { - DEBUG.println("OCSP extension: " + responseExtension); + Extension ext = new Extension(responseExtDer[i]); + if (debug != null) { + debug.println("OCSP extension: " + ext); } - if (responseExtension.getExtensionId().equals((Object) - OCSP_NONCE_EXTENSION_OID)) { - /* - ocspNonce = - responseExtension[i].getExtensionValue(); - */ - } else if (responseExtension.isCritical()) { + // Only the NONCE extension is recognized + if (ext.getExtensionId().equals((Object) + OCSP.NONCE_EXTENSION_OID)) + { + nonce = ext.getExtensionValue(); + } else if (ext.isCritical()) { throw new IOException( "Unsupported OCSP critical extension: " + - responseExtension.getExtensionId()); + ext.getExtensionId()); } } } } + responseNonce = nonce; // signatureAlgorithmId - AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]); + sigAlgId = AlgorithmId.parse(seqTmp[1]); // signature - byte[] signature = seqTmp[2].getBitString(); - X509CertImpl[] x509Certs = null; + signature = seqTmp[2].getBitString(); // if seq[3] is available , then it is a sequence of certificates if (seqTmp.length > 3) { @@ -330,30 +342,59 @@ throw new IOException("Bad encoding in certs element of " + "OCSP response: expected ASN.1 context specific tag 0."); } - DerValue[] certs = seqCert.getData().getSequence(3); - x509Certs = new X509CertImpl[certs.length]; + DerValue[] derCerts = seqCert.getData().getSequence(3); + certs = new ArrayList<X509CertImpl>(derCerts.length); try { - for (int i = 0; i < certs.length; i++) { - x509Certs[i] = new X509CertImpl(certs[i].toByteArray()); + for (int i = 0; i < derCerts.length; i++) { + certs.add(new X509CertImpl(derCerts[i].toByteArray())); } } catch (CertificateException ce) { throw new IOException("Bad encoding in X509 Certificate", ce); } + } else { + certs = Collections.<X509CertImpl>emptyList(); } + } + + void verify(List<CertId> certIds, X509Certificate responderCert, + Date date, byte[] nonce) + throws CertPathValidatorException + { + if (responseStatus != ResponseStatus.SUCCESSFUL) { + throw new CertPathValidatorException + ("OCSP response error: " + responseStatus); + } + + // Check that the response includes a response for all of the + // certs that were supplied in the request + for (CertId certId : certIds) { + SingleResponse sr = getSingleResponse(certId); + if (sr == null) { + if (debug != null) { + debug.println("No response found for CertId: " + certId); + } + throw new CertPathValidatorException( + "OCSP response does not include a response for a " + + "certificate supplied in the OCSP request"); + } + if (debug != null) { + debug.println("Status of certificate (with serial number " + + certId.getSerialNumber() + ") is: " + sr.getCertStatus()); + } + } + // Check whether the cert returned by the responder is trusted - if (x509Certs != null && x509Certs[0] != null) { - X509CertImpl cert = x509Certs[0]; - - // First check if the cert matches the responder cert which - // was set locally. + if (!certs.isEmpty()) { + X509CertImpl cert = certs.get(0); + // First check if the cert matches the expected responder cert if (cert.equals(responderCert)) { // cert is trusted, now verify the signed response // Next check if the cert was issued by the responder cert // which was set locally. } else if (cert.getIssuerX500Principal().equals( - responderCert.getSubjectX500Principal())) { + responderCert.getSubjectX500Principal())) { // Check for the OCSPSigning key purpose try { @@ -380,12 +421,12 @@ // check the validity try { - if (dateCheckedAgainst == null) { + if (date == null) { cert.checkValidity(); } else { - cert.checkValidity(dateCheckedAgainst); + cert.checkValidity(date); } - } catch (GeneralSecurityException e) { + } catch (CertificateException e) { throw new CertPathValidatorException( "Responder's certificate not within the " + "validity period", e); @@ -401,8 +442,8 @@ Extension noCheck = cert.getExtension(PKIXExtensions.OCSPNoCheck_Id); if (noCheck != null) { - if (DEBUG != null) { - DEBUG.println("Responder's certificate includes " + + if (debug != null) { + debug.println("Responder's certificate includes " + "the extension id-pkix-ocsp-nocheck."); } } else { @@ -433,15 +474,44 @@ // "jdk.certpath.disabledAlgorithms". AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId); - if (!verifyResponse(responseDataDer, responderCert, - sigAlgId, signature)) { + if (!verifySignature(responderCert)) { throw new CertPathValidatorException( - "Error verifying OCSP Responder's signature"); + "Error verifying OCSP Response's signature"); } } else { // Need responder's cert in order to verify the signature throw new CertPathValidatorException( - "Unable to verify OCSP Responder's signature"); + "Unable to verify OCSP Response's signature"); + } + + // Check freshness of OCSPResponse + if (nonce != null) { + if (responseNonce != null && !Arrays.equals(nonce, responseNonce)) { + throw new CertPathValidatorException("Nonces don't match"); + } + } + + long now = (date == null) ? System.currentTimeMillis() : date.getTime(); + Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW); + Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW); + for (SingleResponse sr : singleResponseMap.values()) { + if (debug != null) { + String until = ""; + if (sr.nextUpdate != null) { + until = " until " + sr.nextUpdate; + } + debug.println("Response's validity interval is from " + + sr.thisUpdate + until); + } + + // Check that the test date is within the validity interval + if ((sr.thisUpdate != null && nowPlusSkew.before(sr.thisUpdate)) || + (sr.nextUpdate != null && nowMinusSkew.after(sr.nextUpdate))) + { + throw new CertPathValidatorException( + "Response is unreliable: its validity " + + "interval is out-of-date"); + } } } @@ -456,34 +526,31 @@ * Verify the signature of the OCSP response. * The responder's cert is implicitly trusted. */ - private boolean verifyResponse(byte[] responseData, X509Certificate cert, - AlgorithmId sigAlgId, byte[] signBytes) + private boolean verifySignature(X509Certificate cert) throws CertPathValidatorException { try { Signature respSignature = Signature.getInstance(sigAlgId.getName()); respSignature.initVerify(cert); - respSignature.update(responseData); + respSignature.update(tbsResponseData); - if (respSignature.verify(signBytes)) { - if (DEBUG != null) { - DEBUG.println("Verified signature of OCSP Responder"); + if (respSignature.verify(signature)) { + if (debug != null) { + debug.println("Verified signature of OCSP Response"); } return true; } else { - if (DEBUG != null) { - DEBUG.println( - "Error verifying signature of OCSP Responder"); + if (debug != null) { + debug.println( + "Error verifying signature of OCSP Response"); } return false; } - } catch (InvalidKeyException ike) { - throw new CertPathValidatorException(ike); - } catch (NoSuchAlgorithmException nsae) { - throw new CertPathValidatorException(nsae); - } catch (SignatureException se) { - throw new CertPathValidatorException(se); + } catch (InvalidKeyException | NoSuchAlgorithmException | + SignatureException e) + { + throw new CertPathValidatorException(e); } } @@ -537,9 +604,9 @@ revocationReason = CRLReason.UNSPECIFIED; } // RevokedInfo - if (DEBUG != null) { - DEBUG.println("Revocation time: " + revocationTime); - DEBUG.println("Revocation reason: " + revocationReason); + if (debug != null) { + debug.println("Revocation time: " + revocationTime); + debug.println("Revocation reason: " + revocationReason); } } else { revocationTime = null; @@ -585,8 +652,8 @@ (singleExtDer.length); for (int i = 0; i < singleExtDer.length; i++) { Extension ext = new Extension(singleExtDer[i]); - if (DEBUG != null) { - DEBUG.println("OCSP single extension: " + ext); + if (debug != null) { + debug.println("OCSP single extension: " + ext); } // We don't support any extensions yet. Therefore, if it // is critical we must throw an exception because we @@ -604,29 +671,6 @@ } else { singleExtensions = Collections.emptyMap(); } - - long now = System.currentTimeMillis(); - Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW); - Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW); - if (DEBUG != null) { - String until = ""; - if (nextUpdate != null) { - until = " until " + nextUpdate; - } - DEBUG.println("Response's validity interval is from " + - thisUpdate + until); - } - // Check that the test date is within the validity interval - if ((thisUpdate != null && nowPlusSkew.before(thisUpdate)) || - (nextUpdate != null && nowMinusSkew.after(nextUpdate))) { - - if (DEBUG != null) { - DEBUG.println("Response is unreliable: its validity " + - "interval is out-of-date"); - } - throw new IOException("Response is unreliable: its validity " + - "interval is out-of-date"); - } } /* diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/PKIX.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIX.java Wed May 30 17:19:46 2012 -0400 @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.security.provider.certpath; + +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyStore; +import java.security.cert.*; +import java.util.*; +import javax.security.auth.x500.X500Principal; + +import sun.security.util.Debug; + +/** + * Common utility methods and classes used by the PKIX CertPathValidator and + * CertPathBuilder implementation. + */ +class PKIX { + + private static final Debug debug = Debug.getInstance("certpath"); + + private PKIX() { } + + static ValidatorParams checkParams(CertPath cp, CertPathParameters params) + throws InvalidAlgorithmParameterException + { + if (!(params instanceof PKIXParameters)) { + throw new InvalidAlgorithmParameterException("inappropriate " + + "params, must be an instance of PKIXParameters"); + } + return new ValidatorParams(cp, (PKIXParameters)params); + } + + static BuilderParams checkBuilderParams(CertPathParameters params) + throws InvalidAlgorithmParameterException + { + if (!(params instanceof PKIXBuilderParameters)) { + throw new InvalidAlgorithmParameterException("inappropriate " + + "params, must be an instance of PKIXBuilderParameters"); + } + return new BuilderParams((PKIXBuilderParameters)params); + } + + /** + * PKIXParameters that are shared by the PKIX CertPathValidator + * implementation. Provides additional functionality and avoids + * unnecessary cloning. + */ + static class ValidatorParams { + private final PKIXParameters params; + private CertPath certPath; + private List<PKIXCertPathChecker> checkers; + private List<CertStore> stores; + private boolean gotDate; + private Date date; + private Set<String> policies; + private boolean gotConstraints; + private CertSelector constraints; + private Set<TrustAnchor> anchors; + private List<X509Certificate> certs; + + ValidatorParams(CertPath cp, PKIXParameters params) + throws InvalidAlgorithmParameterException + { + this(params); + if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) { + throw new InvalidAlgorithmParameterException("inappropriate " + + "CertPath type specified, must be X.509 or X509"); + } + this.certPath = cp; + } + + ValidatorParams(PKIXParameters params) + throws InvalidAlgorithmParameterException + { + this.anchors = params.getTrustAnchors(); + // Make sure that none of the trust anchors include name constraints + // (not supported). + for (TrustAnchor anchor : this.anchors) { + if (anchor.getNameConstraints() != null) { + throw new InvalidAlgorithmParameterException + ("name constraints in trust anchor not supported"); + } + } + this.params = params; + } + + CertPath certPath() { + return certPath; + } + // called by CertPathBuilder after path has been built + void setCertPath(CertPath cp) { + this.certPath = cp; + } + List<X509Certificate> certificates() { + if (certs == null) { + if (certPath == null) { + certs = Collections.emptyList(); + } else { + // Reverse the ordering for validation so that the target + // cert is the last certificate + @SuppressWarnings("unchecked") + List<X509Certificate> xc = new ArrayList<> + ((List<X509Certificate>)certPath.getCertificates()); + Collections.reverse(xc); + certs = xc; + } + } + return certs; + } + List<PKIXCertPathChecker> certPathCheckers() { + if (checkers == null) + checkers = params.getCertPathCheckers(); + return checkers; + } + List<CertStore> certStores() { + if (stores == null) + stores = params.getCertStores(); + return stores; + } + Date date() { + if (!gotDate) { + date = params.getDate(); + if (date == null) + date = new Date(); + gotDate = true; + } + return date; + } + Set<String> initialPolicies() { + if (policies == null) + policies = params.getInitialPolicies(); + return policies; + } + CertSelector targetCertConstraints() { + if (!gotConstraints) { + constraints = params.getTargetCertConstraints(); + gotConstraints = true; + } + return constraints; + } + Set<TrustAnchor> trustAnchors() { + return anchors; + } + boolean revocationEnabled() { + return params.isRevocationEnabled(); + } + boolean policyMappingInhibited() { + return params.isPolicyMappingInhibited(); + } + boolean explicitPolicyRequired() { + return params.isExplicitPolicyRequired(); + } + boolean policyQualifiersRejected() { + return params.getPolicyQualifiersRejected(); + } + String sigProvider() { return params.getSigProvider(); } + boolean anyPolicyInhibited() { return params.isAnyPolicyInhibited(); } + + // in rare cases we need access to the original params, for example + // in order to clone CertPathCheckers before building a new chain + PKIXParameters getPKIXParameters() { + return params; + } + } + + static class BuilderParams extends ValidatorParams { + private PKIXBuilderParameters params; + private boolean buildForward = true; + private List<CertStore> stores; + private X500Principal targetSubject; + + BuilderParams(PKIXBuilderParameters params) + throws InvalidAlgorithmParameterException + { + super(params); + checkParams(params); + } + private void checkParams(PKIXBuilderParameters params) + throws InvalidAlgorithmParameterException + { + CertSelector sel = targetCertConstraints(); + if (!(sel instanceof X509CertSelector)) { + throw new InvalidAlgorithmParameterException("the " + + "targetCertConstraints parameter must be an " + + "X509CertSelector"); + } + if (params instanceof SunCertPathBuilderParameters) { + buildForward = + ((SunCertPathBuilderParameters)params).getBuildForward(); + } + this.params = params; + this.targetSubject = getTargetSubject( + certStores(), (X509CertSelector)targetCertConstraints()); + } + @Override List<CertStore> certStores() { + if (stores == null) { + // reorder CertStores so that local CertStores are tried first + stores = new ArrayList<>(params.getCertStores()); + Collections.sort(stores, new CertStoreComparator()); + } + return stores; + } + int maxPathLength() { return params.getMaxPathLength(); } + boolean buildForward() { return buildForward; } + PKIXBuilderParameters params() { return params; } + X500Principal targetSubject() { return targetSubject; } + + /** + * Returns the target subject DN from the first X509Certificate that + * is fetched that matches the specified X509CertSelector. + */ + private static X500Principal getTargetSubject(List<CertStore> stores, + X509CertSelector sel) + throws InvalidAlgorithmParameterException + { + X500Principal subject = sel.getSubject(); + if (subject != null) { + return subject; + } + X509Certificate cert = sel.getCertificate(); + if (cert != null) { + subject = cert.getSubjectX500Principal(); + } + if (subject != null) { + return subject; + } + for (CertStore store : stores) { + try { + Collection<? extends Certificate> certs = + (Collection<? extends Certificate>) + store.getCertificates(sel); + if (!certs.isEmpty()) { + X509Certificate xc = + (X509Certificate)certs.iterator().next(); + return xc.getSubjectX500Principal(); + } + } catch (CertStoreException e) { + // ignore but log it + if (debug != null) { + debug.println("BuilderParams.getTargetSubjectDN: " + + "non-fatal exception retrieving certs: " + e); + e.printStackTrace(); + } + } + } + throw new InvalidAlgorithmParameterException + ("Could not determine unique target subject"); + } + } + + /** + * Comparator that orders CertStores so that local CertStores come before + * remote CertStores. + */ + private static class CertStoreComparator implements Comparator<CertStore> { + @Override + public int compare(CertStore store1, CertStore store2) { + if (store1.getType().equals("Collection") || + store1.getCertStoreParameters() instanceof + CollectionCertStoreParameters) { + return -1; + } else { + return 1; + } + } + } +} diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java --- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,55 +25,38 @@ package sun.security.provider.certpath; -import java.security.AccessController; +import java.io.IOException; import java.security.InvalidAlgorithmParameterException; -import java.security.cert.CertPath; -import java.security.cert.CertPathParameters; -import java.security.cert.CertPathValidatorException; -import java.security.cert.CertPathValidatorSpi; -import java.security.cert.CertPathValidatorResult; -import java.security.cert.PKIXCertPathChecker; -import java.security.cert.PKIXCertPathValidatorResult; -import java.security.cert.PKIXParameters; -import java.security.cert.PKIXReason; -import java.security.cert.PolicyNode; -import java.security.cert.TrustAnchor; -import java.security.cert.X509Certificate; -import java.util.Collections; -import java.util.List; -import java.util.ArrayList; -import java.util.Date; -import java.util.Set; -import sun.security.action.GetBooleanSecurityPropertyAction; +import java.security.cert.*; +import java.util.*; + +import sun.security.provider.certpath.PKIX.ValidatorParams; +import sun.security.x509.X509CertImpl; import sun.security.util.Debug; -import sun.security.x509.X509CertImpl; - - /** * This class implements the PKIX validation algorithm for certification * paths consisting exclusively of <code>X509Certificates</code>. It uses * the specified input parameter set (which must be a - * <code>PKIXParameters</code> object) and signature provider (if any). + * <code>PKIXParameters</code> object). * * @since 1.4 * @author Yassir Elley */ -public class PKIXCertPathValidator extends CertPathValidatorSpi { +public final class PKIXCertPathValidator extends CertPathValidatorSpi { private static final Debug debug = Debug.getInstance("certpath"); - private Date testDate; - private List<PKIXCertPathChecker> userCheckers; - private String sigProvider; - private BasicChecker basicChecker; - private boolean ocspEnabled = false; - private boolean onlyEECert = false; /** * Default constructor. */ public PKIXCertPathValidator() {} + @Override + public CertPathChecker engineGetRevocationChecker() { + return new RevocationChecker(); + } + /** * Validates a certification path consisting exclusively of * <code>X509Certificate</code>s using the PKIX validation algorithm, @@ -81,98 +64,70 @@ * The input parameter set must be a <code>PKIXParameters</code> object. * * @param cp the X509 certification path - * @param param the input PKIX parameter set + * @param params the input PKIX parameter set * @return the result - * @exception CertPathValidatorException Exception thrown if cert path - * does not validate. - * @exception InvalidAlgorithmParameterException if the specified - * parameters are inappropriate for this certification path validator + * @throws CertPathValidatorException if cert path does not validate. + * @throws InvalidAlgorithmParameterException if the specified + * parameters are inappropriate for this CertPathValidator */ + @Override public CertPathValidatorResult engineValidate(CertPath cp, - CertPathParameters param) + CertPathParameters params) throws CertPathValidatorException, InvalidAlgorithmParameterException { + ValidatorParams valParams = PKIX.checkParams(cp, params); + return validate(valParams); + } + + private static PKIXCertPathValidatorResult validate(ValidatorParams params) + throws CertPathValidatorException + { if (debug != null) debug.println("PKIXCertPathValidator.engineValidate()..."); - if (!(param instanceof PKIXParameters)) { - throw new InvalidAlgorithmParameterException("inappropriate " - + "parameters, must be an instance of PKIXParameters"); - } - - if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) { - throw new InvalidAlgorithmParameterException("inappropriate " - + "certification path type specified, must be X.509 or X509"); - } - - PKIXParameters pkixParam = (PKIXParameters) param; - - // Make sure that none of the trust anchors include name constraints - // (not supported). - Set<TrustAnchor> anchors = pkixParam.getTrustAnchors(); - for (TrustAnchor anchor : anchors) { - if (anchor.getNameConstraints() != null) { - throw new InvalidAlgorithmParameterException - ("name constraints in trust anchor not supported"); - } - } - - // the certpath which has been passed in (cp) - // has the target cert as the first certificate - we - // need to keep this cp so we can return it - // in case of an exception and for policy qualifier - // processing - however, for certpath validation, - // we need to create a reversed path, where we reverse the - // ordering so that the target cert is the last certificate - - // Must copy elements of certList into a new modifiable List before - // calling Collections.reverse(). - // If cp is not an X.509 or X509 certpath, an - // InvalidAlgorithmParameterException will have been thrown by now. - @SuppressWarnings("unchecked") - ArrayList<X509Certificate> certList = new ArrayList<X509Certificate> - ((List<X509Certificate>)cp.getCertificates()); - if (debug != null) { - if (certList.isEmpty()) { - debug.println("PKIXCertPathValidator.engineValidate() " - + "certList is empty"); - } - debug.println("PKIXCertPathValidator.engineValidate() " - + "reversing certpath..."); - } - Collections.reverse(certList); - - // now certList has the target cert as the last cert and we - // can proceed with normal validation - - populateVariables(pkixParam); - // Retrieve the first certificate in the certpath // (to be used later in pre-screening) - X509Certificate firstCert = null; + AdaptableX509CertSelector selector = null; + List<X509Certificate> certList = params.certificates(); if (!certList.isEmpty()) { - firstCert = certList.get(0); + selector = new AdaptableX509CertSelector(); + X509Certificate firstCert = certList.get(0); + // check trusted certificate's subject + selector.setSubject(firstCert.getIssuerX500Principal()); + // check the validity period + selector.setValidityPeriod(firstCert.getNotBefore(), + firstCert.getNotAfter()); + /* + * Facilitate certification path construction with authority + * key identifier and subject key identifier. + */ + try { + X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert); + selector.parseAuthorityKeyIdentifierExtension( + firstCertImpl.getAuthorityKeyIdentifierExtension()); + } catch (CertificateException | IOException e) { + // ignore + } } CertPathValidatorException lastException = null; // We iterate through the set of trust anchors until we find // one that works at which time we stop iterating - for (TrustAnchor anchor : anchors) { + for (TrustAnchor anchor : params.trustAnchors()) { X509Certificate trustedCert = anchor.getTrustedCert(); if (trustedCert != null) { - if (debug != null) { - debug.println("PKIXCertPathValidator.engineValidate() " - + "anchor.getTrustedCert() != null"); - } - // if this trust anchor is not worth trying, // we move on to the next one - if (!isWorthTrying(trustedCert, firstCert)) { + if (selector != null && !selector.match(trustedCert)) { + if (debug != null) { + debug.println("NO - don't try this trustedCert"); + } continue; } if (debug != null) { + debug.println("YES - try this trustedCert"); debug.println("anchor.getTrustedCert()." + "getSubjectX500Principal() = " + trustedCert.getSubjectX500Principal()); @@ -185,14 +140,7 @@ } try { - PolicyNodeImpl rootNode = new PolicyNodeImpl(null, - PolicyChecker.ANY_POLICY, null, false, - Collections.singleton(PolicyChecker.ANY_POLICY), false); - PolicyNode policyTree = - doValidate(anchor, cp, certList, pkixParam, rootNode); - // if this anchor works, return success - return new PKIXCertPathValidatorResult(anchor, policyTree, - basicChecker.getPublicKey()); + return validate(anchor, params); } catch (CertPathValidatorException cpe) { // remember this exception lastException = cpe; @@ -210,144 +158,59 @@ null, null, -1, PKIXReason.NO_TRUST_ANCHOR); } - /** - * Internal method to do some simple checks to see if a given cert is - * worth trying to validate in the chain. - */ - private boolean isWorthTrying(X509Certificate trustedCert, - X509Certificate firstCert) { - - boolean worthy = false; - - if (debug != null) { - debug.println("PKIXCertPathValidator.isWorthTrying() checking " - + "if this trusted cert is worth trying ..."); - } - - if (firstCert == null) { - return true; - } - - AdaptableX509CertSelector issuerSelector = - new AdaptableX509CertSelector(); - - // check trusted certificate's subject - issuerSelector.setSubject(firstCert.getIssuerX500Principal()); + private static PKIXCertPathValidatorResult validate(TrustAnchor anchor, + ValidatorParams params) + throws CertPathValidatorException + { + int certPathLen = params.certificates().size(); - // check the validity period - issuerSelector.setValidityPeriod(firstCert.getNotBefore(), - firstCert.getNotAfter()); + // create PKIXCertPathCheckers + List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>(); + // add standard checkers that we will be using + certPathCheckers.add(new AlgorithmChecker(anchor)); + certPathCheckers.add(new KeyChecker(certPathLen, + params.targetCertConstraints())); + certPathCheckers.add(new ConstraintsChecker(certPathLen)); + PolicyNodeImpl rootNode = + new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null, false, + Collections.singleton(PolicyChecker.ANY_POLICY), + false); + PolicyChecker pc = new PolicyChecker(params.initialPolicies(), + certPathLen, + params.explicitPolicyRequired(), + params.policyMappingInhibited(), + params.anyPolicyInhibited(), + params.policyQualifiersRejected(), + rootNode); + certPathCheckers.add(pc); + // default value for date is current time + BasicChecker bc = new BasicChecker(anchor, params.date(), + params.sigProvider(), false); + certPathCheckers.add(bc); - /* - * Facilitate certification path construction with authority - * key identifier and subject key identifier. - */ - try { - X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert); - issuerSelector.parseAuthorityKeyIdentifierExtension( - firstCertImpl.getAuthorityKeyIdentifierExtension()); - - worthy = issuerSelector.match(trustedCert); - } catch (Exception e) { - // It is not worth trying. - } - - if (debug != null) { - if (worthy) { - debug.println("YES - try this trustedCert"); - } else { - debug.println("NO - don't try this trustedCert"); + boolean revCheckerAdded = false; + List<PKIXCertPathChecker> checkers = params.certPathCheckers(); + for (PKIXCertPathChecker checker : checkers) { + if (checker instanceof PKIXRevocationChecker) { + revCheckerAdded = true; + // if it's our own, initialize it + if (checker instanceof RevocationChecker) + ((RevocationChecker)checker).init(anchor, params); } } - - return worthy; - } - - /** - * Internal method to setup the internal state - */ - private void populateVariables(PKIXParameters pkixParam) - { - // default value for testDate is current time - testDate = pkixParam.getDate(); - if (testDate == null) { - testDate = new Date(System.currentTimeMillis()); + // only add a RevocationChecker if revocation is enabled and + // a PKIXRevocationChecker has not already been added + if (params.revocationEnabled() && !revCheckerAdded) { + certPathCheckers.add(new RevocationChecker(anchor, params)); } - - userCheckers = pkixParam.getCertPathCheckers(); - sigProvider = pkixParam.getSigProvider(); - - if (pkixParam.isRevocationEnabled()) { - // Examine OCSP security property - ocspEnabled = AccessController.doPrivileged( - new GetBooleanSecurityPropertyAction - (OCSPChecker.OCSP_ENABLE_PROP)); - onlyEECert = AccessController.doPrivileged( - new GetBooleanSecurityPropertyAction - ("com.sun.security.onlyCheckRevocationOfEECert")); - } - } - - /** - * Internal method to actually validate a constructed path. - * - * @return the valid policy tree - */ - private PolicyNode doValidate( - TrustAnchor anchor, CertPath cpOriginal, - ArrayList<X509Certificate> certList, PKIXParameters pkixParam, - PolicyNodeImpl rootNode) throws CertPathValidatorException - { - int certPathLen = certList.size(); + // add user-specified checkers + certPathCheckers.addAll(checkers); - basicChecker = new BasicChecker(anchor, testDate, sigProvider, false); - AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor); - KeyChecker keyChecker = new KeyChecker(certPathLen, - pkixParam.getTargetCertConstraints()); - ConstraintsChecker constraintsChecker = - new ConstraintsChecker(certPathLen); - - PolicyChecker policyChecker = - new PolicyChecker(pkixParam.getInitialPolicies(), certPathLen, - pkixParam.isExplicitPolicyRequired(), - pkixParam.isPolicyMappingInhibited(), - pkixParam.isAnyPolicyInhibited(), - pkixParam.getPolicyQualifiersRejected(), - rootNode); - - ArrayList<PKIXCertPathChecker> certPathCheckers = - new ArrayList<PKIXCertPathChecker>(); - // add standard checkers that we will be using - certPathCheckers.add(algorithmChecker); - certPathCheckers.add(keyChecker); - certPathCheckers.add(constraintsChecker); - certPathCheckers.add(policyChecker); - certPathCheckers.add(basicChecker); + PKIXMasterCertPathValidator.validate(params.certPath(), + params.certificates(), + certPathCheckers); - // only add a revocationChecker if revocation is enabled - if (pkixParam.isRevocationEnabled()) { - - // Use OCSP if it has been enabled - if (ocspEnabled) { - OCSPChecker ocspChecker = - new OCSPChecker(cpOriginal, pkixParam, onlyEECert); - certPathCheckers.add(ocspChecker); - } - - // Always use CRLs - CrlRevocationChecker revocationChecker = new - CrlRevocationChecker(anchor, pkixParam, certList, onlyEECert); - certPathCheckers.add(revocationChecker); - } - - // add user-specified checkers - certPathCheckers.addAll(userCheckers); - - PKIXMasterCertPathValidator masterValidator = - new PKIXMasterCertPathValidator(certPathCheckers); - - masterValidator.validate(cpOriginal, certList); - - return policyChecker.getPolicyTree(); + return new PKIXCertPathValidatorResult(anchor, pc.getPolicyTree(), + bc.getPublicKey()); } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java --- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,8 @@ import java.util.Collections; import java.util.List; import java.util.Set; -import java.security.cert.CertificateRevokedException; import java.security.cert.CertPath; import java.security.cert.CertPathValidatorException; -import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.PKIXCertPathChecker; import java.security.cert.PKIXReason; import java.security.cert.X509Certificate; @@ -49,32 +47,22 @@ class PKIXMasterCertPathValidator { private static final Debug debug = Debug.getInstance("certpath"); - private List<PKIXCertPathChecker> certPathCheckers; - - /** - * Initializes the list of PKIXCertPathCheckers whose checks - * will be performed on each certificate in the certpath. - * - * @param certPathCheckers a List of checkers to use - */ - PKIXMasterCertPathValidator(List<PKIXCertPathChecker> certPathCheckers) { - this.certPathCheckers = certPathCheckers; - } /** * Validates a certification path consisting exclusively of - * <code>X509Certificate</code>s using the - * <code>PKIXCertPathChecker</code>s specified - * in the constructor. It is assumed that the + * <code>X509Certificate</code>s using the specified + * <code>PKIXCertPathChecker</code>s. It is assumed that the * <code>PKIXCertPathChecker</code>s * have been initialized with any input parameters they may need. * * @param cpOriginal the original X509 CertPath passed in by the user * @param reversedCertList the reversed X509 CertPath (as a List) - * @exception CertPathValidatorException Exception thrown if cert - * path does not validate. + * @param certPathCheckers the PKIXCertPathCheckers + * @throws CertPathValidatorException if cert path does not validate */ - void validate(CertPath cpOriginal, List<X509Certificate> reversedCertList) + static void validate(CertPath cpOriginal, + List<X509Certificate> reversedCertList, + List<PKIXCertPathChecker> certPathCheckers) throws CertPathValidatorException { // we actually process reversedCertList, but we keep cpOriginal because @@ -104,20 +92,18 @@ debug.println("Checking cert" + (i+1) + " ..."); X509Certificate currCert = reversedCertList.get(i); - Set<String> unresolvedCritExts = - currCert.getCriticalExtensionOIDs(); - if (unresolvedCritExts == null) { - unresolvedCritExts = Collections.<String>emptySet(); + Set<String> unresCritExts = currCert.getCriticalExtensionOIDs(); + if (unresCritExts == null) { + unresCritExts = Collections.<String>emptySet(); } - if (debug != null && !unresolvedCritExts.isEmpty()) { + if (debug != null && !unresCritExts.isEmpty()) { debug.println("Set of critical extensions:"); - for (String oid : unresolvedCritExts) { + for (String oid : unresCritExts) { debug.println(oid); } } - CertPathValidatorException ocspCause = null; for (int j = 0; j < certPathCheckers.size(); j++) { PKIXCertPathChecker currChecker = certPathCheckers.get(j); @@ -130,65 +116,21 @@ currChecker.init(false); try { - currChecker.check(currCert, unresolvedCritExts); + currChecker.check(currCert, unresCritExts); - // OCSP has validated the cert so skip the CRL check - if (isRevocationCheck(currChecker, j, certPathCheckers)) { - if (debug != null) { - debug.println("-checker" + (j + 1) + - " validation succeeded"); - } - j++; - continue; // skip + if (debug != null) { + debug.println("-checker" + (j + 1) + + " validation succeeded"); } } catch (CertPathValidatorException cpve) { - // Throw the saved OCSP exception unless the CRL - // checker has determined that the cert is revoked - if (ocspCause != null && - currChecker instanceof CrlRevocationChecker) { - if (cpve.getReason() == BasicReason.REVOKED) { - throw cpve; - } else { - throw ocspCause; - } - } - /* - * Handle failover from OCSP to CRLs - */ - CertPathValidatorException currentCause = - new CertPathValidatorException(cpve.getMessage(), - cpve.getCause(), cpOriginal, cpSize - (i + 1), - cpve.getReason()); - - // Check if OCSP has confirmed that the cert was revoked - if (cpve.getReason() == BasicReason.REVOKED) { - throw currentCause; - } - // Check if it is appropriate to failover - if (! isRevocationCheck(currChecker, j, certPathCheckers)) { - // no failover - throw currentCause; - } - // Save the current exception - // (in case the CRL check also fails) - ocspCause = currentCause; - - // Otherwise, failover to CRLs - if (debug != null) { - debug.println(cpve.getMessage()); - debug.println( - "preparing to failover (from OCSP to CRLs)"); - } + throw new CertPathValidatorException(cpve.getMessage(), + cpve.getCause(), cpOriginal, cpSize - (i + 1), + cpve.getReason()); } - - if (debug != null) - debug.println("-checker" + (j+1) + " validation succeeded"); } - if (debug != null) - debug.println("checking for unresolvedCritExts"); - if (!unresolvedCritExts.isEmpty()) { + if (!unresCritExts.isEmpty()) { throw new CertPathValidatorException("unrecognized " + "critical extension(s)", null, cpOriginal, cpSize-(i+1), PKIXReason.UNRECOGNIZED_CRIT_EXT); @@ -200,26 +142,9 @@ if (debug != null) { debug.println("Cert path validation succeeded. (PKIX validation " - + "algorithm)"); + + "algorithm)"); debug.println("-------------------------------------------------" - + "-------------"); + + "-------------"); } } - - /* - * Examines the list of PKIX cert path checkers to determine whether - * both the current checker and the next checker are revocation checkers. - * OCSPChecker and CrlRevocationChecker are both revocation checkers. - */ - private static boolean isRevocationCheck(PKIXCertPathChecker checker, - int index, List<PKIXCertPathChecker> checkers) { - - if (checker instanceof OCSPChecker && index + 1 < checkers.size()) { - PKIXCertPathChecker nextChecker = checkers.get(index + 1); - if (nextChecker instanceof CrlRevocationChecker) { - return true; - } - } - return false; - } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java --- a/jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,9 +25,8 @@ package sun.security.provider.certpath; -import java.util.*; import java.io.IOException; - +import java.security.GeneralSecurityException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; @@ -36,13 +35,14 @@ import java.security.cert.PolicyNode; import java.security.cert.PolicyQualifierInfo; import java.security.cert.X509Certificate; +import java.util.*; import sun.security.util.Debug; import sun.security.x509.CertificatePoliciesExtension; import sun.security.x509.PolicyConstraintsExtension; import sun.security.x509.PolicyMappingsExtension; import sun.security.x509.CertificatePolicyMap; -import sun.security.x509.PKIXExtensions; +import static sun.security.x509.PKIXExtensions.*; import sun.security.x509.PolicyInformation; import sun.security.x509.X509CertImpl; import sun.security.x509.InhibitAnyPolicyExtension; @@ -88,7 +88,7 @@ PolicyChecker(Set<String> initialPolicies, int certPathLen, boolean expPolicyRequired, boolean polMappingInhibited, boolean anyPolicyInhibited, boolean rejectPolicyQualifiers, - PolicyNodeImpl rootNode) throws CertPathValidatorException + PolicyNodeImpl rootNode) { if (initialPolicies.isEmpty()) { // if no initialPolicies are specified by user, set @@ -104,18 +104,18 @@ this.anyPolicyInhibited = anyPolicyInhibited; this.rejectPolicyQualifiers = rejectPolicyQualifiers; this.rootNode = rootNode; - init(false); } /** * Initializes the internal state of the checker from parameters * specified in the constructor * - * @param forward a boolean indicating whether this checker should - * be initialized capable of building in the forward direction - * @exception CertPathValidatorException Exception thrown if user - * wants to enable forward checking and forward checking is not supported. + * @param forward a boolean indicating whether this checker should be + * initialized capable of building in the forward direction + * @throws CertPathValidatorException if user wants to enable forward + * checking and forward checking is not supported. */ + @Override public void init(boolean forward) throws CertPathValidatorException { if (forward) { throw new CertPathValidatorException @@ -136,6 +136,7 @@ * * @return true if forward checking is supported, false otherwise */ + @Override public boolean isForwardCheckingSupported() { return false; } @@ -150,13 +151,14 @@ * @return the Set of extensions supported by this PKIXCertPathChecker, * or null if no extensions are supported */ + @Override public Set<String> getSupportedExtensions() { if (supportedExts == null) { - supportedExts = new HashSet<String>(); - supportedExts.add(PKIXExtensions.CertificatePolicies_Id.toString()); - supportedExts.add(PKIXExtensions.PolicyMappings_Id.toString()); - supportedExts.add(PKIXExtensions.PolicyConstraints_Id.toString()); - supportedExts.add(PKIXExtensions.InhibitAnyPolicy_Id.toString()); + supportedExts = new HashSet<String>(4); + supportedExts.add(CertificatePolicies_Id.toString()); + supportedExts.add(PolicyMappings_Id.toString()); + supportedExts.add(PolicyConstraints_Id.toString()); + supportedExts.add(InhibitAnyPolicy_Id.toString()); supportedExts = Collections.unmodifiableSet(supportedExts); } return supportedExts; @@ -168,9 +170,9 @@ * * @param cert the Certificate to be processed * @param unresCritExts the unresolved critical extensions - * @exception CertPathValidatorException Exception thrown if - * the certificate does not verify. + * @throws CertPathValidatorException if the certificate does not verify */ + @Override public void check(Certificate cert, Collection<String> unresCritExts) throws CertPathValidatorException { @@ -178,10 +180,10 @@ checkPolicy((X509Certificate) cert); if (unresCritExts != null && !unresCritExts.isEmpty()) { - unresCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString()); - unresCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString()); - unresCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString()); - unresCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString()); + unresCritExts.remove(CertificatePolicies_Id.toString()); + unresCritExts.remove(PolicyMappings_Id.toString()); + unresCritExts.remove(PolicyConstraints_Id.toString()); + unresCritExts.remove(InhibitAnyPolicy_Id.toString()); } } @@ -290,7 +292,7 @@ if (require == 0) explicitPolicy = require; } - } catch (Exception e) { + } catch (IOException e) { if (debug != null) { debug.println("PolicyChecker.mergeExplicitPolicy " + "unexpected exception"); @@ -339,7 +341,7 @@ policyMapping = inhibit; } } - } catch (Exception e) { + } catch (IOException e) { if (debug != null) { debug.println("PolicyChecker.mergePolicyMapping " + "unexpected exception"); @@ -372,7 +374,7 @@ try { InhibitAnyPolicyExtension inhAnyPolExt = (InhibitAnyPolicyExtension) - currCert.getExtension(PKIXExtensions.InhibitAnyPolicy_Id); + currCert.getExtension(InhibitAnyPolicy_Id); if (inhAnyPolExt == null) return inhibitAnyPolicy; @@ -387,7 +389,7 @@ inhibitAnyPolicy = skipCerts; } } - } catch (Exception e) { + } catch (IOException e) { if (debug != null) { debug.println("PolicyChecker.mergeInhibitAnyPolicy " + "unexpected exception"); @@ -429,7 +431,7 @@ boolean policiesCritical = false; List<PolicyInformation> policyInfo; PolicyNodeImpl rootNode = null; - Set<PolicyQualifierInfo> anyQuals = new HashSet<PolicyQualifierInfo>(); + Set<PolicyQualifierInfo> anyQuals = new HashSet<>(); if (origRootNode == null) rootNode = null; @@ -600,7 +602,7 @@ PolicyNodeImpl parentNode = (PolicyNodeImpl)anyNode.getParent(); parentNode.deleteChild(anyNode); // see if there are any initialPolicies not represented by leaf nodes - Set<String> initial = new HashSet<String>(initPolicies); + Set<String> initial = new HashSet<>(initPolicies); for (PolicyNodeImpl node : rootNode.getPolicyNodes(certIndex)) { initial.remove(node.getValidPolicy()); } @@ -697,7 +699,7 @@ } } - Set<String> expPols = new HashSet<String>(); + Set<String> expPols = new HashSet<>(); expPols.add(curParExpPol); curNode = new PolicyNodeImpl @@ -762,8 +764,7 @@ } boolean childDeleted = false; - for (int j = 0; j < maps.size(); j++) { - CertificatePolicyMap polMap = maps.get(j); + for (CertificatePolicyMap polMap : maps) { String issuerDomain = polMap.getIssuerIdentifier().getIdentifier().toString(); String subjectDomain @@ -816,7 +817,7 @@ PolicyNodeImpl curAnyNodeParent = (PolicyNodeImpl) curAnyNode.getParent(); - Set<String> expPols = new HashSet<String>(); + Set<String> expPols = new HashSet<>(); expPols.add(subjectDomain); PolicyNodeImpl curNode = new PolicyNodeImpl diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java --- a/jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -134,30 +134,37 @@ node.mCriticalityIndicator, node.mExpectedPolicySet, false); } + @Override public PolicyNode getParent() { return mParent; } + @Override public Iterator<PolicyNodeImpl> getChildren() { return Collections.unmodifiableSet(mChildren).iterator(); } + @Override public int getDepth() { return mDepth; } + @Override public String getValidPolicy() { return mValidPolicy; } + @Override public Set<PolicyQualifierInfo> getPolicyQualifiers() { return Collections.unmodifiableSet(mQualifierSet); } + @Override public Set<String> getExpectedPolicies() { return Collections.unmodifiableSet(mExpectedPolicySet); } + @Override public boolean isCritical() { return mCriticalityIndicator; } @@ -169,12 +176,12 @@ * * @return a String describing the contents of the Policy Node */ + @Override public String toString() { - StringBuffer buffer = new StringBuffer(this.asString()); + StringBuilder buffer = new StringBuilder(this.asString()); - Iterator<PolicyNodeImpl> it = getChildren(); - while (it.hasNext()) { - buffer.append(it.next()); + for (PolicyNodeImpl node : mChildren) { + buffer.append(node); } return buffer.toString(); } @@ -293,7 +300,7 @@ * @return a <code>Set</code> of all nodes at the specified depth */ Set<PolicyNodeImpl> getPolicyNodes(int depth) { - Set<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>(); + Set<PolicyNodeImpl> set = new HashSet<>(); getPolicyNodes(depth, set); return set; } @@ -337,7 +344,7 @@ private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth, String expectedOID, boolean matchAny) { - HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>(); + HashSet<PolicyNodeImpl> set = new HashSet<>(); if (mDepth < depth) { for (PolicyNodeImpl node : mChildren) { @@ -367,7 +374,7 @@ * @return a Set of matched <code>PolicyNode</code>s */ Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) { - HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>(); + HashSet<PolicyNodeImpl> set = new HashSet<>(); if (mDepth < depth) { for (PolicyNodeImpl node : mChildren) { @@ -396,7 +403,7 @@ if (mParent == null) { return "anyPolicy ROOT\n"; } else { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i = 0, n = getDepth(); i < n; i++) { sb.append(" "); } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -51,9 +51,10 @@ import javax.security.auth.x500.X500Principal; +import sun.security.provider.certpath.PKIX.BuilderParams; import sun.security.util.Debug; import sun.security.x509.Extension; -import sun.security.x509.PKIXExtensions; +import static sun.security.x509.PKIXExtensions.*; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; import sun.security.x509.PolicyMappingsExtension; @@ -72,28 +73,24 @@ private Debug debug = Debug.getInstance("certpath"); - Set<String> initPolicies; + private final Set<String> initPolicies; /** * Initialize the builder with the input parameters. * * @param params the parameter set used to build a certification path */ - ReverseBuilder(PKIXBuilderParameters buildParams, - X500Principal targetSubjectDN) { + ReverseBuilder(BuilderParams buildParams) { + super(buildParams); - super(buildParams, targetSubjectDN); - - Set<String> initialPolicies = buildParams.getInitialPolicies(); + Set<String> initialPolicies = buildParams.initialPolicies(); initPolicies = new HashSet<String>(); if (initialPolicies.isEmpty()) { // if no initialPolicies are specified by user, set // initPolicies to be anyPolicy by default initPolicies.add(PolicyChecker.ANY_POLICY); } else { - for (String policy : initialPolicies) { - initPolicies.add(policy); - } + initPolicies.addAll(initialPolicies); } } @@ -106,6 +103,7 @@ * Must be an instance of <code>ReverseState</code> * @param certStores list of CertStores */ + @Override Collection<X509Certificate> getMatchingCerts (State currState, List<CertStore> certStores) throws CertStoreException, CertificateException, IOException @@ -138,56 +136,56 @@ (ReverseState currentState, List<CertStore> certStores) throws CertStoreException, CertificateException, IOException { - /* - * Compose a CertSelector to filter out - * certs which do not satisfy requirements. - * - * First, retrieve clone of current target cert constraints, - * and then add more selection criteria based on current validation state. - */ - X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone(); + /* + * Compose a CertSelector to filter out + * certs which do not satisfy requirements. + * + * First, retrieve clone of current target cert constraints, and + * then add more selection criteria based on current validation state. + */ + X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone(); - /* - * Match on issuer (subject of previous cert) - */ - sel.setIssuer(currentState.subjectDN); + /* + * Match on issuer (subject of previous cert) + */ + sel.setIssuer(currentState.subjectDN); - /* - * Match on certificate validity date. - */ - sel.setCertificateValid(date); + /* + * Match on certificate validity date. + */ + sel.setCertificateValid(buildParams.date()); - /* - * Policy processing optimizations - */ - if (currentState.explicitPolicy == 0) - sel.setPolicy(getMatchingPolicies()); + /* + * Policy processing optimizations + */ + if (currentState.explicitPolicy == 0) + sel.setPolicy(getMatchingPolicies()); - /* - * If previous cert has a subject key identifier extension, - * use it to match on authority key identifier extension. - */ - /*if (currentState.subjKeyId != null) { - AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension( + /* + * If previous cert has a subject key identifier extension, + * use it to match on authority key identifier extension. + */ + /*if (currentState.subjKeyId != null) { + AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension( (KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID), null, null); sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue()); - }*/ + }*/ - /* - * Require EE certs - */ - sel.setBasicConstraints(-2); + /* + * Require EE certs + */ + sel.setBasicConstraints(-2); - /* Retrieve matching certs from CertStores */ - HashSet<X509Certificate> eeCerts = new HashSet<X509Certificate>(); - addMatchingCerts(sel, certStores, eeCerts, true); + /* Retrieve matching certs from CertStores */ + HashSet<X509Certificate> eeCerts = new HashSet<>(); + addMatchingCerts(sel, certStores, eeCerts, true); - if (debug != null) { - debug.println("ReverseBuilder.getMatchingEECerts got " + eeCerts.size() - + " certs."); - } - return eeCerts; + if (debug != null) { + debug.println("ReverseBuilder.getMatchingEECerts got " + + eeCerts.size() + " certs."); + } + return eeCerts; } /* @@ -198,63 +196,71 @@ (ReverseState currentState, List<CertStore> certStores) throws CertificateException, CertStoreException, IOException { - /* - * Compose a CertSelector to filter out - * certs which do not satisfy requirements. - */ - X509CertSelector sel = new X509CertSelector(); + /* + * Compose a CertSelector to filter out + * certs which do not satisfy requirements. + */ + X509CertSelector sel = new X509CertSelector(); - /* - * Match on issuer (subject of previous cert) - */ - sel.setIssuer(currentState.subjectDN); + /* + * Match on issuer (subject of previous cert) + */ + sel.setIssuer(currentState.subjectDN); - /* - * Match on certificate validity date. - */ - sel.setCertificateValid(date); + /* + * Match on certificate validity date. + */ + sel.setCertificateValid(buildParams.date()); - /* - * Match on target subject name (checks that current cert's - * name constraints permit it to certify target). - * (4 is the integer type for DIRECTORY name). - */ - sel.addPathToName(4, targetCertConstraints.getSubjectAsBytes()); + /* + * Match on target subject name (checks that current cert's + * name constraints permit it to certify target). + * (4 is the integer type for DIRECTORY name). + */ + byte[] subject = targetCertConstraints.getSubjectAsBytes(); + if (subject != null) { + sel.addPathToName(4, subject); + } else { + X509Certificate cert = targetCertConstraints.getCertificate(); + if (cert != null) { + sel.addPathToName(4, + cert.getSubjectX500Principal().getEncoded()); + } + } - /* - * Policy processing optimizations - */ - if (currentState.explicitPolicy == 0) - sel.setPolicy(getMatchingPolicies()); + /* + * Policy processing optimizations + */ + if (currentState.explicitPolicy == 0) + sel.setPolicy(getMatchingPolicies()); - /* - * If previous cert has a subject key identifier extension, - * use it to match on authority key identifier extension. - */ - /*if (currentState.subjKeyId != null) { - AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension( + /* + * If previous cert has a subject key identifier extension, + * use it to match on authority key identifier extension. + */ + /*if (currentState.subjKeyId != null) { + AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension( (KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID), null, null); - sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue()); - }*/ + sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue()); + }*/ - /* - * Require CA certs - */ - sel.setBasicConstraints(0); + /* + * Require CA certs + */ + sel.setBasicConstraints(0); - /* Retrieve matching certs from CertStores */ - ArrayList<X509Certificate> reverseCerts = - new ArrayList<X509Certificate>(); - addMatchingCerts(sel, certStores, reverseCerts, true); + /* Retrieve matching certs from CertStores */ + ArrayList<X509Certificate> reverseCerts = new ArrayList<>(); + addMatchingCerts(sel, certStores, reverseCerts, true); - /* Sort remaining certs using name constraints */ - Collections.sort(reverseCerts, new PKIXCertComparator()); + /* Sort remaining certs using name constraints */ + Collections.sort(reverseCerts, new PKIXCertComparator()); - if (debug != null) - debug.println("ReverseBuilder.getMatchingCACerts got " + - reverseCerts.size() + " certs."); - return reverseCerts; + if (debug != null) + debug.println("ReverseBuilder.getMatchingCACerts got " + + reverseCerts.size() + " certs."); + return reverseCerts; } /* @@ -269,23 +275,25 @@ private Debug debug = Debug.getInstance("certpath"); + @Override public int compare(X509Certificate cert1, X509Certificate cert2) { /* * if either cert certifies the target, always * put at head of list. */ - if (cert1.getSubjectX500Principal().equals(targetSubjectDN)) { + X500Principal targetSubject = buildParams.targetSubject(); + if (cert1.getSubjectX500Principal().equals(targetSubject)) { return -1; } - if (cert2.getSubjectX500Principal().equals(targetSubjectDN)) { + if (cert2.getSubjectX500Principal().equals(targetSubject)) { return 1; } int targetDist1; int targetDist2; try { - X500Name targetSubjectName = X500Name.asX500Name(targetSubjectDN); + X500Name targetSubjectName = X500Name.asX500Name(targetSubject); targetDist1 = Builder.targetDistance( null, cert1, targetSubjectName); targetDist2 = Builder.targetDistance( @@ -330,6 +338,7 @@ * @param currentState the current state against which the cert is verified * @param certPathList the certPathList generated thus far */ + @Override void verifyCert(X509Certificate cert, State currState, List<X509Certificate> certPathList) throws GeneralSecurityException @@ -358,8 +367,7 @@ * of the same certificate, we reverse the certpathlist first */ if ((certPathList != null) && (!certPathList.isEmpty())) { - List<X509Certificate> reverseCertList = - new ArrayList<X509Certificate>(); + List<X509Certificate> reverseCertList = new ArrayList<>(); for (X509Certificate c : certPathList) { reverseCertList.add(0, c); } @@ -374,8 +382,8 @@ } if (debug != null) debug.println("policyMappingFound = " + policyMappingFound); - if (cert.equals(cpListCert)){ - if ((buildParams.isPolicyMappingInhibited()) || + if (cert.equals(cpListCert)) { + if ((buildParams.policyMappingInhibited()) || (!policyMappingFound)){ if (debug != null) debug.println("loop detected!!"); @@ -386,7 +394,7 @@ } /* check if target cert */ - boolean finalCert = cert.getSubjectX500Principal().equals(targetSubjectDN); + boolean finalCert = cert.getSubjectX500Principal().equals(buildParams.targetSubject()); /* check if CA cert */ boolean caCert = (cert.getBasicConstraints() != -1 ? true : false); @@ -427,23 +435,20 @@ /* * Check revocation. */ - if (buildParams.isRevocationEnabled()) { - - currentState.crlChecker.check(cert, - currentState.pubKey, - currentState.crlSign); + if (buildParams.revocationEnabled() && currentState.revChecker != null) { + currentState.revChecker.check(cert, Collections.<String>emptySet()); } /* Check name constraints if this is not a self-issued cert */ if (finalCert || !X509CertImpl.isSelfIssued(cert)){ - if (currentState.nc != null){ + if (currentState.nc != null) { try { if (!currentState.nc.verify(cert)){ throw new CertPathValidatorException ("name constraints check failed", null, null, -1, PKIXReason.INVALID_NAME); } - } catch (IOException ioe){ + } catch (IOException ioe) { throw new CertPathValidatorException(ioe); } } @@ -457,7 +462,7 @@ (currentState.certIndex, initPolicies, currentState.explicitPolicy, currentState.policyMapping, currentState.inhibitAnyPolicy, - buildParams.getPolicyQualifiersRejected(), currentState.rootNode, + buildParams.policyQualifiersRejected(), currentState.rootNode, certImpl, finalCert); /* @@ -482,15 +487,15 @@ * already checked. If there are any left, throw an exception! */ if (!unresolvedCritExts.isEmpty()) { - unresolvedCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString()); - unresolvedCritExts.remove(PKIXExtensions.NameConstraints_Id.toString()); - unresolvedCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString()); - unresolvedCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString()); - unresolvedCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString()); - unresolvedCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString()); - unresolvedCritExts.remove(PKIXExtensions.SubjectAlternativeName_Id.toString()); - unresolvedCritExts.remove(PKIXExtensions.KeyUsage_Id.toString()); - unresolvedCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString()); + unresolvedCritExts.remove(BasicConstraints_Id.toString()); + unresolvedCritExts.remove(NameConstraints_Id.toString()); + unresolvedCritExts.remove(CertificatePolicies_Id.toString()); + unresolvedCritExts.remove(PolicyMappings_Id.toString()); + unresolvedCritExts.remove(PolicyConstraints_Id.toString()); + unresolvedCritExts.remove(InhibitAnyPolicy_Id.toString()); + unresolvedCritExts.remove(SubjectAlternativeName_Id.toString()); + unresolvedCritExts.remove(KeyUsage_Id.toString()); + unresolvedCritExts.remove(ExtendedKeyUsage_Id.toString()); if (!unresolvedCritExts.isEmpty()) throw new CertPathValidatorException @@ -501,8 +506,8 @@ /* * Check signature. */ - if (buildParams.getSigProvider() != null) { - cert.verify(currentState.pubKey, buildParams.getSigProvider()); + if (buildParams.sigProvider() != null) { + cert.verify(currentState.pubKey, buildParams.sigProvider()); } else { cert.verify(currentState.pubKey); } @@ -515,8 +520,9 @@ * @param cert the certificate to test * @return a boolean value indicating whether the cert completes the path. */ + @Override boolean isPathCompleted(X509Certificate cert) { - return cert.getSubjectX500Principal().equals(targetSubjectDN); + return cert.getSubjectX500Principal().equals(buildParams.targetSubject()); } /** Adds the certificate to the certPathList @@ -524,6 +530,7 @@ * @param cert the certificate to be added * @param certPathList the certification path list */ + @Override void addCertToPath(X509Certificate cert, LinkedList<X509Certificate> certPathList) { certPathList.addLast(cert); @@ -533,6 +540,7 @@ * * @param certPathList the certification path list */ + @Override void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) { certPathList.removeLast(); } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -40,6 +40,7 @@ import java.util.Set; import javax.security.auth.x500.X500Principal; +import sun.security.provider.certpath.PKIX.BuilderParams; import sun.security.util.Debug; import sun.security.x509.NameConstraintsExtension; import sun.security.x509.SubjectKeyIdentifierExtension; @@ -94,7 +95,7 @@ private boolean init = true; /* the checker used for revocation status */ - public CrlRevocationChecker crlChecker; + RevocationChecker revChecker; /* the algorithm checker */ AlgorithmChecker algorithmChecker; @@ -105,7 +106,7 @@ /* Flag indicating if current cert can vouch for the CRL for * the next cert */ - public boolean crlSign = true; + boolean crlSign = true; /** * Returns a boolean flag indicating if the state is initial @@ -113,6 +114,7 @@ * * @return boolean flag indicating if the state is initial (just starting) */ + @Override public boolean isInitial() { return init; } @@ -120,44 +122,32 @@ /** * Display state for debugging purposes */ + @Override public String toString() { - StringBuffer sb = new StringBuffer(); - try { - sb.append("State ["); - sb.append("\n subjectDN of last cert: " + subjectDN); - sb.append("\n subjectKeyIdentifier: " + String.valueOf(subjKeyId)); - sb.append("\n nameConstraints: " + String.valueOf(nc)); - sb.append("\n certIndex: " + certIndex); - sb.append("\n explicitPolicy: " + explicitPolicy); - sb.append("\n policyMapping: " + policyMapping); - sb.append("\n inhibitAnyPolicy: " + inhibitAnyPolicy); - sb.append("\n rootNode: " + rootNode); - sb.append("\n remainingCACerts: " + remainingCACerts); - sb.append("\n crlSign: " + crlSign); - sb.append("\n init: " + init); - sb.append("\n]\n"); - } catch (Exception e) { - if (debug != null) { - debug.println("ReverseState.toString() unexpected exception"); - e.printStackTrace(); - } - } + StringBuilder sb = new StringBuilder(); + sb.append("State ["); + sb.append("\n subjectDN of last cert: ").append(subjectDN); + sb.append("\n subjectKeyIdentifier: ").append + (String.valueOf(subjKeyId)); + sb.append("\n nameConstraints: ").append(String.valueOf(nc)); + sb.append("\n certIndex: ").append(certIndex); + sb.append("\n explicitPolicy: ").append(explicitPolicy); + sb.append("\n policyMapping: ").append(policyMapping); + sb.append("\n inhibitAnyPolicy: ").append(inhibitAnyPolicy); + sb.append("\n rootNode: ").append(rootNode); + sb.append("\n remainingCACerts: ").append(remainingCACerts); + sb.append("\n crlSign: ").append(crlSign); + sb.append("\n init: ").append(init); + sb.append("\n]\n"); return sb.toString(); } /** * Initialize the state. * - * @param maxPathLen The maximum number of CA certs in a path, where -1 - * means unlimited and 0 means only a single EE cert is allowed. - * @param explicitPolicyRequired True, if explicit policy is required. - * @param policyMappingInhibited True, if policy mapping is inhibited. - * @param anyPolicyInhibited True, if any policy is inhibited. - * @param certPathCheckers the list of user-defined PKIXCertPathCheckers + * @param buildParams builder parameters */ - public void initState(int maxPathLen, boolean explicitPolicyRequired, - boolean policyMappingInhibited, boolean anyPolicyInhibited, - List<PKIXCertPathChecker> certPathCheckers) + public void initState(BuilderParams buildParams) throws CertPathValidatorException { /* @@ -165,60 +155,52 @@ * Note that -1 maxPathLen implies unlimited. * 0 implies only an EE cert is acceptable. */ - remainingCACerts = (maxPathLen == -1 ? Integer.MAX_VALUE : maxPathLen); + int maxPathLen = buildParams.maxPathLength(); + remainingCACerts = (maxPathLen == -1) ? Integer.MAX_VALUE + : maxPathLen; /* Initialize explicit policy state variable */ - if (explicitPolicyRequired) { + if (buildParams.explicitPolicyRequired()) { explicitPolicy = 0; } else { // unconstrained if maxPathLen is -1, // otherwise, we want to initialize this to the value of the // longest possible path + 1 (i.e. maxpathlen + finalcert + 1) - explicitPolicy = (maxPathLen == -1) - ? maxPathLen - : maxPathLen + 2; + explicitPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2; } /* Initialize policy mapping state variable */ - if (policyMappingInhibited) { + if (buildParams.policyMappingInhibited()) { policyMapping = 0; } else { - policyMapping = (maxPathLen == -1) - ? maxPathLen - : maxPathLen + 2; + policyMapping = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2; } /* Initialize inhibit any policy state variable */ - if (anyPolicyInhibited) { + if (buildParams.anyPolicyInhibited()) { inhibitAnyPolicy = 0; } else { - inhibitAnyPolicy = (maxPathLen == -1) - ? maxPathLen - : maxPathLen + 2; + inhibitAnyPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2; } /* Initialize certIndex */ certIndex = 1; /* Initialize policy tree */ - Set<String> initExpPolSet = new HashSet<String>(1); + Set<String> initExpPolSet = new HashSet<>(1); initExpPolSet.add(PolicyChecker.ANY_POLICY); - rootNode = new PolicyNodeImpl - (null, PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false); + rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null, + false, initExpPolSet, false); /* * Initialize each user-defined checker + * Shallow copy the checkers */ - if (certPathCheckers != null) { - /* Shallow copy the checkers */ - userCheckers = new ArrayList<PKIXCertPathChecker>(certPathCheckers); - /* initialize each checker (just in case) */ - for (PKIXCertPathChecker checker : certPathCheckers) { - checker.init(false); - } - } else { - userCheckers = new ArrayList<PKIXCertPathChecker>(); + userCheckers = new ArrayList<>(buildParams.certPathCheckers()); + /* initialize each checker (just in case) */ + for (PKIXCertPathChecker checker : userCheckers) { + checker.init(false); } /* Start by trusting the cert to sign CRLs */ @@ -231,8 +213,9 @@ * Update the state with the specified trust anchor. * * @param anchor the most-trusted CA + * @param buildParams builder parameters */ - public void updateState(TrustAnchor anchor) + public void updateState(TrustAnchor anchor, BuilderParams buildParams) throws CertificateException, IOException, CertPathValidatorException { trustAnchor = anchor; @@ -244,14 +227,26 @@ updateState(anchor.getCAPublicKey(), caName); } - // The user specified AlgorithmChecker may not be + // The user specified AlgorithmChecker and RevocationChecker may not be // able to set the trust anchor until now. + boolean revCheckerAdded = false; for (PKIXCertPathChecker checker : userCheckers) { if (checker instanceof AlgorithmChecker) { ((AlgorithmChecker)checker).trySetTrustAnchor(anchor); + } else if (checker instanceof RevocationChecker) { + ((RevocationChecker)checker).init(anchor, buildParams); + ((RevocationChecker)checker).init(false); + revCheckerAdded = true; } } + // only create a RevocationChecker if revocation is enabled and + // a PKIXRevocationChecker has not already been added + if (buildParams.revocationEnabled() && !revCheckerAdded) { + revChecker = new RevocationChecker(anchor, buildParams); + revChecker.init(false); + } + init = false; } @@ -310,7 +305,7 @@ subjKeyId = icert.getSubjectKeyIdentifierExtension(); /* update crlSign */ - crlSign = CrlRevocationChecker.certCanSignCrl(cert); + crlSign = RevocationChecker.certCanSignCrl(cert); /* update current name constraints */ if (nc != null) { @@ -349,6 +344,7 @@ * * @return boolean flag indicating if key lacking parameters encountered. */ + @Override public boolean keyParamsNeeded() { /* when building in reverse, we immediately get parameters needed * or else throw an exception @@ -365,6 +361,7 @@ * because some of them (e.g., subjKeyId) will * not have their contents modified by subsequent calls to updateState. */ + @Override @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly public Object clone() { try { diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java Wed May 30 17:19:46 2012 -0400 @@ -0,0 +1,1095 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider.certpath; + +import java.io.IOException; +import java.math.BigInteger; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.AccessController; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedAction; +import java.security.PublicKey; +import java.security.Security; +import java.security.cert.CertPathValidatorException.BasicReason; +import java.security.cert.Extension; +import java.security.cert.*; +import java.security.interfaces.DSAPublicKey; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.security.auth.x500.X500Principal; + +import static sun.security.provider.certpath.OCSP.*; +import sun.security.provider.certpath.PKIX.ValidatorParams; +import sun.security.action.GetPropertyAction; +import sun.security.x509.*; +import static sun.security.x509.PKIXExtensions.*; +import sun.security.util.Debug; + +class RevocationChecker extends PKIXRevocationChecker { + + private static final Debug debug = Debug.getInstance("certpath"); + + private TrustAnchor anchor; + private ValidatorParams params; + private boolean onlyEE; + private boolean softFail; + private boolean crlDP; + private URI responderURI; + private X509Certificate responderCert; + private List<CertStore> certStores; + private Map<X509Certificate, byte[]> ocspStapled; + private List<Extension> ocspExtensions; + private boolean legacy; + + // state variables + private X509Certificate issuerCert; + private PublicKey prevPubKey; + private boolean crlSignFlag; + + private enum Mode { PREFER_OCSP, PREFER_CRLS, ONLY_CRLS }; + private Mode mode = Mode.PREFER_OCSP; + + private static class RevocationProperties { + boolean onlyEE; + boolean ocspEnabled; + boolean crlDPEnabled; + String ocspUrl; + String ocspSubject; + String ocspIssuer; + String ocspSerial; + } + + RevocationChecker() { + legacy = false; + } + + RevocationChecker(TrustAnchor anchor, ValidatorParams params) + throws CertPathValidatorException + { + legacy = true; + init(anchor, params); + } + + void init(TrustAnchor anchor, ValidatorParams params) + throws CertPathValidatorException + { + RevocationProperties rp = getRevocationProperties(); + URI uri = getOCSPResponder(); + responderURI = (uri == null) ? toURI(rp.ocspUrl) : uri; + X509Certificate cert = getOCSPResponderCert(); + responderCert = (cert == null) + ? getResponderCert(rp, params.trustAnchors(), + params.certStores()) + : cert; + Set<Option> options = getOptions(); + for (Option option : options) { + switch (option) { + case ONLY_END_ENTITY: + case PREFER_CRLS: + case SOFT_FAIL: + break; + default: + throw new CertPathValidatorException( + "Unrecognized revocation parameter option: " + option); + } + } + + // set mode, only end entity flag + if (legacy) { + mode = (rp.ocspEnabled) ? Mode.PREFER_OCSP : Mode.ONLY_CRLS; + onlyEE = rp.onlyEE; + } else { + if (options.contains(Option.PREFER_CRLS)) { + mode = Mode.PREFER_CRLS; + } + onlyEE = options.contains(Option.ONLY_END_ENTITY); + } + softFail = options.contains(Option.SOFT_FAIL); + if (legacy) { + crlDP = rp.crlDPEnabled; + } else { + crlDP = true; + } + ocspStapled = getOCSPStapledResponses(); + ocspExtensions = getOCSPExtensions(); + + this.anchor = anchor; + this.params = params; + this.certStores = new ArrayList<>(params.certStores()); + try { + this.certStores.add(CertStore.getInstance("Collection", + new CollectionCertStoreParameters(params.certificates()))); + } catch (InvalidAlgorithmParameterException | + NoSuchAlgorithmException e) { + // should never occur but not necessarily fatal, so log it, + // ignore and continue + if (debug != null) { + debug.println("RevocationChecker: " + + "error creating Collection CertStore: " + e); + } + } + } + + private static URI toURI(String uriString) + throws CertPathValidatorException + { + try { + if (uriString != null) { + return new URI(uriString); + } + return null; + } catch (URISyntaxException e) { + throw new CertPathValidatorException( + "cannot parse ocsp.responderURL property", e); + } + } + + private static RevocationProperties getRevocationProperties() { + return AccessController.doPrivileged( + new PrivilegedAction<RevocationProperties>() { + public RevocationProperties run() { + RevocationProperties rp = new RevocationProperties(); + String onlyEE = Security.getProperty( + "com.sun.security.onlyCheckRevocationOfEECert"); + rp.onlyEE = onlyEE != null + && onlyEE.equalsIgnoreCase("true"); + String ocspEnabled = Security.getProperty("ocsp.enable"); + rp.ocspEnabled = ocspEnabled != null + && ocspEnabled.equalsIgnoreCase("true"); + rp.ocspUrl = Security.getProperty("ocsp.responderURL"); + rp.ocspSubject + = Security.getProperty("ocsp.responderCertSubjectName"); + rp.ocspIssuer + = Security.getProperty("ocsp.responderCertIssuerName"); + rp.ocspSerial + = Security.getProperty("ocsp.responderCertSerialNumber"); + rp.crlDPEnabled + = Boolean.getBoolean("com.sun.security.enableCRLDP"); + return rp; + } + } + ); + } + + private static X509Certificate getResponderCert(RevocationProperties rp, + Set<TrustAnchor> anchors, + List<CertStore> stores) + throws CertPathValidatorException + { + if (rp.ocspSubject != null) { + return getResponderCert(rp.ocspSubject, anchors, stores); + } else if (rp.ocspIssuer != null && rp.ocspSerial != null) { + return getResponderCert(rp.ocspIssuer, rp.ocspSerial, + anchors, stores); + } else if (rp.ocspIssuer != null || rp.ocspSerial != null) { + throw new CertPathValidatorException( + "Must specify both ocsp.responderCertIssuerName and " + + "ocsp.responderCertSerialNumber properties"); + } + return null; + } + + private static X509Certificate getResponderCert(String subject, + Set<TrustAnchor> anchors, + List<CertStore> stores) + throws CertPathValidatorException + { + X509CertSelector sel = new X509CertSelector(); + try { + sel.setSubject(new X500Principal(subject)); + } catch (IllegalArgumentException e) { + throw new CertPathValidatorException( + "cannot parse ocsp.responderCertSubjectName property", e); + } + return getResponderCert(sel, anchors, stores); + } + + private static X509Certificate getResponderCert(String issuer, + String serial, + Set<TrustAnchor> anchors, + List<CertStore> stores) + throws CertPathValidatorException + { + X509CertSelector sel = new X509CertSelector(); + try { + sel.setIssuer(new X500Principal(issuer)); + } catch (IllegalArgumentException e) { + throw new CertPathValidatorException( + "cannot parse ocsp.responderCertIssuerName property", e); + } + try { + sel.setSerialNumber(new BigInteger(stripOutSeparators(serial), 16)); + } catch (NumberFormatException e) { + throw new CertPathValidatorException( + "cannot parse ocsp.responderCertSerialNumber property", e); + } + return getResponderCert(sel, anchors, stores); + } + + private static X509Certificate getResponderCert(X509CertSelector sel, + Set<TrustAnchor> anchors, + List<CertStore> stores) + throws CertPathValidatorException + { + // first check TrustAnchors + for (TrustAnchor anchor : anchors) { + X509Certificate cert = anchor.getTrustedCert(); + if (cert == null) { + continue; + } + if (sel.match(cert)) { + return cert; + } + } + // now check CertStores + for (CertStore store : stores) { + try { + Collection<? extends Certificate> certs = + store.getCertificates(sel); + if (!certs.isEmpty()) { + return (X509Certificate)certs.iterator().next(); + } + } catch (CertStoreException e) { + // ignore and try next CertStore + if (debug != null) { + debug.println("CertStore exception:" + e); + } + continue; + } + } + throw new CertPathValidatorException( + "Cannot find the responder's certificate " + + "(set using the OCSP security properties)."); + } + + @Override + public void init(boolean forward) throws CertPathValidatorException { + if (forward) { + throw new + CertPathValidatorException("forward checking not supported"); + } else { + if (anchor != null) { + issuerCert = anchor.getTrustedCert(); + prevPubKey = (issuerCert != null) ? issuerCert.getPublicKey() + : anchor.getCAPublicKey(); + } + crlSignFlag = true; + } + } + + @Override + public boolean isForwardCheckingSupported() { + return false; + } + + @Override + public Set<String> getSupportedExtensions() { + return null; + } + + @Override + public void check(Certificate cert, Collection<String> unresolvedCritExts) + throws CertPathValidatorException + { + X509Certificate xcert = (X509Certificate)cert; + if (onlyEE && xcert.getBasicConstraints() != -1) { + if (debug != null) { + debug.println("Skipping revocation check, not end entity cert"); + } + } else { + check(xcert, unresolvedCritExts, prevPubKey, crlSignFlag); + } + updateState(xcert); + } + + void check(X509Certificate xcert, Collection<String> unresolvedCritExts, + PublicKey pubKey, boolean crlSignFlag) + throws CertPathValidatorException + { + try { + switch (mode) { + case PREFER_OCSP: + checkOCSP(xcert, unresolvedCritExts); + break; + case PREFER_CRLS: + case ONLY_CRLS: + checkCRLs(xcert, unresolvedCritExts, null, + pubKey, crlSignFlag); + break; + } + } catch (CertPathValidatorException e) { + if (e.getReason() == BasicReason.REVOKED) { + throw e; + } + CertPathValidatorException cause = e; + if (softFail && e instanceof NetworkFailureException) { + if (mode == Mode.ONLY_CRLS) return; + } + // Rethrow the exception if ONLY_CRLS + if (mode == Mode.ONLY_CRLS) { + throw e; + } + // Otherwise, failover + if (debug != null) { + debug.println("RevocationChecker.check() " + e.getMessage()); + debug.println("RevocationChecker.check() preparing to failover"); + } + try { + switch (mode) { + case PREFER_OCSP: + checkCRLs(xcert, unresolvedCritExts, null, + pubKey, crlSignFlag); + break; + case PREFER_CRLS: + checkOCSP(xcert, unresolvedCritExts); + break; + } + } catch (CertPathValidatorException x) { + if (debug != null) { + debug.println("RevocationChecker.check() failover failed"); + debug.println("RevocationChecker.check() " + x.getMessage()); + } + if (x.getReason() == BasicReason.REVOKED) { + throw x; + } + if (cause != null) { + if (softFail && cause instanceof NetworkFailureException) { + return; + } else { + cause.addSuppressed(x); + throw cause; + } + } + if (softFail && x instanceof NetworkFailureException) { + return; + } + throw x; + } + } + } + + private void updateState(X509Certificate cert) + throws CertPathValidatorException + { + issuerCert = cert; + + // Make new public key if parameters are missing + PublicKey pubKey = cert.getPublicKey(); + if (pubKey instanceof DSAPublicKey && + ((DSAPublicKey)pubKey).getParams() == null) { + // pubKey needs to inherit DSA parameters from prev key + pubKey = BasicChecker.makeInheritedParamsKey(pubKey, prevPubKey); + } + prevPubKey = pubKey; + crlSignFlag = certCanSignCrl(cert); + } + + // Maximum clock skew in milliseconds (15 minutes) allowed when checking + // validity of CRLs + private static final long MAX_CLOCK_SKEW = 900000; + private void checkCRLs(X509Certificate cert, + Collection<String> unresolvedCritExts, + Set<X509Certificate> stackedCerts, + PublicKey pubKey, boolean signFlag) + throws CertPathValidatorException + { + checkCRLs(cert, pubKey, signFlag, true, + stackedCerts, params.trustAnchors()); + } + + private void checkCRLs(X509Certificate cert, PublicKey prevKey, + boolean signFlag, boolean allowSeparateKey, + Set<X509Certificate> stackedCerts, + Set<TrustAnchor> anchors) + throws CertPathValidatorException + { + if (debug != null) { + debug.println("RevocationChecker.checkCRLs()" + + " ---checking revocation status ..."); + } + + // reject circular dependencies - RFC 3280 is not explicit on how + // to handle this, so we feel it is safest to reject them until + // the issue is resolved in the PKIX WG. + if (stackedCerts != null && stackedCerts.contains(cert)) { + if (debug != null) { + debug.println("RevocationChecker.checkCRLs()" + + " circular dependency"); + } + throw new CertPathValidatorException + ("Could not determine revocation status", null, null, -1, + BasicReason.UNDETERMINED_REVOCATION_STATUS); + } + + Set<X509CRL> possibleCRLs = new HashSet<>(); + Set<X509CRL> approvedCRLs = new HashSet<>(); + X509CRLSelector sel = new X509CRLSelector(); + sel.setCertificateChecking(cert); + CertPathHelper.setDateAndTime(sel, params.date(), MAX_CLOCK_SKEW); + + // First, check cached CRLs + for (CertStore store : certStores) { + try { + for (CRL crl : store.getCRLs(sel)) { + possibleCRLs.add((X509CRL)crl); + } + } catch (CertStoreException e) { + // XXX ignore? + } + } + + if (debug != null) { + debug.println("RevocationChecker.checkCRLs() " + + "possible crls.size() = " + possibleCRLs.size()); + } + boolean[] reasonsMask = new boolean[9]; + if (!possibleCRLs.isEmpty()) { + // Now that we have a list of possible CRLs, see which ones can + // be approved + approvedCRLs.addAll(verifyPossibleCRLs(possibleCRLs, cert, prevKey, + signFlag, reasonsMask, + anchors)); + } + + if (debug != null) { + debug.println("RevocationChecker.checkCRLs() " + + "approved crls.size() = " + approvedCRLs.size()); + } + + // make sure that we have at least one CRL that _could_ cover + // the certificate in question and all reasons are covered + if (!approvedCRLs.isEmpty() && + Arrays.equals(reasonsMask, ALL_REASONS)) + { + checkApprovedCRLs(cert, approvedCRLs); + } else { + // Check Distribution Points + // all CRLs returned by the DP Fetcher have also been verified + try { + if (crlDP) { + approvedCRLs.addAll(DistributionPointFetcher.getCRLs( + sel, signFlag, prevKey, + params.sigProvider(), certStores, + reasonsMask, anchors, params.date())); + } + } catch (CertStoreException e) { + if (debug != null) { + debug.println("RevocationChecker.checkCRLs() " + + "unexpected exception: " + e.getMessage()); + } + throw new CertPathValidatorException(e); + } + if (!approvedCRLs.isEmpty() && + Arrays.equals(reasonsMask, ALL_REASONS)) + { + checkApprovedCRLs(cert, approvedCRLs); + } else { + if (allowSeparateKey) { + verifyWithSeparateSigningKey(cert, prevKey, signFlag, + stackedCerts); + return; + } else { + throw new CertPathValidatorException + ("Could not determine revocation status", null, null, -1, + BasicReason.UNDETERMINED_REVOCATION_STATUS); + } + } + } + } + + private void checkApprovedCRLs(X509Certificate cert, + Set<X509CRL> approvedCRLs) + throws CertPathValidatorException + { + // See if the cert is in the set of approved crls. + if (debug != null) { + BigInteger sn = cert.getSerialNumber(); + debug.println("RevocationChecker.checkApprovedCRLs() " + + "starting the final sweep..."); + debug.println("RevocationChecker.checkApprovedCRLs()" + + " cert SN: " + sn.toString()); + } + + CRLReason reasonCode = CRLReason.UNSPECIFIED; + X509CRLEntryImpl entry = null; + for (X509CRL crl : approvedCRLs) { + X509CRLEntry e = crl.getRevokedCertificate(cert); + if (e != null) { + try { + entry = X509CRLEntryImpl.toImpl(e); + } catch (CRLException ce) { + throw new CertPathValidatorException(ce); + } + if (debug != null) { + debug.println("RevocationChecker.checkApprovedCRLs()" + + " CRL entry: " + entry.toString()); + } + + /* + * Abort CRL validation and throw exception if there are any + * unrecognized critical CRL entry extensions (see section + * 5.3 of RFC 3280). + */ + Set<String> unresCritExts = entry.getCriticalExtensionOIDs(); + if (unresCritExts != null && !unresCritExts.isEmpty()) { + /* remove any that we will process */ + unresCritExts.remove(ReasonCode_Id.toString()); + unresCritExts.remove(CertificateIssuer_Id.toString()); + if (!unresCritExts.isEmpty()) { + if (debug != null) { + debug.println("Unrecognized " + + "critical extension(s) in revoked CRL entry: " + + unresCritExts); + } + throw new CertPathValidatorException + ("Could not determine revocation status", null, null, + -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); + } + } + + reasonCode = entry.getRevocationReason(); + if (reasonCode == null) { + reasonCode = CRLReason.UNSPECIFIED; + } + Throwable t = new CertificateRevokedException + (entry.getRevocationDate(), reasonCode, + crl.getIssuerX500Principal(), entry.getExtensions()); + throw new CertPathValidatorException(t.getMessage(), t, + null, -1, BasicReason.REVOKED); + } + } + } + + private void checkOCSP(X509Certificate cert, + Collection<String> unresolvedCritExts) + throws CertPathValidatorException + { + X509CertImpl currCert = null; + try { + currCert = X509CertImpl.toImpl(cert); + } catch (CertificateException ce) { + throw new CertPathValidatorException(ce); + } + + URI responderURI = (this.responderURI != null) + ? this.responderURI : getOCSPServerURI(currCert); + + X509Certificate respCert = (responderCert == null) ? issuerCert + : responderCert; + + // The algorithm constraints of the OCSP trusted responder certificate + // does not need to be checked in this code. The constraints will be + // checked when the responder's certificate is validated. + + OCSPResponse response = null; + CertId certId = null; + try { + certId = new CertId(issuerCert, currCert.getSerialNumberObject()); + + // check if there is a stapled OCSP response available + byte[] responseBytes = ocspStapled.get(cert); + if (responseBytes != null) { + if (debug != null) { + debug.println("Found stapled OCSP response"); + } + response = new OCSPResponse(responseBytes); + + // verify the response + byte[] nonce = null; + for (Extension ext : ocspExtensions) { + if (ext.getId().equals("1.3.6.1.5.5.7.48.1.2")) { + nonce = ext.getValue(); + } + } + response.verify(Collections.singletonList(certId), respCert, + params.date(), nonce); + + } else { + response = OCSP.check(Collections.singletonList(certId), + responderURI, respCert, params.date(), + ocspExtensions); + } + } catch (IOException e) { + throw new CertPathValidatorException(e); + } + + RevocationStatus rs = + (RevocationStatus)response.getSingleResponse(certId); + RevocationStatus.CertStatus certStatus = rs.getCertStatus(); + if (certStatus == RevocationStatus.CertStatus.REVOKED) { + Throwable t = new CertificateRevokedException( + rs.getRevocationTime(), rs.getRevocationReason(), + respCert.getSubjectX500Principal(), rs.getSingleExtensions()); + throw new CertPathValidatorException(t.getMessage(), t, null, + -1, BasicReason.REVOKED); + } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) { + throw new CertPathValidatorException( + "Certificate's revocation status is unknown", null, + params.certPath(), -1, + BasicReason.UNDETERMINED_REVOCATION_STATUS); + } + } + + /* + * Removes any non-hexadecimal characters from a string. + */ + private static final String HEX_DIGITS = "0123456789ABCDEFabcdef"; + private static String stripOutSeparators(String value) { + char[] chars = value.toCharArray(); + StringBuilder hexNumber = new StringBuilder(); + for (int i = 0; i < chars.length; i++) { + if (HEX_DIGITS.indexOf(chars[i]) != -1) { + hexNumber.append(chars[i]); + } + } + return hexNumber.toString(); + } + + private static URI getOCSPServerURI(X509CertImpl cert) + throws CertPathValidatorException + { + // Examine the certificate's AuthorityInfoAccess extension + AuthorityInfoAccessExtension aia = + cert.getAuthorityInfoAccessExtension(); + if (aia == null) { + throw new CertPathValidatorException( + "Must specify the location of an OCSP Responder"); + } + + List<AccessDescription> descriptions = aia.getAccessDescriptions(); + for (AccessDescription description : descriptions) { + if (description.getAccessMethod().equals((Object) + AccessDescription.Ad_OCSP_Id)) { + + GeneralName generalName = description.getAccessLocation(); + if (generalName.getType() == GeneralNameInterface.NAME_URI) { + URIName uri = (URIName)generalName.getName(); + return uri.getURI(); + } + } + } + + throw new CertPathValidatorException( + "Cannot find the location of the OCSP Responder"); + } + + /** + * Checks that a cert can be used to verify a CRL. + * + * @param cert an X509Certificate to check + * @return a boolean specifying if the cert is allowed to vouch for the + * validity of a CRL + */ + static boolean certCanSignCrl(X509Certificate cert) { + // if the cert doesn't include the key usage ext, or + // the key usage ext asserts cRLSigning, return true, + // otherwise return false. + boolean[] keyUsage = cert.getKeyUsage(); + if (keyUsage != null) { + return keyUsage[6]; + } + return false; + } + + /** + * Internal method that verifies a set of possible_crls, + * and sees if each is approved, based on the cert. + * + * @param crls a set of possible CRLs to test for acceptability + * @param cert the certificate whose revocation status is being checked + * @param signFlag <code>true</code> if prevKey was trusted to sign CRLs + * @param prevKey the public key of the issuer of cert + * @param reasonsMask the reason code mask + * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s> + * @return a collection of approved crls (or an empty collection) + */ + private static final boolean[] ALL_REASONS = + {true, true, true, true, true, true, true, true, true}; + private Collection<X509CRL> verifyPossibleCRLs(Set<X509CRL> crls, + X509Certificate cert, + PublicKey prevKey, + boolean signFlag, + boolean[] reasonsMask, + Set<TrustAnchor> anchors) + throws CertPathValidatorException + { + try { + X509CertImpl certImpl = X509CertImpl.toImpl(cert); + if (debug != null) { + debug.println("RevocationChecker.verifyPossibleCRLs: " + + "Checking CRLDPs for " + + certImpl.getSubjectX500Principal()); + } + CRLDistributionPointsExtension ext = + certImpl.getCRLDistributionPointsExtension(); + List<DistributionPoint> points = null; + if (ext == null) { + // assume a DP with reasons and CRLIssuer fields omitted + // and a DP name of the cert issuer. + // TODO add issuerAltName too + X500Name certIssuer = (X500Name)certImpl.getIssuerDN(); + DistributionPoint point = new DistributionPoint( + new GeneralNames().add(new GeneralName(certIssuer)), + null, null); + points = Collections.singletonList(point); + } else { + points = ext.get(CRLDistributionPointsExtension.POINTS); + } + Set<X509CRL> results = new HashSet<>(); + for (DistributionPoint point : points) { + for (X509CRL crl : crls) { + if (DistributionPointFetcher.verifyCRL( + certImpl, point, crl, reasonsMask, signFlag, + prevKey, params.sigProvider(), anchors, + certStores, params.date())) + { + results.add(crl); + } + } + if (Arrays.equals(reasonsMask, ALL_REASONS)) + break; + } + return results; + } catch (CertificateException | CRLException | IOException e) { + if (debug != null) { + debug.println("Exception while verifying CRL: "+e.getMessage()); + e.printStackTrace(); + } + return Collections.emptySet(); + } + } + + /** + * We have a cert whose revocation status couldn't be verified by + * a CRL issued by the cert that issued the CRL. See if we can + * find a valid CRL issued by a separate key that can verify the + * revocation status of this certificate. + * <p> + * Note that this does not provide support for indirect CRLs, + * only CRLs signed with a different key (but the same issuer + * name) as the certificate being checked. + * + * @param currCert the <code>X509Certificate</code> to be checked + * @param prevKey the <code>PublicKey</code> that failed + * @param signFlag <code>true</code> if that key was trusted to sign CRLs + * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s> + * whose revocation status depends on the + * non-revoked status of this cert. To avoid + * circular dependencies, we assume they're + * revoked while checking the revocation + * status of this cert. + * @throws CertPathValidatorException if the cert's revocation status + * cannot be verified successfully with another key + */ + private void verifyWithSeparateSigningKey(X509Certificate cert, + PublicKey prevKey, + boolean signFlag, + Set<X509Certificate> stackedCerts) + throws CertPathValidatorException + { + String msg = "revocation status"; + if (debug != null) { + debug.println( + "RevocationChecker.verifyWithSeparateSigningKey()" + + " ---checking " + msg + "..."); + } + + // reject circular dependencies - RFC 3280 is not explicit on how + // to handle this, so we feel it is safest to reject them until + // the issue is resolved in the PKIX WG. + if ((stackedCerts != null) && stackedCerts.contains(cert)) { + if (debug != null) { + debug.println( + "RevocationChecker.verifyWithSeparateSigningKey()" + + " circular dependency"); + } + throw new CertPathValidatorException + ("Could not determine revocation status", null, null, + -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); + } + + // Try to find another key that might be able to sign + // CRLs vouching for this cert. + // If prevKey wasn't trusted, maybe we just didn't have the right + // path to it. Don't rule that key out. + if (!signFlag) { + buildToNewKey(cert, null, stackedCerts); + } else { + buildToNewKey(cert, prevKey, stackedCerts); + } + } + + /** + * Tries to find a CertPath that establishes a key that can be + * used to verify the revocation status of a given certificate. + * Ignores keys that have previously been tried. Throws a + * CertPathValidatorException if no such key could be found. + * + * @param currCert the <code>X509Certificate</code> to be checked + * @param prevKey the <code>PublicKey</code> of the certificate whose key + * cannot be used to vouch for the CRL and should be ignored + * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s> + * whose revocation status depends on the + * establishment of this path. + * @throws CertPathValidatorException on failure + */ + private static final boolean [] CRL_SIGN_USAGE = + { false, false, false, false, false, false, true }; + private void buildToNewKey(X509Certificate currCert, + PublicKey prevKey, + Set<X509Certificate> stackedCerts) + throws CertPathValidatorException + { + + if (debug != null) { + debug.println("RevocationChecker.buildToNewKey()" + + " starting work"); + } + Set<PublicKey> badKeys = new HashSet<>(); + if (prevKey != null) { + badKeys.add(prevKey); + } + X509CertSelector certSel = new RejectKeySelector(badKeys); + certSel.setSubject(currCert.getIssuerX500Principal()); + certSel.setKeyUsage(CRL_SIGN_USAGE); + + Set<TrustAnchor> newAnchors = anchor == null ? + params.trustAnchors() : + Collections.singleton(anchor); + + PKIXBuilderParameters builderParams; + try { + builderParams = new PKIXBuilderParameters(newAnchors, certSel); + } catch (InvalidAlgorithmParameterException iape) { + throw new RuntimeException(iape); // should never occur + } + builderParams.setInitialPolicies(params.initialPolicies()); + builderParams.setCertStores(certStores); + builderParams.setExplicitPolicyRequired + (params.explicitPolicyRequired()); + builderParams.setPolicyMappingInhibited + (params.policyMappingInhibited()); + builderParams.setAnyPolicyInhibited(params.anyPolicyInhibited()); + // Policy qualifiers must be rejected, since we don't have + // any way to convey them back to the application. + // That's the default, so no need to write code. + builderParams.setDate(params.date()); + // CertPathCheckers need to be cloned to start from fresh state + builderParams.setCertPathCheckers( + params.getPKIXParameters().getCertPathCheckers()); + builderParams.setSigProvider(params.sigProvider()); + + // Skip revocation during this build to detect circular + // references. But check revocation afterwards, using the + // key (or any other that works). + builderParams.setRevocationEnabled(false); + + // check for AuthorityInformationAccess extension + if (Builder.USE_AIA == true) { + X509CertImpl currCertImpl = null; + try { + currCertImpl = X509CertImpl.toImpl(currCert); + } catch (CertificateException ce) { + // ignore but log it + if (debug != null) { + debug.println("RevocationChecker.buildToNewKey: " + + "error decoding cert: " + ce); + } + } + AuthorityInfoAccessExtension aiaExt = null; + if (currCertImpl != null) { + aiaExt = currCertImpl.getAuthorityInfoAccessExtension(); + } + if (aiaExt != null) { + List<AccessDescription> adList = aiaExt.getAccessDescriptions(); + if (adList != null) { + for (AccessDescription ad : adList) { + CertStore cs = URICertStore.getInstance(ad); + if (cs != null) { + if (debug != null) { + debug.println("adding AIAext CertStore"); + } + builderParams.addCertStore(cs); + } + } + } + } + } + + CertPathBuilder builder = null; + try { + builder = CertPathBuilder.getInstance("PKIX"); + } catch (NoSuchAlgorithmException nsae) { + throw new CertPathValidatorException(nsae); + } + while (true) { + try { + if (debug != null) { + debug.println("RevocationChecker.buildToNewKey()" + + " about to try build ..."); + } + PKIXCertPathBuilderResult cpbr = + (PKIXCertPathBuilderResult)builder.build(builderParams); + + if (debug != null) { + debug.println("RevocationChecker.buildToNewKey()" + + " about to check revocation ..."); + } + // Now check revocation of all certs in path, assuming that + // the stackedCerts are revoked. + if (stackedCerts == null) { + stackedCerts = new HashSet<X509Certificate>(); + } + stackedCerts.add(currCert); + TrustAnchor ta = cpbr.getTrustAnchor(); + PublicKey prevKey2 = ta.getCAPublicKey(); + if (prevKey2 == null) { + prevKey2 = ta.getTrustedCert().getPublicKey(); + } + boolean signFlag = true; + List<? extends Certificate> cpList = + cpbr.getCertPath().getCertificates(); + try { + for (int i = cpList.size()-1; i >= 0; i-- ) { + X509Certificate cert = (X509Certificate)cpList.get(i); + + if (debug != null) { + debug.println("RevocationChecker.buildToNewKey()" + + " index " + i + " checking " + + cert); + } + checkCRLs(cert, prevKey2, signFlag, true, + stackedCerts, newAnchors); + signFlag = certCanSignCrl(cert); + prevKey2 = cert.getPublicKey(); + } + } catch (CertPathValidatorException cpve) { + // ignore it and try to get another key + badKeys.add(cpbr.getPublicKey()); + continue; + } + + if (debug != null) { + debug.println("RevocationChecker.buildToNewKey()" + + " got key " + cpbr.getPublicKey()); + } + // Now check revocation on the current cert using that key. + // If it doesn't check out, try to find a different key. + // And if we can't find a key, then return false. + PublicKey newKey = cpbr.getPublicKey(); + try { + checkCRLs(currCert, newKey, true, false, null, + params.trustAnchors()); + // If that passed, the cert is OK! + return; + } catch (CertPathValidatorException cpve) { + // If it is revoked, rethrow exception + if (cpve.getReason() == BasicReason.REVOKED) { + throw cpve; + } + // Otherwise, ignore the exception and + // try to get another key. + } + badKeys.add(newKey); + } catch (InvalidAlgorithmParameterException iape) { + throw new CertPathValidatorException(iape); + } catch (CertPathBuilderException cpbe) { + throw new CertPathValidatorException + ("Could not determine revocation status", null, null, + -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); + } + } + } + + /* + * This inner class extends the X509CertSelector to add an additional + * check to make sure the subject public key isn't on a particular list. + * This class is used by buildToNewKey() to make sure the builder doesn't + * end up with a CertPath to a public key that has already been rejected. + */ + private static class RejectKeySelector extends X509CertSelector { + private final Set<PublicKey> badKeySet; + + /** + * Creates a new <code>RejectKeySelector</code>. + * + * @param badPublicKeys a <code>Set</code> of + * <code>PublicKey</code>s that + * should be rejected (or <code>null</code> + * if no such check should be done) + */ + RejectKeySelector(Set<PublicKey> badPublicKeys) { + this.badKeySet = badPublicKeys; + } + + /** + * Decides whether a <code>Certificate</code> should be selected. + * + * @param cert the <code>Certificate</code> to be checked + * @return <code>true</code> if the <code>Certificate</code> should be + * selected, <code>false</code> otherwise + */ + @Override + public boolean match(Certificate cert) { + if (!super.match(cert)) + return(false); + + if (badKeySet.contains(cert.getPublicKey())) { + if (debug != null) + debug.println("RejectKeySelector.match: bad key"); + return false; + } + + if (debug != null) + debug.println("RejectKeySelector.match: returning true"); + return true; + } + + /** + * Return a printable representation of the <code>CertSelector</code>. + * + * @return a <code>String</code> describing the contents of the + * <code>CertSelector</code> + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("RejectKeySelector: [\n"); + sb.append(super.toString()); + sb.append(badKeySet); + sb.append("]"); + return sb.toString(); + } + } +} diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java --- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,10 +26,8 @@ package sun.security.provider.certpath; import java.io.IOException; -import java.security.AccessController; import java.security.GeneralSecurityException; import java.security.InvalidAlgorithmParameterException; -import java.security.Principal; import java.security.PublicKey; import java.security.cert.*; import java.security.cert.PKIXReason; @@ -37,7 +35,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -45,9 +42,8 @@ import java.util.Set; import javax.security.auth.x500.X500Principal; -import sun.security.action.GetBooleanSecurityPropertyAction; -import sun.security.x509.X500Name; -import sun.security.x509.PKIXExtensions; +import sun.security.provider.certpath.PKIX.BuilderParams; +import static sun.security.x509.PKIXExtensions.*; import sun.security.util.Debug; /** @@ -78,16 +74,12 @@ /* * private objects shared by methods */ - private PKIXBuilderParameters buildParams; + private BuilderParams buildParams; private CertificateFactory cf; private boolean pathCompleted = false; - private X500Principal targetSubjectDN; private PolicyNode policyTreeResult; private TrustAnchor trustAnchor; private PublicKey finalPublicKey; - private X509CertSelector targetSel; - private List<CertStore> orderedCertStores; - private boolean onlyEECert = false; /** * Create an instance of <code>SunCertPathBuilder</code>. @@ -100,9 +92,11 @@ } catch (CertificateException e) { throw new CertPathBuilderException(e); } - onlyEECert = AccessController.doPrivileged( - new GetBooleanSecurityPropertyAction - ("com.sun.security.onlyCheckRevocationOfEECert")); + } + + @Override + public CertPathChecker engineGetRevocationChecker() { + return new RevocationChecker(); } /** @@ -125,6 +119,7 @@ * @throws InvalidAlgorithmParameterException if the given parameters are * inappropriate for this certification path builder. */ + @Override public CertPathBuilderResult engineBuild(CertPathParameters params) throws CertPathBuilderException, InvalidAlgorithmParameterException { @@ -132,66 +127,20 @@ debug.println("SunCertPathBuilder.engineBuild(" + params + ")"); } - if (!(params instanceof PKIXBuilderParameters)) { - throw new InvalidAlgorithmParameterException("inappropriate " + - "parameter type, must be an instance of PKIXBuilderParameters"); - } - - boolean buildForward = true; - if (params instanceof SunCertPathBuilderParameters) { - buildForward = - ((SunCertPathBuilderParameters)params).getBuildForward(); - } - - buildParams = (PKIXBuilderParameters)params; - - /* Check mandatory parameters */ - - // Make sure that none of the trust anchors include name constraints - // (not supported). - for (TrustAnchor anchor : buildParams.getTrustAnchors()) { - if (anchor.getNameConstraints() != null) { - throw new InvalidAlgorithmParameterException - ("name constraints in trust anchor not supported"); - } - } + buildParams = PKIX.checkBuilderParams(params); + return build(); + } - CertSelector sel = buildParams.getTargetCertConstraints(); - if (!(sel instanceof X509CertSelector)) { - throw new InvalidAlgorithmParameterException("the " - + "targetCertConstraints parameter must be an " - + "X509CertSelector"); - } - targetSel = (X509CertSelector)sel; - targetSubjectDN = targetSel.getSubject(); - if (targetSubjectDN == null) { - X509Certificate targetCert = targetSel.getCertificate(); - if (targetCert != null) { - targetSubjectDN = targetCert.getSubjectX500Principal(); - } - } - // reorder CertStores so that local CertStores are tried first - orderedCertStores = - new ArrayList<CertStore>(buildParams.getCertStores()); - Collections.sort(orderedCertStores, new CertStoreComparator()); - if (targetSubjectDN == null) { - targetSubjectDN = getTargetSubjectDN(orderedCertStores, targetSel); - } - if (targetSubjectDN == null) { - throw new InvalidAlgorithmParameterException - ("Could not determine unique target subject"); - } - - List<List<Vertex>> adjList = new ArrayList<List<Vertex>>(); - CertPathBuilderResult result = - buildCertPath(buildForward, false, adjList); + private PKIXCertPathBuilderResult build() throws CertPathBuilderException { + List<List<Vertex>> adjList = new ArrayList<>(); + PKIXCertPathBuilderResult result = buildCertPath(false, adjList); if (result == null) { if (debug != null) { debug.println("SunCertPathBuilder.engineBuild: 2nd pass"); } // try again adjList.clear(); - result = buildCertPath(buildForward, true, adjList); + result = buildCertPath(true, adjList); if (result == null) { throw new SunCertPathBuilderException("unable to find valid " + "certification path to requested target", @@ -201,24 +150,23 @@ return result; } - private CertPathBuilderResult buildCertPath(boolean buildForward, - boolean searchAllCertStores, List<List<Vertex>> adjList) - throws CertPathBuilderException { - + private PKIXCertPathBuilderResult buildCertPath(boolean searchAllCertStores, + List<List<Vertex>> adjList) + throws CertPathBuilderException + { // Init shared variables and build certification path pathCompleted = false; trustAnchor = null; finalPublicKey = null; policyTreeResult = null; - LinkedList<X509Certificate> certPathList = - new LinkedList<X509Certificate>(); + LinkedList<X509Certificate> certPathList = new LinkedList<>(); try { - if (buildForward) { + if (buildParams.buildForward()) { buildForward(adjList, certPathList, searchAllCertStores); } else { buildReverse(adjList, certPathList); } - } catch (Exception e) { + } catch (GeneralSecurityException | IOException e) { if (debug != null) { debug.println("SunCertPathBuilder.engineBuild() exception in " + "build"); @@ -242,11 +190,11 @@ Collections.reverse(certPathList); return new SunCertPathBuilderResult( - cf.generateCertPath(certPathList), this.trustAnchor, + cf.generateCertPath(certPathList), trustAnchor, policyTreeResult, finalPublicKey, new AdjacencyList(adjList)); } - } catch (Exception e) { + } catch (CertificateException e) { if (debug != null) { debug.println("SunCertPathBuilder.engineBuild() exception " + "in wrap-up"); @@ -264,12 +212,13 @@ * Private build reverse method. */ private void buildReverse(List<List<Vertex>> adjacencyList, - LinkedList<X509Certificate> certPathList) throws Exception + LinkedList<X509Certificate> certPathList) + throws GeneralSecurityException, IOException { if (debug != null) { debug.println("SunCertPathBuilder.buildReverse()..."); debug.println("SunCertPathBuilder.buildReverse() InitialPolicies: " - + buildParams.getInitialPolicies()); + + buildParams.initialPolicies()); } ReverseState currentState = new ReverseState(); @@ -281,11 +230,11 @@ * Perform a search using each trust anchor, until a valid * path is found */ - Iterator<TrustAnchor> iter = buildParams.getTrustAnchors().iterator(); + Iterator<TrustAnchor> iter = buildParams.trustAnchors().iterator(); while (iter.hasNext()) { TrustAnchor anchor = iter.next(); /* check if anchor satisfies target constraints */ - if (anchorIsTarget(anchor, targetSel)) { + if (anchorIsTarget(anchor, buildParams.targetCertConstraints())) { this.trustAnchor = anchor; this.pathCompleted = true; this.finalPublicKey = anchor.getTrustedCert().getPublicKey(); @@ -293,21 +242,15 @@ } /* Initialize current state */ - currentState.initState(buildParams.getMaxPathLength(), - buildParams.isExplicitPolicyRequired(), - buildParams.isPolicyMappingInhibited(), - buildParams.isAnyPolicyInhibited(), - buildParams.getCertPathCheckers()); - currentState.updateState(anchor); - // init the crl checker - currentState.crlChecker = - new CrlRevocationChecker(null, buildParams, null, onlyEECert); + currentState.initState(buildParams); + currentState.updateState(anchor, buildParams); + currentState.algorithmChecker = new AlgorithmChecker(anchor); try { depthFirstSearchReverse(null, currentState, - new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList, - certPathList); - } catch (Exception e) { + new ReverseBuilder(buildParams), + adjacencyList, certPathList); + } catch (GeneralSecurityException | IOException e) { // continue on error if more anchors to try if (iter.hasNext()) continue; @@ -331,7 +274,8 @@ * Private build forward method. */ private void buildForward(List<List<Vertex>> adjacencyList, - LinkedList<X509Certificate> certPathList, boolean searchAllCertStores) + LinkedList<X509Certificate> certPathList, + boolean searchAllCertStores) throws GeneralSecurityException, IOException { if (debug != null) { @@ -340,20 +284,16 @@ /* Initialize current state */ ForwardState currentState = new ForwardState(); - currentState.initState(buildParams.getCertPathCheckers()); + currentState.initState(buildParams.certPathCheckers()); /* Initialize adjacency list */ adjacencyList.clear(); adjacencyList.add(new LinkedList<Vertex>()); - // init the crl checker - currentState.crlChecker - = new CrlRevocationChecker(null, buildParams, null, onlyEECert); - - depthFirstSearchForward(targetSubjectDN, currentState, - new ForwardBuilder - (buildParams, targetSubjectDN, searchAllCertStores, onlyEECert), - adjacencyList, certPathList); + depthFirstSearchForward(buildParams.targetSubject(), currentState, + new ForwardBuilder(buildParams, + searchAllCertStores), + adjacencyList, certPathList); } /* @@ -371,27 +311,28 @@ * @param dN the distinguished name being currently searched for certs * @param currentState the current PKIX validation state */ - void depthFirstSearchForward(X500Principal dN, ForwardState currentState, - ForwardBuilder builder, List<List<Vertex>> adjList, - LinkedList<X509Certificate> certPathList) + private void depthFirstSearchForward(X500Principal dN, + ForwardState currentState, + ForwardBuilder builder, + List<List<Vertex>> adjList, + LinkedList<X509Certificate> cpList) throws GeneralSecurityException, IOException { - //XXX This method should probably catch & handle exceptions - if (debug != null) { debug.println("SunCertPathBuilder.depthFirstSearchForward(" + dN - + ", " + currentState.toString() + ")"); + + ", " + currentState.toString() + ")"); } /* * Find all the certificates issued to dN which * satisfy the PKIX certification path constraints. */ - List<Vertex> vertices = addVertices - (builder.getMatchingCerts(currentState, orderedCertStores), adjList); + Collection<X509Certificate> certs = + builder.getMatchingCerts(currentState, buildParams.certStores()); + List<Vertex> vertices = addVertices(certs, adjList); if (debug != null) { debug.println("SunCertPathBuilder.depthFirstSearchForward(): " - + "certs.size=" + vertices.size()); + + "certs.size=" + vertices.size()); } /* @@ -411,14 +352,14 @@ * the next matching cert is tried. */ ForwardState nextState = (ForwardState) currentState.clone(); - X509Certificate cert = (X509Certificate) vertex.getCertificate(); + X509Certificate cert = vertex.getCertificate(); try { - builder.verifyCert(cert, nextState, certPathList); + builder.verifyCert(cert, nextState, cpList); } catch (GeneralSecurityException gse) { if (debug != null) { debug.println("SunCertPathBuilder.depthFirstSearchForward()" - + ": validation failed: " + gse); + + ": validation failed: " + gse); gse.printStackTrace(); } vertex.setThrowable(gse); @@ -436,51 +377,44 @@ */ if (builder.isPathCompleted(cert)) { - BasicChecker basicChecker = null; if (debug != null) debug.println("SunCertPathBuilder.depthFirstSearchForward()" - + ": commencing final verification"); + + ": commencing final verification"); - ArrayList<X509Certificate> appendedCerts = - new ArrayList<X509Certificate>(certPathList); + List<X509Certificate> appendedCerts = new ArrayList<>(cpList); /* * if the trust anchor selected is specified as a trusted * public key rather than a trusted cert, then verify this * cert (which is signed by the trusted public key), but - * don't add it yet to the certPathList + * don't add it yet to the cpList */ if (builder.trustAnchor.getTrustedCert() == null) { appendedCerts.add(0, cert); } - HashSet<String> initExpPolSet = new HashSet<String>(1); - initExpPolSet.add(PolicyChecker.ANY_POLICY); + Set<String> initExpPolSet = + Collections.singleton(PolicyChecker.ANY_POLICY); PolicyNodeImpl rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false); + List<PKIXCertPathChecker> checkers = new ArrayList<>(); PolicyChecker policyChecker - = new PolicyChecker(buildParams.getInitialPolicies(), - appendedCerts.size(), - buildParams.isExplicitPolicyRequired(), - buildParams.isPolicyMappingInhibited(), - buildParams.isAnyPolicyInhibited(), - buildParams.getPolicyQualifiersRejected(), - rootNode); + = new PolicyChecker(buildParams.initialPolicies(), + appendedCerts.size(), + buildParams.explicitPolicyRequired(), + buildParams.policyMappingInhibited(), + buildParams.anyPolicyInhibited(), + buildParams.policyQualifiersRejected(), + rootNode); - List<PKIXCertPathChecker> userCheckers = new - ArrayList<PKIXCertPathChecker> - (buildParams.getCertPathCheckers()); - int mustCheck = 0; - userCheckers.add(mustCheck, policyChecker); - mustCheck++; + checkers.add(policyChecker); // add the algorithm checker - userCheckers.add(mustCheck, - new AlgorithmChecker(builder.trustAnchor)); - mustCheck++; + checkers.add(new AlgorithmChecker(builder.trustAnchor)); + BasicChecker basicChecker = null; if (nextState.keyParamsNeeded()) { PublicKey rootKey = cert.getPublicKey(); if (builder.trustAnchor.getTrustedCert() == null) { @@ -495,24 +429,38 @@ (cert.getSubjectX500Principal(), rootKey, null); // add the basic checker - basicChecker = new BasicChecker(anchor, - builder.date, - buildParams.getSigProvider(), - true); - userCheckers.add(mustCheck, basicChecker); - mustCheck++; + basicChecker = new BasicChecker(anchor, buildParams.date(), + buildParams.sigProvider(), + true); + checkers.add(basicChecker); + } + + buildParams.setCertPath(cf.generateCertPath(appendedCerts)); - // add the crl revocation checker - if (buildParams.isRevocationEnabled()) { - userCheckers.add(mustCheck, new CrlRevocationChecker - (anchor, buildParams, null, onlyEECert)); - mustCheck++; + boolean revCheckerAdded = false; + List<PKIXCertPathChecker> ckrs = buildParams.certPathCheckers(); + for (PKIXCertPathChecker ckr : ckrs) { + if (ckr instanceof PKIXRevocationChecker) { + revCheckerAdded = true; + // if it's our own, initialize it + if (ckr instanceof RevocationChecker) + ((RevocationChecker)ckr).init(builder.trustAnchor, + buildParams); } } - // Why we don't need BasicChecker and CrlRevocationChecker + // only add a RevocationChecker if revocation is enabled and + // a PKIXRevocationChecker has not already been added + if (buildParams.revocationEnabled() && !revCheckerAdded) { + checkers.add(new RevocationChecker(builder.trustAnchor, + buildParams)); + } + + checkers.addAll(ckrs); + + // Why we don't need BasicChecker and RevocationChecker // if nextState.keyParamsNeeded() is false? - for (int i=0; i<appendedCerts.size(); i++) { + for (int i = 0; i < appendedCerts.size(); i++) { X509Certificate currCert = appendedCerts.get(i); if (debug != null) debug.println("current subject = " @@ -523,18 +471,15 @@ unresCritExts = Collections.<String>emptySet(); } - for (int j=0; j<userCheckers.size(); j++) { - PKIXCertPathChecker currChecker = userCheckers.get(j); - if (j < mustCheck || - !currChecker.isForwardCheckingSupported()) { + for (PKIXCertPathChecker currChecker : checkers) { + if (!currChecker.isForwardCheckingSupported()) { if (i == 0) { currChecker.init(false); // The user specified // AlgorithmChecker may not be // able to set the trust anchor until now. - if (j >= mustCheck && - currChecker instanceof AlgorithmChecker) { + if (currChecker instanceof AlgorithmChecker) { ((AlgorithmChecker)currChecker). trySetTrustAnchor(builder.trustAnchor); } @@ -560,7 +505,7 @@ * are capable of processing. */ for (PKIXCertPathChecker checker : - buildParams.getCertPathCheckers()) + buildParams.certPathCheckers()) { if (checker.isForwardCheckingSupported()) { Set<String> suppExts = @@ -572,24 +517,16 @@ } if (!unresCritExts.isEmpty()) { - unresCritExts.remove - (PKIXExtensions.BasicConstraints_Id.toString()); - unresCritExts.remove - (PKIXExtensions.NameConstraints_Id.toString()); - unresCritExts.remove - (PKIXExtensions.CertificatePolicies_Id.toString()); - unresCritExts.remove - (PKIXExtensions.PolicyMappings_Id.toString()); - unresCritExts.remove - (PKIXExtensions.PolicyConstraints_Id.toString()); - unresCritExts.remove - (PKIXExtensions.InhibitAnyPolicy_Id.toString()); - unresCritExts.remove(PKIXExtensions. + unresCritExts.remove(BasicConstraints_Id.toString()); + unresCritExts.remove(NameConstraints_Id.toString()); + unresCritExts.remove(CertificatePolicies_Id.toString()); + unresCritExts.remove(PolicyMappings_Id.toString()); + unresCritExts.remove(PolicyConstraints_Id.toString()); + unresCritExts.remove(InhibitAnyPolicy_Id.toString()); + unresCritExts.remove( SubjectAlternativeName_Id.toString()); - unresCritExts.remove - (PKIXExtensions.KeyUsage_Id.toString()); - unresCritExts.remove - (PKIXExtensions.ExtendedKeyUsage_Id.toString()); + unresCritExts.remove(KeyUsage_Id.toString()); + unresCritExts.remove(ExtendedKeyUsage_Id.toString()); if (!unresCritExts.isEmpty()) { throw new CertPathValidatorException @@ -606,10 +543,10 @@ /* * if the user specified a trusted public key rather than * trusted certs, then add this cert (which is signed by - * the trusted public key) to the certPathList + * the trusted public key) to the cpList */ if (builder.trustAnchor.getTrustedCert() == null) - builder.addCertToPath(cert, certPathList); + builder.addCertToPath(cert, cpList); // Save the trust anchor this.trustAnchor = builder.trustAnchor; @@ -620,10 +557,10 @@ finalPublicKey = basicChecker.getPublicKey(); } else { Certificate finalCert; - if (certPathList.size() == 0) { + if (cpList.isEmpty()) { finalCert = builder.trustAnchor.getTrustedCert(); } else { - finalCert = certPathList.get(certPathList.size()-1); + finalCert = cpList.getLast(); } finalPublicKey = finalCert.getPublicKey(); } @@ -631,7 +568,7 @@ policyTreeResult = policyChecker.getPolicyTree(); return; } else { - builder.addCertToPath(cert, certPathList); + builder.addCertToPath(cert, cpList); } /* Update the PKIX state */ @@ -645,8 +582,8 @@ vertex.setIndex(adjList.size() - 1); /* recursively search for matching certs at next dN */ - depthFirstSearchForward(cert.getIssuerX500Principal(), nextState, builder, - adjList, certPathList); + depthFirstSearchForward(cert.getIssuerX500Principal(), nextState, + builder, adjList, cpList); /* * If path has been completed, return ASAP! @@ -662,8 +599,8 @@ */ if (debug != null) debug.println("SunCertPathBuilder.depthFirstSearchForward()" - + ": backtracking"); - builder.removeFinalCertFromPath(certPathList); + + ": backtracking"); + builder.removeFinalCertFromPath(cpList); } } } @@ -683,9 +620,11 @@ * @param dN the distinguished name being currently searched for certs * @param currentState the current PKIX validation state */ - void depthFirstSearchReverse(X500Principal dN, ReverseState currentState, - ReverseBuilder builder, List<List<Vertex>> adjList, - LinkedList<X509Certificate> certPathList) + private void depthFirstSearchReverse(X500Principal dN, + ReverseState currentState, + ReverseBuilder builder, + List<List<Vertex>> adjList, + LinkedList<X509Certificate> cpList) throws GeneralSecurityException, IOException { if (debug != null) @@ -696,8 +635,9 @@ * Find all the certificates issued by dN which * satisfy the PKIX certification path constraints. */ - List<Vertex> vertices = addVertices - (builder.getMatchingCerts(currentState, orderedCertStores), adjList); + Collection<X509Certificate> certs = + builder.getMatchingCerts(currentState, buildParams.certStores()); + List<Vertex> vertices = addVertices(certs, adjList); if (debug != null) debug.println("SunCertPathBuilder.depthFirstSearchReverse(): " + "certs.size=" + vertices.size()); @@ -717,9 +657,9 @@ * the next matching cert is tried. */ ReverseState nextState = (ReverseState) currentState.clone(); - X509Certificate cert = (X509Certificate) vertex.getCertificate(); + X509Certificate cert = vertex.getCertificate(); try { - builder.verifyCert(cert, nextState, certPathList); + builder.verifyCert(cert, nextState, cpList); } catch (GeneralSecurityException gse) { if (debug != null) debug.println("SunCertPathBuilder.depthFirstSearchReverse()" @@ -733,7 +673,7 @@ * self-signed cert) and update state */ if (!currentState.isInitial()) - builder.addCertToPath(cert, certPathList); + builder.addCertToPath(cert, cpList); // save trust anchor this.trustAnchor = currentState.trustAnchor; @@ -782,7 +722,7 @@ /* recursively search for matching certs at next dN */ depthFirstSearchReverse(cert.getSubjectX500Principal(), nextState, - builder, adjList, certPathList); + builder, adjList, cpList); /* * If path has been completed, return ASAP! @@ -800,7 +740,7 @@ debug.println("SunCertPathBuilder.depthFirstSearchReverse()" + ": backtracking"); if (!currentState.isInitial()) - builder.removeFinalCertFromPath(certPathList); + builder.removeFinalCertFromPath(cpList); } } if (debug != null) @@ -812,13 +752,14 @@ * Adds a collection of matching certificates to the * adjacency list. */ - private List<Vertex> addVertices(Collection<X509Certificate> certs, - List<List<Vertex>> adjList) { + private static List<Vertex> addVertices(Collection<X509Certificate> certs, + List<List<Vertex>> adjList) + { List<Vertex> l = adjList.get(adjList.size() - 1); for (X509Certificate cert : certs) { - Vertex v = new Vertex(cert); - l.add(v); + Vertex v = new Vertex(cert); + l.add(v); } return l; @@ -828,53 +769,13 @@ * Returns true if trust anchor certificate matches specified * certificate constraints. */ - private boolean anchorIsTarget(TrustAnchor anchor, X509CertSelector sel) { + private static boolean anchorIsTarget(TrustAnchor anchor, + CertSelector sel) + { X509Certificate anchorCert = anchor.getTrustedCert(); if (anchorCert != null) { return sel.match(anchorCert); } return false; } - - /** - * Comparator that orders CertStores so that local CertStores come before - * remote CertStores. - */ - private static class CertStoreComparator implements Comparator<CertStore> { - public int compare(CertStore store1, CertStore store2) { - if (Builder.isLocalCertStore(store1)) { - return -1; - } else { - return 1; - } - } - } - - /** - * Returns the target subject DN from the first X509Certificate that - * is fetched that matches the specified X509CertSelector. - */ - private X500Principal getTargetSubjectDN(List<CertStore> stores, - X509CertSelector targetSel) { - for (CertStore store : stores) { - try { - Collection<? extends Certificate> targetCerts = - (Collection<? extends Certificate>) - store.getCertificates(targetSel); - if (!targetCerts.isEmpty()) { - X509Certificate targetCert = - (X509Certificate)targetCerts.iterator().next(); - return targetCert.getSubjectX500Principal(); - } - } catch (CertStoreException e) { - // ignore but log it - if (debug != null) { - debug.println("SunCertPathBuilder.getTargetSubjectDN: " + - "non-fatal exception retrieving certs: " + e); - e.printStackTrace(); - } - } - } - return null; - } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java --- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,12 +25,11 @@ package sun.security.provider.certpath; -import java.util.Set; - import java.security.InvalidAlgorithmParameterException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.cert.*; +import java.util.Set; /** * This class specifies the set of parameters used as input for the Sun @@ -120,8 +119,9 @@ * * @return a formatted string describing the parameters. */ + @Override public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("[\n"); sb.append(super.toString()); sb.append(" Build Forward Flag: " + String.valueOf(buildForward) + "\n"); diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java --- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2012, 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 @@ -213,6 +213,7 @@ * match the specified selector * @throws CertStoreException if an exception occurs */ + @Override @SuppressWarnings("unchecked") public synchronized Collection<X509Certificate> engineGetCertificates (CertSelector selector) throws CertStoreException { @@ -322,6 +323,7 @@ * match the specified selector * @throws CertStoreException if an exception occurs */ + @Override @SuppressWarnings("unchecked") public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector) throws CertStoreException { @@ -418,14 +420,14 @@ URICertStoreParameters(URI uri) { this.uri = uri; } - public boolean equals(Object obj) { + @Override public boolean equals(Object obj) { if (!(obj instanceof URICertStoreParameters)) { return false; } URICertStoreParameters params = (URICertStoreParameters) obj; return uri.equals(params.uri); } - public int hashCode() { + @Override public int hashCode() { if (hashCode == 0) { int result = 17; result = 37*result + uri.hashCode(); @@ -433,7 +435,7 @@ } return hashCode; } - public Object clone() { + @Override public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/Vertex.java --- a/jdk/src/share/classes/sun/security/provider/certpath/Vertex.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/Vertex.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,12 +25,11 @@ package sun.security.provider.certpath; -import sun.security.util.Debug; - -import java.security.cert.Certificate; +import java.io.IOException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import sun.security.util.Debug; import sun.security.x509.AuthorityKeyIdentifierExtension; import sun.security.x509.KeyIdentifier; import sun.security.x509.SubjectKeyIdentifierExtension; @@ -50,17 +49,17 @@ public class Vertex { private static final Debug debug = Debug.getInstance("certpath"); - private Certificate cert; - private int index; - private Throwable throwable; + private X509Certificate cert; + private int index; + private Throwable throwable; /** * Constructor; creates vertex with index of -1 * Use setIndex method to set another index. * - * @param cert Certificate associated with vertex + * @param cert X509Certificate associated with vertex */ - Vertex(Certificate cert) { + Vertex(X509Certificate cert) { this.cert = cert; this.index = -1; } @@ -68,9 +67,9 @@ /** * return the certificate for this vertex * - * @returns Certificate + * @returns X509Certificate */ - public Certificate getCertificate() { + public X509Certificate getCertificate() { return cert; } @@ -121,6 +120,7 @@ * * @returns String representation of vertex */ + @Override public String toString() { return certToString() + throwableToString() + indexToString(); } @@ -132,70 +132,65 @@ * @returns String representation of certificate info */ public String certToString() { - String out = ""; - if (cert == null || ! (cert instanceof X509Certificate)) - return "Cert: Not an X509Certificate\n"; + StringBuilder sb = new StringBuilder(); X509CertImpl x509Cert = null; try { - x509Cert = X509CertImpl.toImpl((X509Certificate)cert); + x509Cert = X509CertImpl.toImpl(cert); } catch (CertificateException ce) { if (debug != null) { debug.println("Vertex.certToString() unexpected exception"); ce.printStackTrace(); } - return out; + return sb.toString(); } - out = "Issuer: " + x509Cert.getIssuerX500Principal() + "\n"; - out = out + "Subject: " + x509Cert.getSubjectX500Principal() + "\n"; - out = out + "SerialNum: " + (x509Cert.getSerialNumber()).toString(16) + "\n"; - out = out + "Expires: " + x509Cert.getNotAfter().toString() + "\n"; + sb.append("Issuer: ").append + (x509Cert.getIssuerX500Principal()).append("\n"); + sb.append("Subject: ").append + (x509Cert.getSubjectX500Principal()).append("\n"); + sb.append("SerialNum: ").append + (x509Cert.getSerialNumber().toString(16)).append("\n"); + sb.append("Expires: ").append + (x509Cert.getNotAfter().toString()).append("\n"); boolean[] iUID = x509Cert.getIssuerUniqueID(); if (iUID != null) { - out = out + "IssuerUID: "; - for (int i=0; i < iUID.length; i++) { - out = out + (iUID[i]?1:0); + sb.append("IssuerUID: "); + for (boolean b : iUID) { + sb.append(b ? 1 : 0); } - out = out + "\n"; + sb.append("\n"); } boolean[] sUID = x509Cert.getSubjectUniqueID(); if (sUID != null) { - out = out + "SubjectUID: "; - for (int i=0; i< sUID.length; i++) { - out = out + (sUID[i]?1:0); + sb.append("SubjectUID: "); + for (boolean b : sUID) { + sb.append(b ? 1 : 0); } - out = out + "\n"; + sb.append("\n"); } - SubjectKeyIdentifierExtension sKeyID = null; try { - sKeyID = x509Cert.getSubjectKeyIdentifierExtension(); + SubjectKeyIdentifierExtension sKeyID = + x509Cert.getSubjectKeyIdentifierExtension(); if (sKeyID != null) { KeyIdentifier keyID = sKeyID.get( SubjectKeyIdentifierExtension.KEY_ID); - out = out + "SubjKeyID: " + keyID.toString(); + sb.append("SubjKeyID: ").append(keyID.toString()); } - } catch (Exception e) { + AuthorityKeyIdentifierExtension aKeyID = + x509Cert.getAuthorityKeyIdentifierExtension(); + if (aKeyID != null) { + KeyIdentifier keyID = (KeyIdentifier)aKeyID.get( + AuthorityKeyIdentifierExtension.KEY_ID); + sb.append("AuthKeyID: ").append(keyID.toString()); + } + } catch (IOException e) { if (debug != null) { debug.println("Vertex.certToString() unexpected exception"); e.printStackTrace(); } } - AuthorityKeyIdentifierExtension aKeyID = null; - try { - aKeyID = x509Cert.getAuthorityKeyIdentifierExtension(); - if (aKeyID != null) { - KeyIdentifier keyID = (KeyIdentifier)aKeyID.get( - AuthorityKeyIdentifierExtension.KEY_ID); - out = out + "AuthKeyID: " + keyID.toString(); - } - } catch (Exception e) { - if (debug != null) { - debug.println("Vertex.certToString() 2 unexpected exception"); - e.printStackTrace(); - } - } - return out; + return sb.toString(); } /** @@ -205,13 +200,13 @@ * @returns String form of exception (or "none") */ public String throwableToString() { - String out = "Exception: "; + StringBuilder sb = new StringBuilder("Exception: "); if (throwable != null) - out = out + throwable.toString(); + sb.append(throwable.toString()); else - out = out + "null"; - out = out + "\n"; - return out; + sb.append("null"); + sb.append("\n"); + return sb.toString(); } /** @@ -222,10 +217,10 @@ * @returns String form of index as "Last cert? [Yes/No] */ public String moreToString() { - String out = "Last cert? "; - out = out + ((index == -1)?"Yes":"No"); - out = out + "\n"; - return out; + StringBuilder sb = new StringBuilder("Last cert? "); + sb.append((index == -1) ? "Yes" : "No"); + sb.append("\n"); + return sb.toString(); } /** @@ -235,7 +230,6 @@ * @returns String form of index as "Index: [numeric index]" */ public String indexToString() { - String out = "Index: " + index + "\n"; - return out; + return "Index: " + index + "\n"; } } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java --- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -33,9 +33,10 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; +import java.security.cert.CertPath; import java.security.cert.X509Certificate; import java.util.*; -import java.security.cert.CertPath; + import sun.security.pkcs.ContentInfo; import sun.security.pkcs.PKCS7; import sun.security.pkcs.SignerInfo; @@ -44,7 +45,6 @@ import sun.security.util.DerOutputStream; import sun.security.util.DerInputStream; - /** * A {@link java.security.cert.CertPath CertPath} (certification path) * consisting exclusively of @@ -83,7 +83,7 @@ private static final Collection<String> encodingList; static { - List<String> list = new ArrayList<String>(2); + List<String> list = new ArrayList<>(2); list.add(PKIPATH_ENCODING); list.add(PKCS7_ENCODING); encodingList = Collections.unmodifiableCollection(list); @@ -272,6 +272,7 @@ * @return the encoded bytes * @exception CertificateEncodingException if an encoding error occurs */ + @Override public byte[] getEncoded() throws CertificateEncodingException { // @@@ Should cache the encoded form return encodePKIPATH(); @@ -342,6 +343,7 @@ * @exception CertificateEncodingException if an encoding error occurs or * the encoding requested is not supported */ + @Override public byte[] getEncoded(String encoding) throws CertificateEncodingException { switch (encoding) { @@ -376,6 +378,7 @@ * @return an <code>Iterator</code> over the names of the supported * encodings (as Strings) */ + @Override public Iterator<String> getEncodings() { return getEncodingsStatic(); } @@ -387,6 +390,7 @@ * @return an immutable <code>List</code> of <code>X509Certificate</code>s * (may be empty, but not null) */ + @Override public List<X509Certificate> getCertificates() { return certs; } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java --- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java Wed May 30 17:19:46 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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 @@ -207,13 +207,14 @@ * * @return A String describing the contents of the pair. */ + @Override public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("X.509 Certificate Pair: [\n"); if (forward != null) - sb.append(" Forward: " + forward + "\n"); + sb.append(" Forward: ").append(forward).append("\n"); if (reverse != null) - sb.append(" Reverse: " + reverse + "\n"); + sb.append(" Reverse: ").append(reverse).append("\n"); sb.append("]"); return sb.toString(); } diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java --- a/jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java Mon Jan 23 04:44:16 2012 -0800 +++ b/jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java Wed May 30 17:19:46 2012 -0400 @@ -31,6 +31,7 @@ import java.security.cert.X509CRLEntry; import java.math.BigInteger; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; @@ -500,6 +501,9 @@ } public Map<String, java.security.cert.Extension> getExtensions() { + if (extensions == null) { + return Collections.emptyMap(); + } Collection<Extension> exts = extensions.getAllExtensions(); HashMap<String, java.security.cert.Extension> map = new HashMap<String, java.security.cert.Extension>(exts.size()); diff -r 5fe35861f07e -r 9ffbd4e43413 jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java Wed May 30 17:19:46 2012 -0400 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2012, 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 6854712 + * @summary Basic unit test for PKIXRevocationChecker + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import java.security.cert.CertificateFactory; +import java.security.cert.CertPathChecker; +import java.security.cert.CertPathValidator; +import java.security.cert.Extension; +import java.security.cert.PKIXRevocationChecker; +import java.security.cert.PKIXRevocationChecker.Option; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class UnitTest { + + public static void main(String[] args) throws Exception { + + CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); + CertPathChecker cpc = cpv.getRevocationChecker(); + PKIXRevocationChecker prc = (PKIXRevocationChecker)cpc; + + System.out.println("Testing that get methods return null or " + + "empty lists/sets/maps"); + requireNull(prc.getOCSPResponder(), "getOCSPResponder()"); + requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()"); + requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()"); + requireEmpty(prc.getOCSPStapledResponses(), + "getOCSPStapledResponses()"); + requireEmpty(prc.getOptions(), "getOptions()"); + + System.out.println("Testing that get methods return same parameters " + + "that are passed to set methods"); + URI uri = new URI("http://localhost"); + prc.setOCSPResponder(uri); + requireEquals(uri, prc.getOCSPResponder(), "getOCSPResponder()"); + + X509Certificate cert = getCert(); + prc.setOCSPResponderCert(cert); + requireEquals(cert, prc.getOCSPResponderCert(), + "getOCSPResponderCert()"); + + List<Extension> exts = new ArrayList<>(); + for (String oid : cert.getNonCriticalExtensionOIDs()) { + System.out.println(oid); + exts.add(new ExtensionImpl(oid, + cert.getExtensionValue(oid), false)); + } + prc.setOCSPExtensions(exts); + requireEquals(exts, prc.getOCSPExtensions(), "getOCSPExtensions()"); + + Set<Option> options = EnumSet.of(Option.ONLY_END_ENTITY); + prc.setOptions(options); + requireEquals(options, prc.getOptions(), "getOptions()"); + + System.out.println("Testing that parameters are re-initialized to " + + "default values if null is passed to set methods"); + prc.setOCSPResponder(null); + requireNull(prc.getOCSPResponder(), "getOCSPResponder()"); + prc.setOCSPResponderCert(null); + requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()"); + prc.setOCSPExtensions(null); + requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()"); + prc.setOCSPStapledResponses(null); + requireEmpty(prc.getOCSPStapledResponses(), + "getOCSPStapledResponses()"); + prc.setOptions(null); + requireEmpty(prc.getOptions(), "getOptions()"); + } + + static void requireNull(Object o, String msg) throws Exception { + if (o != null) { + throw new Exception("FAILED: " + msg + " must return null"); + } + } + + static void requireEmpty(Map<?,?> m, String msg) throws Exception { + if (!m.isEmpty()) { + throw new Exception("FAILED: " + msg + " must return an empty map"); + } + } + + static void requireEmpty(List<?> l, String msg) throws Exception { + if (!l.isEmpty()) { + throw new Exception("FAILED: " + msg +" must return an empty list"); + } + } + + static void requireEmpty(Set<?> s, String msg) throws Exception { + if (!s.isEmpty()) { + throw new Exception("FAILED: " + msg + " must return an empty set"); + } + } + + static void requireEquals(Object a, Object b, String msg) throws Exception { + if (!a.equals(b)) { + throw new Exception("FAILED: " + msg + " does not return the " + + "same object that was set"); + } + } + + static X509Certificate getCert() throws Exception { + String b64 = + "-----BEGIN CERTIFICATE-----\n" + + "MIIBLTCB2KADAgECAgEDMA0GCSqGSIb3DQEBBAUAMA0xCzAJBgNVBAMTAkNBMB4X\n" + + "DTAyMTEwNzExNTcwM1oXDTIyMTEwNzExNTcwM1owFTETMBEGA1UEAxMKRW5kIEVu\n" + + "dGl0eTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDVBDfF+uBr5s5jzzDs1njKlZNt\n" + + "h8hHzEt3ASh67Peos+QrDzgpUyFXT6fdW2h7iPf0ifjM8eW2xa+3EnPjjU5jAgMB\n" + + "AAGjGzAZMBcGA1UdIAQQMA4wBgYEVR0gADAEBgIqADANBgkqhkiG9w0BAQQFAANB\n" + + "AFo//WOboCNOCcA1fvcWW9oc4MvV8ZPvFIAbyEbgyFd4id5lGDTRbRPvvNZRvdsN\n" + + "NM2gXYr+f87NHIXc9EF3pzw=\n" + + "-----END CERTIFICATE-----"; + + InputStream is = new ByteArrayInputStream(b64.getBytes("UTF-8")); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + return (X509Certificate)cf.generateCertificate(is); + } + + static class ExtensionImpl implements Extension { + private final String oid; + private final byte[] val; + private final boolean critical; + + ExtensionImpl(String oid, byte[] val, boolean critical) { + this.oid = oid; + this.val = val; + this.critical = critical; + } + + public void encode(OutputStream out) throws IOException { + throw new UnsupportedOperationException(); + } + + public String getId() { + return oid; + } + + public byte[] getValue() { + return val.clone(); + } + + public boolean isCritical() { + return critical; + } + } +}