1 /* 2 * Copyright (c) 2012, 2015, 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 sun.security.provider.certpath; 26 27 import java.security.InvalidAlgorithmParameterException; 28 import java.security.PublicKey; 29 import java.security.cert.*; 30 import java.security.interfaces.DSAPublicKey; 31 import java.util.*; 32 import javax.security.auth.x500.X500Principal; 33 34 import sun.security.util.Debug; 35 36 /** 37 * Common utility methods and classes used by the PKIX CertPathValidator and 38 * CertPathBuilder implementation. 39 */ 40 class PKIX { 41 42 private static final Debug debug = Debug.getInstance("certpath"); 43 PKIX()44 private PKIX() { } 45 isDSAPublicKeyWithoutParams(PublicKey publicKey)46 static boolean isDSAPublicKeyWithoutParams(PublicKey publicKey) { 47 return (publicKey instanceof DSAPublicKey && 48 ((DSAPublicKey)publicKey).getParams() == null); 49 } 50 checkParams(CertPath cp, CertPathParameters params)51 static ValidatorParams checkParams(CertPath cp, CertPathParameters params) 52 throws InvalidAlgorithmParameterException 53 { 54 if (!(params instanceof PKIXParameters)) { 55 throw new InvalidAlgorithmParameterException("inappropriate " 56 + "params, must be an instance of PKIXParameters"); 57 } 58 return new ValidatorParams(cp, (PKIXParameters)params); 59 } 60 checkBuilderParams(CertPathParameters params)61 static BuilderParams checkBuilderParams(CertPathParameters params) 62 throws InvalidAlgorithmParameterException 63 { 64 if (!(params instanceof PKIXBuilderParameters)) { 65 throw new InvalidAlgorithmParameterException("inappropriate " 66 + "params, must be an instance of PKIXBuilderParameters"); 67 } 68 return new BuilderParams((PKIXBuilderParameters)params); 69 } 70 71 /** 72 * PKIXParameters that are shared by the PKIX CertPathValidator 73 * implementation. Provides additional functionality and avoids 74 * unnecessary cloning. 75 */ 76 static class ValidatorParams { 77 private final PKIXParameters params; 78 private CertPath certPath; 79 private List<PKIXCertPathChecker> checkers; 80 private List<CertStore> stores; 81 private boolean gotDate; 82 private Date date; 83 private Set<String> policies; 84 private boolean gotConstraints; 85 private CertSelector constraints; 86 private Set<TrustAnchor> anchors; 87 private List<X509Certificate> certs; 88 ValidatorParams(CertPath cp, PKIXParameters params)89 ValidatorParams(CertPath cp, PKIXParameters params) 90 throws InvalidAlgorithmParameterException 91 { 92 this(params); 93 if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) { 94 throw new InvalidAlgorithmParameterException("inappropriate " 95 + "CertPath type specified, must be X.509 or X509"); 96 } 97 this.certPath = cp; 98 } 99 ValidatorParams(PKIXParameters params)100 ValidatorParams(PKIXParameters params) 101 throws InvalidAlgorithmParameterException 102 { 103 this.anchors = params.getTrustAnchors(); 104 // Make sure that none of the trust anchors include name constraints 105 // (not supported). 106 for (TrustAnchor anchor : this.anchors) { 107 if (anchor.getNameConstraints() != null) { 108 throw new InvalidAlgorithmParameterException 109 ("name constraints in trust anchor not supported"); 110 } 111 } 112 this.params = params; 113 } 114 certPath()115 CertPath certPath() { 116 return certPath; 117 } 118 // called by CertPathBuilder after path has been built setCertPath(CertPath cp)119 void setCertPath(CertPath cp) { 120 this.certPath = cp; 121 } certificates()122 List<X509Certificate> certificates() { 123 if (certs == null) { 124 if (certPath == null) { 125 certs = Collections.emptyList(); 126 } else { 127 // Reverse the ordering for validation so that the target 128 // cert is the last certificate 129 @SuppressWarnings("unchecked") 130 List<X509Certificate> xc = new ArrayList<> 131 ((List<X509Certificate>)certPath.getCertificates()); 132 Collections.reverse(xc); 133 certs = xc; 134 } 135 } 136 return certs; 137 } certPathCheckers()138 List<PKIXCertPathChecker> certPathCheckers() { 139 if (checkers == null) 140 checkers = params.getCertPathCheckers(); 141 return checkers; 142 } certStores()143 List<CertStore> certStores() { 144 if (stores == null) 145 stores = params.getCertStores(); 146 return stores; 147 } date()148 Date date() { 149 if (!gotDate) { 150 date = params.getDate(); 151 if (date == null) 152 date = new Date(); 153 gotDate = true; 154 } 155 return date; 156 } initialPolicies()157 Set<String> initialPolicies() { 158 if (policies == null) 159 policies = params.getInitialPolicies(); 160 return policies; 161 } targetCertConstraints()162 CertSelector targetCertConstraints() { 163 if (!gotConstraints) { 164 constraints = params.getTargetCertConstraints(); 165 gotConstraints = true; 166 } 167 return constraints; 168 } trustAnchors()169 Set<TrustAnchor> trustAnchors() { 170 return anchors; 171 } revocationEnabled()172 boolean revocationEnabled() { 173 return params.isRevocationEnabled(); 174 } policyMappingInhibited()175 boolean policyMappingInhibited() { 176 return params.isPolicyMappingInhibited(); 177 } explicitPolicyRequired()178 boolean explicitPolicyRequired() { 179 return params.isExplicitPolicyRequired(); 180 } policyQualifiersRejected()181 boolean policyQualifiersRejected() { 182 return params.getPolicyQualifiersRejected(); 183 } sigProvider()184 String sigProvider() { return params.getSigProvider(); } anyPolicyInhibited()185 boolean anyPolicyInhibited() { return params.isAnyPolicyInhibited(); } 186 187 // in rare cases we need access to the original params, for example 188 // in order to clone CertPathCheckers before building a new chain getPKIXParameters()189 PKIXParameters getPKIXParameters() { 190 return params; 191 } 192 } 193 194 static class BuilderParams extends ValidatorParams { 195 private PKIXBuilderParameters params; 196 private List<CertStore> stores; 197 private X500Principal targetSubject; 198 BuilderParams(PKIXBuilderParameters params)199 BuilderParams(PKIXBuilderParameters params) 200 throws InvalidAlgorithmParameterException 201 { 202 super(params); 203 checkParams(params); 204 } checkParams(PKIXBuilderParameters params)205 private void checkParams(PKIXBuilderParameters params) 206 throws InvalidAlgorithmParameterException 207 { 208 CertSelector sel = targetCertConstraints(); 209 if (!(sel instanceof X509CertSelector)) { 210 throw new InvalidAlgorithmParameterException("the " 211 + "targetCertConstraints parameter must be an " 212 + "X509CertSelector"); 213 } 214 this.params = params; 215 this.targetSubject = getTargetSubject( 216 certStores(), (X509CertSelector)targetCertConstraints()); 217 } certStores()218 @Override List<CertStore> certStores() { 219 if (stores == null) { 220 // reorder CertStores so that local CertStores are tried first 221 stores = new ArrayList<>(params.getCertStores()); 222 Collections.sort(stores, new CertStoreComparator()); 223 } 224 return stores; 225 } maxPathLength()226 int maxPathLength() { return params.getMaxPathLength(); } params()227 PKIXBuilderParameters params() { return params; } targetSubject()228 X500Principal targetSubject() { return targetSubject; } 229 230 /** 231 * Returns the target subject DN from the first X509Certificate that 232 * is fetched that matches the specified X509CertSelector. 233 */ getTargetSubject(List<CertStore> stores, X509CertSelector sel)234 private static X500Principal getTargetSubject(List<CertStore> stores, 235 X509CertSelector sel) 236 throws InvalidAlgorithmParameterException 237 { 238 X500Principal subject = sel.getSubject(); 239 if (subject != null) { 240 return subject; 241 } 242 X509Certificate cert = sel.getCertificate(); 243 if (cert != null) { 244 subject = cert.getSubjectX500Principal(); 245 } 246 if (subject != null) { 247 return subject; 248 } 249 for (CertStore store : stores) { 250 try { 251 Collection<? extends Certificate> certs = 252 (Collection<? extends Certificate>) 253 store.getCertificates(sel); 254 if (!certs.isEmpty()) { 255 X509Certificate xc = 256 (X509Certificate)certs.iterator().next(); 257 return xc.getSubjectX500Principal(); 258 } 259 } catch (CertStoreException e) { 260 // ignore but log it 261 if (debug != null) { 262 debug.println("BuilderParams.getTargetSubjectDN: " + 263 "non-fatal exception retrieving certs: " + e); 264 e.printStackTrace(); 265 } 266 } 267 } 268 throw new InvalidAlgorithmParameterException 269 ("Could not determine unique target subject"); 270 } 271 } 272 273 /** 274 * A CertStoreException with additional information about the type of 275 * CertStore that generated the exception. 276 */ 277 static class CertStoreTypeException extends CertStoreException { 278 private static final long serialVersionUID = 7463352639238322556L; 279 280 private final String type; 281 CertStoreTypeException(String type, CertStoreException cse)282 CertStoreTypeException(String type, CertStoreException cse) { 283 super(cse.getMessage(), cse.getCause()); 284 this.type = type; 285 } getType()286 String getType() { 287 return type; 288 } 289 } 290 291 /** 292 * Comparator that orders CertStores so that local CertStores come before 293 * remote CertStores. 294 */ 295 private static class CertStoreComparator implements Comparator<CertStore> { 296 @Override compare(CertStore store1, CertStore store2)297 public int compare(CertStore store1, CertStore store2) { 298 if (store1.getType().equals("Collection") || 299 store1.getCertStoreParameters() instanceof 300 CollectionCertStoreParameters) { 301 return -1; 302 } else { 303 return 1; 304 } 305 } 306 } 307 } 308