1 /* |
1 /* |
2 * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. |
2 * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Sun designates this |
7 * published by the Free Software Foundation. Sun designates this |
36 import java.security.cert.CertPathValidatorSpi; |
36 import java.security.cert.CertPathValidatorSpi; |
37 import java.security.cert.CertPathValidatorResult; |
37 import java.security.cert.CertPathValidatorResult; |
38 import java.security.cert.PKIXCertPathChecker; |
38 import java.security.cert.PKIXCertPathChecker; |
39 import java.security.cert.PKIXCertPathValidatorResult; |
39 import java.security.cert.PKIXCertPathValidatorResult; |
40 import java.security.cert.PKIXParameters; |
40 import java.security.cert.PKIXParameters; |
|
41 import java.security.cert.PKIXReason; |
41 import java.security.cert.PolicyNode; |
42 import java.security.cert.PolicyNode; |
42 import java.security.cert.TrustAnchor; |
43 import java.security.cert.TrustAnchor; |
43 import java.security.cert.X509Certificate; |
44 import java.security.cert.X509Certificate; |
44 import java.security.cert.X509CertSelector; |
45 import java.security.cert.X509CertSelector; |
45 import java.util.Collections; |
46 import java.util.Collections; |
46 import java.util.List; |
47 import java.util.List; |
47 import java.util.ArrayList; |
48 import java.util.ArrayList; |
48 import java.util.Date; |
49 import java.util.Date; |
49 import java.util.Set; |
50 import java.util.Set; |
50 import java.util.HashSet; |
|
51 import javax.security.auth.x500.X500Principal; |
51 import javax.security.auth.x500.X500Principal; |
52 import sun.security.util.Debug; |
52 import sun.security.util.Debug; |
53 |
53 |
54 /** |
54 /** |
55 * This class implements the PKIX validation algorithm for certification |
55 * This class implements the PKIX validation algorithm for certification |
65 private static final Debug debug = Debug.getInstance("certpath"); |
65 private static final Debug debug = Debug.getInstance("certpath"); |
66 private Date testDate; |
66 private Date testDate; |
67 private List<PKIXCertPathChecker> userCheckers; |
67 private List<PKIXCertPathChecker> userCheckers; |
68 private String sigProvider; |
68 private String sigProvider; |
69 private BasicChecker basicChecker; |
69 private BasicChecker basicChecker; |
|
70 private String ocspProperty; |
70 |
71 |
71 /** |
72 /** |
72 * Default constructor. |
73 * Default constructor. |
73 */ |
74 */ |
74 public PKIXCertPathValidator() {} |
75 public PKIXCertPathValidator() {} |
124 // we need to create a reversed path, where we reverse the |
125 // we need to create a reversed path, where we reverse the |
125 // ordering so that the target cert is the last certificate |
126 // ordering so that the target cert is the last certificate |
126 |
127 |
127 // Must copy elements of certList into a new modifiable List before |
128 // Must copy elements of certList into a new modifiable List before |
128 // calling Collections.reverse(). |
129 // calling Collections.reverse(). |
129 List<X509Certificate> certList = new ArrayList<X509Certificate> |
130 ArrayList<X509Certificate> certList = new ArrayList<X509Certificate> |
130 ((List<X509Certificate>)cp.getCertificates()); |
131 ((List<X509Certificate>)cp.getCertificates()); |
131 if (debug != null) { |
132 if (debug != null) { |
132 if (certList.isEmpty()) { |
133 if (certList.isEmpty()) { |
133 debug.println("PKIXCertPathValidator.engineValidate() " |
134 debug.println("PKIXCertPathValidator.engineValidate() " |
134 + "certList is empty"); |
135 + "certList is empty"); |
199 if (lastException != null) { |
200 if (lastException != null) { |
200 throw lastException; |
201 throw lastException; |
201 } |
202 } |
202 // (b) otherwise, generate new exception |
203 // (b) otherwise, generate new exception |
203 throw new CertPathValidatorException |
204 throw new CertPathValidatorException |
204 ("Path does not chain with any of the trust anchors"); |
205 ("Path does not chain with any of the trust anchors", |
|
206 null, null, -1, PKIXReason.NO_TRUST_ANCHOR); |
205 } |
207 } |
206 |
208 |
207 /** |
209 /** |
208 * Internal method to do some simple checks to see if a given cert is |
210 * Internal method to do some simple checks to see if a given cert is |
209 * worth trying to validate in the chain. |
211 * worth trying to validate in the chain. |
210 */ |
212 */ |
211 private boolean isWorthTrying(X509Certificate trustedCert, |
213 private boolean isWorthTrying(X509Certificate trustedCert, |
212 X509Certificate firstCert) |
214 X509Certificate firstCert) |
213 throws CertPathValidatorException |
|
214 { |
215 { |
215 if (debug != null) { |
216 if (debug != null) { |
216 debug.println("PKIXCertPathValidator.isWorthTrying() checking " |
217 debug.println("PKIXCertPathValidator.isWorthTrying() checking " |
217 + "if this trusted cert is worth trying ..."); |
218 + "if this trusted cert is worth trying ..."); |
218 } |
219 } |
238 |
239 |
239 /** |
240 /** |
240 * Internal method to setup the internal state |
241 * Internal method to setup the internal state |
241 */ |
242 */ |
242 private void populateVariables(PKIXParameters pkixParam) |
243 private void populateVariables(PKIXParameters pkixParam) |
243 throws CertPathValidatorException |
|
244 { |
244 { |
245 // default value for testDate is current time |
245 // default value for testDate is current time |
246 testDate = pkixParam.getDate(); |
246 testDate = pkixParam.getDate(); |
247 if (testDate == null) { |
247 if (testDate == null) { |
248 testDate = new Date(System.currentTimeMillis()); |
248 testDate = new Date(System.currentTimeMillis()); |
249 } |
249 } |
250 |
250 |
251 userCheckers = pkixParam.getCertPathCheckers(); |
251 userCheckers = pkixParam.getCertPathCheckers(); |
252 sigProvider = pkixParam.getSigProvider(); |
252 sigProvider = pkixParam.getSigProvider(); |
|
253 |
|
254 if (pkixParam.isRevocationEnabled()) { |
|
255 // Examine OCSP security property |
|
256 ocspProperty = AccessController.doPrivileged( |
|
257 new PrivilegedAction<String>() { |
|
258 public String run() { |
|
259 return |
|
260 Security.getProperty(OCSPChecker.OCSP_ENABLE_PROP); |
|
261 } |
|
262 }); |
|
263 } |
253 } |
264 } |
254 |
265 |
255 /** |
266 /** |
256 * Internal method to actually validate a constructed path. |
267 * Internal method to actually validate a constructed path. |
257 * |
268 * |
258 * @return the valid policy tree |
269 * @return the valid policy tree |
259 */ |
270 */ |
260 private PolicyNode doValidate( |
271 private PolicyNode doValidate( |
261 TrustAnchor anchor, CertPath cpOriginal, |
272 TrustAnchor anchor, CertPath cpOriginal, |
262 List<X509Certificate> certList, PKIXParameters pkixParam, |
273 ArrayList<X509Certificate> certList, PKIXParameters pkixParam, |
263 PolicyNodeImpl rootNode) throws CertPathValidatorException |
274 PolicyNodeImpl rootNode) throws CertPathValidatorException |
264 { |
275 { |
265 List<PKIXCertPathChecker> certPathCheckers = |
|
266 new ArrayList<PKIXCertPathChecker>(); |
|
267 |
|
268 int certPathLen = certList.size(); |
276 int certPathLen = certList.size(); |
269 |
277 |
270 basicChecker = new BasicChecker(anchor, testDate, sigProvider, false); |
278 basicChecker = new BasicChecker(anchor, testDate, sigProvider, false); |
271 KeyChecker keyChecker = new KeyChecker(certPathLen, |
279 KeyChecker keyChecker = new KeyChecker(certPathLen, |
272 pkixParam.getTargetCertConstraints()); |
280 pkixParam.getTargetCertConstraints()); |
279 pkixParam.isPolicyMappingInhibited(), |
287 pkixParam.isPolicyMappingInhibited(), |
280 pkixParam.isAnyPolicyInhibited(), |
288 pkixParam.isAnyPolicyInhibited(), |
281 pkixParam.getPolicyQualifiersRejected(), |
289 pkixParam.getPolicyQualifiersRejected(), |
282 rootNode); |
290 rootNode); |
283 |
291 |
|
292 ArrayList<PKIXCertPathChecker> certPathCheckers = |
|
293 new ArrayList<PKIXCertPathChecker>(); |
284 // add standard checkers that we will be using |
294 // add standard checkers that we will be using |
285 certPathCheckers.add(keyChecker); |
295 certPathCheckers.add(keyChecker); |
286 certPathCheckers.add(constraintsChecker); |
296 certPathCheckers.add(constraintsChecker); |
287 certPathCheckers.add(policyChecker); |
297 certPathCheckers.add(policyChecker); |
288 certPathCheckers.add(basicChecker); |
298 certPathCheckers.add(basicChecker); |
289 |
299 |
290 // only add a revocationChecker if revocation is enabled |
300 // only add a revocationChecker if revocation is enabled |
291 if (pkixParam.isRevocationEnabled()) { |
301 if (pkixParam.isRevocationEnabled()) { |
292 |
302 |
293 // Examine OCSP security property |
|
294 String ocspProperty = AccessController.doPrivileged( |
|
295 new PrivilegedAction<String>() { |
|
296 public String run() { |
|
297 return |
|
298 Security.getProperty(OCSPChecker.OCSP_ENABLE_PROP); |
|
299 } |
|
300 }); |
|
301 |
|
302 // Use OCSP if it has been enabled |
303 // Use OCSP if it has been enabled |
303 if ("true".equalsIgnoreCase(ocspProperty)) { |
304 if ("true".equalsIgnoreCase(ocspProperty)) { |
304 OCSPChecker ocspChecker = |
305 OCSPChecker ocspChecker = |
305 new OCSPChecker(cpOriginal, pkixParam); |
306 new OCSPChecker(cpOriginal, pkixParam); |
306 certPathCheckers.add(ocspChecker); |
307 certPathCheckers.add(ocspChecker); |