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