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&nbsp;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&nbsp;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