1 /* 2 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.x509; 27 28 import java.lang.reflect.*; 29 import java.io.IOException; 30 import java.security.PrivilegedExceptionAction; 31 import java.security.AccessController; 32 import java.security.Principal; 33 import java.util.*; 34 35 import sun.security.util.*; 36 import javax.security.auth.x500.X500Principal; 37 38 /** 39 * Note: As of 1.4, the public class, 40 * javax.security.auth.x500.X500Principal, 41 * should be used when parsing, generating, and comparing X.500 DNs. 42 * This class contains other useful methods for checking name constraints 43 * and retrieving DNs by keyword. 44 * 45 * <p> X.500 names are used to identify entities, such as those which are 46 * identified by X.509 certificates. They are world-wide, hierarchical, 47 * and descriptive. Entities can be identified by attributes, and in 48 * some systems can be searched for according to those attributes. 49 * <p> 50 * The ASN.1 for this is: 51 * <pre> 52 * GeneralName ::= CHOICE { 53 * .... 54 * directoryName [4] Name, 55 * .... 56 * Name ::= CHOICE { 57 * RDNSequence } 58 * 59 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 60 * 61 * RelativeDistinguishedName ::= 62 * SET OF AttributeTypeAndValue 63 * 64 * AttributeTypeAndValue ::= SEQUENCE { 65 * type AttributeType, 66 * value AttributeValue } 67 * 68 * AttributeType ::= OBJECT IDENTIFIER 69 * 70 * AttributeValue ::= ANY DEFINED BY AttributeType 71 * .... 72 * DirectoryString ::= CHOICE { 73 * teletexString TeletexString (SIZE (1..MAX)), 74 * printableString PrintableString (SIZE (1..MAX)), 75 * universalString UniversalString (SIZE (1..MAX)), 76 * utf8String UTF8String (SIZE (1.. MAX)), 77 * bmpString BMPString (SIZE (1..MAX)) } 78 * </pre> 79 * <p> 80 * This specification requires only a subset of the name comparison 81 * functionality specified in the X.500 series of specifications. The 82 * requirements for conforming implementations are as follows: 83 * <ol TYPE=a> 84 * <li>attribute values encoded in different types (e.g., 85 * PrintableString and BMPString) may be assumed to represent 86 * different strings; 87 * <p> 88 * <li>attribute values in types other than PrintableString are case 89 * sensitive (this permits matching of attribute values as binary 90 * objects); 91 * <p> 92 * <li>attribute values in PrintableString are not case sensitive 93 * (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and 94 * <p> 95 * <li>attribute values in PrintableString are compared after 96 * removing leading and trailing white space and converting internal 97 * substrings of one or more consecutive white space characters to a 98 * single space. 99 * </ol> 100 * <p> 101 * These name comparison rules permit a certificate user to validate 102 * certificates issued using languages or encodings unfamiliar to the 103 * certificate user. 104 * <p> 105 * In addition, implementations of this specification MAY use these 106 * comparison rules to process unfamiliar attribute types for name 107 * chaining. This allows implementations to process certificates with 108 * unfamiliar attributes in the issuer name. 109 * <p> 110 * Note that the comparison rules defined in the X.500 series of 111 * specifications indicate that the character sets used to encode data 112 * in distinguished names are irrelevant. The characters themselves are 113 * compared without regard to encoding. Implementations of the profile 114 * are permitted to use the comparison algorithm defined in the X.500 115 * series. Such an implementation will recognize a superset of name 116 * matches recognized by the algorithm specified above. 117 * <p> 118 * Note that instances of this class are immutable. 119 * 120 * @author David Brownell 121 * @author Amit Kapoor 122 * @author Hemma Prafullchandra 123 * @see GeneralName 124 * @see GeneralNames 125 * @see GeneralNameInterface 126 */ 127 128 public class X500Name implements GeneralNameInterface, Principal { 129 130 private String dn; // roughly RFC 1779 DN, or null 131 private String rfc1779Dn; // RFC 1779 compliant DN, or null 132 private String rfc2253Dn; // RFC 2253 DN, or null 133 private String canonicalDn; // canonical RFC 2253 DN or null 134 private RDN[] names; // RDNs (never null) 135 private X500Principal x500Principal; 136 private byte[] encoded; 137 138 // cached immutable list of the RDNs and all the AVAs 139 private volatile List<RDN> rdnList; 140 private volatile List<AVA> allAvaList; 141 142 /** 143 * Constructs a name from a conventionally formatted string, such 144 * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US". 145 * (RFC 1779, 2253, or 4514 style). 146 * 147 * @param dname the X.500 Distinguished Name 148 */ 149 public X500Name(String dname) throws IOException { 150 this(dname, Collections.<String, String>emptyMap()); 151 } 152 153 /** 154 * Constructs a name from a conventionally formatted string, such 155 * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US". 156 * (RFC 1779, 2253, or 4514 style). 157 * 158 * @param dname the X.500 Distinguished Name 159 * @param keywordMap an additional keyword/OID map 160 */ 161 public X500Name(String dname, Map<String, String> keywordMap) 162 throws IOException { 163 parseDN(dname, keywordMap); 164 } 165 166 /** 167 * Constructs a name from a string formatted according to format. 168 * Currently, the formats DEFAULT and RFC2253 are supported. 169 * DEFAULT is the default format used by the X500Name(String) 170 * constructor. RFC2253 is the format strictly according to RFC2253 171 * without extensions. 172 * 173 * @param dname the X.500 Distinguished Name 174 * @param format the specified format of the String DN 175 */ 176 public X500Name(String dname, String format) throws IOException { 177 if (dname == null) { 178 throw new NullPointerException("Name must not be null"); 179 } 180 if (format.equalsIgnoreCase("RFC2253")) { 181 parseRFC2253DN(dname); 182 } else if (format.equalsIgnoreCase("DEFAULT")) { 183 parseDN(dname, Collections.<String, String>emptyMap()); 184 } else { 185 throw new IOException("Unsupported format " + format); 186 } 187 } 188 189 /** 190 * Constructs a name from fields common in enterprise application 191 * environments. 192 * 193 * <P><EM><STRONG>NOTE:</STRONG> The behaviour when any of 194 * these strings contain characters outside the ASCII range 195 * is unspecified in currently relevant standards.</EM> 196 * 197 * @param commonName common name of a person, e.g. "Vivette Davis" 198 * @param organizationUnit small organization name, e.g. "Purchasing" 199 * @param organizationName large organization name, e.g. "Onizuka, Inc." 200 * @param country two letter country code, e.g. "CH" 201 */ 202 public X500Name(String commonName, String organizationUnit, 203 String organizationName, String country) 204 throws IOException { 205 names = new RDN[4]; 206 /* 207 * NOTE: it's only on output that little-endian 208 * ordering is used. 209 */ 210 names[3] = new RDN(1); 211 names[3].assertion[0] = new AVA(commonName_oid, 212 new DerValue(commonName)); 213 names[2] = new RDN(1); 214 names[2].assertion[0] = new AVA(orgUnitName_oid, 215 new DerValue(organizationUnit)); 216 names[1] = new RDN(1); 217 names[1].assertion[0] = new AVA(orgName_oid, 218 new DerValue(organizationName)); 219 names[0] = new RDN(1); 220 names[0].assertion[0] = new AVA(countryName_oid, 221 new DerValue(country)); 222 } 223 224 /** 225 * Constructs a name from fields common in Internet application 226 * environments. 227 * 228 * <P><EM><STRONG>NOTE:</STRONG> The behaviour when any of 229 * these strings contain characters outside the ASCII range 230 * is unspecified in currently relevant standards.</EM> 231 * 232 * @param commonName common name of a person, e.g. "Vivette Davis" 233 * @param organizationUnit small organization name, e.g. "Purchasing" 234 * @param organizationName large organization name, e.g. "Onizuka, Inc." 235 * @param localityName locality (city) name, e.g. "Palo Alto" 236 * @param stateName state name, e.g. "California" 237 * @param country two letter country code, e.g. "CH" 238 */ 239 public X500Name(String commonName, String organizationUnit, 240 String organizationName, String localityName, 241 String stateName, String country) 242 throws IOException { 243 names = new RDN[6]; 244 /* 245 * NOTE: it's only on output that little-endian 246 * ordering is used. 247 */ 248 names[5] = new RDN(1); 249 names[5].assertion[0] = new AVA(commonName_oid, 250 new DerValue(commonName)); 251 names[4] = new RDN(1); 252 names[4].assertion[0] = new AVA(orgUnitName_oid, 253 new DerValue(organizationUnit)); 254 names[3] = new RDN(1); 255 names[3].assertion[0] = new AVA(orgName_oid, 256 new DerValue(organizationName)); 257 names[2] = new RDN(1); 258 names[2].assertion[0] = new AVA(localityName_oid, 259 new DerValue(localityName)); 260 names[1] = new RDN(1); 261 names[1].assertion[0] = new AVA(stateName_oid, 262 new DerValue(stateName)); 263 names[0] = new RDN(1); 264 names[0].assertion[0] = new AVA(countryName_oid, 265 new DerValue(country)); 266 } 267 268 /** 269 * Constructs a name from an array of relative distinguished names 270 * 271 * @param rdnArray array of relative distinguished names 272 * @throws IOException on error 273 */ 274 public X500Name(RDN[] rdnArray) throws IOException { 275 if (rdnArray == null) { 276 names = new RDN[0]; 277 } else { 278 names = rdnArray.clone(); 279 for (int i = 0; i < names.length; i++) { 280 if (names[i] == null) { 281 throw new IOException("Cannot create an X500Name"); 282 } 283 } 284 } 285 } 286 287 /** 288 * Constructs a name from an ASN.1 encoded value. The encoding 289 * of the name in the stream uses DER (a BER/1 subset). 290 * 291 * @param value a DER-encoded value holding an X.500 name. 292 */ 293 public X500Name(DerValue value) throws IOException { 294 //Note that toDerInputStream uses only the buffer (data) and not 295 //the tag, so an empty SEQUENCE (OF) will yield an empty DerInputStream 296 this(value.toDerInputStream()); 297 } 298 299 /** 300 * Constructs a name from an ASN.1 encoded input stream. The encoding 301 * of the name in the stream uses DER (a BER/1 subset). 302 * 303 * @param in DER-encoded data holding an X.500 name. 304 */ 305 public X500Name(DerInputStream in) throws IOException { 306 parseDER(in); 307 } 308 309 /** 310 * Constructs a name from an ASN.1 encoded byte array. 311 * 312 * @param name DER-encoded byte array holding an X.500 name. 313 */ 314 public X500Name(byte[] name) throws IOException { 315 DerInputStream in = new DerInputStream(name); 316 parseDER(in); 317 } 318 319 /** 320 * Return an immutable List of all RDNs in this X500Name. 321 */ 322 public List<RDN> rdns() { 323 List<RDN> list = rdnList; 324 if (list == null) { 325 list = Collections.unmodifiableList(Arrays.asList(names)); 326 rdnList = list; 327 } 328 return list; 329 } 330 331 /** 332 * Return the number of RDNs in this X500Name. 333 */ 334 public int size() { 335 return names.length; 336 } 337 338 /** 339 * Return an immutable List of the the AVAs contained in all the 340 * RDNs of this X500Name. 341 */ 342 public List<AVA> allAvas() { 343 List<AVA> list = allAvaList; 344 if (list == null) { 345 list = new ArrayList<AVA>(); 346 for (int i = 0; i < names.length; i++) { 347 list.addAll(names[i].avas()); 348 } 349 list = Collections.unmodifiableList(list); 350 allAvaList = list; 351 } 352 return list; 353 } 354 355 /** 356 * Return the total number of AVAs contained in all the RDNs of 357 * this X500Name. 358 */ 359 public int avaSize() { 360 return allAvas().size(); 361 } 362 363 /** 364 * Return whether this X500Name is empty. An X500Name is not empty 365 * if it has at least one RDN containing at least one AVA. 366 */ 367 public boolean isEmpty() { 368 int n = names.length; 369 for (int i = 0; i < n; i++) { 370 if (names[i].assertion.length != 0) { 371 return false; 372 } 373 } 374 return true; 375 } 376 377 /** 378 * Calculates a hash code value for the object. Objects 379 * which are equal will also have the same hashcode. 380 */ 381 public int hashCode() { 382 return getRFC2253CanonicalName().hashCode(); 383 } 384 385 /** 386 * Compares this name with another, for equality. 387 * 388 * @return true iff the names are identical. 389 */ 390 public boolean equals(Object obj) { 391 if (this == obj) { 392 return true; 393 } 394 if (obj instanceof X500Name == false) { 395 return false; 396 } 397 X500Name other = (X500Name)obj; 398 // if we already have the canonical forms, compare now 399 if ((this.canonicalDn != null) && (other.canonicalDn != null)) { 400 return this.canonicalDn.equals(other.canonicalDn); 401 } 402 // quick check that number of RDNs and AVAs match before canonicalizing 403 int n = this.names.length; 404 if (n != other.names.length) { 405 return false; 406 } 407 for (int i = 0; i < n; i++) { 408 RDN r1 = this.names[i]; 409 RDN r2 = other.names[i]; 410 if (r1.assertion.length != r2.assertion.length) { 411 return false; 412 } 413 } 414 // definite check via canonical form 415 String thisCanonical = this.getRFC2253CanonicalName(); 416 String otherCanonical = other.getRFC2253CanonicalName(); 417 return thisCanonical.equals(otherCanonical); 418 } 419 420 /* 421 * Returns the name component as a Java string, regardless of its 422 * encoding restrictions. 423 */ 424 private String getString(DerValue attribute) throws IOException { 425 if (attribute == null) 426 return null; 427 String value = attribute.getAsString(); 428 429 if (value == null) 430 throw new IOException("not a DER string encoding, " 431 + attribute.tag); 432 else 433 return value; 434 } 435 436 /** 437 * Return type of GeneralName. 438 */ 439 public int getType() { 440 return (GeneralNameInterface.NAME_DIRECTORY); 441 } 442 443 /** 444 * Returns a "Country" name component. If more than one 445 * such attribute exists, the topmost one is returned. 446 * 447 * @return "C=" component of the name, if any. 448 */ 449 public String getCountry() throws IOException { 450 DerValue attr = findAttribute(countryName_oid); 451 452 return getString(attr); 453 } 454 455 456 /** 457 * Returns an "Organization" name component. If more than 458 * one such attribute exists, the topmost one is returned. 459 * 460 * @return "O=" component of the name, if any. 461 */ 462 public String getOrganization() throws IOException { 463 DerValue attr = findAttribute(orgName_oid); 464 465 return getString(attr); 466 } 467 468 469 /** 470 * Returns an "Organizational Unit" name component. If more 471 * than one such attribute exists, the topmost one is returned. 472 * 473 * @return "OU=" component of the name, if any. 474 */ 475 public String getOrganizationalUnit() throws IOException { 476 DerValue attr = findAttribute(orgUnitName_oid); 477 478 return getString(attr); 479 } 480 481 482 /** 483 * Returns a "Common Name" component. If more than one such 484 * attribute exists, the topmost one is returned. 485 * 486 * @return "CN=" component of the name, if any. 487 */ 488 public String getCommonName() throws IOException { 489 DerValue attr = findAttribute(commonName_oid); 490 491 return getString(attr); 492 } 493 494 495 /** 496 * Returns a "Locality" name component. If more than one 497 * such component exists, the topmost one is returned. 498 * 499 * @return "L=" component of the name, if any. 500 */ 501 public String getLocality() throws IOException { 502 DerValue attr = findAttribute(localityName_oid); 503 504 return getString(attr); 505 } 506 507 /** 508 * Returns a "State" name component. If more than one 509 * such component exists, the topmost one is returned. 510 * 511 * @return "S=" component of the name, if any. 512 */ 513 public String getState() throws IOException { 514 DerValue attr = findAttribute(stateName_oid); 515 516 return getString(attr); 517 } 518 519 /** 520 * Returns a "Domain" name component. If more than one 521 * such component exists, the topmost one is returned. 522 * 523 * @return "DC=" component of the name, if any. 524 */ 525 public String getDomain() throws IOException { 526 DerValue attr = findAttribute(DOMAIN_COMPONENT_OID); 527 528 return getString(attr); 529 } 530 531 /** 532 * Returns a "DN Qualifier" name component. If more than one 533 * such component exists, the topmost one is returned. 534 * 535 * @return "DNQ=" component of the name, if any. 536 */ 537 public String getDNQualifier() throws IOException { 538 DerValue attr = findAttribute(DNQUALIFIER_OID); 539 540 return getString(attr); 541 } 542 543 /** 544 * Returns a "Surname" name component. If more than one 545 * such component exists, the topmost one is returned. 546 * 547 * @return "SURNAME=" component of the name, if any. 548 */ 549 public String getSurname() throws IOException { 550 DerValue attr = findAttribute(SURNAME_OID); 551 552 return getString(attr); 553 } 554 555 /** 556 * Returns a "Given Name" name component. If more than one 557 * such component exists, the topmost one is returned. 558 * 559 * @return "GIVENNAME=" component of the name, if any. 560 */ 561 public String getGivenName() throws IOException { 562 DerValue attr = findAttribute(GIVENNAME_OID); 563 564 return getString(attr); 565 } 566 567 /** 568 * Returns an "Initials" name component. If more than one 569 * such component exists, the topmost one is returned. 570 * 571 * @return "INITIALS=" component of the name, if any. 572 */ 573 public String getInitials() throws IOException { 574 DerValue attr = findAttribute(INITIALS_OID); 575 576 return getString(attr); 577 } 578 579 /** 580 * Returns a "Generation Qualifier" name component. If more than one 581 * such component exists, the topmost one is returned. 582 * 583 * @return "GENERATION=" component of the name, if any. 584 */ 585 public String getGeneration() throws IOException { 586 DerValue attr = findAttribute(GENERATIONQUALIFIER_OID); 587 588 return getString(attr); 589 } 590 591 /** 592 * Returns an "IP address" name component. If more than one 593 * such component exists, the topmost one is returned. 594 * 595 * @return "IP=" component of the name, if any. 596 */ 597 public String getIP() throws IOException { 598 DerValue attr = findAttribute(ipAddress_oid); 599 600 return getString(attr); 601 } 602 603 /** 604 * Returns a string form of the X.500 distinguished name. 605 * The format of the string is from RFC 1779. The returned string 606 * may contain non-standardised keywords for more readability 607 * (keywords from RFCs 1779, 2253, and 3280). 608 */ 609 public String toString() { 610 if (dn == null) { 611 generateDN(); 612 } 613 return dn; 614 } 615 616 /** 617 * Returns a string form of the X.500 distinguished name 618 * using the algorithm defined in RFC 1779. Only standard attribute type 619 * keywords defined in RFC 1779 are emitted. 620 */ 621 public String getRFC1779Name() { 622 return getRFC1779Name(Collections.<String, String>emptyMap()); 623 } 624 625 /** 626 * Returns a string form of the X.500 distinguished name 627 * using the algorithm defined in RFC 1779. Attribute type 628 * keywords defined in RFC 1779 are emitted, as well as additional 629 * keywords contained in the OID/keyword map. 630 */ 631 public String getRFC1779Name(Map<String, String> oidMap) 632 throws IllegalArgumentException { 633 if (oidMap.isEmpty()) { 634 // return cached result 635 if (rfc1779Dn != null) { 636 return rfc1779Dn; 637 } else { 638 rfc1779Dn = generateRFC1779DN(oidMap); 639 return rfc1779Dn; 640 } 641 } 642 return generateRFC1779DN(oidMap); 643 } 644 645 /** 646 * Returns a string form of the X.500 distinguished name 647 * using the algorithm defined in RFC 2253. Only standard attribute type 648 * keywords defined in RFC 2253 are emitted. 649 */ 650 public String getRFC2253Name() { 651 return getRFC2253Name(Collections.<String, String>emptyMap()); 652 } 653 654 /** 655 * Returns a string form of the X.500 distinguished name 656 * using the algorithm defined in RFC 2253. Attribute type 657 * keywords defined in RFC 2253 are emitted, as well as additional 658 * keywords contained in the OID/keyword map. 659 */ 660 public String getRFC2253Name(Map<String, String> oidMap) { 661 /* check for and return cached name */ 662 if (oidMap.isEmpty()) { 663 if (rfc2253Dn != null) { 664 return rfc2253Dn; 665 } else { 666 rfc2253Dn = generateRFC2253DN(oidMap); 667 return rfc2253Dn; 668 } 669 } 670 return generateRFC2253DN(oidMap); 671 } 672 673 private String generateRFC2253DN(Map<String, String> oidMap) { 674 /* 675 * Section 2.1 : if the RDNSequence is an empty sequence 676 * the result is the empty or zero length string. 677 */ 678 if (names.length == 0) { 679 return ""; 680 } 681 682 /* 683 * 2.1 (continued) : Otherwise, the output consists of the string 684 * encodings of each RelativeDistinguishedName in the RDNSequence 685 * (according to 2.2), starting with the last element of the sequence 686 * and moving backwards toward the first. 687 * 688 * The encodings of adjoining RelativeDistinguishedNames are separated 689 * by a comma character (',' ASCII 44). 690 */ 691 StringBuilder fullname = new StringBuilder(48); 692 for (int i = names.length - 1; i >= 0; i--) { 693 if (i < names.length - 1) { 694 fullname.append(','); 695 } 696 fullname.append(names[i].toRFC2253String(oidMap)); 697 } 698 return fullname.toString(); 699 } 700 701 public String getRFC2253CanonicalName() { 702 /* check for and return cached name */ 703 if (canonicalDn != null) { 704 return canonicalDn; 705 } 706 /* 707 * Section 2.1 : if the RDNSequence is an empty sequence 708 * the result is the empty or zero length string. 709 */ 710 if (names.length == 0) { 711 canonicalDn = ""; 712 return canonicalDn; 713 } 714 715 /* 716 * 2.1 (continued) : Otherwise, the output consists of the string 717 * encodings of each RelativeDistinguishedName in the RDNSequence 718 * (according to 2.2), starting with the last element of the sequence 719 * and moving backwards toward the first. 720 * 721 * The encodings of adjoining RelativeDistinguishedNames are separated 722 * by a comma character (',' ASCII 44). 723 */ 724 StringBuilder fullname = new StringBuilder(48); 725 for (int i = names.length - 1; i >= 0; i--) { 726 if (i < names.length - 1) { 727 fullname.append(','); 728 } 729 fullname.append(names[i].toRFC2253String(true)); 730 } 731 canonicalDn = fullname.toString(); 732 return canonicalDn; 733 } 734 735 /** 736 * Returns the value of toString(). This call is needed to 737 * implement the java.security.Principal interface. 738 */ 739 public String getName() { return toString(); } 740 741 /** 742 * Find the first instance of this attribute in a "top down" 743 * search of all the attributes in the name. 744 */ 745 private DerValue findAttribute(ObjectIdentifier attribute) { 746 if (names != null) { 747 for (int i = 0; i < names.length; i++) { 748 DerValue value = names[i].findAttribute(attribute); 749 if (value != null) { 750 return value; 751 } 752 } 753 } 754 return null; 755 } 756 757 /** 758 * Find the most specific ("last") attribute of the given 759 * type. 760 */ 761 public DerValue findMostSpecificAttribute(ObjectIdentifier attribute) { 762 if (names != null) { 763 for (int i = names.length - 1; i >= 0; i--) { 764 DerValue value = names[i].findAttribute(attribute); 765 if (value != null) { 766 return value; 767 } 768 } 769 } 770 return null; 771 } 772 773 /****************************************************************/ 774 775 private void parseDER(DerInputStream in) throws IOException { 776 // 777 // X.500 names are a "SEQUENCE OF" RDNs, which means zero or 778 // more and order matters. We scan them in order, which 779 // conventionally is big-endian. 780 // 781 DerValue[] nameseq = null; 782 byte[] derBytes = in.toByteArray(); 783 784 try { 785 nameseq = in.getSequence(5); 786 } catch (IOException ioe) { 787 if (derBytes == null) { 788 nameseq = null; 789 } else { 790 DerValue derVal = new DerValue(DerValue.tag_Sequence, 791 derBytes); 792 derBytes = derVal.toByteArray(); 793 nameseq = new DerInputStream(derBytes).getSequence(5); 794 } 795 } 796 797 if (nameseq == null) { 798 names = new RDN[0]; 799 } else { 800 names = new RDN[nameseq.length]; 801 for (int i = 0; i < nameseq.length; i++) { 802 names[i] = new RDN(nameseq[i]); 803 } 804 } 805 } 806 807 /** 808 * Encodes the name in DER-encoded form. 809 * 810 * @deprecated Use encode() instead 811 * @param out where to put the DER-encoded X.500 name 812 */ 813 @Deprecated 814 public void emit(DerOutputStream out) throws IOException { 815 encode(out); 816 } 817 818 /** 819 * Encodes the name in DER-encoded form. 820 * 821 * @param out where to put the DER-encoded X.500 name 822 */ 823 public void encode(DerOutputStream out) throws IOException { 824 DerOutputStream tmp = new DerOutputStream(); 825 for (int i = 0; i < names.length; i++) { 826 names[i].encode(tmp); 827 } 828 out.write(DerValue.tag_Sequence, tmp); 829 } 830 831 /** 832 * Returned the encoding as an uncloned byte array. Callers must 833 * guarantee that they neither modify it not expose it to untrusted 834 * code. 835 */ 836 public byte[] getEncodedInternal() throws IOException { 837 if (encoded == null) { 838 DerOutputStream out = new DerOutputStream(); 839 DerOutputStream tmp = new DerOutputStream(); 840 for (int i = 0; i < names.length; i++) { 841 names[i].encode(tmp); 842 } 843 out.write(DerValue.tag_Sequence, tmp); 844 encoded = out.toByteArray(); 845 } 846 return encoded; 847 } 848 849 /** 850 * Gets the name in DER-encoded form. 851 * 852 * @return the DER encoded byte array of this name. 853 */ 854 public byte[] getEncoded() throws IOException { 855 return getEncodedInternal().clone(); 856 } 857 858 /* 859 * Parses a Distinguished Name (DN) in printable representation. 860 * 861 * According to RFC 1779, RDNs in a DN are separated by comma. 862 * The following examples show both methods of quoting a comma, so that it 863 * is not considered a separator: 864 * 865 * O="Sue, Grabbit and Runn" or 866 * O=Sue\, Grabbit and Runn 867 * 868 * This method can parse RFC 1779, 2253 or 4514 DNs and non-standard 3280 869 * keywords. Additional keywords can be specified in the keyword/OID map. 870 */ 871 private void parseDN(String input, Map<String, String> keywordMap) 872 throws IOException { 873 if (input == null || input.length() == 0) { 874 names = new RDN[0]; 875 return; 876 } 877 878 List<RDN> dnVector = new ArrayList<>(); 879 int dnOffset = 0; 880 int rdnEnd; 881 String rdnString; 882 int quoteCount = 0; 883 884 String dnString = input; 885 886 int searchOffset = 0; 887 int nextComma = dnString.indexOf(','); 888 int nextSemiColon = dnString.indexOf(';'); 889 while (nextComma >=0 || nextSemiColon >=0) { 890 891 if (nextSemiColon < 0) { 892 rdnEnd = nextComma; 893 } else if (nextComma < 0) { 894 rdnEnd = nextSemiColon; 895 } else { 896 rdnEnd = Math.min(nextComma, nextSemiColon); 897 } 898 quoteCount += countQuotes(dnString, searchOffset, rdnEnd); 899 900 /* 901 * We have encountered an RDN delimiter (comma or a semicolon). 902 * If the comma or semicolon in the RDN under consideration is 903 * preceded by a backslash (escape), or by a double quote, it 904 * is part of the RDN. Otherwise, it is used as a separator, to 905 * delimit the RDN under consideration from any subsequent RDNs. 906 */ 907 if (rdnEnd >= 0 && quoteCount != 1 && 908 !escaped(rdnEnd, searchOffset, dnString)) { 909 910 /* 911 * Comma/semicolon is a separator 912 */ 913 rdnString = dnString.substring(dnOffset, rdnEnd); 914 915 // Parse RDN, and store it in vector 916 RDN rdn = new RDN(rdnString, keywordMap); 917 dnVector.add(rdn); 918 919 // Increase the offset 920 dnOffset = rdnEnd + 1; 921 922 // Set quote counter back to zero 923 quoteCount = 0; 924 } 925 926 searchOffset = rdnEnd + 1; 927 nextComma = dnString.indexOf(',', searchOffset); 928 nextSemiColon = dnString.indexOf(';', searchOffset); 929 } 930 931 // Parse last or only RDN, and store it in vector 932 rdnString = dnString.substring(dnOffset); 933 RDN rdn = new RDN(rdnString, keywordMap); 934 dnVector.add(rdn); 935 936 /* 937 * Store the vector elements as an array of RDNs 938 * NOTE: It's only on output that little-endian ordering is used. 939 */ 940 Collections.reverse(dnVector); 941 names = dnVector.toArray(new RDN[dnVector.size()]); 942 } 943 944 private void parseRFC2253DN(String dnString) throws IOException { 945 if (dnString.length() == 0) { 946 names = new RDN[0]; 947 return; 948 } 949 950 List<RDN> dnVector = new ArrayList<>(); 951 int dnOffset = 0; 952 String rdnString; 953 int searchOffset = 0; 954 int rdnEnd = dnString.indexOf(','); 955 while (rdnEnd >=0) { 956 /* 957 * We have encountered an RDN delimiter (comma). 958 * If the comma in the RDN under consideration is 959 * preceded by a backslash (escape), it 960 * is part of the RDN. Otherwise, it is used as a separator, to 961 * delimit the RDN under consideration from any subsequent RDNs. 962 */ 963 if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) { 964 965 /* 966 * Comma is a separator 967 */ 968 rdnString = dnString.substring(dnOffset, rdnEnd); 969 970 // Parse RDN, and store it in vector 971 RDN rdn = new RDN(rdnString, "RFC2253"); 972 dnVector.add(rdn); 973 974 // Increase the offset 975 dnOffset = rdnEnd + 1; 976 } 977 978 searchOffset = rdnEnd + 1; 979 rdnEnd = dnString.indexOf(',', searchOffset); 980 } 981 982 // Parse last or only RDN, and store it in vector 983 rdnString = dnString.substring(dnOffset); 984 RDN rdn = new RDN(rdnString, "RFC2253"); 985 dnVector.add(rdn); 986 987 /* 988 * Store the vector elements as an array of RDNs 989 * NOTE: It's only on output that little-endian ordering is used. 990 */ 991 Collections.reverse(dnVector); 992 names = dnVector.toArray(new RDN[dnVector.size()]); 993 } 994 995 /* 996 * Counts double quotes in string. 997 * Escaped quotes are ignored. 998 */ 999 static int countQuotes(String string, int from, int to) { 1000 int count = 0; 1001 1002 for (int i = from; i < to; i++) { 1003 if ((string.charAt(i) == '"' && i == from) || 1004 (string.charAt(i) == '"' && string.charAt(i-1) != '\\')) { 1005 count++; 1006 } 1007 } 1008 1009 return count; 1010 } 1011 1012 private static boolean escaped 1013 (int rdnEnd, int searchOffset, String dnString) { 1014 1015 if (rdnEnd == 1 && dnString.charAt(rdnEnd - 1) == '\\') { 1016 1017 // case 1: 1018 // \, 1019 1020 return true; 1021 1022 } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' && 1023 dnString.charAt(rdnEnd - 2) != '\\') { 1024 1025 // case 2: 1026 // foo\, 1027 1028 return true; 1029 1030 } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' && 1031 dnString.charAt(rdnEnd - 2) == '\\') { 1032 1033 // case 3: 1034 // foo\\\\\, 1035 1036 int count = 0; 1037 rdnEnd--; // back up to last backSlash 1038 while (rdnEnd >= searchOffset) { 1039 if (dnString.charAt(rdnEnd) == '\\') { 1040 count++; // count consecutive backslashes 1041 } 1042 rdnEnd--; 1043 } 1044 1045 // if count is odd, then rdnEnd is escaped 1046 return (count % 2) != 0 ? true : false; 1047 1048 } else { 1049 return false; 1050 } 1051 } 1052 1053 /* 1054 * Dump the printable form of a distinguished name. Each relative 1055 * name is separated from the next by a ",", and assertions in the 1056 * relative names have "label=value" syntax. 1057 * 1058 * Uses RFC 1779 syntax (i.e. little-endian, comma separators) 1059 */ 1060 private void generateDN() { 1061 if (names.length == 1) { 1062 dn = names[0].toString(); 1063 return; 1064 } 1065 1066 StringBuilder sb = new StringBuilder(48); 1067 if (names != null) { 1068 for (int i = names.length - 1; i >= 0; i--) { 1069 if (i != names.length - 1) { 1070 sb.append(", "); 1071 } 1072 sb.append(names[i].toString()); 1073 } 1074 } 1075 dn = sb.toString(); 1076 } 1077 1078 /* 1079 * Dump the printable form of a distinguished name. Each relative 1080 * name is separated from the next by a ",", and assertions in the 1081 * relative names have "label=value" syntax. 1082 * 1083 * Uses RFC 1779 syntax (i.e. little-endian, comma separators) 1084 * Valid keywords from RFC 1779 are used. Additional keywords can be 1085 * specified in the OID/keyword map. 1086 */ 1087 private String generateRFC1779DN(Map<String, String> oidMap) { 1088 if (names.length == 1) { 1089 return names[0].toRFC1779String(oidMap); 1090 } 1091 1092 StringBuilder sb = new StringBuilder(48); 1093 if (names != null) { 1094 for (int i = names.length - 1; i >= 0; i--) { 1095 if (i != names.length - 1) { 1096 sb.append(", "); 1097 } 1098 sb.append(names[i].toRFC1779String(oidMap)); 1099 } 1100 } 1101 return sb.toString(); 1102 } 1103 1104 /****************************************************************/ 1105 1106 /* 1107 * Maybe return a preallocated OID, to reduce storage costs 1108 * and speed recognition of common X.500 attributes. 1109 */ 1110 static ObjectIdentifier intern(ObjectIdentifier oid) { 1111 ObjectIdentifier interned = internedOIDs.putIfAbsent(oid, oid); 1112 return (interned == null) ? oid : interned; 1113 } 1114 1115 private static final Map<ObjectIdentifier,ObjectIdentifier> internedOIDs 1116 = new HashMap<ObjectIdentifier,ObjectIdentifier>(); 1117 1118 /* 1119 * Selected OIDs from X.520 1120 * Includes all those specified in RFC 3280 as MUST or SHOULD 1121 * be recognized 1122 */ 1123 private static final int commonName_data[] = { 2, 5, 4, 3 }; 1124 private static final int SURNAME_DATA[] = { 2, 5, 4, 4 }; 1125 private static final int SERIALNUMBER_DATA[] = { 2, 5, 4, 5 }; 1126 private static final int countryName_data[] = { 2, 5, 4, 6 }; 1127 private static final int localityName_data[] = { 2, 5, 4, 7 }; 1128 private static final int stateName_data[] = { 2, 5, 4, 8 }; 1129 private static final int streetAddress_data[] = { 2, 5, 4, 9 }; 1130 private static final int orgName_data[] = { 2, 5, 4, 10 }; 1131 private static final int orgUnitName_data[] = { 2, 5, 4, 11 }; 1132 private static final int title_data[] = { 2, 5, 4, 12 }; 1133 private static final int GIVENNAME_DATA[] = { 2, 5, 4, 42 }; 1134 private static final int INITIALS_DATA[] = { 2, 5, 4, 43 }; 1135 private static final int GENERATIONQUALIFIER_DATA[] = { 2, 5, 4, 44 }; 1136 private static final int DNQUALIFIER_DATA[] = { 2, 5, 4, 46 }; 1137 1138 private static final int ipAddress_data[] = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; 1139 private static final int DOMAIN_COMPONENT_DATA[] = 1140 { 0, 9, 2342, 19200300, 100, 1, 25 }; 1141 private static final int userid_data[] = 1142 { 0, 9, 2342, 19200300, 100, 1, 1 }; 1143 1144 1145 public static final ObjectIdentifier commonName_oid; 1146 public static final ObjectIdentifier countryName_oid; 1147 public static final ObjectIdentifier localityName_oid; 1148 public static final ObjectIdentifier orgName_oid; 1149 public static final ObjectIdentifier orgUnitName_oid; 1150 public static final ObjectIdentifier stateName_oid; 1151 public static final ObjectIdentifier streetAddress_oid; 1152 public static final ObjectIdentifier title_oid; 1153 public static final ObjectIdentifier DNQUALIFIER_OID; 1154 public static final ObjectIdentifier SURNAME_OID; 1155 public static final ObjectIdentifier GIVENNAME_OID; 1156 public static final ObjectIdentifier INITIALS_OID; 1157 public static final ObjectIdentifier GENERATIONQUALIFIER_OID; 1158 public static final ObjectIdentifier ipAddress_oid; 1159 public static final ObjectIdentifier DOMAIN_COMPONENT_OID; 1160 public static final ObjectIdentifier userid_oid; 1161 public static final ObjectIdentifier SERIALNUMBER_OID; 1162 1163 static { 1164 /** OID for the "CN=" attribute, denoting a person's common name. */ 1165 commonName_oid = intern(ObjectIdentifier.newInternal(commonName_data)); 1166 1167 /** OID for the "SERIALNUMBER=" attribute, denoting a serial number for. 1168 a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the 1169 certificate serial number. */ 1170 SERIALNUMBER_OID = intern(ObjectIdentifier.newInternal(SERIALNUMBER_DATA)); 1171 1172 /** OID for the "C=" attribute, denoting a country. */ 1173 countryName_oid = intern(ObjectIdentifier.newInternal(countryName_data)); 1174 1175 /** OID for the "L=" attribute, denoting a locality (such as a city) */ 1176 localityName_oid = intern(ObjectIdentifier.newInternal(localityName_data)); 1177 1178 /** OID for the "O=" attribute, denoting an organization name */ 1179 orgName_oid = intern(ObjectIdentifier.newInternal(orgName_data)); 1180 1181 /** OID for the "OU=" attribute, denoting an organizational unit name */ 1182 orgUnitName_oid = intern(ObjectIdentifier.newInternal(orgUnitName_data)); 1183 1184 /** OID for the "S=" attribute, denoting a state (such as Delaware) */ 1185 stateName_oid = intern(ObjectIdentifier.newInternal(stateName_data)); 1186 1187 /** OID for the "STREET=" attribute, denoting a street address. */ 1188 streetAddress_oid = intern(ObjectIdentifier.newInternal(streetAddress_data)); 1189 1190 /** OID for the "T=" attribute, denoting a person's title. */ 1191 title_oid = intern(ObjectIdentifier.newInternal(title_data)); 1192 1193 /** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN 1194 disambiguating information.*/ 1195 DNQUALIFIER_OID = intern(ObjectIdentifier.newInternal(DNQUALIFIER_DATA)); 1196 1197 /** OID for the "SURNAME=" attribute, denoting a person's surname.*/ 1198 SURNAME_OID = intern(ObjectIdentifier.newInternal(SURNAME_DATA)); 1199 1200 /** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/ 1201 GIVENNAME_OID = intern(ObjectIdentifier.newInternal(GIVENNAME_DATA)); 1202 1203 /** OID for the "INITIALS=" attribute, denoting a person's initials.*/ 1204 INITIALS_OID = intern(ObjectIdentifier.newInternal(INITIALS_DATA)); 1205 1206 /** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/ 1207 GENERATIONQUALIFIER_OID = 1208 intern(ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA)); 1209 1210 /* 1211 * OIDs from other sources which show up in X.500 names we 1212 * expect to deal with often 1213 */ 1214 /** OID for "IP=" IP address attributes, used with SKIP. */ 1215 ipAddress_oid = intern(ObjectIdentifier.newInternal(ipAddress_data)); 1216 1217 /* 1218 * Domain component OID from RFC 1274, RFC 2247, RFC 3280 1219 */ 1220 1221 /* 1222 * OID for "DC=" domain component attributes, used with DNSNames in DN 1223 * format 1224 */ 1225 DOMAIN_COMPONENT_OID = 1226 intern(ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA)); 1227 1228 /** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */ 1229 userid_oid = intern(ObjectIdentifier.newInternal(userid_data)); 1230 } 1231 1232 /** 1233 * Return constraint type:<ul> 1234 * <li>NAME_DIFF_TYPE = -1: input name is different type from this name 1235 * (i.e. does not constrain) 1236 * <li>NAME_MATCH = 0: input name matches this name 1237 * <li>NAME_NARROWS = 1: input name narrows this name 1238 * <li>NAME_WIDENS = 2: input name widens this name 1239 * <li>NAME_SAME_TYPE = 3: input name does not match or narrow this name, 1240 & but is same type 1241 * </ul>. These results are used in checking NameConstraints during 1242 * certification path verification. 1243 * 1244 * @param inputName to be checked for being constrained 1245 * @returns constraint type above 1246 * @throws UnsupportedOperationException if name is not exact match, but 1247 * narrowing and widening are not supported for this name type. 1248 */ 1249 public int constrains(GeneralNameInterface inputName) 1250 throws UnsupportedOperationException { 1251 int constraintType; 1252 if (inputName == null) { 1253 constraintType = NAME_DIFF_TYPE; 1254 } else if (inputName.getType() != NAME_DIRECTORY) { 1255 constraintType = NAME_DIFF_TYPE; 1256 } else { // type == NAME_DIRECTORY 1257 X500Name inputX500 = (X500Name)inputName; 1258 if (inputX500.equals(this)) { 1259 constraintType = NAME_MATCH; 1260 } else if (inputX500.names.length == 0) { 1261 constraintType = NAME_WIDENS; 1262 } else if (this.names.length == 0) { 1263 constraintType = NAME_NARROWS; 1264 } else if (inputX500.isWithinSubtree(this)) { 1265 constraintType = NAME_NARROWS; 1266 } else if (isWithinSubtree(inputX500)) { 1267 constraintType = NAME_WIDENS; 1268 } else { 1269 constraintType = NAME_SAME_TYPE; 1270 } 1271 } 1272 return constraintType; 1273 } 1274 1275 /** 1276 * Compares this name with another and determines if 1277 * it is within the subtree of the other. Useful for 1278 * checking against the name constraints extension. 1279 * 1280 * @return true iff this name is within the subtree of other. 1281 */ 1282 private boolean isWithinSubtree(X500Name other) { 1283 if (this == other) { 1284 return true; 1285 } 1286 if (other == null) { 1287 return false; 1288 } 1289 if (other.names.length == 0) { 1290 return true; 1291 } 1292 if (this.names.length == 0) { 1293 return false; 1294 } 1295 if (names.length < other.names.length) { 1296 return false; 1297 } 1298 for (int i = 0; i < other.names.length; i++) { 1299 if (!names[i].equals(other.names[i])) { 1300 return false; 1301 } 1302 } 1303 return true; 1304 } 1305 1306 /** 1307 * Return subtree depth of this name for purposes of determining 1308 * NameConstraints minimum and maximum bounds and for calculating 1309 * path lengths in name subtrees. 1310 * 1311 * @returns distance of name from root 1312 * @throws UnsupportedOperationException if not supported for this name type 1313 */ 1314 public int subtreeDepth() throws UnsupportedOperationException { 1315 return names.length; 1316 } 1317 1318 /** 1319 * Return lowest common ancestor of this name and other name 1320 * 1321 * @param other another X500Name 1322 * @return X500Name of lowest common ancestor; null if none 1323 */ 1324 public X500Name commonAncestor(X500Name other) { 1325 1326 if (other == null) { 1327 return null; 1328 } 1329 int otherLen = other.names.length; 1330 int thisLen = this.names.length; 1331 if (thisLen == 0 || otherLen == 0) { 1332 return null; 1333 } 1334 int minLen = (thisLen < otherLen) ? thisLen: otherLen; 1335 1336 //Compare names from highest RDN down the naming tree 1337 //Note that these are stored in RDN[0]... 1338 int i=0; 1339 for (; i < minLen; i++) { 1340 if (!names[i].equals(other.names[i])) { 1341 if (i == 0) { 1342 return null; 1343 } else { 1344 break; 1345 } 1346 } 1347 } 1348 1349 //Copy matching RDNs into new RDN array 1350 RDN[] ancestor = new RDN[i]; 1351 for (int j=0; j < i; j++) { 1352 ancestor[j] = names[j]; 1353 } 1354 1355 X500Name commonAncestor = null; 1356 try { 1357 commonAncestor = new X500Name(ancestor); 1358 } catch (IOException ioe) { 1359 return null; 1360 } 1361 return commonAncestor; 1362 } 1363 1364 /** 1365 * Constructor object for use by asX500Principal(). 1366 */ 1367 private static final Constructor<X500Principal> principalConstructor; 1368 1369 /** 1370 * Field object for use by asX500Name(). 1371 */ 1372 private static final Field principalField; 1373 1374 /** 1375 * Retrieve the Constructor and Field we need for reflective access 1376 * and make them accessible. 1377 */ 1378 static { 1379 PrivilegedExceptionAction<Object[]> pa = 1380 new PrivilegedExceptionAction<Object[]>() { 1381 public Object[] run() throws Exception { 1382 Class<X500Principal> pClass = X500Principal.class; 1383 Class<?>[] args = new Class<?>[] { X500Name.class }; 1384 Constructor<X500Principal> cons = pClass.getDeclaredConstructor(args); 1385 cons.setAccessible(true); 1386 Field field = pClass.getDeclaredField("thisX500Name"); 1387 field.setAccessible(true); 1388 return new Object[] {cons, field}; 1389 } 1390 }; 1391 try { 1392 Object[] result = AccessController.doPrivileged(pa); 1393 @SuppressWarnings("unchecked") 1394 Constructor<X500Principal> constr = 1395 (Constructor<X500Principal>)result[0]; 1396 principalConstructor = constr; 1397 principalField = (Field)result[1]; 1398 } catch (Exception e) { 1399 throw new InternalError("Could not obtain X500Principal access", e); 1400 } 1401 } 1402 1403 /** 1404 * Get an X500Principal backed by this X500Name. 1405 * 1406 * Note that we are using privileged reflection to access the hidden 1407 * package private constructor in X500Principal. 1408 */ 1409 public X500Principal asX500Principal() { 1410 if (x500Principal == null) { 1411 try { 1412 Object[] args = new Object[] {this}; 1413 x500Principal = principalConstructor.newInstance(args); 1414 } catch (Exception e) { 1415 throw new RuntimeException("Unexpected exception", e); 1416 } 1417 } 1418 return x500Principal; 1419 } 1420 1421 /** 1422 * Get the X500Name contained in the given X500Principal. 1423 * 1424 * Note that the X500Name is retrieved using reflection. 1425 */ 1426 public static X500Name asX500Name(X500Principal p) { 1427 try { 1428 X500Name name = (X500Name)principalField.get(p); 1429 name.x500Principal = p; 1430 return name; 1431 } catch (Exception e) { 1432 throw new RuntimeException("Unexpected exception", e); 1433 } 1434 } 1435 1436 }