1 /*
   2  * Copyright (c) 2012, 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.
  54  *
  55  * <p>A {@code PKIXRevocationChecker} is obtained by calling the
  56  * {@link CertPathValidator#getRevocationChecker getRevocationChecker} method
  57  * of a PKIX {@code CertPathValidator}. Additional parameters and options
  58  * specific to revocation can be set (by calling {@link #setOCSPResponder}
  59  * method for instance). The {@code PKIXRevocationChecker} is added to
  60  * a {@code PKIXParameters} object using the
  61  * {@link PKIXParameters#addCertPathChecker addCertPathChecker}
  62  * or {@link PKIXParameters#setCertPathCheckers setCertPathCheckers} method,
  63  * and then the {@code PKIXParameters} is passed along with the {@code CertPath}
  64  * to be validated to the {@link CertPathValidator#validate validate} method
  65  * of a PKIX {@code CertPathValidator}. When supplying a revocation checker in
  66  * this manner, do not enable the default revocation checking mechanism (by
  67  * calling {@link PKIXParameters#setRevocationEnabled}.
  68  *
  69  * <p>Note that when a {@code PKIXRevocationChecker} is added to
  70  * {@code PKIXParameters}, it clones the {@code PKIXRevocationChecker};
  71  * thus any subsequent modifications to the {@code PKIXRevocationChecker}
  72  * have no effect.
  73  *
  74  * <p>Any parameter that is not set (or is set to {@code null}) will be set to
  75  * the default value for that parameter.
  76  *
  77  * <p><b>Concurrent Access</b>
  78  *
  79  * <p>Unless otherwise specified, the methods defined in this class are not
  80  * thread-safe. Multiple threads that need to access a single object
  81  * concurrently should synchronize amongst themselves and provide the
  82  * necessary locking. Multiple threads each manipulating separate objects
  83  * need not synchronize.
  84  *
  85  * @since 1.8
  86  */
  87 public abstract class PKIXRevocationChecker extends PKIXCertPathChecker {
  88     private URI ocspResponder;
  89     private X509Certificate ocspResponderCert;
  90     private List<Extension> ocspExtensions = Collections.<Extension>emptyList();
  91     private Map<X509Certificate, byte[]> ocspStapled = Collections.emptyMap();
  92     private Set<Option> options = Collections.emptySet();
  93 
  94     protected PKIXRevocationChecker() {}
  95 
  96     /**
  97      * Sets the URI that identifies the location of the OCSP responder. This
  98      * overrides the {@code ocsp.responderURL} security property and any
  99      * responder specified in a certificate's Authority Information Access
 100      * Extension, as defined in RFC 5280.
 101      *
 102      * @param uri the responder URI
 103      */
 104     public void setOCSPResponder(URI uri) {
 105         this.ocspResponder = uri;
 106     }
 107 
 108     /**
 109      * Gets the URI that identifies the location of the OCSP responder. This
 110      * overrides the {@code ocsp.responderURL} security property. If this
 111      * parameter or the {@code ocsp.responderURL} property is not set, the
 112      * location is determined from the certificate's Authority Information
 113      * Access Extension, as defined in RFC 5280.
 114      *
 115      * @return the responder URI, or {@code null} if not set
 116      */
 117     public URI getOCSPResponder() {
 118         return ocspResponder;
 119     }
 120 
 121     /**
 122      * Sets the OCSP responder's certificate. This overrides the
 123      * {@code ocsp.responderCertSubjectName},
 124      * {@code ocsp.responderCertIssuerName},
 125      * and {@code ocsp.responderCertSerialNumber} security properties.
 126      *
 127      * @param cert the responder's certificate
 128      */
 129     public void setOCSPResponderCert(X509Certificate cert) {
 130         this.ocspResponderCert = cert;
 131     }
 132 
 133     /**
 134      * Gets the OCSP responder's certificate. This overrides the
 135      * {@code ocsp.responderCertSubjectName},
 136      * {@code ocsp.responderCertIssuerName},
 137      * and {@code ocsp.responderCertSerialNumber} security properties. If this
 138      * parameter or the aforementioned properties are not set, then the
 139      * responder's certificate is determined as specified in RFC 2560.
 140      *
 141      * @return the responder's certificate, or {@code null} if not set
 142      */
 143     public X509Certificate getOCSPResponderCert() {
 144         return ocspResponderCert;
 145     }
 146 
 147     // request extensions; single extensions not supported
 148     /**
 149      * Sets the optional OCSP request extensions.
 150      *
 151      * @param extensions a list of extensions. The list is copied to protect
 152      *        against subsequent modification.
 153      */
 154     public void setOCSPExtensions(List<Extension> extensions)
 155     {
 156         this.ocspExtensions = (extensions == null)
 157                               ? Collections.<Extension>emptyList()
 158                               : new ArrayList<Extension>(extensions);
 159     }
 160 
 161     /**
 162      * Gets the optional OCSP request extensions.
 163      *
 164      * @return an unmodifiable list of extensions. Returns an empty list if no
 165      *         extensions have been specified.
 166      */
 167     public List<Extension> getOCSPExtensions() {
 168         return Collections.unmodifiableList(ocspExtensions);
 169     }
 170 
 171     /**
 172      * Sets the stapled OCSP responses. These responses are used to determine
 173      * the revocation status of the specified certificates when OCSP is used.
 174      *
 175      * @param responses a map of stapled OCSP responses. Each key is an
 176      *        {@code X509Certificate} that maps to the corresponding
 177      *        DER-encoded OCSP response for that certificate. A deep copy of
 178      *        the map is performed to protect against subsequent modification.
 179      */
 180     public void setOCSPStapledResponses(Map<X509Certificate, byte[]> responses)
 181     {
 182         if (responses == null) {
 183             this.ocspStapled = Collections.<X509Certificate, byte[]>emptyMap();
 184         } else {
 185             Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size());
 186             for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) {
 187                 copy.put(e.getKey(), e.getValue().clone());
 188             }
 189             this.ocspStapled = copy;
 190         }
 191     }
 192 
 193     /**
 194      * Gets the stapled OCSP responses. These responses are used to determine
 195      * the revocation status of the specified certificates when OCSP is used.
 196      *
 197      * @return a map of stapled OCSP responses. Each key is an
 198      *        {@code X509Certificate} that maps to the corresponding
 199      *        DER-encoded OCSP response for that certificate. A deep copy of
 200      *        the map is returned to protect against subsequent modification.
 201      *        Returns an empty map if no responses have been specified.
 202      */
 203     public Map<X509Certificate, byte[]> getOCSPStapledResponses() {
 204         Map<X509Certificate, byte[]> copy = new HashMap<>(ocspStapled.size());
 205         for (Map.Entry<X509Certificate, byte[]> e : ocspStapled.entrySet()) {
 206             copy.put(e.getKey(), e.getValue().clone());
 207         }
 208         return copy;
 209     }
 210 
 211     /**
 212      * Sets the revocation options.
 213      *
 214      * @param options a set of revocation options. The set is copied to protect
 215      *        against subsequent modification.
 216      */
 217     public void setOptions(Set<Option> options) {
 218         this.options = (options == null)
 219                        ? Collections.<Option>emptySet()
 220                        : new HashSet<Option>(options);
 221     }
 222 
 223     /**
 224      * Gets the revocation options.
 225      *
 226      * @return an unmodifiable set of revocation options, or an empty set if
 227      *         none are specified
 228      */
 229     public Set<Option> getOptions() {
 230         return Collections.unmodifiableSet(options);
 231     }
 232 
 233     @Override
 234     public Object clone() {
 235         PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone();
 236         copy.ocspExtensions = new ArrayList<>(ocspExtensions);
 237         copy.ocspStapled = new HashMap<>(ocspStapled);
 238         // deep-copy the encoded stapled responses, since they are mutable
 239         for (Map.Entry<X509Certificate, byte[]> entry :
 240                  copy.ocspStapled.entrySet())
 241         {
 242             byte[] encoded = entry.getValue();
 243             entry.setValue(encoded.clone());
 244         }
 245         copy.options = new HashSet<>(options);
 246         return copy;
 247     }
 248 
 249     /**
 250      * Various revocation options that can be specified for the revocation
 251      * checking mechanism.
 252      */
 253     public enum Option {
 254         /**
 255          * Only check the revocation status of end-entity certificates.
 256          */
 257         ONLY_END_ENTITY,
 258         /**
 259          * Prefer CRLs to OSCP. The default behavior is to prefer OCSP. Each
 260          * PKIX implementation should document further details of their
 261          * specific preference rules and fallback policies.
 262          */
 263         PREFER_CRLS,
 264         /**
 265          * Ignore network failures. The default behavior is to consider it a
 266          * failure if the revocation status of a certificate cannot be obtained
 267          * due to a network error. This option applies to both OCSP and CRLs.
 268          */
 269         SOFT_FAIL
 270     }
 271 }