/* * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. 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 PREFER_CRLS} option. In addition, the fallback * mechanism can be disabled with the {@link Option#NO_FALLBACK NO_FALLBACK} * 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 the * {@link #setOcspResponder 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, it will be used to check revocation irrespective of the setting * of the {@link PKIXParameters#isRevocationEnabled RevocationEnabled} flag. * Similarly, a {@code PKIXRevocationChecker} may be added to a * {@code PKIXBuilderParameters} object for use with a PKIX * {@code CertPathBuilder}. * * <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 * * @see <a href="http://www.ietf.org/rfc/rfc2560.txt"><i>RFC 2560: X.509 * Internet Public Key Infrastructure Online Certificate Status Protocol - * OCSP</i></a>, <br><a * href="http://www.ietf.org/rfc/rfc5280.txt"><i>RFC 5280: Internet X.509 * Public Key Infrastructure Certificate and Certificate Revocation List (CRL) * Profile</i></a> */ public abstract class PKIXRevocationChecker extends PKIXCertPathChecker { private URI ocspResponder; private X509Certificate ocspResponderCert; private List<Extension> ocspExtensions = Collections.<Extension>emptyList(); private Map<X509Certificate, byte[]> ocspResponses = Collections.emptyMap(); private Set<Option> options = Collections.emptySet(); /** * Default constructor. */ 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. The list is empty if no * extensions have been specified. */ public List<Extension> getOcspExtensions() { return Collections.unmodifiableList(ocspExtensions); } /** * Sets the OCSP responses. These responses are used to determine * the revocation status of the specified certificates when OCSP is used. * * @param responses a map of 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 setOcspResponses(Map<X509Certificate, byte[]> responses) { if (responses == null) { this.ocspResponses = 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.ocspResponses = copy; } } /** * Gets the OCSP responses. These responses are used to determine * the revocation status of the specified certificates when OCSP is used. * * @return a map of 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[]> getOcspResponses() { Map<X509Certificate, byte[]> copy = new HashMap<>(ocspResponses.size()); for (Map.Entry<X509Certificate, byte[]> e : ocspResponses.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. The set is empty if * no options have been specified. */ public Set<Option> getOptions() { return Collections.unmodifiableSet(options); } /** * Returns a list containing the exceptions that are ignored by the * revocation checker when the {@link Option#SOFT_FAIL SOFT_FAIL} option * is set. The list is cleared each time {@link #init init} is called. * The list is ordered in ascending order according to the certificate * index returned by {@link CertPathValidatorException#getIndex getIndex} * method of each entry. * <p> * An implementation of {@code PKIXRevocationChecker} is responsible for * adding the ignored exceptions to the list. * * @return an unmodifiable list containing the ignored exceptions. The list * is empty if no exceptions have been ignored. */ public abstract List<CertPathValidatorException> getSoftFailExceptions(); @Override public PKIXRevocationChecker clone() { PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone(); copy.ocspExtensions = new ArrayList<>(ocspExtensions); copy.ocspResponses = new HashMap<>(ocspResponses); // deep-copy the encoded responses, since they are mutable for (Map.Entry<X509Certificate, byte[]> entry : copy.ocspResponses.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, /** * Disable the fallback mechanism. */ NO_FALLBACK, /** * Allow revocation check to succeed if the revocation status cannot be * determined for one of the following reasons: * <p><ul> * <li>The CRL or OCSP response cannot be obtained because of a * network error. * <li>The OCSP responder returns one of the following errors * specified in section 2.3 of RFC 2560: internalError or tryLater. * </ul><br> * Note that these conditions apply to both OCSP and CRLs, and unless * the {@code NO_FALLBACK} option is set, the revocation check is * allowed to succeed only if both mechanisms fail under one of the * conditions as stated above. * Exceptions that cause the network errors are ignored but can be * later retrieved by calling the * {@link #getSoftFailExceptions getSoftFailExceptions} method. */ SOFT_FAIL } }