1 /* |
1 /* |
2 * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved. |
2 * Copyright 2002-2009 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 |
127 if (date == null) { |
127 if (date == null) { |
128 date = new Date(); |
128 date = new Date(); |
129 } |
129 } |
130 // verify top down, starting at the certificate issued by |
130 // verify top down, starting at the certificate issued by |
131 // the trust anchor |
131 // the trust anchor |
|
132 int maxPathLength = chain.length - 1; |
132 for (int i = chain.length - 2; i >= 0; i--) { |
133 for (int i = chain.length - 2; i >= 0; i--) { |
133 X509Certificate issuerCert = chain[i + 1]; |
134 X509Certificate issuerCert = chain[i + 1]; |
134 X509Certificate cert = chain[i]; |
135 X509Certificate cert = chain[i]; |
135 |
136 |
136 |
137 |
155 (ValidatorException.T_SIGNATURE_ERROR, cert, e); |
156 (ValidatorException.T_SIGNATURE_ERROR, cert, e); |
156 } |
157 } |
157 |
158 |
158 // check extensions for CA certs |
159 // check extensions for CA certs |
159 if (i != 0) { |
160 if (i != 0) { |
160 checkExtensions(cert, i); |
161 maxPathLength = checkExtensions(cert, maxPathLength); |
161 } |
162 } |
162 } |
163 } |
163 |
164 |
164 return chain; |
165 return chain; |
165 } |
166 } |
166 |
167 |
167 private void checkExtensions(X509Certificate cert, int index) |
168 private int checkExtensions(X509Certificate cert, int maxPathLen) |
168 throws CertificateException { |
169 throws CertificateException { |
169 Set<String> critSet = cert.getCriticalExtensionOIDs(); |
170 Set<String> critSet = cert.getCriticalExtensionOIDs(); |
170 if (critSet == null) { |
171 if (critSet == null) { |
171 critSet = Collections.<String>emptySet(); |
172 critSet = Collections.<String>emptySet(); |
172 } |
173 } |
173 |
174 |
174 // Check the basic constraints extension |
175 // Check the basic constraints extension |
175 checkBasicConstraints(cert, critSet, index); |
176 int pathLenConstraint = |
|
177 checkBasicConstraints(cert, critSet, maxPathLen); |
176 |
178 |
177 // Check the key usage and extended key usage extensions |
179 // Check the key usage and extended key usage extensions |
178 checkKeyUsage(cert, critSet); |
180 checkKeyUsage(cert, critSet); |
179 |
181 |
180 // check Netscape certificate type extension |
182 // check Netscape certificate type extension |
183 if (!critSet.isEmpty()) { |
185 if (!critSet.isEmpty()) { |
184 throw new ValidatorException |
186 throw new ValidatorException |
185 ("Certificate contains unknown critical extensions: " + critSet, |
187 ("Certificate contains unknown critical extensions: " + critSet, |
186 ValidatorException.T_CA_EXTENSIONS, cert); |
188 ValidatorException.T_CA_EXTENSIONS, cert); |
187 } |
189 } |
|
190 |
|
191 return pathLenConstraint; |
188 } |
192 } |
189 |
193 |
190 private void checkNetscapeCertType(X509Certificate cert, |
194 private void checkNetscapeCertType(X509Certificate cert, |
191 Set<String> critSet) throws CertificateException { |
195 Set<String> critSet) throws CertificateException { |
192 if (variant.equals(VAR_GENERIC)) { |
196 if (variant.equals(VAR_GENERIC)) { |
244 } catch (IOException e) { |
248 } catch (IOException e) { |
245 return false; |
249 return false; |
246 } |
250 } |
247 } |
251 } |
248 |
252 |
249 private void checkBasicConstraints(X509Certificate cert, |
253 private int checkBasicConstraints(X509Certificate cert, |
250 Set<String> critSet, int index) throws CertificateException { |
254 Set<String> critSet, int maxPathLen) throws CertificateException { |
251 |
255 |
252 critSet.remove(OID_BASIC_CONSTRAINTS); |
256 critSet.remove(OID_BASIC_CONSTRAINTS); |
253 int constraints = cert.getBasicConstraints(); |
257 int constraints = cert.getBasicConstraints(); |
254 // reject, if extension missing or not a CA (constraints == -1) |
258 // reject, if extension missing or not a CA (constraints == -1) |
255 if (constraints < 0) { |
259 if (constraints < 0) { |
256 throw new ValidatorException("End user tried to act as a CA", |
260 throw new ValidatorException("End user tried to act as a CA", |
257 ValidatorException.T_CA_EXTENSIONS, cert); |
261 ValidatorException.T_CA_EXTENSIONS, cert); |
258 } |
262 } |
259 if (index - 1 > constraints) { |
263 |
260 throw new ValidatorException("Violated path length constraints", |
264 // if the certificate is self-issued, ignore the pathLenConstraint |
261 ValidatorException.T_CA_EXTENSIONS, cert); |
265 // checking. |
262 } |
266 if (!X509CertImpl.isSelfIssued(cert)) { |
|
267 if (maxPathLen <= 1) { // reserved one for end-entity certificate |
|
268 throw new ValidatorException("Violated path length constraints", |
|
269 ValidatorException.T_CA_EXTENSIONS, cert); |
|
270 } |
|
271 |
|
272 maxPathLen--; |
|
273 } |
|
274 |
|
275 if (maxPathLen > constraints) { |
|
276 maxPathLen = constraints; |
|
277 } |
|
278 |
|
279 return maxPathLen; |
263 } |
280 } |
264 |
281 |
265 /* |
282 /* |
266 * Verify the key usage and extended key usage for intermediate |
283 * Verify the key usage and extended key usage for intermediate |
267 * certificates. |
284 * certificates. |
302 c.add(trustedCert); |
319 c.add(trustedCert); |
303 return c.toArray(CHAIN0); |
320 return c.toArray(CHAIN0); |
304 } |
321 } |
305 c.add(cert); |
322 c.add(cert); |
306 } |
323 } |
|
324 |
307 // check if we can append a trusted cert |
325 // check if we can append a trusted cert |
308 X509Certificate cert = chain[chain.length - 1]; |
326 X509Certificate cert = chain[chain.length - 1]; |
309 X500Principal subject = cert.getSubjectX500Principal(); |
327 X500Principal subject = cert.getSubjectX500Principal(); |
310 X500Principal issuer = cert.getIssuerX500Principal(); |
328 X500Principal issuer = cert.getIssuerX500Principal(); |
311 if (subject.equals(issuer) == false) { |
329 List<X509Certificate> list = trustedX500Principals.get(issuer); |
312 List<X509Certificate> list = trustedX500Principals.get(issuer); |
330 if (list != null) { |
313 if (list != null) { |
331 X509Certificate trustedCert = list.iterator().next(); |
314 X509Certificate trustedCert = list.iterator().next(); |
332 c.add(trustedCert); |
315 c.add(trustedCert); |
333 return c.toArray(CHAIN0); |
316 return c.toArray(CHAIN0); |
334 } |
317 } |
335 |
318 } |
|
319 // no trusted cert found, error |
336 // no trusted cert found, error |
320 throw new ValidatorException(ValidatorException.T_NO_TRUST_ANCHOR); |
337 throw new ValidatorException(ValidatorException.T_NO_TRUST_ANCHOR); |
321 } |
338 } |
322 |
339 |
323 /** |
340 /** |