1 /*
   2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.security.cert;
  26 
  27 import java.net.URI;
  28 import java.util.ArrayList;
  29 import java.util.Collections;
  30 import java.util.HashMap;
  31 import java.util.HashSet;
  32 import java.util.List;
  33 import java.util.Map;
  34 import java.util.Map.Entry;
  35 import java.util.Set;
  36 
  37 /**
  38  * A {@code PKIXCertPathChecker} for checking the revocation status of
  39  * certificates with the PKIX algorithm.
  40  *
  41  * <p>A {@code PKIXRevocationChecker} checks the revocation status of
  42  * certificates with the Online Certificate Status Protocol (OCSP) or
  43  * Certificate Revocation Lists (CRLs). OCSP is described in RFC 2560 and
  44  * is a network protocol for determining the status of a certificate. A CRL
  45  * is a time-stamped list identifying revoked certificates, and RFC 5280
  46  * describes an algorithm for determining the revocation status of certificates
  47  * using CRLs.
  48  *
  49  * <p>Each {@code PKIXRevocationChecker} must be able to check the revocation
  50  * status of certificates with OCSP and CRLs. By default, OCSP is the
  51  * preferred mechanism for checking revocation status, with CRLs as the
  52  * fallback mechanism. However, this preference can be switched to CRLs with
  53  * the {@link Option#PREFER_CRLS PREFER_CRLS} option. In addition, the fallback
  54  * mechanism can be disabled with the {@link Option#NO_FALLBACK NO_FALLBACK}
  55  * option.
  56  *
  57  * <p>A {@code PKIXRevocationChecker} is obtained by calling the
  58  * {@link CertPathValidator#getRevocationChecker getRevocationChecker} method
  59  * of a PKIX {@code CertPathValidator}. Additional parameters and options
  60  * specific to revocation can be set (by calling the
  61  * {@link #setOcspResponder setOcspResponder} method for instance). The
  62  * {@code PKIXRevocationChecker} is added to a {@code PKIXParameters} object
  63  * using the {@link PKIXParameters#addCertPathChecker addCertPathChecker}
  64  * or {@link PKIXParameters#setCertPathCheckers setCertPathCheckers} method,
  65  * and then the {@code PKIXParameters} is passed along with the {@code CertPath}
  66  * to be validated to the {@link CertPathValidator#validate validate} method
  67  * of a PKIX {@code CertPathValidator}. When supplying a revocation checker in
  68  * this manner, it will be used to check revocation irrespective of the setting
  69  * of the {@link PKIXParameters#isRevocationEnabled RevocationEnabled} flag.
  70  * Similarly, a {@code PKIXRevocationChecker} may be added to a
  71  * {@code PKIXBuilderParameters} object for use with a PKIX
  72  * {@code CertPathBuilder}.
  73  *
  74  * <p>Note that when a {@code PKIXRevocationChecker} is added to
  75  * {@code PKIXParameters}, it clones the {@code PKIXRevocationChecker};
  76  * thus any subsequent modifications to the {@code PKIXRevocationChecker}
  77  * have no effect.
  78  *
  79  * <p>Any parameter that is not set (or is set to {@code null}) will be set to
  80  * the default value for that parameter.
  81  *
  82  * <p><b>Concurrent Access</b>
  83  *
  84  * <p>Unless otherwise specified, the methods defined in this class are not
  85  * thread-safe. Multiple threads that need to access a single object
  86  * concurrently should synchronize amongst themselves and provide the
  87  * necessary locking. Multiple threads each manipulating separate objects
  88  * need not synchronize.
  89  *
  90  * @since 1.8
  91  *
  92  * @see <a href="http://www.ietf.org/rfc/rfc2560.txt"><i>RFC&nbsp;2560: X.509
  93  * Internet Public Key Infrastructure Online Certificate Status Protocol -
  94  * OCSP</i></a>, <br><a
  95  * href="http://www.ietf.org/rfc/rfc5280.txt"><i>RFC&nbsp;5280: Internet X.509
  96  * Public Key Infrastructure Certificate and Certificate Revocation List (CRL)
  97  * Profile</i></a>
  98  */
  99 public abstract class PKIXRevocationChecker extends PKIXCertPathChecker {
 100     private URI ocspResponder;
 101     private X509Certificate ocspResponderCert;
 102     private List<Extension> ocspExtensions = Collections.<Extension>emptyList();
 103     private Map<X509Certificate, byte[]> ocspResponses = Collections.emptyMap();
 104     private Set<Option> options = Collections.emptySet();
 105 
 106     /**
 107      * Default constructor.
 108      */
 109     protected PKIXRevocationChecker() {}
 110 
 111     /**
 112      * Sets the URI that identifies the location of the OCSP responder. This
 113      * overrides the {@code ocsp.responderURL} security property and any
 114      * responder specified in a certificate's Authority Information Access
 115      * Extension, as defined in RFC 5280.
 116      *
 117      * @param uri the responder URI
 118      */
 119     public void setOcspResponder(URI uri) {
 120         this.ocspResponder = uri;
 121     }
 122 
 123     /**
 124      * Gets the URI that identifies the location of the OCSP responder. This
 125      * overrides the {@code ocsp.responderURL} security property. If this
 126      * parameter or the {@code ocsp.responderURL} property is not set, the
 127      * location is determined from the certificate's Authority Information
 128      * Access Extension, as defined in RFC 5280.
 129      *
 130      * @return the responder URI, or {@code null} if not set
 131      */
 132     public URI getOcspResponder() {
 133         return ocspResponder;
 134     }
 135 
 136     /**
 137      * Sets the OCSP responder's certificate. This overrides the
 138      * {@code ocsp.responderCertSubjectName},
 139      * {@code ocsp.responderCertIssuerName},
 140      * and {@code ocsp.responderCertSerialNumber} security properties.
 141      *
 142      * @param cert the responder's certificate
 143      */
 144     public void setOcspResponderCert(X509Certificate cert) {
 145         this.ocspResponderCert = cert;
 146     }
 147 
 148     /**
 149      * Gets the OCSP responder's certificate. This overrides the
 150      * {@code ocsp.responderCertSubjectName},
 151      * {@code ocsp.responderCertIssuerName},
 152      * and {@code ocsp.responderCertSerialNumber} security properties. If this
 153      * parameter or the aforementioned properties are not set, then the
 154      * responder's certificate is determined as specified in RFC 2560.
 155      *
 156      * @return the responder's certificate, or {@code null} if not set
 157      */
 158     public X509Certificate getOcspResponderCert() {
 159         return ocspResponderCert;
 160     }
 161 
 162     // request extensions; single extensions not supported
 163     /**
 164      * Sets the optional OCSP request extensions.
 165      *
 166      * @param extensions a list of extensions. The list is copied to protect
 167      *        against subsequent modification.
 168      */
 169     public void setOcspExtensions(List<Extension> extensions)
 170     {
 171         this.ocspExtensions = (extensions == null)
 172                               ? Collections.<Extension>emptyList()
 173                               : new ArrayList<Extension>(extensions);
 174     }
 175 
 176     /**
 177      * Gets the optional OCSP request extensions.
 178      *
 179      * @return an unmodifiable list of extensions. The list is empty if no
 180      *         extensions have been specified.
 181      */
 182     public List<Extension> getOcspExtensions() {
 183         return Collections.unmodifiableList(ocspExtensions);
 184     }
 185 
 186     /**
 187      * Sets the OCSP responses. These responses are used to determine
 188      * the revocation status of the specified certificates when OCSP is used.
 189      *
 190      * @param responses a map of OCSP responses. Each key is an
 191      *        {@code X509Certificate} that maps to the corresponding
 192      *        DER-encoded OCSP response for that certificate. A deep copy of
 193      *        the map is performed to protect against subsequent modification.
 194      */
 195     public void setOcspResponses(Map<X509Certificate, byte[]> responses)
 196     {
 197         if (responses == null) {
 198             this.ocspResponses = Collections.<X509Certificate, byte[]>emptyMap();
 199         } else {
 200             Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size());
 201             for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) {
 202                 copy.put(e.getKey(), e.getValue().clone());
 203             }
 204             this.ocspResponses = copy;
 205         }
 206     }
 207 
 208     /**
 209      * Gets the OCSP responses. These responses are used to determine
 210      * the revocation status of the specified certificates when OCSP is used.
 211      *
 212      * @return a map of OCSP responses. Each key is an
 213      *        {@code X509Certificate} that maps to the corresponding
 214      *        DER-encoded OCSP response for that certificate. A deep copy of
 215      *        the map is returned to protect against subsequent modification.
 216      *        Returns an empty map if no responses have been specified.
 217      */
 218     public Map<X509Certificate, byte[]> getOcspResponses() {
 219         Map<X509Certificate, byte[]> copy = new HashMap<>(ocspResponses.size());
 220         for (Map.Entry<X509Certificate, byte[]> e : ocspResponses.entrySet()) {
 221             copy.put(e.getKey(), e.getValue().clone());
 222         }
 223         return copy;
 224     }
 225 
 226     /**
 227      * Sets the revocation options.
 228      *
 229      * @param options a set of revocation options. The set is copied to protect
 230      *        against subsequent modification.
 231      */
 232     public void setOptions(Set<Option> options) {
 233         this.options = (options == null)
 234                        ? Collections.<Option>emptySet()
 235                        : new HashSet<Option>(options);
 236     }
 237 
 238     /**
 239      * Gets the revocation options.
 240      *
 241      * @return an unmodifiable set of revocation options. The set is empty if
 242      *         no options have been specified.
 243      */
 244     public Set<Option> getOptions() {
 245         return Collections.unmodifiableSet(options);
 246     }
 247 
 248     /**
 249      * Returns a list containing the exceptions that are ignored by the
 250      * revocation checker when the {@link Option#SOFT_FAIL SOFT_FAIL} option
 251      * is set. The list is cleared each time {@link #init init} is called.
 252      * The list is ordered in ascending order according to the certificate
 253      * index returned by {@link CertPathValidatorException#getIndex getIndex}
 254      * method of each entry.
 255      * <p>
 256      * An implementation of {@code PKIXRevocationChecker} is responsible for
 257      * adding the ignored exceptions to the list.
 258      *
 259      * @return an unmodifiable list containing the ignored exceptions. The list
 260      *         is empty if no exceptions have been ignored.
 261      */
 262     public abstract List<CertPathValidatorException> getSoftFailExceptions();
 263 
 264     @Override
 265     public PKIXRevocationChecker clone() {
 266         PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone();
 267         copy.ocspExtensions = new ArrayList<>(ocspExtensions);
 268         copy.ocspResponses = new HashMap<>(ocspResponses);
 269         // deep-copy the encoded responses, since they are mutable
 270         for (Map.Entry<X509Certificate, byte[]> entry :
 271                  copy.ocspResponses.entrySet())
 272         {
 273             byte[] encoded = entry.getValue();
 274             entry.setValue(encoded.clone());
 275         }
 276         copy.options = new HashSet<>(options);
 277         return copy;
 278     }
 279 
 280     /**
 281      * Various revocation options that can be specified for the revocation
 282      * checking mechanism.
 283      */
 284     public enum Option {
 285         /**
 286          * Only check the revocation status of end-entity certificates.
 287          */
 288         ONLY_END_ENTITY,
 289         /**
 290          * Prefer CRLs to OSCP. The default behavior is to prefer OCSP. Each
 291          * PKIX implementation should document further details of their
 292          * specific preference rules and fallback policies.
 293          */
 294         PREFER_CRLS,
 295         /**
 296          * Disable the fallback mechanism.
 297          */
 298         NO_FALLBACK,
 299         /**
 300          * Allow revocation check to succeed if the revocation status cannot be
 301          * determined for one of the following reasons:
 302          * <ul>
 303          *  <li>The CRL or OCSP response cannot be obtained because of a
 304          *      network error.
 305          *  <li>The OCSP responder returns one of the following errors
 306          *      specified in section 2.3 of RFC 2560: internalError or tryLater.
 307          * </ul><br>
 308          * Note that these conditions apply to both OCSP and CRLs, and unless
 309          * the {@code NO_FALLBACK} option is set, the revocation check is
 310          * allowed to succeed only if both mechanisms fail under one of the
 311          * conditions as stated above.
 312          * Exceptions that cause the network errors are ignored but can be
 313          * later retrieved by calling the
 314          * {@link #getSoftFailExceptions getSoftFailExceptions} method.
 315          */
 316         SOFT_FAIL
 317     }
 318 }