Mercurial Hosting > luan
comparison src/org/eclipse/jetty/util/security/CertificateValidator.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 8e9db0bbf4f9 |
comparison
equal
deleted
inserted
replaced
801:6a21393191c1 | 802:3428c60d7cfc |
---|---|
1 // | |
2 // ======================================================================== | |
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
4 // ------------------------------------------------------------------------ | |
5 // All rights reserved. This program and the accompanying materials | |
6 // are made available under the terms of the Eclipse Public License v1.0 | |
7 // and Apache License v2.0 which accompanies this distribution. | |
8 // | |
9 // The Eclipse Public License is available at | |
10 // http://www.eclipse.org/legal/epl-v10.html | |
11 // | |
12 // The Apache License v2.0 is available at | |
13 // http://www.opensource.org/licenses/apache2.0.php | |
14 // | |
15 // You may elect to redistribute this code under either of these licenses. | |
16 // ======================================================================== | |
17 // | |
18 | |
19 package org.eclipse.jetty.util.security; | |
20 | |
21 import java.security.GeneralSecurityException; | |
22 import java.security.InvalidParameterException; | |
23 import java.security.KeyStore; | |
24 import java.security.KeyStoreException; | |
25 import java.security.Security; | |
26 import java.security.cert.CRL; | |
27 import java.security.cert.CertPathBuilder; | |
28 import java.security.cert.CertPathBuilderResult; | |
29 import java.security.cert.CertPathValidator; | |
30 import java.security.cert.CertStore; | |
31 import java.security.cert.Certificate; | |
32 import java.security.cert.CertificateException; | |
33 import java.security.cert.CollectionCertStoreParameters; | |
34 import java.security.cert.PKIXBuilderParameters; | |
35 import java.security.cert.X509CertSelector; | |
36 import java.security.cert.X509Certificate; | |
37 import java.util.ArrayList; | |
38 import java.util.Collection; | |
39 import java.util.Enumeration; | |
40 import java.util.concurrent.atomic.AtomicLong; | |
41 | |
42 import org.eclipse.jetty.util.log.Log; | |
43 import org.eclipse.jetty.util.log.Logger; | |
44 | |
45 /** | |
46 * Convenience class to handle validation of certificates, aliases and keystores | |
47 * | |
48 * Allows specifying Certificate Revocation List (CRL), as well as enabling | |
49 * CRL Distribution Points Protocol (CRLDP) certificate extension support, | |
50 * and also enabling On-Line Certificate Status Protocol (OCSP) support. | |
51 * | |
52 * IMPORTANT: at least one of the above mechanisms *MUST* be configured and | |
53 * operational, otherwise certificate validation *WILL FAIL* unconditionally. | |
54 */ | |
55 public class CertificateValidator | |
56 { | |
57 private static final Logger LOG = Log.getLogger(CertificateValidator.class); | |
58 private static AtomicLong __aliasCount = new AtomicLong(); | |
59 | |
60 private KeyStore _trustStore; | |
61 private Collection<? extends CRL> _crls; | |
62 | |
63 /** Maximum certification path length (n - number of intermediate certs, -1 for unlimited) */ | |
64 private int _maxCertPathLength = -1; | |
65 /** CRL Distribution Points (CRLDP) support */ | |
66 private boolean _enableCRLDP = false; | |
67 /** On-Line Certificate Status Protocol (OCSP) support */ | |
68 private boolean _enableOCSP = false; | |
69 /** Location of OCSP Responder */ | |
70 private String _ocspResponderURL; | |
71 | |
72 /** | |
73 * creates an instance of the certificate validator | |
74 * | |
75 * @param trustStore | |
76 * @param crls | |
77 */ | |
78 public CertificateValidator(KeyStore trustStore, Collection<? extends CRL> crls) | |
79 { | |
80 if (trustStore == null) | |
81 { | |
82 throw new InvalidParameterException("TrustStore must be specified for CertificateValidator."); | |
83 } | |
84 | |
85 _trustStore = trustStore; | |
86 _crls = crls; | |
87 } | |
88 | |
89 /** | |
90 * validates all aliases inside of a given keystore | |
91 * | |
92 * @param keyStore | |
93 * @throws CertificateException | |
94 */ | |
95 public void validate( KeyStore keyStore ) throws CertificateException | |
96 { | |
97 try | |
98 { | |
99 Enumeration<String> aliases = keyStore.aliases(); | |
100 | |
101 for ( ; aliases.hasMoreElements(); ) | |
102 { | |
103 String alias = aliases.nextElement(); | |
104 | |
105 validate(keyStore,alias); | |
106 } | |
107 | |
108 } | |
109 catch ( KeyStoreException kse ) | |
110 { | |
111 throw new CertificateException("Unable to retrieve aliases from keystore", kse); | |
112 } | |
113 } | |
114 | |
115 | |
116 /** | |
117 * validates a specific alias inside of the keystore being passed in | |
118 * | |
119 * @param keyStore | |
120 * @param keyAlias | |
121 * @return the keyAlias if valid | |
122 * @throws CertificateException | |
123 */ | |
124 public String validate(KeyStore keyStore, String keyAlias) throws CertificateException | |
125 { | |
126 String result = null; | |
127 | |
128 if (keyAlias != null) | |
129 { | |
130 try | |
131 { | |
132 validate(keyStore, keyStore.getCertificate(keyAlias)); | |
133 } | |
134 catch (KeyStoreException kse) | |
135 { | |
136 LOG.debug(kse); | |
137 throw new CertificateException("Unable to validate certificate" + | |
138 " for alias [" + keyAlias + "]: " + kse.getMessage(), kse); | |
139 } | |
140 result = keyAlias; | |
141 } | |
142 | |
143 return result; | |
144 } | |
145 | |
146 /** | |
147 * validates a specific certificate inside of the keystore being passed in | |
148 * | |
149 * @param keyStore | |
150 * @param cert | |
151 * @throws CertificateException | |
152 */ | |
153 public void validate(KeyStore keyStore, Certificate cert) throws CertificateException | |
154 { | |
155 Certificate[] certChain = null; | |
156 | |
157 if (cert != null && cert instanceof X509Certificate) | |
158 { | |
159 ((X509Certificate)cert).checkValidity(); | |
160 | |
161 String certAlias = null; | |
162 try | |
163 { | |
164 if (keyStore == null) | |
165 { | |
166 throw new InvalidParameterException("Keystore cannot be null"); | |
167 } | |
168 | |
169 certAlias = keyStore.getCertificateAlias((X509Certificate)cert); | |
170 if (certAlias == null) | |
171 { | |
172 certAlias = "JETTY" + String.format("%016X",__aliasCount.incrementAndGet()); | |
173 keyStore.setCertificateEntry(certAlias, cert); | |
174 } | |
175 | |
176 certChain = keyStore.getCertificateChain(certAlias); | |
177 if (certChain == null || certChain.length == 0) | |
178 { | |
179 throw new IllegalStateException("Unable to retrieve certificate chain"); | |
180 } | |
181 } | |
182 catch (KeyStoreException kse) | |
183 { | |
184 LOG.debug(kse); | |
185 throw new CertificateException("Unable to validate certificate" + | |
186 (certAlias == null ? "":" for alias [" +certAlias + "]") + ": " + kse.getMessage(), kse); | |
187 } | |
188 | |
189 validate(certChain); | |
190 } | |
191 } | |
192 | |
193 public void validate(Certificate[] certChain) throws CertificateException | |
194 { | |
195 try | |
196 { | |
197 ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>(); | |
198 for (Certificate item : certChain) | |
199 { | |
200 if (item == null) | |
201 continue; | |
202 | |
203 if (!(item instanceof X509Certificate)) | |
204 { | |
205 throw new IllegalStateException("Invalid certificate type in chain"); | |
206 } | |
207 | |
208 certList.add((X509Certificate)item); | |
209 } | |
210 | |
211 if (certList.isEmpty()) | |
212 { | |
213 throw new IllegalStateException("Invalid certificate chain"); | |
214 | |
215 } | |
216 | |
217 X509CertSelector certSelect = new X509CertSelector(); | |
218 certSelect.setCertificate(certList.get(0)); | |
219 | |
220 // Configure certification path builder parameters | |
221 PKIXBuilderParameters pbParams = new PKIXBuilderParameters(_trustStore, certSelect); | |
222 pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList))); | |
223 | |
224 // Set maximum certification path length | |
225 pbParams.setMaxPathLength(_maxCertPathLength); | |
226 | |
227 // Enable revocation checking | |
228 pbParams.setRevocationEnabled(true); | |
229 | |
230 // Set static Certificate Revocation List | |
231 if (_crls != null && !_crls.isEmpty()) | |
232 { | |
233 pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(_crls))); | |
234 } | |
235 | |
236 // Enable On-Line Certificate Status Protocol (OCSP) support | |
237 if (_enableOCSP) | |
238 { | |
239 Security.setProperty("ocsp.enable","true"); | |
240 } | |
241 // Enable Certificate Revocation List Distribution Points (CRLDP) support | |
242 if (_enableCRLDP) | |
243 { | |
244 System.setProperty("com.sun.security.enableCRLDP","true"); | |
245 } | |
246 | |
247 // Build certification path | |
248 CertPathBuilderResult buildResult = CertPathBuilder.getInstance("PKIX").build(pbParams); | |
249 | |
250 // Validate certification path | |
251 CertPathValidator.getInstance("PKIX").validate(buildResult.getCertPath(),pbParams); | |
252 } | |
253 catch (GeneralSecurityException gse) | |
254 { | |
255 LOG.debug(gse); | |
256 throw new CertificateException("Unable to validate certificate: " + gse.getMessage(), gse); | |
257 } | |
258 } | |
259 | |
260 public KeyStore getTrustStore() | |
261 { | |
262 return _trustStore; | |
263 } | |
264 | |
265 public Collection<? extends CRL> getCrls() | |
266 { | |
267 return _crls; | |
268 } | |
269 | |
270 /** | |
271 * @return Maximum number of intermediate certificates in | |
272 * the certification path (-1 for unlimited) | |
273 */ | |
274 public int getMaxCertPathLength() | |
275 { | |
276 return _maxCertPathLength; | |
277 } | |
278 | |
279 /* ------------------------------------------------------------ */ | |
280 /** | |
281 * @param maxCertPathLength | |
282 * maximum number of intermediate certificates in | |
283 * the certification path (-1 for unlimited) | |
284 */ | |
285 public void setMaxCertPathLength(int maxCertPathLength) | |
286 { | |
287 _maxCertPathLength = maxCertPathLength; | |
288 } | |
289 | |
290 /* ------------------------------------------------------------ */ | |
291 /** | |
292 * @return true if CRL Distribution Points support is enabled | |
293 */ | |
294 public boolean isEnableCRLDP() | |
295 { | |
296 return _enableCRLDP; | |
297 } | |
298 | |
299 /* ------------------------------------------------------------ */ | |
300 /** Enables CRL Distribution Points Support | |
301 * @param enableCRLDP true - turn on, false - turns off | |
302 */ | |
303 public void setEnableCRLDP(boolean enableCRLDP) | |
304 { | |
305 _enableCRLDP = enableCRLDP; | |
306 } | |
307 | |
308 /* ------------------------------------------------------------ */ | |
309 /** | |
310 * @return true if On-Line Certificate Status Protocol support is enabled | |
311 */ | |
312 public boolean isEnableOCSP() | |
313 { | |
314 return _enableOCSP; | |
315 } | |
316 | |
317 /* ------------------------------------------------------------ */ | |
318 /** Enables On-Line Certificate Status Protocol support | |
319 * @param enableOCSP true - turn on, false - turn off | |
320 */ | |
321 public void setEnableOCSP(boolean enableOCSP) | |
322 { | |
323 _enableOCSP = enableOCSP; | |
324 } | |
325 | |
326 /* ------------------------------------------------------------ */ | |
327 /** | |
328 * @return Location of the OCSP Responder | |
329 */ | |
330 public String getOcspResponderURL() | |
331 { | |
332 return _ocspResponderURL; | |
333 } | |
334 | |
335 /* ------------------------------------------------------------ */ | |
336 /** Set the location of the OCSP Responder. | |
337 * @param ocspResponderURL location of the OCSP Responder | |
338 */ | |
339 public void setOcspResponderURL(String ocspResponderURL) | |
340 { | |
341 _ocspResponderURL = ocspResponderURL; | |
342 } | |
343 } |