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 * // Android-changed: Changed invalid `@`see to "See". 93 * See <a href="http://www.ietf.org/rfc/rfc2560.txt"><i>RFC 2560: X.509 94 * Internet Public Key Infrastructure Online Certificate Status Protocol - 95 * OCSP</i></a>, <br><a 96 * href="http://www.ietf.org/rfc/rfc5280.txt"><i>RFC 5280: Internet X.509 97 * Public Key Infrastructure Certificate and Certificate Revocation List (CRL) 98 * Profile</i></a> 99 */ 100 public abstract class PKIXRevocationChecker extends PKIXCertPathChecker { 101 private URI ocspResponder; 102 private X509Certificate ocspResponderCert; 103 private List<Extension> ocspExtensions = Collections.<Extension>emptyList(); 104 private Map<X509Certificate, byte[]> ocspResponses = Collections.emptyMap(); 105 private Set<Option> options = Collections.emptySet(); 106 107 /** 108 * Default constructor. 109 */ PKIXRevocationChecker()110 protected PKIXRevocationChecker() {} 111 112 /** 113 * Sets the URI that identifies the location of the OCSP responder. This 114 * overrides the {@code ocsp.responderURL} security property and any 115 * responder specified in a certificate's Authority Information Access 116 * Extension, as defined in RFC 5280. 117 * 118 * @param uri the responder URI 119 */ setOcspResponder(URI uri)120 public void setOcspResponder(URI uri) { 121 this.ocspResponder = uri; 122 } 123 124 /** 125 * Gets the URI that identifies the location of the OCSP responder. This 126 * overrides the {@code ocsp.responderURL} security property. If this 127 * parameter or the {@code ocsp.responderURL} property is not set, the 128 * location is determined from the certificate's Authority Information 129 * Access Extension, as defined in RFC 5280. 130 * 131 * @return the responder URI, or {@code null} if not set 132 */ getOcspResponder()133 public URI getOcspResponder() { 134 return ocspResponder; 135 } 136 137 /** 138 * Sets the OCSP responder's certificate. This overrides the 139 * {@code ocsp.responderCertSubjectName}, 140 * {@code ocsp.responderCertIssuerName}, 141 * and {@code ocsp.responderCertSerialNumber} security properties. 142 * 143 * @param cert the responder's certificate 144 */ setOcspResponderCert(X509Certificate cert)145 public void setOcspResponderCert(X509Certificate cert) { 146 this.ocspResponderCert = cert; 147 } 148 149 /** 150 * Gets the OCSP responder's certificate. This overrides the 151 * {@code ocsp.responderCertSubjectName}, 152 * {@code ocsp.responderCertIssuerName}, 153 * and {@code ocsp.responderCertSerialNumber} security properties. If this 154 * parameter or the aforementioned properties are not set, then the 155 * responder's certificate is determined as specified in RFC 2560. 156 * 157 * @return the responder's certificate, or {@code null} if not set 158 */ getOcspResponderCert()159 public X509Certificate getOcspResponderCert() { 160 return ocspResponderCert; 161 } 162 163 // request extensions; single extensions not supported 164 /** 165 * Sets the optional OCSP request extensions. 166 * 167 * @param extensions a list of extensions. The list is copied to protect 168 * against subsequent modification. 169 */ setOcspExtensions(List<Extension> extensions)170 public void setOcspExtensions(List<Extension> extensions) 171 { 172 this.ocspExtensions = (extensions == null) 173 ? Collections.<Extension>emptyList() 174 : new ArrayList<>(extensions); 175 } 176 177 /** 178 * Gets the optional OCSP request extensions. 179 * 180 * @return an unmodifiable list of extensions. The list is empty if no 181 * extensions have been specified. 182 */ getOcspExtensions()183 public List<Extension> getOcspExtensions() { 184 return Collections.unmodifiableList(ocspExtensions); 185 } 186 187 /** 188 * Sets the OCSP responses. These responses are used to determine 189 * the revocation status of the specified certificates when OCSP is used. 190 * 191 * @param responses a map of OCSP responses. Each key is an 192 * {@code X509Certificate} that maps to the corresponding 193 * DER-encoded OCSP response for that certificate. A deep copy of 194 * the map is performed to protect against subsequent modification. 195 */ setOcspResponses(Map<X509Certificate, byte[]> responses)196 public void setOcspResponses(Map<X509Certificate, byte[]> responses) 197 { 198 if (responses == null) { 199 this.ocspResponses = Collections.<X509Certificate, byte[]>emptyMap(); 200 } else { 201 Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size()); 202 for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) { 203 copy.put(e.getKey(), e.getValue().clone()); 204 } 205 this.ocspResponses = copy; 206 } 207 } 208 209 /** 210 * Gets the OCSP responses. These responses are used to determine 211 * the revocation status of the specified certificates when OCSP is used. 212 * 213 * @return a map of OCSP responses. Each key is an 214 * {@code X509Certificate} that maps to the corresponding 215 * DER-encoded OCSP response for that certificate. A deep copy of 216 * the map is returned to protect against subsequent modification. 217 * Returns an empty map if no responses have been specified. 218 */ getOcspResponses()219 public Map<X509Certificate, byte[]> getOcspResponses() { 220 Map<X509Certificate, byte[]> copy = new HashMap<>(ocspResponses.size()); 221 for (Map.Entry<X509Certificate, byte[]> e : ocspResponses.entrySet()) { 222 copy.put(e.getKey(), e.getValue().clone()); 223 } 224 return copy; 225 } 226 227 /** 228 * Sets the revocation options. 229 * 230 * @param options a set of revocation options. The set is copied to protect 231 * against subsequent modification. 232 */ setOptions(Set<Option> options)233 public void setOptions(Set<Option> options) { 234 this.options = (options == null) 235 ? Collections.<Option>emptySet() 236 : new HashSet<>(options); 237 } 238 239 /** 240 * Gets the revocation options. 241 * 242 * @return an unmodifiable set of revocation options. The set is empty if 243 * no options have been specified. 244 */ getOptions()245 public Set<Option> getOptions() { 246 return Collections.unmodifiableSet(options); 247 } 248 249 /** 250 * Returns a list containing the exceptions that are ignored by the 251 * revocation checker when the {@link Option#SOFT_FAIL SOFT_FAIL} option 252 * is set. The list is cleared each time {@link #init init} is called. 253 * The list is ordered in ascending order according to the certificate 254 * index returned by {@link CertPathValidatorException#getIndex getIndex} 255 * method of each entry. 256 * <p> 257 * An implementation of {@code PKIXRevocationChecker} is responsible for 258 * adding the ignored exceptions to the list. 259 * 260 * @return an unmodifiable list containing the ignored exceptions. The list 261 * is empty if no exceptions have been ignored. 262 */ getSoftFailExceptions()263 public abstract List<CertPathValidatorException> getSoftFailExceptions(); 264 265 @Override clone()266 public PKIXRevocationChecker clone() { 267 PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone(); 268 copy.ocspExtensions = new ArrayList<>(ocspExtensions); 269 copy.ocspResponses = new HashMap<>(ocspResponses); 270 // deep-copy the encoded responses, since they are mutable 271 for (Map.Entry<X509Certificate, byte[]> entry : 272 copy.ocspResponses.entrySet()) 273 { 274 byte[] encoded = entry.getValue(); 275 entry.setValue(encoded.clone()); 276 } 277 copy.options = new HashSet<>(options); 278 return copy; 279 } 280 281 /** 282 * Various revocation options that can be specified for the revocation 283 * checking mechanism. 284 */ 285 public enum Option { 286 /** 287 * Only check the revocation status of end-entity certificates. 288 */ 289 ONLY_END_ENTITY, 290 /** 291 * Prefer CRLs to OSCP. The default behavior is to prefer OCSP. Each 292 * PKIX implementation should document further details of their 293 * specific preference rules and fallback policies. 294 */ 295 PREFER_CRLS, 296 /** 297 * Disable the fallback mechanism. 298 */ 299 NO_FALLBACK, 300 /** 301 * Allow revocation check to succeed if the revocation status cannot be 302 * determined for one of the following reasons: 303 * <ul> 304 * <li>The CRL or OCSP response cannot be obtained because of a 305 * network error. 306 * <li>The OCSP responder returns one of the following errors 307 * specified in section 2.3 of RFC 2560: internalError or tryLater. 308 * </ul><br> 309 * Note that these conditions apply to both OCSP and CRLs, and unless 310 * the {@code NO_FALLBACK} option is set, the revocation check is 311 * allowed to succeed only if both mechanisms fail under one of the 312 * conditions as stated above. 313 * Exceptions that cause the network errors are ignored but can be 314 * later retrieved by calling the 315 * {@link #getSoftFailExceptions getSoftFailExceptions} method. 316 */ 317 SOFT_FAIL 318 } 319 } 320