1 /* 2 * Copyright (c) 2000, 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 26 package java.security.cert; 27 28 import java.io.IOException; 29 import java.math.BigInteger; 30 import java.security.PublicKey; 31 import java.util.*; 32 import javax.security.auth.x500.X500Principal; 33 34 import sun.misc.HexDumpEncoder; 35 import sun.security.util.Debug; 36 import sun.security.util.DerInputStream; 37 import sun.security.util.DerValue; 38 import sun.security.util.ObjectIdentifier; 39 import sun.security.x509.*; 40 41 /** 42 * A {@code CertSelector} that selects {@code X509Certificates} that 43 * match all specified criteria. This class is particularly useful when 44 * selecting certificates from a {@code CertStore} to build a 45 * PKIX-compliant certification path. 46 * <p> 47 * When first constructed, an {@code X509CertSelector} has no criteria 48 * enabled and each of the {@code get} methods return a default value 49 * ({@code null}, or {@code -1} for the {@link #getBasicConstraints 50 * getBasicConstraints} method). Therefore, the {@link #match match} 51 * method would return {@code true} for any {@code X509Certificate}. 52 * Typically, several criteria are enabled (by calling 53 * {@link #setIssuer setIssuer} or 54 * {@link #setKeyUsage setKeyUsage}, for instance) and then the 55 * {@code X509CertSelector} is passed to 56 * {@link CertStore#getCertificates CertStore.getCertificates} or some similar 57 * method. 58 * <p> 59 * Several criteria can be enabled (by calling {@link #setIssuer setIssuer} 60 * and {@link #setSerialNumber setSerialNumber}, 61 * for example) such that the {@code match} method 62 * usually uniquely matches a single {@code X509Certificate}. We say 63 * usually, since it is possible for two issuing CAs to have the same 64 * distinguished name and each issue a certificate with the same serial 65 * number. Other unique combinations include the issuer, subject, 66 * subjectKeyIdentifier and/or the subjectPublicKey criteria. 67 * <p> 68 * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: 69 * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a> for 70 * definitions of the X.509 certificate extensions mentioned below. 71 * <p> 72 * <b>Concurrent Access</b> 73 * <p> 74 * Unless otherwise specified, the methods defined in this class are not 75 * thread-safe. Multiple threads that need to access a single 76 * object concurrently should synchronize amongst themselves and 77 * provide the necessary locking. Multiple threads each manipulating 78 * separate objects need not synchronize. 79 * 80 * @see CertSelector 81 * @see X509Certificate 82 * 83 * @since 1.4 84 * @author Steve Hanna 85 */ 86 public class X509CertSelector implements CertSelector { 87 88 private static final Debug debug = Debug.getInstance("certpath"); 89 90 private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE = 91 ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0}); 92 93 static { CertPathHelperImpl.initialize()94 CertPathHelperImpl.initialize(); 95 } 96 97 private BigInteger serialNumber; 98 private X500Principal issuer; 99 private X500Principal subject; 100 private byte[] subjectKeyID; 101 private byte[] authorityKeyID; 102 private Date certificateValid; 103 private Date privateKeyValid; 104 private ObjectIdentifier subjectPublicKeyAlgID; 105 private PublicKey subjectPublicKey; 106 private byte[] subjectPublicKeyBytes; 107 private boolean[] keyUsage; 108 private Set<String> keyPurposeSet; 109 private Set<ObjectIdentifier> keyPurposeOIDSet; 110 private Set<List<?>> subjectAlternativeNames; 111 private Set<GeneralNameInterface> subjectAlternativeGeneralNames; 112 private CertificatePolicySet policy; 113 private Set<String> policySet; 114 private Set<List<?>> pathToNames; 115 private Set<GeneralNameInterface> pathToGeneralNames; 116 private NameConstraintsExtension nc; 117 private byte[] ncBytes; 118 private int basicConstraints = -1; 119 private X509Certificate x509Cert; 120 private boolean matchAllSubjectAltNames = true; 121 122 private static final Boolean FALSE = Boolean.FALSE; 123 124 private static final int PRIVATE_KEY_USAGE_ID = 0; 125 private static final int SUBJECT_ALT_NAME_ID = 1; 126 private static final int NAME_CONSTRAINTS_ID = 2; 127 private static final int CERT_POLICIES_ID = 3; 128 private static final int EXTENDED_KEY_USAGE_ID = 4; 129 private static final int NUM_OF_EXTENSIONS = 5; 130 private static final String[] EXTENSION_OIDS = new String[NUM_OF_EXTENSIONS]; 131 132 static { 133 EXTENSION_OIDS[PRIVATE_KEY_USAGE_ID] = "2.5.29.16"; 134 EXTENSION_OIDS[SUBJECT_ALT_NAME_ID] = "2.5.29.17"; 135 EXTENSION_OIDS[NAME_CONSTRAINTS_ID] = "2.5.29.30"; 136 EXTENSION_OIDS[CERT_POLICIES_ID] = "2.5.29.32"; 137 EXTENSION_OIDS[EXTENDED_KEY_USAGE_ID] = "2.5.29.37"; 138 }; 139 140 /* Constants representing the GeneralName types */ 141 static final int NAME_ANY = 0; 142 static final int NAME_RFC822 = 1; 143 static final int NAME_DNS = 2; 144 static final int NAME_X400 = 3; 145 static final int NAME_DIRECTORY = 4; 146 static final int NAME_EDI = 5; 147 static final int NAME_URI = 6; 148 static final int NAME_IP = 7; 149 static final int NAME_OID = 8; 150 151 /** 152 * Creates an {@code X509CertSelector}. Initially, no criteria are set 153 * so any {@code X509Certificate} will match. 154 */ X509CertSelector()155 public X509CertSelector() { 156 // empty 157 } 158 159 /** 160 * Sets the certificateEquals criterion. The specified 161 * {@code X509Certificate} must be equal to the 162 * {@code X509Certificate} passed to the {@code match} method. 163 * If {@code null}, then this check is not applied. 164 * 165 * <p>This method is particularly useful when it is necessary to 166 * match a single certificate. Although other criteria can be specified 167 * in conjunction with the certificateEquals criterion, it is usually not 168 * practical or necessary. 169 * 170 * @param cert the {@code X509Certificate} to match (or 171 * {@code null}) 172 * @see #getCertificate 173 */ setCertificate(X509Certificate cert)174 public void setCertificate(X509Certificate cert) { 175 x509Cert = cert; 176 } 177 178 /** 179 * Sets the serialNumber criterion. The specified serial number 180 * must match the certificate serial number in the 181 * {@code X509Certificate}. If {@code null}, any certificate 182 * serial number will do. 183 * 184 * @param serial the certificate serial number to match 185 * (or {@code null}) 186 * @see #getSerialNumber 187 */ setSerialNumber(BigInteger serial)188 public void setSerialNumber(BigInteger serial) { 189 serialNumber = serial; 190 } 191 192 /** 193 * Sets the issuer criterion. The specified distinguished name 194 * must match the issuer distinguished name in the 195 * {@code X509Certificate}. If {@code null}, any issuer 196 * distinguished name will do. 197 * 198 * @param issuer a distinguished name as X500Principal 199 * (or {@code null}) 200 * @since 1.5 201 */ setIssuer(X500Principal issuer)202 public void setIssuer(X500Principal issuer) { 203 this.issuer = issuer; 204 } 205 206 /** 207 * <strong>Denigrated</strong>, use {@linkplain #setIssuer(X500Principal)} 208 * or {@linkplain #setIssuer(byte[])} instead. This method should not be 209 * relied on as it can fail to match some certificates because of a loss of 210 * encoding information in the 211 * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a> String form 212 * of some distinguished names. 213 * <p> 214 * Sets the issuer criterion. The specified distinguished name 215 * must match the issuer distinguished name in the 216 * {@code X509Certificate}. If {@code null}, any issuer 217 * distinguished name will do. 218 * <p> 219 * If {@code issuerDN} is not {@code null}, it should contain a 220 * distinguished name, in RFC 2253 format. 221 * 222 * @param issuerDN a distinguished name in RFC 2253 format 223 * (or {@code null}) 224 * @throws IOException if a parsing error occurs (incorrect form for DN) 225 */ setIssuer(String issuerDN)226 public void setIssuer(String issuerDN) throws IOException { 227 if (issuerDN == null) { 228 issuer = null; 229 } else { 230 issuer = new X500Name(issuerDN).asX500Principal(); 231 } 232 } 233 234 /** 235 * Sets the issuer criterion. The specified distinguished name 236 * must match the issuer distinguished name in the 237 * {@code X509Certificate}. If {@code null} is specified, 238 * the issuer criterion is disabled and any issuer distinguished name will 239 * do. 240 * <p> 241 * If {@code issuerDN} is not {@code null}, it should contain a 242 * single DER encoded distinguished name, as defined in X.501. The ASN.1 243 * notation for this structure is as follows. 244 * <pre>{@code 245 * Name ::= CHOICE { 246 * RDNSequence } 247 * 248 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 249 * 250 * RelativeDistinguishedName ::= 251 * SET SIZE (1 .. MAX) OF AttributeTypeAndValue 252 * 253 * AttributeTypeAndValue ::= SEQUENCE { 254 * type AttributeType, 255 * value AttributeValue } 256 * 257 * AttributeType ::= OBJECT IDENTIFIER 258 * 259 * AttributeValue ::= ANY DEFINED BY AttributeType 260 * .... 261 * DirectoryString ::= CHOICE { 262 * teletexString TeletexString (SIZE (1..MAX)), 263 * printableString PrintableString (SIZE (1..MAX)), 264 * universalString UniversalString (SIZE (1..MAX)), 265 * utf8String UTF8String (SIZE (1.. MAX)), 266 * bmpString BMPString (SIZE (1..MAX)) } 267 * }</pre> 268 * <p> 269 * Note that the byte array specified here is cloned to protect against 270 * subsequent modifications. 271 * 272 * @param issuerDN a byte array containing the distinguished name 273 * in ASN.1 DER encoded form (or {@code null}) 274 * @throws IOException if an encoding error occurs (incorrect form for DN) 275 */ setIssuer(byte[] issuerDN)276 public void setIssuer(byte[] issuerDN) throws IOException { 277 try { 278 issuer = (issuerDN == null ? null : new X500Principal(issuerDN)); 279 } catch (IllegalArgumentException e) { 280 throw new IOException("Invalid name", e); 281 } 282 } 283 284 /** 285 * Sets the subject criterion. The specified distinguished name 286 * must match the subject distinguished name in the 287 * {@code X509Certificate}. If {@code null}, any subject 288 * distinguished name will do. 289 * 290 * @param subject a distinguished name as X500Principal 291 * (or {@code null}) 292 * @since 1.5 293 */ setSubject(X500Principal subject)294 public void setSubject(X500Principal subject) { 295 this.subject = subject; 296 } 297 298 /** 299 * <strong>Denigrated</strong>, use {@linkplain #setSubject(X500Principal)} 300 * or {@linkplain #setSubject(byte[])} instead. This method should not be 301 * relied on as it can fail to match some certificates because of a loss of 302 * encoding information in the RFC 2253 String form of some distinguished 303 * names. 304 * <p> 305 * Sets the subject criterion. The specified distinguished name 306 * must match the subject distinguished name in the 307 * {@code X509Certificate}. If {@code null}, any subject 308 * distinguished name will do. 309 * <p> 310 * If {@code subjectDN} is not {@code null}, it should contain a 311 * distinguished name, in RFC 2253 format. 312 * 313 * @param subjectDN a distinguished name in RFC 2253 format 314 * (or {@code null}) 315 * @throws IOException if a parsing error occurs (incorrect form for DN) 316 */ setSubject(String subjectDN)317 public void setSubject(String subjectDN) throws IOException { 318 if (subjectDN == null) { 319 subject = null; 320 } else { 321 subject = new X500Name(subjectDN).asX500Principal(); 322 } 323 } 324 325 /** 326 * Sets the subject criterion. The specified distinguished name 327 * must match the subject distinguished name in the 328 * {@code X509Certificate}. If {@code null}, any subject 329 * distinguished name will do. 330 * <p> 331 * If {@code subjectDN} is not {@code null}, it should contain a 332 * single DER encoded distinguished name, as defined in X.501. For the ASN.1 333 * notation for this structure, see 334 * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}. 335 * 336 * @param subjectDN a byte array containing the distinguished name in 337 * ASN.1 DER format (or {@code null}) 338 * @throws IOException if an encoding error occurs (incorrect form for DN) 339 */ setSubject(byte[] subjectDN)340 public void setSubject(byte[] subjectDN) throws IOException { 341 try { 342 subject = (subjectDN == null ? null : new X500Principal(subjectDN)); 343 } catch (IllegalArgumentException e) { 344 throw new IOException("Invalid name", e); 345 } 346 } 347 348 /** 349 * Sets the subjectKeyIdentifier criterion. The 350 * {@code X509Certificate} must contain a SubjectKeyIdentifier 351 * extension for which the contents of the extension 352 * matches the specified criterion value. 353 * If the criterion value is {@code null}, no 354 * subjectKeyIdentifier check will be done. 355 * <p> 356 * If {@code subjectKeyID} is not {@code null}, it 357 * should contain a single DER encoded value corresponding to the contents 358 * of the extension value (not including the object identifier, 359 * criticality setting, and encapsulating OCTET STRING) 360 * for a SubjectKeyIdentifier extension. 361 * The ASN.1 notation for this structure follows. 362 * 363 * <pre>{@code 364 * SubjectKeyIdentifier ::= KeyIdentifier 365 * 366 * KeyIdentifier ::= OCTET STRING 367 * }</pre> 368 * <p> 369 * Since the format of subject key identifiers is not mandated by 370 * any standard, subject key identifiers are not parsed by the 371 * {@code X509CertSelector}. Instead, the values are compared using 372 * a byte-by-byte comparison. 373 * <p> 374 * Note that the byte array supplied here is cloned to protect against 375 * subsequent modifications. 376 * 377 * @param subjectKeyID the subject key identifier (or {@code null}) 378 * @see #getSubjectKeyIdentifier 379 */ setSubjectKeyIdentifier(byte[] subjectKeyID)380 public void setSubjectKeyIdentifier(byte[] subjectKeyID) { 381 if (subjectKeyID == null) { 382 this.subjectKeyID = null; 383 } else { 384 this.subjectKeyID = subjectKeyID.clone(); 385 } 386 } 387 388 /** 389 * Sets the authorityKeyIdentifier criterion. The 390 * {@code X509Certificate} must contain an 391 * AuthorityKeyIdentifier extension for which the contents of the 392 * extension value matches the specified criterion value. 393 * If the criterion value is {@code null}, no 394 * authorityKeyIdentifier check will be done. 395 * <p> 396 * If {@code authorityKeyID} is not {@code null}, it 397 * should contain a single DER encoded value corresponding to the contents 398 * of the extension value (not including the object identifier, 399 * criticality setting, and encapsulating OCTET STRING) 400 * for an AuthorityKeyIdentifier extension. 401 * The ASN.1 notation for this structure follows. 402 * 403 * <pre>{@code 404 * AuthorityKeyIdentifier ::= SEQUENCE { 405 * keyIdentifier [0] KeyIdentifier OPTIONAL, 406 * authorityCertIssuer [1] GeneralNames OPTIONAL, 407 * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } 408 * 409 * KeyIdentifier ::= OCTET STRING 410 * }</pre> 411 * <p> 412 * Authority key identifiers are not parsed by the 413 * {@code X509CertSelector}. Instead, the values are 414 * compared using a byte-by-byte comparison. 415 * <p> 416 * When the {@code keyIdentifier} field of 417 * {@code AuthorityKeyIdentifier} is populated, the value is 418 * usually taken from the {@code SubjectKeyIdentifier} extension 419 * in the issuer's certificate. Note, however, that the result of 420 * {@code X509Certificate.getExtensionValue(<SubjectKeyIdentifier Object 421 * Identifier>)} on the issuer's certificate may NOT be used 422 * directly as the input to {@code setAuthorityKeyIdentifier}. 423 * This is because the SubjectKeyIdentifier contains 424 * only a KeyIdentifier OCTET STRING, and not a SEQUENCE of 425 * KeyIdentifier, GeneralNames, and CertificateSerialNumber. 426 * In order to use the extension value of the issuer certificate's 427 * {@code SubjectKeyIdentifier} 428 * extension, it will be necessary to extract the value of the embedded 429 * {@code KeyIdentifier} OCTET STRING, then DER encode this OCTET 430 * STRING inside a SEQUENCE. 431 * For more details on SubjectKeyIdentifier, see 432 * {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}. 433 * <p> 434 * Note also that the byte array supplied here is cloned to protect against 435 * subsequent modifications. 436 * 437 * @param authorityKeyID the authority key identifier 438 * (or {@code null}) 439 * @see #getAuthorityKeyIdentifier 440 */ setAuthorityKeyIdentifier(byte[] authorityKeyID)441 public void setAuthorityKeyIdentifier(byte[] authorityKeyID) { 442 if (authorityKeyID == null) { 443 this.authorityKeyID = null; 444 } else { 445 this.authorityKeyID = authorityKeyID.clone(); 446 } 447 } 448 449 /** 450 * Sets the certificateValid criterion. The specified date must fall 451 * within the certificate validity period for the 452 * {@code X509Certificate}. If {@code null}, no certificateValid 453 * check will be done. 454 * <p> 455 * Note that the {@code Date} supplied here is cloned to protect 456 * against subsequent modifications. 457 * 458 * @param certValid the {@code Date} to check (or {@code null}) 459 * @see #getCertificateValid 460 */ setCertificateValid(Date certValid)461 public void setCertificateValid(Date certValid) { 462 if (certValid == null) { 463 certificateValid = null; 464 } else { 465 certificateValid = (Date)certValid.clone(); 466 } 467 } 468 469 /** 470 * Sets the privateKeyValid criterion. The specified date must fall 471 * within the private key validity period for the 472 * {@code X509Certificate}. If {@code null}, no privateKeyValid 473 * check will be done. 474 * <p> 475 * Note that the {@code Date} supplied here is cloned to protect 476 * against subsequent modifications. 477 * 478 * @param privateKeyValid the {@code Date} to check (or 479 * {@code null}) 480 * @see #getPrivateKeyValid 481 */ setPrivateKeyValid(Date privateKeyValid)482 public void setPrivateKeyValid(Date privateKeyValid) { 483 if (privateKeyValid == null) { 484 this.privateKeyValid = null; 485 } else { 486 this.privateKeyValid = (Date)privateKeyValid.clone(); 487 } 488 } 489 490 /** 491 * Sets the subjectPublicKeyAlgID criterion. The 492 * {@code X509Certificate} must contain a subject public key 493 * with the specified algorithm. If {@code null}, no 494 * subjectPublicKeyAlgID check will be done. 495 * 496 * @param oid The object identifier (OID) of the algorithm to check 497 * for (or {@code null}). An OID is represented by a 498 * set of nonnegative integers separated by periods. 499 * @throws IOException if the OID is invalid, such as 500 * the first component being not 0, 1 or 2 or the second component 501 * being greater than 39. 502 * 503 * @see #getSubjectPublicKeyAlgID 504 */ setSubjectPublicKeyAlgID(String oid)505 public void setSubjectPublicKeyAlgID(String oid) throws IOException { 506 if (oid == null) { 507 subjectPublicKeyAlgID = null; 508 } else { 509 subjectPublicKeyAlgID = new ObjectIdentifier(oid); 510 } 511 } 512 513 /** 514 * Sets the subjectPublicKey criterion. The 515 * {@code X509Certificate} must contain the specified subject public 516 * key. If {@code null}, no subjectPublicKey check will be done. 517 * 518 * @param key the subject public key to check for (or {@code null}) 519 * @see #getSubjectPublicKey 520 */ setSubjectPublicKey(PublicKey key)521 public void setSubjectPublicKey(PublicKey key) { 522 if (key == null) { 523 subjectPublicKey = null; 524 subjectPublicKeyBytes = null; 525 } else { 526 subjectPublicKey = key; 527 subjectPublicKeyBytes = key.getEncoded(); 528 } 529 } 530 531 /** 532 * Sets the subjectPublicKey criterion. The {@code X509Certificate} 533 * must contain the specified subject public key. If {@code null}, 534 * no subjectPublicKey check will be done. 535 * <p> 536 * Because this method allows the public key to be specified as a byte 537 * array, it may be used for unknown key types. 538 * <p> 539 * If {@code key} is not {@code null}, it should contain a 540 * single DER encoded SubjectPublicKeyInfo structure, as defined in X.509. 541 * The ASN.1 notation for this structure is as follows. 542 * <pre>{@code 543 * SubjectPublicKeyInfo ::= SEQUENCE { 544 * algorithm AlgorithmIdentifier, 545 * subjectPublicKey BIT STRING } 546 * 547 * AlgorithmIdentifier ::= SEQUENCE { 548 * algorithm OBJECT IDENTIFIER, 549 * parameters ANY DEFINED BY algorithm OPTIONAL } 550 * -- contains a value of the type 551 * -- registered for use with the 552 * -- algorithm object identifier value 553 * }</pre> 554 * <p> 555 * Note that the byte array supplied here is cloned to protect against 556 * subsequent modifications. 557 * 558 * @param key a byte array containing the subject public key in ASN.1 DER 559 * form (or {@code null}) 560 * @throws IOException if an encoding error occurs (incorrect form for 561 * subject public key) 562 * @see #getSubjectPublicKey 563 */ setSubjectPublicKey(byte[] key)564 public void setSubjectPublicKey(byte[] key) throws IOException { 565 if (key == null) { 566 subjectPublicKey = null; 567 subjectPublicKeyBytes = null; 568 } else { 569 subjectPublicKeyBytes = key.clone(); 570 subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes)); 571 } 572 } 573 574 /** 575 * Sets the keyUsage criterion. The {@code X509Certificate} 576 * must allow the specified keyUsage values. If {@code null}, no 577 * keyUsage check will be done. Note that an {@code X509Certificate} 578 * that has no keyUsage extension implicitly allows all keyUsage values. 579 * <p> 580 * Note that the boolean array supplied here is cloned to protect against 581 * subsequent modifications. 582 * 583 * @param keyUsage a boolean array in the same format as the boolean 584 * array returned by 585 * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}. 586 * Or {@code null}. 587 * @see #getKeyUsage 588 */ setKeyUsage(boolean[] keyUsage)589 public void setKeyUsage(boolean[] keyUsage) { 590 if (keyUsage == null) { 591 this.keyUsage = null; 592 } else { 593 this.keyUsage = keyUsage.clone(); 594 } 595 } 596 597 /** 598 * Sets the extendedKeyUsage criterion. The {@code X509Certificate} 599 * must allow the specified key purposes in its extended key usage 600 * extension. If {@code keyPurposeSet} is empty or {@code null}, 601 * no extendedKeyUsage check will be done. Note that an 602 * {@code X509Certificate} that has no extendedKeyUsage extension 603 * implicitly allows all key purposes. 604 * <p> 605 * Note that the {@code Set} is cloned to protect against 606 * subsequent modifications. 607 * 608 * @param keyPurposeSet a {@code Set} of key purpose OIDs in string 609 * format (or {@code null}). Each OID is represented by a set of 610 * nonnegative integers separated by periods. 611 * @throws IOException if the OID is invalid, such as 612 * the first component being not 0, 1 or 2 or the second component 613 * being greater than 39. 614 * @see #getExtendedKeyUsage 615 */ setExtendedKeyUsage(Set<String> keyPurposeSet)616 public void setExtendedKeyUsage(Set<String> keyPurposeSet) throws IOException { 617 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) { 618 this.keyPurposeSet = null; 619 keyPurposeOIDSet = null; 620 } else { 621 this.keyPurposeSet = 622 Collections.unmodifiableSet(new HashSet<String>(keyPurposeSet)); 623 keyPurposeOIDSet = new HashSet<ObjectIdentifier>(); 624 for (String s : this.keyPurposeSet) { 625 keyPurposeOIDSet.add(new ObjectIdentifier(s)); 626 } 627 } 628 } 629 630 /** 631 * Enables/disables matching all of the subjectAlternativeNames 632 * specified in the {@link #setSubjectAlternativeNames 633 * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName 634 * addSubjectAlternativeName} methods. If enabled, 635 * the {@code X509Certificate} must contain all of the 636 * specified subject alternative names. If disabled, the 637 * {@code X509Certificate} must contain at least one of the 638 * specified subject alternative names. 639 * 640 * <p>The matchAllNames flag is {@code true} by default. 641 * 642 * @param matchAllNames if {@code true}, the flag is enabled; 643 * if {@code false}, the flag is disabled. 644 * @see #getMatchAllSubjectAltNames 645 */ setMatchAllSubjectAltNames(boolean matchAllNames)646 public void setMatchAllSubjectAltNames(boolean matchAllNames) { 647 this.matchAllSubjectAltNames = matchAllNames; 648 } 649 650 /** 651 * Sets the subjectAlternativeNames criterion. The 652 * {@code X509Certificate} must contain all or at least one of the 653 * specified subjectAlternativeNames, depending on the value of 654 * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames 655 * setMatchAllSubjectAltNames}). 656 * <p> 657 * This method allows the caller to specify, with a single method call, 658 * the complete set of subject alternative names for the 659 * subjectAlternativeNames criterion. The specified value replaces 660 * the previous value for the subjectAlternativeNames criterion. 661 * <p> 662 * The {@code names} parameter (if not {@code null}) is a 663 * {@code Collection} with one 664 * entry for each name to be included in the subject alternative name 665 * criterion. Each entry is a {@code List} whose first entry is an 666 * {@code Integer} (the name type, 0-8) and whose second 667 * entry is a {@code String} or a byte array (the name, in 668 * string or ASN.1 DER encoded form, respectively). 669 * There can be multiple names of the same type. If {@code null} 670 * is supplied as the value for this argument, no 671 * subjectAlternativeNames check will be performed. 672 * <p> 673 * Each subject alternative name in the {@code Collection} 674 * may be specified either as a {@code String} or as an ASN.1 encoded 675 * byte array. For more details about the formats used, see 676 * {@link #addSubjectAlternativeName(int type, String name) 677 * addSubjectAlternativeName(int type, String name)} and 678 * {@link #addSubjectAlternativeName(int type, byte [] name) 679 * addSubjectAlternativeName(int type, byte [] name)}. 680 * <p> 681 * <strong>Note:</strong> for distinguished names, specify the byte 682 * array form instead of the String form. See the note in 683 * {@link #addSubjectAlternativeName(int, String)} for more information. 684 * <p> 685 * Note that the {@code names} parameter can contain duplicate 686 * names (same name and name type), but they may be removed from the 687 * {@code Collection} of names returned by the 688 * {@link #getSubjectAlternativeNames getSubjectAlternativeNames} method. 689 * <p> 690 * Note that a deep copy is performed on the {@code Collection} to 691 * protect against subsequent modifications. 692 * 693 * @param names a {@code Collection} of names (or {@code null}) 694 * @throws IOException if a parsing error occurs 695 * @see #getSubjectAlternativeNames 696 */ setSubjectAlternativeNames(Collection<List<?>> names)697 public void setSubjectAlternativeNames(Collection<List<?>> names) 698 throws IOException { 699 if (names == null) { 700 subjectAlternativeNames = null; 701 subjectAlternativeGeneralNames = null; 702 } else { 703 if (names.isEmpty()) { 704 subjectAlternativeNames = null; 705 subjectAlternativeGeneralNames = null; 706 return; 707 } 708 Set<List<?>> tempNames = cloneAndCheckNames(names); 709 // Ensure that we either set both of these or neither 710 subjectAlternativeGeneralNames = parseNames(tempNames); 711 subjectAlternativeNames = tempNames; 712 } 713 } 714 715 /** 716 * Adds a name to the subjectAlternativeNames criterion. The 717 * {@code X509Certificate} must contain all or at least one 718 * of the specified subjectAlternativeNames, depending on the value of 719 * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames 720 * setMatchAllSubjectAltNames}). 721 * <p> 722 * This method allows the caller to add a name to the set of subject 723 * alternative names. 724 * The specified name is added to any previous value for the 725 * subjectAlternativeNames criterion. If the specified name is a 726 * duplicate, it may be ignored. 727 * <p> 728 * The name is provided in string format. 729 * <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>, DNS, and URI 730 * names use the well-established string formats for those types (subject to 731 * the restrictions included in RFC 3280). IPv4 address names are 732 * supplied using dotted quad notation. OID address names are represented 733 * as a series of nonnegative integers separated by periods. And 734 * directory names (distinguished names) are supplied in RFC 2253 format. 735 * No standard string format is defined for otherNames, X.400 names, 736 * EDI party names, IPv6 address names, or any other type of names. They 737 * should be specified using the 738 * {@link #addSubjectAlternativeName(int type, byte [] name) 739 * addSubjectAlternativeName(int type, byte [] name)} 740 * method. 741 * <p> 742 * <strong>Note:</strong> for distinguished names, use 743 * {@linkplain #addSubjectAlternativeName(int, byte[])} instead. 744 * This method should not be relied on as it can fail to match some 745 * certificates because of a loss of encoding information in the RFC 2253 746 * String form of some distinguished names. 747 * 748 * @param type the name type (0-8, as specified in 749 * RFC 3280, section 4.2.1.7) 750 * @param name the name in string form (not {@code null}) 751 * @throws IOException if a parsing error occurs 752 */ addSubjectAlternativeName(int type, String name)753 public void addSubjectAlternativeName(int type, String name) 754 throws IOException { 755 addSubjectAlternativeNameInternal(type, name); 756 } 757 758 /** 759 * Adds a name to the subjectAlternativeNames criterion. The 760 * {@code X509Certificate} must contain all or at least one 761 * of the specified subjectAlternativeNames, depending on the value of 762 * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames 763 * setMatchAllSubjectAltNames}). 764 * <p> 765 * This method allows the caller to add a name to the set of subject 766 * alternative names. 767 * The specified name is added to any previous value for the 768 * subjectAlternativeNames criterion. If the specified name is a 769 * duplicate, it may be ignored. 770 * <p> 771 * The name is provided as a byte array. This byte array should contain 772 * the DER encoded name, as it would appear in the GeneralName structure 773 * defined in RFC 3280 and X.509. The encoded byte array should only contain 774 * the encoded value of the name, and should not include the tag associated 775 * with the name in the GeneralName structure. The ASN.1 definition of this 776 * structure appears below. 777 * <pre>{@code 778 * GeneralName ::= CHOICE { 779 * otherName [0] OtherName, 780 * rfc822Name [1] IA5String, 781 * dNSName [2] IA5String, 782 * x400Address [3] ORAddress, 783 * directoryName [4] Name, 784 * ediPartyName [5] EDIPartyName, 785 * uniformResourceIdentifier [6] IA5String, 786 * iPAddress [7] OCTET STRING, 787 * registeredID [8] OBJECT IDENTIFIER} 788 * }</pre> 789 * <p> 790 * Note that the byte array supplied here is cloned to protect against 791 * subsequent modifications. 792 * 793 * @param type the name type (0-8, as listed above) 794 * @param name a byte array containing the name in ASN.1 DER encoded form 795 * @throws IOException if a parsing error occurs 796 */ addSubjectAlternativeName(int type, byte[] name)797 public void addSubjectAlternativeName(int type, byte[] name) 798 throws IOException { 799 // clone because byte arrays are modifiable 800 addSubjectAlternativeNameInternal(type, name.clone()); 801 } 802 803 /** 804 * A private method that adds a name (String or byte array) to the 805 * subjectAlternativeNames criterion. The {@code X509Certificate} 806 * must contain the specified subjectAlternativeName. 807 * 808 * @param type the name type (0-8, as specified in 809 * RFC 3280, section 4.2.1.7) 810 * @param name the name in string or byte array form 811 * @throws IOException if a parsing error occurs 812 */ addSubjectAlternativeNameInternal(int type, Object name)813 private void addSubjectAlternativeNameInternal(int type, Object name) 814 throws IOException { 815 // First, ensure that the name parses 816 GeneralNameInterface tempName = makeGeneralNameInterface(type, name); 817 if (subjectAlternativeNames == null) { 818 subjectAlternativeNames = new HashSet<List<?>>(); 819 } 820 if (subjectAlternativeGeneralNames == null) { 821 subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>(); 822 } 823 List<Object> list = new ArrayList<Object>(2); 824 list.add(Integer.valueOf(type)); 825 list.add(name); 826 subjectAlternativeNames.add(list); 827 subjectAlternativeGeneralNames.add(tempName); 828 } 829 830 /** 831 * Parse an argument of the form passed to setSubjectAlternativeNames, 832 * returning a {@code Collection} of 833 * {@code GeneralNameInterface}s. 834 * Throw an IllegalArgumentException or a ClassCastException 835 * if the argument is malformed. 836 * 837 * @param names a Collection with one entry per name. 838 * Each entry is a {@code List} whose first entry 839 * is an Integer (the name type, 0-8) and whose second 840 * entry is a String or a byte array (the name, in 841 * string or ASN.1 DER encoded form, respectively). 842 * There can be multiple names of the same type. Null is 843 * not an acceptable value. 844 * @return a Set of {@code GeneralNameInterface}s 845 * @throws IOException if a parsing error occurs 846 */ parseNames(Collection<List<?>> names)847 private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException { 848 Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>(); 849 for (List<?> nameList : names) { 850 if (nameList.size() != 2) { 851 throw new IOException("name list size not 2"); 852 } 853 Object o = nameList.get(0); 854 if (!(o instanceof Integer)) { 855 throw new IOException("expected an Integer"); 856 } 857 int nameType = ((Integer)o).intValue(); 858 o = nameList.get(1); 859 genNames.add(makeGeneralNameInterface(nameType, o)); 860 } 861 862 return genNames; 863 } 864 865 /** 866 * Compare for equality two objects of the form passed to 867 * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames). 868 * Throw an {@code IllegalArgumentException} or a 869 * {@code ClassCastException} if one of the objects is malformed. 870 * 871 * @param object1 a Collection containing the first object to compare 872 * @param object2 a Collection containing the second object to compare 873 * @return true if the objects are equal, false otherwise 874 */ equalNames(Collection<?> object1, Collection<?> object2)875 static boolean equalNames(Collection<?> object1, Collection<?> object2) { 876 if ((object1 == null) || (object2 == null)) { 877 return object1 == object2; 878 } 879 return object1.equals(object2); 880 } 881 882 /** 883 * Make a {@code GeneralNameInterface} out of a name type (0-8) and an 884 * Object that may be a byte array holding the ASN.1 DER encoded 885 * name or a String form of the name. Except for X.509 886 * Distinguished Names, the String form of the name must not be the 887 * result from calling toString on an existing GeneralNameInterface 888 * implementing class. The output of toString is not compatible 889 * with the String constructors for names other than Distinguished 890 * Names. 891 * 892 * @param type name type (0-8) 893 * @param name name as ASN.1 Der-encoded byte array or String 894 * @return a GeneralNameInterface name 895 * @throws IOException if a parsing error occurs 896 */ makeGeneralNameInterface(int type, Object name)897 static GeneralNameInterface makeGeneralNameInterface(int type, Object name) 898 throws IOException { 899 GeneralNameInterface result; 900 if (debug != null) { 901 debug.println("X509CertSelector.makeGeneralNameInterface(" 902 + type + ")..."); 903 } 904 905 if (name instanceof String) { 906 if (debug != null) { 907 debug.println("X509CertSelector.makeGeneralNameInterface() " 908 + "name is String: " + name); 909 } 910 switch (type) { 911 case NAME_RFC822: 912 result = new RFC822Name((String)name); 913 break; 914 case NAME_DNS: 915 result = new DNSName((String)name); 916 break; 917 case NAME_DIRECTORY: 918 result = new X500Name((String)name); 919 break; 920 case NAME_URI: 921 result = new URIName((String)name); 922 break; 923 case NAME_IP: 924 result = new IPAddressName((String)name); 925 break; 926 case NAME_OID: 927 result = new OIDName((String)name); 928 break; 929 default: 930 throw new IOException("unable to parse String names of type " 931 + type); 932 } 933 if (debug != null) { 934 debug.println("X509CertSelector.makeGeneralNameInterface() " 935 + "result: " + result.toString()); 936 } 937 } else if (name instanceof byte[]) { 938 DerValue val = new DerValue((byte[]) name); 939 if (debug != null) { 940 debug.println 941 ("X509CertSelector.makeGeneralNameInterface() is byte[]"); 942 } 943 944 switch (type) { 945 case NAME_ANY: 946 result = new OtherName(val); 947 break; 948 case NAME_RFC822: 949 result = new RFC822Name(val); 950 break; 951 case NAME_DNS: 952 result = new DNSName(val); 953 break; 954 case NAME_X400: 955 result = new X400Address(val); 956 break; 957 case NAME_DIRECTORY: 958 result = new X500Name(val); 959 break; 960 case NAME_EDI: 961 result = new EDIPartyName(val); 962 break; 963 case NAME_URI: 964 result = new URIName(val); 965 break; 966 case NAME_IP: 967 result = new IPAddressName(val); 968 break; 969 case NAME_OID: 970 result = new OIDName(val); 971 break; 972 default: 973 throw new IOException("unable to parse byte array names of " 974 + "type " + type); 975 } 976 if (debug != null) { 977 debug.println("X509CertSelector.makeGeneralNameInterface() result: " 978 + result.toString()); 979 } 980 } else { 981 if (debug != null) { 982 debug.println("X509CertSelector.makeGeneralName() input name " 983 + "not String or byte array"); 984 } 985 throw new IOException("name not String or byte array"); 986 } 987 return result; 988 } 989 990 991 /** 992 * Sets the name constraints criterion. The {@code X509Certificate} 993 * must have subject and subject alternative names that 994 * meet the specified name constraints. 995 * <p> 996 * The name constraints are specified as a byte array. This byte array 997 * should contain the DER encoded form of the name constraints, as they 998 * would appear in the NameConstraints structure defined in RFC 3280 999 * and X.509. The ASN.1 definition of this structure appears below. 1000 * 1001 * <pre>{@code 1002 * NameConstraints ::= SEQUENCE { 1003 * permittedSubtrees [0] GeneralSubtrees OPTIONAL, 1004 * excludedSubtrees [1] GeneralSubtrees OPTIONAL } 1005 * 1006 * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree 1007 * 1008 * GeneralSubtree ::= SEQUENCE { 1009 * base GeneralName, 1010 * minimum [0] BaseDistance DEFAULT 0, 1011 * maximum [1] BaseDistance OPTIONAL } 1012 * 1013 * BaseDistance ::= INTEGER (0..MAX) 1014 * 1015 * GeneralName ::= CHOICE { 1016 * otherName [0] OtherName, 1017 * rfc822Name [1] IA5String, 1018 * dNSName [2] IA5String, 1019 * x400Address [3] ORAddress, 1020 * directoryName [4] Name, 1021 * ediPartyName [5] EDIPartyName, 1022 * uniformResourceIdentifier [6] IA5String, 1023 * iPAddress [7] OCTET STRING, 1024 * registeredID [8] OBJECT IDENTIFIER} 1025 * }</pre> 1026 * <p> 1027 * Note that the byte array supplied here is cloned to protect against 1028 * subsequent modifications. 1029 * 1030 * @param bytes a byte array containing the ASN.1 DER encoding of 1031 * a NameConstraints extension to be used for checking 1032 * name constraints. Only the value of the extension is 1033 * included, not the OID or criticality flag. Can be 1034 * {@code null}, 1035 * in which case no name constraints check will be performed. 1036 * @throws IOException if a parsing error occurs 1037 * @see #getNameConstraints 1038 */ setNameConstraints(byte[] bytes)1039 public void setNameConstraints(byte[] bytes) throws IOException { 1040 if (bytes == null) { 1041 ncBytes = null; 1042 nc = null; 1043 } else { 1044 ncBytes = bytes.clone(); 1045 nc = new NameConstraintsExtension(FALSE, bytes); 1046 } 1047 } 1048 1049 /** 1050 * Sets the basic constraints constraint. If the value is greater than or 1051 * equal to zero, {@code X509Certificates} must include a 1052 * basicConstraints extension with 1053 * a pathLen of at least this value. If the value is -2, only end-entity 1054 * certificates are accepted. If the value is -1, no check is done. 1055 * <p> 1056 * This constraint is useful when building a certification path forward 1057 * (from the target toward the trust anchor. If a partial path has been 1058 * built, any candidate certificate must have a maxPathLen value greater 1059 * than or equal to the number of certificates in the partial path. 1060 * 1061 * @param minMaxPathLen the value for the basic constraints constraint 1062 * @throws IllegalArgumentException if the value is less than -2 1063 * @see #getBasicConstraints 1064 */ setBasicConstraints(int minMaxPathLen)1065 public void setBasicConstraints(int minMaxPathLen) { 1066 if (minMaxPathLen < -2) { 1067 throw new IllegalArgumentException("basic constraints less than -2"); 1068 } 1069 basicConstraints = minMaxPathLen; 1070 } 1071 1072 /** 1073 * Sets the policy constraint. The {@code X509Certificate} must 1074 * include at least one of the specified policies in its certificate 1075 * policies extension. If {@code certPolicySet} is empty, then the 1076 * {@code X509Certificate} must include at least some specified policy 1077 * in its certificate policies extension. If {@code certPolicySet} is 1078 * {@code null}, no policy check will be performed. 1079 * <p> 1080 * Note that the {@code Set} is cloned to protect against 1081 * subsequent modifications. 1082 * 1083 * @param certPolicySet a {@code Set} of certificate policy OIDs in 1084 * string format (or {@code null}). Each OID is 1085 * represented by a set of nonnegative integers 1086 * separated by periods. 1087 * @throws IOException if a parsing error occurs on the OID such as 1088 * the first component is not 0, 1 or 2 or the second component is 1089 * greater than 39. 1090 * @see #getPolicy 1091 */ setPolicy(Set<String> certPolicySet)1092 public void setPolicy(Set<String> certPolicySet) throws IOException { 1093 if (certPolicySet == null) { 1094 policySet = null; 1095 policy = null; 1096 } else { 1097 // Snapshot set and parse it 1098 Set<String> tempSet = Collections.unmodifiableSet 1099 (new HashSet<String>(certPolicySet)); 1100 /* Convert to Vector of ObjectIdentifiers */ 1101 Iterator<String> i = tempSet.iterator(); 1102 Vector<CertificatePolicyId> polIdVector = new Vector<CertificatePolicyId>(); 1103 while (i.hasNext()) { 1104 Object o = i.next(); 1105 if (!(o instanceof String)) { 1106 throw new IOException("non String in certPolicySet"); 1107 } 1108 polIdVector.add(new CertificatePolicyId(new ObjectIdentifier( 1109 (String)o))); 1110 } 1111 // If everything went OK, make the changes 1112 policySet = tempSet; 1113 policy = new CertificatePolicySet(polIdVector); 1114 } 1115 } 1116 1117 /** 1118 * Sets the pathToNames criterion. The {@code X509Certificate} must 1119 * not include name constraints that would prohibit building a 1120 * path to the specified names. 1121 * <p> 1122 * This method allows the caller to specify, with a single method call, 1123 * the complete set of names which the {@code X509Certificates}'s 1124 * name constraints must permit. The specified value replaces 1125 * the previous value for the pathToNames criterion. 1126 * <p> 1127 * This constraint is useful when building a certification path forward 1128 * (from the target toward the trust anchor. If a partial path has been 1129 * built, any candidate certificate must not include name constraints that 1130 * would prohibit building a path to any of the names in the partial path. 1131 * <p> 1132 * The {@code names} parameter (if not {@code null}) is a 1133 * {@code Collection} with one 1134 * entry for each name to be included in the pathToNames 1135 * criterion. Each entry is a {@code List} whose first entry is an 1136 * {@code Integer} (the name type, 0-8) and whose second 1137 * entry is a {@code String} or a byte array (the name, in 1138 * string or ASN.1 DER encoded form, respectively). 1139 * There can be multiple names of the same type. If {@code null} 1140 * is supplied as the value for this argument, no 1141 * pathToNames check will be performed. 1142 * <p> 1143 * Each name in the {@code Collection} 1144 * may be specified either as a {@code String} or as an ASN.1 encoded 1145 * byte array. For more details about the formats used, see 1146 * {@link #addPathToName(int type, String name) 1147 * addPathToName(int type, String name)} and 1148 * {@link #addPathToName(int type, byte [] name) 1149 * addPathToName(int type, byte [] name)}. 1150 * <p> 1151 * <strong>Note:</strong> for distinguished names, specify the byte 1152 * array form instead of the String form. See the note in 1153 * {@link #addPathToName(int, String)} for more information. 1154 * <p> 1155 * Note that the {@code names} parameter can contain duplicate 1156 * names (same name and name type), but they may be removed from the 1157 * {@code Collection} of names returned by the 1158 * {@link #getPathToNames getPathToNames} method. 1159 * <p> 1160 * Note that a deep copy is performed on the {@code Collection} to 1161 * protect against subsequent modifications. 1162 * 1163 * @param names a {@code Collection} with one entry per name 1164 * (or {@code null}) 1165 * @throws IOException if a parsing error occurs 1166 * @see #getPathToNames 1167 */ setPathToNames(Collection<List<?>> names)1168 public void setPathToNames(Collection<List<?>> names) throws IOException { 1169 if ((names == null) || names.isEmpty()) { 1170 pathToNames = null; 1171 pathToGeneralNames = null; 1172 } else { 1173 Set<List<?>> tempNames = cloneAndCheckNames(names); 1174 pathToGeneralNames = parseNames(tempNames); 1175 // Ensure that we either set both of these or neither 1176 pathToNames = tempNames; 1177 } 1178 } 1179 1180 // called from CertPathHelper setPathToNamesInternal(Set<GeneralNameInterface> names)1181 void setPathToNamesInternal(Set<GeneralNameInterface> names) { 1182 // set names to non-null dummy value 1183 // this breaks getPathToNames() 1184 pathToNames = Collections.<List<?>>emptySet(); 1185 pathToGeneralNames = names; 1186 } 1187 1188 /** 1189 * Adds a name to the pathToNames criterion. The {@code X509Certificate} 1190 * must not include name constraints that would prohibit building a 1191 * path to the specified name. 1192 * <p> 1193 * This method allows the caller to add a name to the set of names which 1194 * the {@code X509Certificates}'s name constraints must permit. 1195 * The specified name is added to any previous value for the 1196 * pathToNames criterion. If the name is a duplicate, it may be ignored. 1197 * <p> 1198 * The name is provided in string format. RFC 822, DNS, and URI names 1199 * use the well-established string formats for those types (subject to 1200 * the restrictions included in RFC 3280). IPv4 address names are 1201 * supplied using dotted quad notation. OID address names are represented 1202 * as a series of nonnegative integers separated by periods. And 1203 * directory names (distinguished names) are supplied in RFC 2253 format. 1204 * No standard string format is defined for otherNames, X.400 names, 1205 * EDI party names, IPv6 address names, or any other type of names. They 1206 * should be specified using the 1207 * {@link #addPathToName(int type, byte [] name) 1208 * addPathToName(int type, byte [] name)} method. 1209 * <p> 1210 * <strong>Note:</strong> for distinguished names, use 1211 * {@linkplain #addPathToName(int, byte[])} instead. 1212 * This method should not be relied on as it can fail to match some 1213 * certificates because of a loss of encoding information in the RFC 2253 1214 * String form of some distinguished names. 1215 * 1216 * @param type the name type (0-8, as specified in 1217 * RFC 3280, section 4.2.1.7) 1218 * @param name the name in string form 1219 * @throws IOException if a parsing error occurs 1220 */ addPathToName(int type, String name)1221 public void addPathToName(int type, String name) throws IOException { 1222 addPathToNameInternal(type, name); 1223 } 1224 1225 /** 1226 * Adds a name to the pathToNames criterion. The {@code X509Certificate} 1227 * must not include name constraints that would prohibit building a 1228 * path to the specified name. 1229 * <p> 1230 * This method allows the caller to add a name to the set of names which 1231 * the {@code X509Certificates}'s name constraints must permit. 1232 * The specified name is added to any previous value for the 1233 * pathToNames criterion. If the name is a duplicate, it may be ignored. 1234 * <p> 1235 * The name is provided as a byte array. This byte array should contain 1236 * the DER encoded name, as it would appear in the GeneralName structure 1237 * defined in RFC 3280 and X.509. The ASN.1 definition of this structure 1238 * appears in the documentation for 1239 * {@link #addSubjectAlternativeName(int type, byte [] name) 1240 * addSubjectAlternativeName(int type, byte [] name)}. 1241 * <p> 1242 * Note that the byte array supplied here is cloned to protect against 1243 * subsequent modifications. 1244 * 1245 * @param type the name type (0-8, as specified in 1246 * RFC 3280, section 4.2.1.7) 1247 * @param name a byte array containing the name in ASN.1 DER encoded form 1248 * @throws IOException if a parsing error occurs 1249 */ addPathToName(int type, byte [] name)1250 public void addPathToName(int type, byte [] name) throws IOException { 1251 // clone because byte arrays are modifiable 1252 addPathToNameInternal(type, name.clone()); 1253 } 1254 1255 /** 1256 * A private method that adds a name (String or byte array) to the 1257 * pathToNames criterion. The {@code X509Certificate} must contain 1258 * the specified pathToName. 1259 * 1260 * @param type the name type (0-8, as specified in 1261 * RFC 3280, section 4.2.1.7) 1262 * @param name the name in string or byte array form 1263 * @throws IOException if an encoding error occurs (incorrect form for DN) 1264 */ addPathToNameInternal(int type, Object name)1265 private void addPathToNameInternal(int type, Object name) 1266 throws IOException { 1267 // First, ensure that the name parses 1268 GeneralNameInterface tempName = makeGeneralNameInterface(type, name); 1269 if (pathToGeneralNames == null) { 1270 pathToNames = new HashSet<List<?>>(); 1271 pathToGeneralNames = new HashSet<GeneralNameInterface>(); 1272 } 1273 List<Object> list = new ArrayList<Object>(2); 1274 list.add(Integer.valueOf(type)); 1275 list.add(name); 1276 pathToNames.add(list); 1277 pathToGeneralNames.add(tempName); 1278 } 1279 1280 /** 1281 * Returns the certificateEquals criterion. The specified 1282 * {@code X509Certificate} must be equal to the 1283 * {@code X509Certificate} passed to the {@code match} method. 1284 * If {@code null}, this check is not applied. 1285 * 1286 * @return the {@code X509Certificate} to match (or {@code null}) 1287 * @see #setCertificate 1288 */ getCertificate()1289 public X509Certificate getCertificate() { 1290 return x509Cert; 1291 } 1292 1293 /** 1294 * Returns the serialNumber criterion. The specified serial number 1295 * must match the certificate serial number in the 1296 * {@code X509Certificate}. If {@code null}, any certificate 1297 * serial number will do. 1298 * 1299 * @return the certificate serial number to match 1300 * (or {@code null}) 1301 * @see #setSerialNumber 1302 */ getSerialNumber()1303 public BigInteger getSerialNumber() { 1304 return serialNumber; 1305 } 1306 1307 /** 1308 * Returns the issuer criterion as an {@code X500Principal}. This 1309 * distinguished name must match the issuer distinguished name in the 1310 * {@code X509Certificate}. If {@code null}, the issuer criterion 1311 * is disabled and any issuer distinguished name will do. 1312 * 1313 * @return the required issuer distinguished name as X500Principal 1314 * (or {@code null}) 1315 * @since 1.5 1316 */ getIssuer()1317 public X500Principal getIssuer() { 1318 return issuer; 1319 } 1320 1321 /** 1322 * <strong>Denigrated</strong>, use {@linkplain #getIssuer()} or 1323 * {@linkplain #getIssuerAsBytes()} instead. This method should not be 1324 * relied on as it can fail to match some certificates because of a loss of 1325 * encoding information in the RFC 2253 String form of some distinguished 1326 * names. 1327 * <p> 1328 * Returns the issuer criterion as a {@code String}. This 1329 * distinguished name must match the issuer distinguished name in the 1330 * {@code X509Certificate}. If {@code null}, the issuer criterion 1331 * is disabled and any issuer distinguished name will do. 1332 * <p> 1333 * If the value returned is not {@code null}, it is a 1334 * distinguished name, in RFC 2253 format. 1335 * 1336 * @return the required issuer distinguished name in RFC 2253 format 1337 * (or {@code null}) 1338 */ getIssuerAsString()1339 public String getIssuerAsString() { 1340 return (issuer == null ? null : issuer.getName()); 1341 } 1342 1343 /** 1344 * Returns the issuer criterion as a byte array. This distinguished name 1345 * must match the issuer distinguished name in the 1346 * {@code X509Certificate}. If {@code null}, the issuer criterion 1347 * is disabled and any issuer distinguished name will do. 1348 * <p> 1349 * If the value returned is not {@code null}, it is a byte 1350 * array containing a single DER encoded distinguished name, as defined in 1351 * X.501. The ASN.1 notation for this structure is supplied in the 1352 * documentation for 1353 * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}. 1354 * <p> 1355 * Note that the byte array returned is cloned to protect against 1356 * subsequent modifications. 1357 * 1358 * @return a byte array containing the required issuer distinguished name 1359 * in ASN.1 DER format (or {@code null}) 1360 * @throws IOException if an encoding error occurs 1361 */ getIssuerAsBytes()1362 public byte[] getIssuerAsBytes() throws IOException { 1363 return (issuer == null ? null: issuer.getEncoded()); 1364 } 1365 1366 /** 1367 * Returns the subject criterion as an {@code X500Principal}. This 1368 * distinguished name must match the subject distinguished name in the 1369 * {@code X509Certificate}. If {@code null}, the subject criterion 1370 * is disabled and any subject distinguished name will do. 1371 * 1372 * @return the required subject distinguished name as X500Principal 1373 * (or {@code null}) 1374 * @since 1.5 1375 */ getSubject()1376 public X500Principal getSubject() { 1377 return subject; 1378 } 1379 1380 /** 1381 * <strong>Denigrated</strong>, use {@linkplain #getSubject()} or 1382 * {@linkplain #getSubjectAsBytes()} instead. This method should not be 1383 * relied on as it can fail to match some certificates because of a loss of 1384 * encoding information in the RFC 2253 String form of some distinguished 1385 * names. 1386 * <p> 1387 * Returns the subject criterion as a {@code String}. This 1388 * distinguished name must match the subject distinguished name in the 1389 * {@code X509Certificate}. If {@code null}, the subject criterion 1390 * is disabled and any subject distinguished name will do. 1391 * <p> 1392 * If the value returned is not {@code null}, it is a 1393 * distinguished name, in RFC 2253 format. 1394 * 1395 * @return the required subject distinguished name in RFC 2253 format 1396 * (or {@code null}) 1397 */ getSubjectAsString()1398 public String getSubjectAsString() { 1399 return (subject == null ? null : subject.getName()); 1400 } 1401 1402 /** 1403 * Returns the subject criterion as a byte array. This distinguished name 1404 * must match the subject distinguished name in the 1405 * {@code X509Certificate}. If {@code null}, the subject criterion 1406 * is disabled and any subject distinguished name will do. 1407 * <p> 1408 * If the value returned is not {@code null}, it is a byte 1409 * array containing a single DER encoded distinguished name, as defined in 1410 * X.501. The ASN.1 notation for this structure is supplied in the 1411 * documentation for 1412 * {@link #setSubject(byte [] subjectDN) setSubject(byte [] subjectDN)}. 1413 * <p> 1414 * Note that the byte array returned is cloned to protect against 1415 * subsequent modifications. 1416 * 1417 * @return a byte array containing the required subject distinguished name 1418 * in ASN.1 DER format (or {@code null}) 1419 * @throws IOException if an encoding error occurs 1420 */ getSubjectAsBytes()1421 public byte[] getSubjectAsBytes() throws IOException { 1422 return (subject == null ? null : subject.getEncoded()); 1423 } 1424 1425 /** 1426 * Returns the subjectKeyIdentifier criterion. The 1427 * {@code X509Certificate} must contain a SubjectKeyIdentifier 1428 * extension with the specified value. If {@code null}, no 1429 * subjectKeyIdentifier check will be done. 1430 * <p> 1431 * Note that the byte array returned is cloned to protect against 1432 * subsequent modifications. 1433 * 1434 * @return the key identifier (or {@code null}) 1435 * @see #setSubjectKeyIdentifier 1436 */ getSubjectKeyIdentifier()1437 public byte[] getSubjectKeyIdentifier() { 1438 if (subjectKeyID == null) { 1439 return null; 1440 } 1441 return subjectKeyID.clone(); 1442 } 1443 1444 /** 1445 * Returns the authorityKeyIdentifier criterion. The 1446 * {@code X509Certificate} must contain a AuthorityKeyIdentifier 1447 * extension with the specified value. If {@code null}, no 1448 * authorityKeyIdentifier check will be done. 1449 * <p> 1450 * Note that the byte array returned is cloned to protect against 1451 * subsequent modifications. 1452 * 1453 * @return the key identifier (or {@code null}) 1454 * @see #setAuthorityKeyIdentifier 1455 */ getAuthorityKeyIdentifier()1456 public byte[] getAuthorityKeyIdentifier() { 1457 if (authorityKeyID == null) { 1458 return null; 1459 } 1460 return authorityKeyID.clone(); 1461 } 1462 1463 /** 1464 * Returns the certificateValid criterion. The specified date must fall 1465 * within the certificate validity period for the 1466 * {@code X509Certificate}. If {@code null}, no certificateValid 1467 * check will be done. 1468 * <p> 1469 * Note that the {@code Date} returned is cloned to protect against 1470 * subsequent modifications. 1471 * 1472 * @return the {@code Date} to check (or {@code null}) 1473 * @see #setCertificateValid 1474 */ getCertificateValid()1475 public Date getCertificateValid() { 1476 if (certificateValid == null) { 1477 return null; 1478 } 1479 return (Date)certificateValid.clone(); 1480 } 1481 1482 /** 1483 * Returns the privateKeyValid criterion. The specified date must fall 1484 * within the private key validity period for the 1485 * {@code X509Certificate}. If {@code null}, no privateKeyValid 1486 * check will be done. 1487 * <p> 1488 * Note that the {@code Date} returned is cloned to protect against 1489 * subsequent modifications. 1490 * 1491 * @return the {@code Date} to check (or {@code null}) 1492 * @see #setPrivateKeyValid 1493 */ getPrivateKeyValid()1494 public Date getPrivateKeyValid() { 1495 if (privateKeyValid == null) { 1496 return null; 1497 } 1498 return (Date)privateKeyValid.clone(); 1499 } 1500 1501 /** 1502 * Returns the subjectPublicKeyAlgID criterion. The 1503 * {@code X509Certificate} must contain a subject public key 1504 * with the specified algorithm. If {@code null}, no 1505 * subjectPublicKeyAlgID check will be done. 1506 * 1507 * @return the object identifier (OID) of the signature algorithm to check 1508 * for (or {@code null}). An OID is represented by a set of 1509 * nonnegative integers separated by periods. 1510 * @see #setSubjectPublicKeyAlgID 1511 */ getSubjectPublicKeyAlgID()1512 public String getSubjectPublicKeyAlgID() { 1513 if (subjectPublicKeyAlgID == null) { 1514 return null; 1515 } 1516 return subjectPublicKeyAlgID.toString(); 1517 } 1518 1519 /** 1520 * Returns the subjectPublicKey criterion. The 1521 * {@code X509Certificate} must contain the specified subject 1522 * public key. If {@code null}, no subjectPublicKey check will be done. 1523 * 1524 * @return the subject public key to check for (or {@code null}) 1525 * @see #setSubjectPublicKey 1526 */ getSubjectPublicKey()1527 public PublicKey getSubjectPublicKey() { 1528 return subjectPublicKey; 1529 } 1530 1531 /** 1532 * Returns the keyUsage criterion. The {@code X509Certificate} 1533 * must allow the specified keyUsage values. If null, no keyUsage 1534 * check will be done. 1535 * <p> 1536 * Note that the boolean array returned is cloned to protect against 1537 * subsequent modifications. 1538 * 1539 * @return a boolean array in the same format as the boolean 1540 * array returned by 1541 * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}. 1542 * Or {@code null}. 1543 * @see #setKeyUsage 1544 */ getKeyUsage()1545 public boolean[] getKeyUsage() { 1546 if (keyUsage == null) { 1547 return null; 1548 } 1549 return keyUsage.clone(); 1550 } 1551 1552 /** 1553 * Returns the extendedKeyUsage criterion. The {@code X509Certificate} 1554 * must allow the specified key purposes in its extended key usage 1555 * extension. If the {@code keyPurposeSet} returned is empty or 1556 * {@code null}, no extendedKeyUsage check will be done. Note that an 1557 * {@code X509Certificate} that has no extendedKeyUsage extension 1558 * implicitly allows all key purposes. 1559 * 1560 * @return an immutable {@code Set} of key purpose OIDs in string 1561 * format (or {@code null}) 1562 * @see #setExtendedKeyUsage 1563 */ getExtendedKeyUsage()1564 public Set<String> getExtendedKeyUsage() { 1565 return keyPurposeSet; 1566 } 1567 1568 /** 1569 * Indicates if the {@code X509Certificate} must contain all 1570 * or at least one of the subjectAlternativeNames 1571 * specified in the {@link #setSubjectAlternativeNames 1572 * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName 1573 * addSubjectAlternativeName} methods. If {@code true}, 1574 * the {@code X509Certificate} must contain all of the 1575 * specified subject alternative names. If {@code false}, the 1576 * {@code X509Certificate} must contain at least one of the 1577 * specified subject alternative names. 1578 * 1579 * @return {@code true} if the flag is enabled; 1580 * {@code false} if the flag is disabled. The flag is 1581 * {@code true} by default. 1582 * @see #setMatchAllSubjectAltNames 1583 */ getMatchAllSubjectAltNames()1584 public boolean getMatchAllSubjectAltNames() { 1585 return matchAllSubjectAltNames; 1586 } 1587 1588 /** 1589 * Returns a copy of the subjectAlternativeNames criterion. 1590 * The {@code X509Certificate} must contain all or at least one 1591 * of the specified subjectAlternativeNames, depending on the value 1592 * of the matchAllNames flag (see {@link #getMatchAllSubjectAltNames 1593 * getMatchAllSubjectAltNames}). If the value returned is 1594 * {@code null}, no subjectAlternativeNames check will be performed. 1595 * <p> 1596 * If the value returned is not {@code null}, it is a 1597 * {@code Collection} with 1598 * one entry for each name to be included in the subject alternative name 1599 * criterion. Each entry is a {@code List} whose first entry is an 1600 * {@code Integer} (the name type, 0-8) and whose second 1601 * entry is a {@code String} or a byte array (the name, in 1602 * string or ASN.1 DER encoded form, respectively). 1603 * There can be multiple names of the same type. Note that the 1604 * {@code Collection} returned may contain duplicate names (same name 1605 * and name type). 1606 * <p> 1607 * Each subject alternative name in the {@code Collection} 1608 * may be specified either as a {@code String} or as an ASN.1 encoded 1609 * byte array. For more details about the formats used, see 1610 * {@link #addSubjectAlternativeName(int type, String name) 1611 * addSubjectAlternativeName(int type, String name)} and 1612 * {@link #addSubjectAlternativeName(int type, byte [] name) 1613 * addSubjectAlternativeName(int type, byte [] name)}. 1614 * <p> 1615 * Note that a deep copy is performed on the {@code Collection} to 1616 * protect against subsequent modifications. 1617 * 1618 * @return a {@code Collection} of names (or {@code null}) 1619 * @see #setSubjectAlternativeNames 1620 */ getSubjectAlternativeNames()1621 public Collection<List<?>> getSubjectAlternativeNames() { 1622 if (subjectAlternativeNames == null) { 1623 return null; 1624 } 1625 return cloneNames(subjectAlternativeNames); 1626 } 1627 1628 /** 1629 * Clone an object of the form passed to 1630 * setSubjectAlternativeNames and setPathToNames. 1631 * Throw a {@code RuntimeException} if the argument is malformed. 1632 * <p> 1633 * This method wraps cloneAndCheckNames, changing any 1634 * {@code IOException} into a {@code RuntimeException}. This 1635 * method should be used when the object being 1636 * cloned has already been checked, so there should never be any exceptions. 1637 * 1638 * @param names a {@code Collection} with one entry per name. 1639 * Each entry is a {@code List} whose first entry 1640 * is an Integer (the name type, 0-8) and whose second 1641 * entry is a String or a byte array (the name, in 1642 * string or ASN.1 DER encoded form, respectively). 1643 * There can be multiple names of the same type. Null 1644 * is not an acceptable value. 1645 * @return a deep copy of the specified {@code Collection} 1646 * @throws RuntimeException if a parsing error occurs 1647 */ cloneNames(Collection<List<?>> names)1648 private static Set<List<?>> cloneNames(Collection<List<?>> names) { 1649 try { 1650 return cloneAndCheckNames(names); 1651 } catch (IOException e) { 1652 throw new RuntimeException("cloneNames encountered IOException: " + 1653 e.getMessage()); 1654 } 1655 } 1656 1657 /** 1658 * Clone and check an argument of the form passed to 1659 * setSubjectAlternativeNames and setPathToNames. 1660 * Throw an {@code IOException} if the argument is malformed. 1661 * 1662 * @param names a {@code Collection} with one entry per name. 1663 * Each entry is a {@code List} whose first entry 1664 * is an Integer (the name type, 0-8) and whose second 1665 * entry is a String or a byte array (the name, in 1666 * string or ASN.1 DER encoded form, respectively). 1667 * There can be multiple names of the same type. 1668 * {@code null} is not an acceptable value. 1669 * @return a deep copy of the specified {@code Collection} 1670 * @throws IOException if a parsing error occurs 1671 */ cloneAndCheckNames(Collection<List<?>> names)1672 private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException { 1673 // Copy the Lists and Collection 1674 Set<List<?>> namesCopy = new HashSet<List<?>>(); 1675 for (List<?> o : names) 1676 { 1677 namesCopy.add(new ArrayList<Object>(o)); 1678 } 1679 1680 // Check the contents of the Lists and clone any byte arrays 1681 for (List<?> list : namesCopy) { 1682 @SuppressWarnings("unchecked") // See javadoc for parameter "names". 1683 List<Object> nameList = (List<Object>)list; 1684 if (nameList.size() != 2) { 1685 throw new IOException("name list size not 2"); 1686 } 1687 Object o = nameList.get(0); 1688 if (!(o instanceof Integer)) { 1689 throw new IOException("expected an Integer"); 1690 } 1691 int nameType = ((Integer)o).intValue(); 1692 if ((nameType < 0) || (nameType > 8)) { 1693 throw new IOException("name type not 0-8"); 1694 } 1695 Object nameObject = nameList.get(1); 1696 if (!(nameObject instanceof byte[]) && 1697 !(nameObject instanceof String)) { 1698 if (debug != null) { 1699 debug.println("X509CertSelector.cloneAndCheckNames() " 1700 + "name not byte array"); 1701 } 1702 throw new IOException("name not byte array or String"); 1703 } 1704 if (nameObject instanceof byte[]) { 1705 nameList.set(1, ((byte[]) nameObject).clone()); 1706 } 1707 } 1708 return namesCopy; 1709 } 1710 1711 /** 1712 * Returns the name constraints criterion. The {@code X509Certificate} 1713 * must have subject and subject alternative names that 1714 * meet the specified name constraints. 1715 * <p> 1716 * The name constraints are returned as a byte array. This byte array 1717 * contains the DER encoded form of the name constraints, as they 1718 * would appear in the NameConstraints structure defined in RFC 3280 1719 * and X.509. The ASN.1 notation for this structure is supplied in the 1720 * documentation for 1721 * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}. 1722 * <p> 1723 * Note that the byte array returned is cloned to protect against 1724 * subsequent modifications. 1725 * 1726 * @return a byte array containing the ASN.1 DER encoding of 1727 * a NameConstraints extension used for checking name constraints. 1728 * {@code null} if no name constraints check will be performed. 1729 * @see #setNameConstraints 1730 */ getNameConstraints()1731 public byte[] getNameConstraints() { 1732 if (ncBytes == null) { 1733 return null; 1734 } else { 1735 return ncBytes.clone(); 1736 } 1737 } 1738 1739 /** 1740 * Returns the basic constraints constraint. If the value is greater than 1741 * or equal to zero, the {@code X509Certificates} must include a 1742 * basicConstraints extension with a pathLen of at least this value. 1743 * If the value is -2, only end-entity certificates are accepted. If 1744 * the value is -1, no basicConstraints check is done. 1745 * 1746 * @return the value for the basic constraints constraint 1747 * @see #setBasicConstraints 1748 */ getBasicConstraints()1749 public int getBasicConstraints() { 1750 return basicConstraints; 1751 } 1752 1753 /** 1754 * Returns the policy criterion. The {@code X509Certificate} must 1755 * include at least one of the specified policies in its certificate policies 1756 * extension. If the {@code Set} returned is empty, then the 1757 * {@code X509Certificate} must include at least some specified policy 1758 * in its certificate policies extension. If the {@code Set} returned is 1759 * {@code null}, no policy check will be performed. 1760 * 1761 * @return an immutable {@code Set} of certificate policy OIDs in 1762 * string format (or {@code null}) 1763 * @see #setPolicy 1764 */ getPolicy()1765 public Set<String> getPolicy() { 1766 return policySet; 1767 } 1768 1769 /** 1770 * Returns a copy of the pathToNames criterion. The 1771 * {@code X509Certificate} must not include name constraints that would 1772 * prohibit building a path to the specified names. If the value 1773 * returned is {@code null}, no pathToNames check will be performed. 1774 * <p> 1775 * If the value returned is not {@code null}, it is a 1776 * {@code Collection} with one 1777 * entry for each name to be included in the pathToNames 1778 * criterion. Each entry is a {@code List} whose first entry is an 1779 * {@code Integer} (the name type, 0-8) and whose second 1780 * entry is a {@code String} or a byte array (the name, in 1781 * string or ASN.1 DER encoded form, respectively). 1782 * There can be multiple names of the same type. Note that the 1783 * {@code Collection} returned may contain duplicate names (same 1784 * name and name type). 1785 * <p> 1786 * Each name in the {@code Collection} 1787 * may be specified either as a {@code String} or as an ASN.1 encoded 1788 * byte array. For more details about the formats used, see 1789 * {@link #addPathToName(int type, String name) 1790 * addPathToName(int type, String name)} and 1791 * {@link #addPathToName(int type, byte [] name) 1792 * addPathToName(int type, byte [] name)}. 1793 * <p> 1794 * Note that a deep copy is performed on the {@code Collection} to 1795 * protect against subsequent modifications. 1796 * 1797 * @return a {@code Collection} of names (or {@code null}) 1798 * @see #setPathToNames 1799 */ getPathToNames()1800 public Collection<List<?>> getPathToNames() { 1801 if (pathToNames == null) { 1802 return null; 1803 } 1804 return cloneNames(pathToNames); 1805 } 1806 1807 /** 1808 * Return a printable representation of the {@code CertSelector}. 1809 * 1810 * @return a {@code String} describing the contents of the 1811 * {@code CertSelector} 1812 */ toString()1813 public String toString() { 1814 StringBuffer sb = new StringBuffer(); 1815 sb.append("X509CertSelector: [\n"); 1816 if (x509Cert != null) { 1817 sb.append(" Certificate: " + x509Cert.toString() + "\n"); 1818 } 1819 if (serialNumber != null) { 1820 sb.append(" Serial Number: " + serialNumber.toString() + "\n"); 1821 } 1822 if (issuer != null) { 1823 sb.append(" Issuer: " + getIssuerAsString() + "\n"); 1824 } 1825 if (subject != null) { 1826 sb.append(" Subject: " + getSubjectAsString() + "\n"); 1827 } 1828 sb.append(" matchAllSubjectAltNames flag: " 1829 + String.valueOf(matchAllSubjectAltNames) + "\n"); 1830 if (subjectAlternativeNames != null) { 1831 sb.append(" SubjectAlternativeNames:\n"); 1832 Iterator<List<?>> i = subjectAlternativeNames.iterator(); 1833 while (i.hasNext()) { 1834 List<?> list = i.next(); 1835 sb.append(" type " + list.get(0) + 1836 ", name " + list.get(1) + "\n"); 1837 } 1838 } 1839 if (subjectKeyID != null) { 1840 HexDumpEncoder enc = new HexDumpEncoder(); 1841 sb.append(" Subject Key Identifier: " + 1842 enc.encodeBuffer(subjectKeyID) + "\n"); 1843 } 1844 if (authorityKeyID != null) { 1845 HexDumpEncoder enc = new HexDumpEncoder(); 1846 sb.append(" Authority Key Identifier: " + 1847 enc.encodeBuffer(authorityKeyID) + "\n"); 1848 } 1849 if (certificateValid != null) { 1850 sb.append(" Certificate Valid: " + 1851 certificateValid.toString() + "\n"); 1852 } 1853 if (privateKeyValid != null) { 1854 sb.append(" Private Key Valid: " + 1855 privateKeyValid.toString() + "\n"); 1856 } 1857 if (subjectPublicKeyAlgID != null) { 1858 sb.append(" Subject Public Key AlgID: " + 1859 subjectPublicKeyAlgID.toString() + "\n"); 1860 } 1861 if (subjectPublicKey != null) { 1862 sb.append(" Subject Public Key: " + 1863 subjectPublicKey.toString() + "\n"); 1864 } 1865 if (keyUsage != null) { 1866 sb.append(" Key Usage: " + keyUsageToString(keyUsage) + "\n"); 1867 } 1868 if (keyPurposeSet != null) { 1869 sb.append(" Extended Key Usage: " + 1870 keyPurposeSet.toString() + "\n"); 1871 } 1872 if (policy != null) { 1873 sb.append(" Policy: " + policy.toString() + "\n"); 1874 } 1875 if (pathToGeneralNames != null) { 1876 sb.append(" Path to names:\n"); 1877 Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator(); 1878 while (i.hasNext()) { 1879 sb.append(" " + i.next() + "\n"); 1880 } 1881 } 1882 sb.append("]"); 1883 return sb.toString(); 1884 } 1885 1886 // Copied from sun.security.x509.KeyUsageExtension 1887 // (without calling the superclass) 1888 /** 1889 * Returns a printable representation of the KeyUsage. 1890 */ keyUsageToString(boolean[] k)1891 private static String keyUsageToString(boolean[] k) { 1892 String s = "KeyUsage [\n"; 1893 try { 1894 if (k[0]) { 1895 s += " DigitalSignature\n"; 1896 } 1897 if (k[1]) { 1898 s += " Non_repudiation\n"; 1899 } 1900 if (k[2]) { 1901 s += " Key_Encipherment\n"; 1902 } 1903 if (k[3]) { 1904 s += " Data_Encipherment\n"; 1905 } 1906 if (k[4]) { 1907 s += " Key_Agreement\n"; 1908 } 1909 if (k[5]) { 1910 s += " Key_CertSign\n"; 1911 } 1912 if (k[6]) { 1913 s += " Crl_Sign\n"; 1914 } 1915 if (k[7]) { 1916 s += " Encipher_Only\n"; 1917 } 1918 if (k[8]) { 1919 s += " Decipher_Only\n"; 1920 } 1921 } catch (ArrayIndexOutOfBoundsException ex) {} 1922 1923 s += "]\n"; 1924 1925 return (s); 1926 } 1927 1928 /** 1929 * Returns an Extension object given any X509Certificate and extension oid. 1930 * Throw an {@code IOException} if the extension byte value is 1931 * malformed. 1932 * 1933 * @param cert a {@code X509Certificate} 1934 * @param extId an {@code integer} which specifies the extension index. 1935 * Currently, the supported extensions are as follows: 1936 * index 0 - PrivateKeyUsageExtension 1937 * index 1 - SubjectAlternativeNameExtension 1938 * index 2 - NameConstraintsExtension 1939 * index 3 - CertificatePoliciesExtension 1940 * index 4 - ExtendedKeyUsageExtension 1941 * @return an {@code Extension} object whose real type is as specified 1942 * by the extension oid. 1943 * @throws IOException if cannot construct the {@code Extension} 1944 * object with the extension encoding retrieved from the passed in 1945 * {@code X509Certificate}. 1946 */ getExtensionObject(X509Certificate cert, int extId)1947 private static Extension getExtensionObject(X509Certificate cert, int extId) 1948 throws IOException { 1949 if (cert instanceof X509CertImpl) { 1950 X509CertImpl impl = (X509CertImpl)cert; 1951 switch (extId) { 1952 case PRIVATE_KEY_USAGE_ID: 1953 return impl.getPrivateKeyUsageExtension(); 1954 case SUBJECT_ALT_NAME_ID: 1955 return impl.getSubjectAlternativeNameExtension(); 1956 case NAME_CONSTRAINTS_ID: 1957 return impl.getNameConstraintsExtension(); 1958 case CERT_POLICIES_ID: 1959 return impl.getCertificatePoliciesExtension(); 1960 case EXTENDED_KEY_USAGE_ID: 1961 return impl.getExtendedKeyUsageExtension(); 1962 default: 1963 return null; 1964 } 1965 } 1966 byte[] rawExtVal = cert.getExtensionValue(EXTENSION_OIDS[extId]); 1967 if (rawExtVal == null) { 1968 return null; 1969 } 1970 DerInputStream in = new DerInputStream(rawExtVal); 1971 byte[] encoded = in.getOctetString(); 1972 switch (extId) { 1973 case PRIVATE_KEY_USAGE_ID: 1974 try { 1975 return new PrivateKeyUsageExtension(FALSE, encoded); 1976 } catch (CertificateException ex) { 1977 throw new IOException(ex.getMessage()); 1978 } 1979 case SUBJECT_ALT_NAME_ID: 1980 return new SubjectAlternativeNameExtension(FALSE, encoded); 1981 case NAME_CONSTRAINTS_ID: 1982 return new NameConstraintsExtension(FALSE, encoded); 1983 case CERT_POLICIES_ID: 1984 return new CertificatePoliciesExtension(FALSE, encoded); 1985 case EXTENDED_KEY_USAGE_ID: 1986 return new ExtendedKeyUsageExtension(FALSE, encoded); 1987 default: 1988 return null; 1989 } 1990 } 1991 1992 /** 1993 * Decides whether a {@code Certificate} should be selected. 1994 * 1995 * @param cert the {@code Certificate} to be checked 1996 * @return {@code true} if the {@code Certificate} should be 1997 * selected, {@code false} otherwise 1998 */ match(Certificate cert)1999 public boolean match(Certificate cert) { 2000 if (!(cert instanceof X509Certificate)) { 2001 return false; 2002 } 2003 X509Certificate xcert = (X509Certificate)cert; 2004 2005 if (debug != null) { 2006 debug.println("X509CertSelector.match(SN: " 2007 + (xcert.getSerialNumber()).toString(16) + "\n Issuer: " 2008 + xcert.getIssuerDN() + "\n Subject: " + xcert.getSubjectDN() 2009 + ")"); 2010 } 2011 2012 /* match on X509Certificate */ 2013 if (x509Cert != null) { 2014 if (!x509Cert.equals(xcert)) { 2015 if (debug != null) { 2016 debug.println("X509CertSelector.match: " 2017 + "certs don't match"); 2018 } 2019 return false; 2020 } 2021 } 2022 2023 /* match on serial number */ 2024 if (serialNumber != null) { 2025 if (!serialNumber.equals(xcert.getSerialNumber())) { 2026 if (debug != null) { 2027 debug.println("X509CertSelector.match: " 2028 + "serial numbers don't match"); 2029 } 2030 return false; 2031 } 2032 } 2033 2034 /* match on issuer name */ 2035 if (issuer != null) { 2036 if (!issuer.equals(xcert.getIssuerX500Principal())) { 2037 if (debug != null) { 2038 debug.println("X509CertSelector.match: " 2039 + "issuer DNs don't match"); 2040 } 2041 return false; 2042 } 2043 } 2044 2045 /* match on subject name */ 2046 if (subject != null) { 2047 if (!subject.equals(xcert.getSubjectX500Principal())) { 2048 if (debug != null) { 2049 debug.println("X509CertSelector.match: " 2050 + "subject DNs don't match"); 2051 } 2052 return false; 2053 } 2054 } 2055 2056 /* match on certificate validity range */ 2057 if (certificateValid != null) { 2058 try { 2059 xcert.checkValidity(certificateValid); 2060 } catch (CertificateException e) { 2061 if (debug != null) { 2062 debug.println("X509CertSelector.match: " 2063 + "certificate not within validity period"); 2064 } 2065 return false; 2066 } 2067 } 2068 2069 /* match on subject public key */ 2070 if (subjectPublicKeyBytes != null) { 2071 byte[] certKey = xcert.getPublicKey().getEncoded(); 2072 if (!Arrays.equals(subjectPublicKeyBytes, certKey)) { 2073 if (debug != null) { 2074 debug.println("X509CertSelector.match: " 2075 + "subject public keys don't match"); 2076 } 2077 return false; 2078 } 2079 } 2080 2081 boolean result = matchBasicConstraints(xcert) 2082 && matchKeyUsage(xcert) 2083 && matchExtendedKeyUsage(xcert) 2084 && matchSubjectKeyID(xcert) 2085 && matchAuthorityKeyID(xcert) 2086 && matchPrivateKeyValid(xcert) 2087 && matchSubjectPublicKeyAlgID(xcert) 2088 && matchPolicy(xcert) 2089 && matchSubjectAlternativeNames(xcert) 2090 && matchPathToNames(xcert) 2091 && matchNameConstraints(xcert); 2092 2093 if (result && (debug != null)) { 2094 debug.println("X509CertSelector.match returning: true"); 2095 } 2096 return result; 2097 } 2098 2099 /* match on subject key identifier extension value */ matchSubjectKeyID(X509Certificate xcert)2100 private boolean matchSubjectKeyID(X509Certificate xcert) { 2101 if (subjectKeyID == null) { 2102 return true; 2103 } 2104 try { 2105 byte[] extVal = xcert.getExtensionValue("2.5.29.14"); 2106 if (extVal == null) { 2107 if (debug != null) { 2108 debug.println("X509CertSelector.match: " 2109 + "no subject key ID extension"); 2110 } 2111 return false; 2112 } 2113 DerInputStream in = new DerInputStream(extVal); 2114 byte[] certSubjectKeyID = in.getOctetString(); 2115 if (certSubjectKeyID == null || 2116 !Arrays.equals(subjectKeyID, certSubjectKeyID)) { 2117 if (debug != null) { 2118 debug.println("X509CertSelector.match: " 2119 + "subject key IDs don't match"); 2120 } 2121 return false; 2122 } 2123 } catch (IOException ex) { 2124 if (debug != null) { 2125 debug.println("X509CertSelector.match: " 2126 + "exception in subject key ID check"); 2127 } 2128 return false; 2129 } 2130 return true; 2131 } 2132 2133 /* match on authority key identifier extension value */ matchAuthorityKeyID(X509Certificate xcert)2134 private boolean matchAuthorityKeyID(X509Certificate xcert) { 2135 if (authorityKeyID == null) { 2136 return true; 2137 } 2138 try { 2139 byte[] extVal = xcert.getExtensionValue("2.5.29.35"); 2140 if (extVal == null) { 2141 if (debug != null) { 2142 debug.println("X509CertSelector.match: " 2143 + "no authority key ID extension"); 2144 } 2145 return false; 2146 } 2147 DerInputStream in = new DerInputStream(extVal); 2148 byte[] certAuthKeyID = in.getOctetString(); 2149 if (certAuthKeyID == null || 2150 !Arrays.equals(authorityKeyID, certAuthKeyID)) { 2151 if (debug != null) { 2152 debug.println("X509CertSelector.match: " 2153 + "authority key IDs don't match"); 2154 } 2155 return false; 2156 } 2157 } catch (IOException ex) { 2158 if (debug != null) { 2159 debug.println("X509CertSelector.match: " 2160 + "exception in authority key ID check"); 2161 } 2162 return false; 2163 } 2164 return true; 2165 } 2166 2167 /* match on private key usage range */ matchPrivateKeyValid(X509Certificate xcert)2168 private boolean matchPrivateKeyValid(X509Certificate xcert) { 2169 if (privateKeyValid == null) { 2170 return true; 2171 } 2172 PrivateKeyUsageExtension ext = null; 2173 try { 2174 ext = (PrivateKeyUsageExtension) 2175 getExtensionObject(xcert, PRIVATE_KEY_USAGE_ID); 2176 if (ext != null) { 2177 ext.valid(privateKeyValid); 2178 } 2179 } catch (CertificateExpiredException e1) { 2180 if (debug != null) { 2181 String time = "n/a"; 2182 try { 2183 Date notAfter = ext.get(PrivateKeyUsageExtension.NOT_AFTER); 2184 time = notAfter.toString(); 2185 } catch (CertificateException ex) { 2186 // not able to retrieve notAfter value 2187 } 2188 debug.println("X509CertSelector.match: private key usage not " 2189 + "within validity date; ext.NOT_After: " 2190 + time + "; X509CertSelector: " 2191 + this.toString()); 2192 e1.printStackTrace(); 2193 } 2194 return false; 2195 } catch (CertificateNotYetValidException e2) { 2196 if (debug != null) { 2197 String time = "n/a"; 2198 try { 2199 Date notBefore = ext.get(PrivateKeyUsageExtension.NOT_BEFORE); 2200 time = notBefore.toString(); 2201 } catch (CertificateException ex) { 2202 // not able to retrieve notBefore value 2203 } 2204 debug.println("X509CertSelector.match: private key usage not " 2205 + "within validity date; ext.NOT_BEFORE: " 2206 + time + "; X509CertSelector: " 2207 + this.toString()); 2208 e2.printStackTrace(); 2209 } 2210 return false; 2211 } catch (IOException e4) { 2212 if (debug != null) { 2213 debug.println("X509CertSelector.match: IOException in " 2214 + "private key usage check; X509CertSelector: " 2215 + this.toString()); 2216 e4.printStackTrace(); 2217 } 2218 return false; 2219 } 2220 return true; 2221 } 2222 2223 /* match on subject public key algorithm OID */ matchSubjectPublicKeyAlgID(X509Certificate xcert)2224 private boolean matchSubjectPublicKeyAlgID(X509Certificate xcert) { 2225 if (subjectPublicKeyAlgID == null) { 2226 return true; 2227 } 2228 try { 2229 byte[] encodedKey = xcert.getPublicKey().getEncoded(); 2230 DerValue val = new DerValue(encodedKey); 2231 if (val.tag != DerValue.tag_Sequence) { 2232 throw new IOException("invalid key format"); 2233 } 2234 2235 AlgorithmId algID = AlgorithmId.parse(val.data.getDerValue()); 2236 if (debug != null) { 2237 debug.println("X509CertSelector.match: subjectPublicKeyAlgID = " 2238 + subjectPublicKeyAlgID + ", xcert subjectPublicKeyAlgID = " 2239 + algID.getOID()); 2240 } 2241 if (!subjectPublicKeyAlgID.equals((Object)algID.getOID())) { 2242 if (debug != null) { 2243 debug.println("X509CertSelector.match: " 2244 + "subject public key alg IDs don't match"); 2245 } 2246 return false; 2247 } 2248 } catch (IOException e5) { 2249 if (debug != null) { 2250 debug.println("X509CertSelector.match: IOException in subject " 2251 + "public key algorithm OID check"); 2252 } 2253 return false; 2254 } 2255 return true; 2256 } 2257 2258 /* match on key usage extension value */ matchKeyUsage(X509Certificate xcert)2259 private boolean matchKeyUsage(X509Certificate xcert) { 2260 if (keyUsage == null) { 2261 return true; 2262 } 2263 boolean[] certKeyUsage = xcert.getKeyUsage(); 2264 if (certKeyUsage != null) { 2265 for (int keyBit = 0; keyBit < keyUsage.length; keyBit++) { 2266 if (keyUsage[keyBit] && 2267 ((keyBit >= certKeyUsage.length) || !certKeyUsage[keyBit])) { 2268 if (debug != null) { 2269 debug.println("X509CertSelector.match: " 2270 + "key usage bits don't match"); 2271 } 2272 return false; 2273 } 2274 } 2275 } 2276 return true; 2277 } 2278 2279 /* match on extended key usage purpose OIDs */ matchExtendedKeyUsage(X509Certificate xcert)2280 private boolean matchExtendedKeyUsage(X509Certificate xcert) { 2281 if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) { 2282 return true; 2283 } 2284 try { 2285 ExtendedKeyUsageExtension ext = 2286 (ExtendedKeyUsageExtension)getExtensionObject(xcert, 2287 EXTENDED_KEY_USAGE_ID); 2288 if (ext != null) { 2289 Vector<ObjectIdentifier> certKeyPurposeVector = 2290 ext.get(ExtendedKeyUsageExtension.USAGES); 2291 if (!certKeyPurposeVector.contains(ANY_EXTENDED_KEY_USAGE) 2292 && !certKeyPurposeVector.containsAll(keyPurposeOIDSet)) { 2293 if (debug != null) { 2294 debug.println("X509CertSelector.match: cert failed " 2295 + "extendedKeyUsage criterion"); 2296 } 2297 return false; 2298 } 2299 } 2300 } catch (IOException ex) { 2301 if (debug != null) { 2302 debug.println("X509CertSelector.match: " 2303 + "IOException in extended key usage check"); 2304 } 2305 return false; 2306 } 2307 return true; 2308 } 2309 2310 /* match on subject alternative name extension names */ matchSubjectAlternativeNames(X509Certificate xcert)2311 private boolean matchSubjectAlternativeNames(X509Certificate xcert) { 2312 if ((subjectAlternativeNames == null) || subjectAlternativeNames.isEmpty()) { 2313 return true; 2314 } 2315 try { 2316 SubjectAlternativeNameExtension sanExt = 2317 (SubjectAlternativeNameExtension) getExtensionObject(xcert, 2318 SUBJECT_ALT_NAME_ID); 2319 if (sanExt == null) { 2320 if (debug != null) { 2321 debug.println("X509CertSelector.match: " 2322 + "no subject alternative name extension"); 2323 } 2324 return false; 2325 } 2326 GeneralNames certNames = 2327 sanExt.get(SubjectAlternativeNameExtension.SUBJECT_NAME); 2328 Iterator<GeneralNameInterface> i = 2329 subjectAlternativeGeneralNames.iterator(); 2330 while (i.hasNext()) { 2331 GeneralNameInterface matchName = i.next(); 2332 boolean found = false; 2333 for (Iterator<GeneralName> t = certNames.iterator(); 2334 t.hasNext() && !found; ) { 2335 GeneralNameInterface certName = (t.next()).getName(); 2336 found = certName.equals(matchName); 2337 } 2338 if (!found && (matchAllSubjectAltNames || !i.hasNext())) { 2339 if (debug != null) { 2340 debug.println("X509CertSelector.match: subject alternative " 2341 + "name " + matchName + " not found"); 2342 } 2343 return false; 2344 } else if (found && !matchAllSubjectAltNames) { 2345 break; 2346 } 2347 } 2348 } catch (IOException ex) { 2349 if (debug != null) 2350 debug.println("X509CertSelector.match: IOException in subject " 2351 + "alternative name check"); 2352 return false; 2353 } 2354 return true; 2355 } 2356 2357 /* match on name constraints */ matchNameConstraints(X509Certificate xcert)2358 private boolean matchNameConstraints(X509Certificate xcert) { 2359 if (nc == null) { 2360 return true; 2361 } 2362 try { 2363 if (!nc.verify(xcert)) { 2364 if (debug != null) { 2365 debug.println("X509CertSelector.match: " 2366 + "name constraints not satisfied"); 2367 } 2368 return false; 2369 } 2370 } catch (IOException e) { 2371 if (debug != null) { 2372 debug.println("X509CertSelector.match: " 2373 + "IOException in name constraints check"); 2374 } 2375 return false; 2376 } 2377 return true; 2378 } 2379 2380 /* match on policy OIDs */ matchPolicy(X509Certificate xcert)2381 private boolean matchPolicy(X509Certificate xcert) { 2382 if (policy == null) { 2383 return true; 2384 } 2385 try { 2386 CertificatePoliciesExtension ext = (CertificatePoliciesExtension) 2387 getExtensionObject(xcert, CERT_POLICIES_ID); 2388 if (ext == null) { 2389 if (debug != null) { 2390 debug.println("X509CertSelector.match: " 2391 + "no certificate policy extension"); 2392 } 2393 return false; 2394 } 2395 List<PolicyInformation> policies = ext.get(CertificatePoliciesExtension.POLICIES); 2396 /* 2397 * Convert the Vector of PolicyInformation to a Vector 2398 * of CertificatePolicyIds for easier comparison. 2399 */ 2400 List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size()); 2401 for (PolicyInformation info : policies) { 2402 policyIDs.add(info.getPolicyIdentifier()); 2403 } 2404 if (policy != null) { 2405 boolean foundOne = false; 2406 /* 2407 * if the user passes in an empty policy Set, then 2408 * we just want to make sure that the candidate certificate 2409 * has some policy OID in its CertPoliciesExtension 2410 */ 2411 if (policy.getCertPolicyIds().isEmpty()) { 2412 if (policyIDs.isEmpty()) { 2413 if (debug != null) { 2414 debug.println("X509CertSelector.match: " 2415 + "cert failed policyAny criterion"); 2416 } 2417 return false; 2418 } 2419 } else { 2420 for (CertificatePolicyId id : policy.getCertPolicyIds()) { 2421 if (policyIDs.contains(id)) { 2422 foundOne = true; 2423 break; 2424 } 2425 } 2426 if (!foundOne) { 2427 if (debug != null) { 2428 debug.println("X509CertSelector.match: " 2429 + "cert failed policyAny criterion"); 2430 } 2431 return false; 2432 } 2433 } 2434 } 2435 } catch (IOException ex) { 2436 if (debug != null) { 2437 debug.println("X509CertSelector.match: " 2438 + "IOException in certificate policy ID check"); 2439 } 2440 return false; 2441 } 2442 return true; 2443 } 2444 2445 /* match on pathToNames */ matchPathToNames(X509Certificate xcert)2446 private boolean matchPathToNames(X509Certificate xcert) { 2447 if (pathToGeneralNames == null) { 2448 return true; 2449 } 2450 try { 2451 NameConstraintsExtension ext = (NameConstraintsExtension) 2452 getExtensionObject(xcert, NAME_CONSTRAINTS_ID); 2453 if (ext == null) { 2454 return true; 2455 } 2456 if ((debug != null) && Debug.isOn("certpath")) { 2457 debug.println("X509CertSelector.match pathToNames:\n"); 2458 Iterator<GeneralNameInterface> i = 2459 pathToGeneralNames.iterator(); 2460 while (i.hasNext()) { 2461 debug.println(" " + i.next() + "\n"); 2462 } 2463 } 2464 2465 GeneralSubtrees permitted = 2466 ext.get(NameConstraintsExtension.PERMITTED_SUBTREES); 2467 GeneralSubtrees excluded = 2468 ext.get(NameConstraintsExtension.EXCLUDED_SUBTREES); 2469 if (excluded != null) { 2470 if (matchExcluded(excluded) == false) { 2471 return false; 2472 } 2473 } 2474 if (permitted != null) { 2475 if (matchPermitted(permitted) == false) { 2476 return false; 2477 } 2478 } 2479 } catch (IOException ex) { 2480 if (debug != null) { 2481 debug.println("X509CertSelector.match: " 2482 + "IOException in name constraints check"); 2483 } 2484 return false; 2485 } 2486 return true; 2487 } 2488 matchExcluded(GeneralSubtrees excluded)2489 private boolean matchExcluded(GeneralSubtrees excluded) { 2490 /* 2491 * Enumerate through excluded and compare each entry 2492 * to all pathToNames. If any pathToName is within any of the 2493 * subtrees listed in excluded, return false. 2494 */ 2495 for (Iterator<GeneralSubtree> t = excluded.iterator(); t.hasNext(); ) { 2496 GeneralSubtree tree = t.next(); 2497 GeneralNameInterface excludedName = tree.getName().getName(); 2498 Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator(); 2499 while (i.hasNext()) { 2500 GeneralNameInterface pathToName = i.next(); 2501 if (excludedName.getType() == pathToName.getType()) { 2502 switch (pathToName.constrains(excludedName)) { 2503 case GeneralNameInterface.NAME_WIDENS: 2504 case GeneralNameInterface.NAME_MATCH: 2505 if (debug != null) { 2506 debug.println("X509CertSelector.match: name constraints " 2507 + "inhibit path to specified name"); 2508 debug.println("X509CertSelector.match: excluded name: " + 2509 pathToName); 2510 } 2511 return false; 2512 default: 2513 } 2514 } 2515 } 2516 } 2517 return true; 2518 } 2519 matchPermitted(GeneralSubtrees permitted)2520 private boolean matchPermitted(GeneralSubtrees permitted) { 2521 /* 2522 * Enumerate through pathToNames, checking that each pathToName 2523 * is in at least one of the subtrees listed in permitted. 2524 * If not, return false. However, if no subtrees of a given type 2525 * are listed, all names of that type are permitted. 2526 */ 2527 Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator(); 2528 while (i.hasNext()) { 2529 GeneralNameInterface pathToName = i.next(); 2530 Iterator<GeneralSubtree> t = permitted.iterator(); 2531 boolean permittedNameFound = false; 2532 boolean nameTypeFound = false; 2533 String names = ""; 2534 while (t.hasNext() && !permittedNameFound) { 2535 GeneralSubtree tree = t.next(); 2536 GeneralNameInterface permittedName = tree.getName().getName(); 2537 if (permittedName.getType() == pathToName.getType()) { 2538 nameTypeFound = true; 2539 names = names + " " + permittedName; 2540 switch (pathToName.constrains(permittedName)) { 2541 case GeneralNameInterface.NAME_WIDENS: 2542 case GeneralNameInterface.NAME_MATCH: 2543 permittedNameFound = true; 2544 break; 2545 default: 2546 } 2547 } 2548 } 2549 if (!permittedNameFound && nameTypeFound) { 2550 if (debug != null) 2551 debug.println("X509CertSelector.match: " + 2552 "name constraints inhibit path to specified name; " + 2553 "permitted names of type " + pathToName.getType() + 2554 ": " + names); 2555 return false; 2556 } 2557 } 2558 return true; 2559 } 2560 2561 /* match on basic constraints */ matchBasicConstraints(X509Certificate xcert)2562 private boolean matchBasicConstraints(X509Certificate xcert) { 2563 if (basicConstraints == -1) { 2564 return true; 2565 } 2566 int maxPathLen = xcert.getBasicConstraints(); 2567 if (basicConstraints == -2) { 2568 if (maxPathLen != -1) { 2569 if (debug != null) { 2570 debug.println("X509CertSelector.match: not an EE cert"); 2571 } 2572 return false; 2573 } 2574 } else { 2575 if (maxPathLen < basicConstraints) { 2576 if (debug != null) { 2577 debug.println("X509CertSelector.match: cert's maxPathLen " + 2578 "is less than the min maxPathLen set by " + 2579 "basicConstraints. " + 2580 "(" + maxPathLen + " < " + basicConstraints + ")"); 2581 } 2582 return false; 2583 } 2584 } 2585 return true; 2586 } 2587 2588 @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly cloneSet(Set<T> set)2589 private static <T> Set<T> cloneSet(Set<T> set) { 2590 if (set instanceof HashSet) { 2591 Object clone = ((HashSet<T>)set).clone(); 2592 return (Set<T>)clone; 2593 } else { 2594 return new HashSet<T>(set); 2595 } 2596 } 2597 2598 /** 2599 * Returns a copy of this object. 2600 * 2601 * @return the copy 2602 */ clone()2603 public Object clone() { 2604 try { 2605 X509CertSelector copy = (X509CertSelector)super.clone(); 2606 // Must clone these because addPathToName et al. modify them 2607 if (subjectAlternativeNames != null) { 2608 copy.subjectAlternativeNames = 2609 cloneSet(subjectAlternativeNames); 2610 copy.subjectAlternativeGeneralNames = 2611 cloneSet(subjectAlternativeGeneralNames); 2612 } 2613 if (pathToGeneralNames != null) { 2614 copy.pathToNames = cloneSet(pathToNames); 2615 copy.pathToGeneralNames = cloneSet(pathToGeneralNames); 2616 } 2617 return copy; 2618 } catch (CloneNotSupportedException e) { 2619 /* Cannot happen */ 2620 throw new InternalError(e.toString(), e); 2621 } 2622 } 2623 } 2624