1 /* 2 * Copyright (c) 1996, 2014, 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 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<>(); 346 for (int i = 0; i < names.length; i++) { 347 list.addAll(names[i].avas()); 348 } 349 } 350 return list; 351 } 352 353 /** 354 * Return the total number of AVAs contained in all the RDNs of 355 * this X500Name. 356 */ 357 public int avaSize() { 358 return allAvas().size(); 359 } 360 361 /** 362 * Return whether this X500Name is empty. An X500Name is not empty 363 * if it has at least one RDN containing at least one AVA. 364 */ 365 public boolean isEmpty() { 366 int n = names.length; 367 if (n == 0) { 368 return true; 369 } 370 for (int i = 0; i < n; i++) { 371 if (names[i].assertion.length != 0) { 372 return false; 373 } 374 } 375 return true; 376 } 377 378 /** 379 * Calculates a hash code value for the object. Objects 380 * which are equal will also have the same hashcode. 381 */ 382 public int hashCode() { 383 return getRFC2253CanonicalName().hashCode(); 384 } 385 386 /** 387 * Compares this name with another, for equality. 388 * 389 * @return true iff the names are identical. 390 */ 391 public boolean equals(Object obj) { 392 if (this == obj) { 393 return true; 394 } 395 if (obj instanceof X500Name == false) { 396 return false; 397 } 398 X500Name other = (X500Name)obj; 399 // if we already have the canonical forms, compare now 400 if ((this.canonicalDn != null) && (other.canonicalDn != null)) { 401 return this.canonicalDn.equals(other.canonicalDn); 402 } 403 // quick check that number of RDNs and AVAs match before canonicalizing 404 int n = this.names.length; 405 if (n != other.names.length) { 406 return false; 407 } 408 for (int i = 0; i < n; i++) { 409 RDN r1 = this.names[i]; 410 RDN r2 = other.names[i]; 411 if (r1.assertion.length != r2.assertion.length) { 412 return false; 413 } 414 } 415 // definite check via canonical form 416 String thisCanonical = this.getRFC2253CanonicalName(); 417 String otherCanonical = other.getRFC2253CanonicalName(); 418 return thisCanonical.equals(otherCanonical); 419 } 420 421 /* 422 * Returns the name component as a Java string, regardless of its 423 * encoding restrictions. 424 */ 425 private String getString(DerValue attribute) throws IOException { 426 if (attribute == null) 427 return null; 428 String value = attribute.getAsString(); 429 430 if (value == null) 431 throw new IOException("not a DER string encoding, " 432 + attribute.tag); 433 else 434 return value; 435 } 436 437 /** 438 * Return type of GeneralName. 439 */ 440 public int getType() { 441 return (GeneralNameInterface.NAME_DIRECTORY); 442 } 443 444 /** 445 * Returns a "Country" name component. If more than one 446 * such attribute exists, the topmost one is returned. 447 * 448 * @return "C=" component of the name, if any. 449 */ 450 public String getCountry() throws IOException { 451 DerValue attr = findAttribute(countryName_oid); 452 453 return getString(attr); 454 } 455 456 457 /** 458 * Returns an "Organization" name component. If more than 459 * one such attribute exists, the topmost one is returned. 460 * 461 * @return "O=" component of the name, if any. 462 */ 463 public String getOrganization() throws IOException { 464 DerValue attr = findAttribute(orgName_oid); 465 466 return getString(attr); 467 } 468 469 470 /** 471 * Returns an "Organizational Unit" name component. If more 472 * than one such attribute exists, the topmost one is returned. 473 * 474 * @return "OU=" component of the name, if any. 475 */ 476 public String getOrganizationalUnit() throws IOException { 477 DerValue attr = findAttribute(orgUnitName_oid); 478 479 return getString(attr); 480 } 481 482 483 /** 484 * Returns a "Common Name" component. If more than one such 485 * attribute exists, the topmost one is returned. 486 * 487 * @return "CN=" component of the name, if any. 488 */ 489 public String getCommonName() throws IOException { 490 DerValue attr = findAttribute(commonName_oid); 491 492 return getString(attr); 493 } 494 495 496 /** 497 * Returns a "Locality" name component. If more than one 498 * such component exists, the topmost one is returned. 499 * 500 * @return "L=" component of the name, if any. 501 */ 502 public String getLocality() throws IOException { 503 DerValue attr = findAttribute(localityName_oid); 504 505 return getString(attr); 506 } 507 508 /** 509 * Returns a "State" name component. If more than one 510 * such component exists, the topmost one is returned. 511 * 512 * @return "S=" component of the name, if any. 513 */ 514 public String getState() throws IOException { 515 DerValue attr = findAttribute(stateName_oid); 516 517 return getString(attr); 518 } 519 520 /** 521 * Returns a "Domain" name component. If more than one 522 * such component exists, the topmost one is returned. 523 * 524 * @return "DC=" component of the name, if any. 525 */ 526 public String getDomain() throws IOException { 527 DerValue attr = findAttribute(DOMAIN_COMPONENT_OID); 528 529 return getString(attr); 530 } 531 532 /** 533 * Returns a "DN Qualifier" name component. If more than one 534 * such component exists, the topmost one is returned. 535 * 536 * @return "DNQ=" component of the name, if any. 537 */ 538 public String getDNQualifier() throws IOException { 539 DerValue attr = findAttribute(DNQUALIFIER_OID); 540 541 return getString(attr); 542 } 543 544 /** 545 * Returns a "Surname" name component. If more than one 546 * such component exists, the topmost one is returned. 547 * 548 * @return "SURNAME=" component of the name, if any. 549 */ 550 public String getSurname() throws IOException { 551 DerValue attr = findAttribute(SURNAME_OID); 552 553 return getString(attr); 554 } 555 556 /** 557 * Returns a "Given Name" name component. If more than one 558 * such component exists, the topmost one is returned. 559 * 560 * @return "GIVENNAME=" component of the name, if any. 561 */ 562 public String getGivenName() throws IOException { 563 DerValue attr = findAttribute(GIVENNAME_OID); 564 565 return getString(attr); 566 } 567 568 /** 569 * Returns an "Initials" name component. If more than one 570 * such component exists, the topmost one is returned. 571 * 572 * @return "INITIALS=" component of the name, if any. 573 */ 574 public String getInitials() throws IOException { 575 DerValue attr = findAttribute(INITIALS_OID); 576 577 return getString(attr); 578 } 579 580 /** 581 * Returns a "Generation Qualifier" name component. If more than one 582 * such component exists, the topmost one is returned. 583 * 584 * @return "GENERATION=" component of the name, if any. 585 */ 586 public String getGeneration() throws IOException { 587 DerValue attr = findAttribute(GENERATIONQUALIFIER_OID); 588 589 return getString(attr); 590 } 591 592 /** 593 * Returns an "IP address" name component. If more than one 594 * such component exists, the topmost one is returned. 595 * 596 * @return "IP=" component of the name, if any. 597 */ 598 public String getIP() throws IOException { 599 DerValue attr = findAttribute(ipAddress_oid); 600 601 return getString(attr); 602 } 603 604 /** 605 * Returns a string form of the X.500 distinguished name. 606 * The format of the string is from RFC 1779. The returned string 607 * may contain non-standardised keywords for more readability 608 * (keywords from RFCs 1779, 2253, and 5280). 609 */ 610 public String toString() { 611 if (dn == null) { 612 generateDN(); 613 } 614 return dn; 615 } 616 617 /** 618 * Returns a string form of the X.500 distinguished name 619 * using the algorithm defined in RFC 1779. Only standard attribute type 620 * keywords defined in RFC 1779 are emitted. 621 */ 622 public String getRFC1779Name() { 623 return getRFC1779Name(Collections.<String, String>emptyMap()); 624 } 625 626 /** 627 * Returns a string form of the X.500 distinguished name 628 * using the algorithm defined in RFC 1779. Attribute type 629 * keywords defined in RFC 1779 are emitted, as well as additional 630 * keywords contained in the OID/keyword map. 631 */ 632 public String getRFC1779Name(Map<String, String> oidMap) 633 throws IllegalArgumentException { 634 if (oidMap.isEmpty()) { 635 // return cached result 636 if (rfc1779Dn != null) { 637 return rfc1779Dn; 638 } else { 639 rfc1779Dn = generateRFC1779DN(oidMap); 640 return rfc1779Dn; 641 } 642 } 643 return generateRFC1779DN(oidMap); 644 } 645 646 /** 647 * Returns a string form of the X.500 distinguished name 648 * using the algorithm defined in RFC 2253. Only standard attribute type 649 * keywords defined in RFC 2253 are emitted. 650 */ 651 public String getRFC2253Name() { 652 return getRFC2253Name(Collections.<String, String>emptyMap()); 653 } 654 655 /** 656 * Returns a string form of the X.500 distinguished name 657 * using the algorithm defined in RFC 2253. Attribute type 658 * keywords defined in RFC 2253 are emitted, as well as additional 659 * keywords contained in the OID/keyword map. 660 */ 661 public String getRFC2253Name(Map<String, String> oidMap) { 662 /* check for and return cached name */ 663 if (oidMap.isEmpty()) { 664 if (rfc2253Dn != null) { 665 return rfc2253Dn; 666 } else { 667 rfc2253Dn = generateRFC2253DN(oidMap); 668 return rfc2253Dn; 669 } 670 } 671 return generateRFC2253DN(oidMap); 672 } 673 674 private String generateRFC2253DN(Map<String, String> oidMap) { 675 /* 676 * Section 2.1 : if the RDNSequence is an empty sequence 677 * the result is the empty or zero length string. 678 */ 679 if (names.length == 0) { 680 return ""; 681 } 682 683 /* 684 * 2.1 (continued) : Otherwise, the output consists of the string 685 * encodings of each RelativeDistinguishedName in the RDNSequence 686 * (according to 2.2), starting with the last element of the sequence 687 * and moving backwards toward the first. 688 * 689 * The encodings of adjoining RelativeDistinguishedNames are separated 690 * by a comma character (',' ASCII 44). 691 */ 692 StringBuilder fullname = new StringBuilder(48); 693 for (int i = names.length - 1; i >= 0; i--) { 694 if (i < names.length - 1) { 695 fullname.append(','); 696 } 697 fullname.append(names[i].toRFC2253String(oidMap)); 698 } 699 return fullname.toString(); 700 } 701 702 public String getRFC2253CanonicalName() { 703 /* check for and return cached name */ 704 if (canonicalDn != null) { 705 return canonicalDn; 706 } 707 /* 708 * Section 2.1 : if the RDNSequence is an empty sequence 709 * the result is the empty or zero length string. 710 */ 711 if (names.length == 0) { 712 canonicalDn = ""; 713 return canonicalDn; 714 } 715 716 /* 717 * 2.1 (continued) : Otherwise, the output consists of the string 718 * encodings of each RelativeDistinguishedName in the RDNSequence 719 * (according to 2.2), starting with the last element of the sequence 720 * and moving backwards toward the first. 721 * 722 * The encodings of adjoining RelativeDistinguishedNames are separated 723 * by a comma character (',' ASCII 44). 724 */ 725 StringBuilder fullname = new StringBuilder(48); 726 for (int i = names.length - 1; i >= 0; i--) { 727 if (i < names.length - 1) { 728 fullname.append(','); 729 } 730 fullname.append(names[i].toRFC2253String(true)); 731 } 732 canonicalDn = fullname.toString(); 733 return canonicalDn; 734 } 735 736 /** 737 * Returns the value of toString(). This call is needed to 738 * implement the java.security.Principal interface. 739 */ 740 public String getName() { return toString(); } 741 742 /** 743 * Find the first instance of this attribute in a "top down" 744 * search of all the attributes in the name. 745 */ 746 private DerValue findAttribute(ObjectIdentifier attribute) { 747 if (names != null) { 748 for (int i = 0; i < names.length; i++) { 749 DerValue value = names[i].findAttribute(attribute); 750 if (value != null) { 751 return value; 752 } 753 } 754 } 755 return null; 756 } 757 758 /** 759 * Find the most specific ("last") attribute of the given 760 * type. 761 */ 762 public DerValue findMostSpecificAttribute(ObjectIdentifier attribute) { 763 if (names != null) { 764 for (int i = names.length - 1; i >= 0; i--) { 765 DerValue value = names[i].findAttribute(attribute); 766 if (value != null) { 767 return value; 768 } 769 } 770 } 771 return null; 772 } 773 774 /****************************************************************/ 775 776 private void parseDER(DerInputStream in) throws IOException { 777 // 778 // X.500 names are a "SEQUENCE OF" RDNs, which means zero or 779 // more and order matters. We scan them in order, which 780 // conventionally is big-endian. 781 // 782 DerValue[] nameseq = null; 783 byte[] derBytes = in.toByteArray(); 784 785 try { 786 nameseq = in.getSequence(5); 787 } catch (IOException ioe) { 788 if (derBytes == null) { 789 nameseq = null; 790 } else { 791 DerValue derVal = new DerValue(DerValue.tag_Sequence, 792 derBytes); 793 derBytes = derVal.toByteArray(); 794 nameseq = new DerInputStream(derBytes).getSequence(5); 795 } 796 } 797 798 if (nameseq == null) { 799 names = new RDN[0]; 800 } else { 801 names = new RDN[nameseq.length]; 802 for (int i = 0; i < nameseq.length; i++) { 803 names[i] = new RDN(nameseq[i]); 804 } 805 } 806 } 807 808 /** 809 * Encodes the name in DER-encoded form. 810 * 811 * @deprecated Use encode() instead 812 * @param out where to put the DER-encoded X.500 name 813 */ 814 @Deprecated 815 public void emit(DerOutputStream out) throws IOException { 816 encode(out); 817 } 818 819 /** 820 * Encodes the name in DER-encoded form. 821 * 822 * @param out where to put the DER-encoded X.500 name 823 */ 824 public void encode(DerOutputStream out) throws IOException { 825 DerOutputStream tmp = new DerOutputStream(); 826 for (int i = 0; i < names.length; i++) { 827 names[i].encode(tmp); 828 } 829 out.write(DerValue.tag_Sequence, tmp); 830 } 831 832 /** 833 * Returned the encoding as an uncloned byte array. Callers must 834 * guarantee that they neither modify it not expose it to untrusted 835 * code. 836 */ 837 public byte[] getEncodedInternal() throws IOException { 838 if (encoded == null) { 839 DerOutputStream out = new DerOutputStream(); 840 DerOutputStream tmp = new DerOutputStream(); 841 for (int i = 0; i < names.length; i++) { 842 names[i].encode(tmp); 843 } 844 out.write(DerValue.tag_Sequence, tmp); 845 encoded = out.toByteArray(); 846 } 847 return encoded; 848 } 849 850 /** 851 * Gets the name in DER-encoded form. 852 * 853 * @return the DER encoded byte array of this name. 854 */ 855 public byte[] getEncoded() throws IOException { 856 return getEncodedInternal().clone(); 857 } 858 859 /* 860 * Parses a Distinguished Name (DN) in printable representation. 861 * 862 * According to RFC 1779, RDNs in a DN are separated by comma. 863 * The following examples show both methods of quoting a comma, so that it 864 * is not considered a separator: 865 * 866 * O="Sue, Grabbit and Runn" or 867 * O=Sue\, Grabbit and Runn 868 * 869 * This method can parse RFC 1779, 2253 or 4514 DNs and non-standard 5280 870 * keywords. Additional keywords can be specified in the keyword/OID map. 871 */ 872 private void parseDN(String input, Map<String, String> keywordMap) 873 throws IOException { 874 if (input == null || input.length() == 0) { 875 names = new RDN[0]; 876 return; 877 } 878 879 List<RDN> dnVector = new ArrayList<>(); 880 int dnOffset = 0; 881 int rdnEnd; 882 String rdnString; 883 int quoteCount = 0; 884 885 String dnString = input; 886 887 int searchOffset = 0; 888 int nextComma = dnString.indexOf(','); 889 int nextSemiColon = dnString.indexOf(';'); 890 while (nextComma >=0 || nextSemiColon >=0) { 891 892 if (nextSemiColon < 0) { 893 rdnEnd = nextComma; 894 } else if (nextComma < 0) { 895 rdnEnd = nextSemiColon; 896 } else { 897 rdnEnd = Math.min(nextComma, nextSemiColon); 898 } 899 quoteCount += countQuotes(dnString, searchOffset, rdnEnd); 900 901 /* 902 * We have encountered an RDN delimiter (comma or a semicolon). 903 * If the comma or semicolon in the RDN under consideration is 904 * preceded by a backslash (escape), or by a double quote, it 905 * is part of the RDN. Otherwise, it is used as a separator, to 906 * delimit the RDN under consideration from any subsequent RDNs. 907 */ 908 if (rdnEnd >= 0 && quoteCount != 1 && 909 !escaped(rdnEnd, searchOffset, dnString)) { 910 911 /* 912 * Comma/semicolon is a separator 913 */ 914 rdnString = dnString.substring(dnOffset, rdnEnd); 915 916 // Parse RDN, and store it in vector 917 RDN rdn = new RDN(rdnString, keywordMap); 918 dnVector.add(rdn); 919 920 // Increase the offset 921 dnOffset = rdnEnd + 1; 922 923 // Set quote counter back to zero 924 quoteCount = 0; 925 } 926 927 searchOffset = rdnEnd + 1; 928 nextComma = dnString.indexOf(',', searchOffset); 929 nextSemiColon = dnString.indexOf(';', searchOffset); 930 } 931 932 // Parse last or only RDN, and store it in vector 933 rdnString = dnString.substring(dnOffset); 934 RDN rdn = new RDN(rdnString, keywordMap); 935 dnVector.add(rdn); 936 937 /* 938 * Store the vector elements as an array of RDNs 939 * NOTE: It's only on output that little-endian ordering is used. 940 */ 941 Collections.reverse(dnVector); 942 names = dnVector.toArray(new RDN[dnVector.size()]); 943 } 944 945 private void parseRFC2253DN(String dnString) throws IOException { 946 if (dnString.length() == 0) { 947 names = new RDN[0]; 948 return; 949 } 950 951 List<RDN> dnVector = new ArrayList<>(); 952 int dnOffset = 0; 953 String rdnString; 954 int searchOffset = 0; 955 int rdnEnd = dnString.indexOf(','); 956 while (rdnEnd >=0) { 957 /* 958 * We have encountered an RDN delimiter (comma). 959 * If the comma in the RDN under consideration is 960 * preceded by a backslash (escape), it 961 * is part of the RDN. Otherwise, it is used as a separator, to 962 * delimit the RDN under consideration from any subsequent RDNs. 963 */ 964 if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) { 965 966 /* 967 * Comma is a separator 968 */ 969 rdnString = dnString.substring(dnOffset, rdnEnd); 970 971 // Parse RDN, and store it in vector 972 RDN rdn = new RDN(rdnString, "RFC2253"); 973 dnVector.add(rdn); 974 975 // Increase the offset 976 dnOffset = rdnEnd + 1; 977 } 978 979 searchOffset = rdnEnd + 1; 980 rdnEnd = dnString.indexOf(',', searchOffset); 981 } 982 983 // Parse last or only RDN, and store it in vector 984 rdnString = dnString.substring(dnOffset); 985 RDN rdn = new RDN(rdnString, "RFC2253"); 986 dnVector.add(rdn); 987 988 /* 989 * Store the vector elements as an array of RDNs 990 * NOTE: It's only on output that little-endian ordering is used. 991 */ 992 Collections.reverse(dnVector); 993 names = dnVector.toArray(new RDN[dnVector.size()]); 994 } 995 996 /* 997 * Counts double quotes in string. 998 * Escaped quotes are ignored. 999 */ 1000 static int countQuotes(String string, int from, int to) { 1001 int count = 0; 1002 1003 for (int i = from; i < to; i++) { 1004 if ((string.charAt(i) == '"' && i == from) || 1005 (string.charAt(i) == '"' && string.charAt(i-1) != '\\')) { 1006 count++; 1007 } 1008 } 1009 1010 return count; 1011 } 1012 1013 private static boolean escaped 1014 (int rdnEnd, int searchOffset, String dnString) { 1015 1016 if (rdnEnd == 1 && dnString.charAt(rdnEnd - 1) == '\\') { 1017 1018 // case 1: 1019 // \, 1020 1021 return true; 1022 1023 } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' && 1024 dnString.charAt(rdnEnd - 2) != '\\') { 1025 1026 // case 2: 1027 // foo\, 1028 1029 return true; 1030 1031 } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' && 1032 dnString.charAt(rdnEnd - 2) == '\\') { 1033 1034 // case 3: 1035 // foo\\\\\, 1036 1037 int count = 0; 1038 rdnEnd--; // back up to last backSlash 1039 while (rdnEnd >= searchOffset) { 1040 if (dnString.charAt(rdnEnd) == '\\') { 1041 count++; // count consecutive backslashes 1042 } 1043 rdnEnd--; 1044 } 1045 1046 // if count is odd, then rdnEnd is escaped 1047 return (count % 2) != 0 ? true : false; 1048 1049 } else { 1050 return false; 1051 } 1052 } 1053 1054 /* 1055 * Dump the printable form of a distinguished name. Each relative 1056 * name is separated from the next by a ",", and assertions in the 1057 * relative names have "label=value" syntax. 1058 * 1059 * Uses RFC 1779 syntax (i.e. little-endian, comma separators) 1060 */ 1061 private void generateDN() { 1062 if (names.length == 1) { 1063 dn = names[0].toString(); 1064 return; 1065 } 1066 1067 StringBuilder sb = new StringBuilder(48); 1068 if (names != null) { 1069 for (int i = names.length - 1; i >= 0; i--) { 1070 if (i != names.length - 1) { 1071 sb.append(", "); 1072 } 1073 sb.append(names[i].toString()); 1074 } 1075 } 1076 dn = sb.toString(); 1077 } 1078 1079 /* 1080 * Dump the printable form of a distinguished name. Each relative 1081 * name is separated from the next by a ",", and assertions in the 1082 * relative names have "label=value" syntax. 1083 * 1084 * Uses RFC 1779 syntax (i.e. little-endian, comma separators) 1085 * Valid keywords from RFC 1779 are used. Additional keywords can be 1086 * specified in the OID/keyword map. 1087 */ 1088 private String generateRFC1779DN(Map<String, String> oidMap) { 1089 if (names.length == 1) { 1090 return names[0].toRFC1779String(oidMap); 1091 } 1092 1093 StringBuilder sb = new StringBuilder(48); 1094 if (names != null) { 1095 for (int i = names.length - 1; i >= 0; i--) { 1096 if (i != names.length - 1) { 1097 sb.append(", "); 1098 } 1099 sb.append(names[i].toRFC1779String(oidMap)); 1100 } 1101 } 1102 return sb.toString(); 1103 } 1104 1105 /****************************************************************/ 1106 1107 /* 1108 * Maybe return a preallocated OID, to reduce storage costs 1109 * and speed recognition of common X.500 attributes. 1110 */ 1111 static ObjectIdentifier intern(ObjectIdentifier oid) { 1112 ObjectIdentifier interned = internedOIDs.get(oid); 1113 if (interned != null) { 1114 return interned; 1115 } 1116 internedOIDs.put(oid, oid); 1117 return oid; 1118 } 1119 1120 private static final Map<ObjectIdentifier,ObjectIdentifier> internedOIDs 1121 = new HashMap<ObjectIdentifier,ObjectIdentifier>(); 1122 1123 /* 1124 * Selected OIDs from X.520 1125 * Includes all those specified in RFC 5280 as MUST or SHOULD 1126 * be recognized 1127 */ 1128 private static final int commonName_data[] = { 2, 5, 4, 3 }; 1129 private static final int SURNAME_DATA[] = { 2, 5, 4, 4 }; 1130 private static final int SERIALNUMBER_DATA[] = { 2, 5, 4, 5 }; 1131 private static final int countryName_data[] = { 2, 5, 4, 6 }; 1132 private static final int localityName_data[] = { 2, 5, 4, 7 }; 1133 private static final int stateName_data[] = { 2, 5, 4, 8 }; 1134 private static final int streetAddress_data[] = { 2, 5, 4, 9 }; 1135 private static final int orgName_data[] = { 2, 5, 4, 10 }; 1136 private static final int orgUnitName_data[] = { 2, 5, 4, 11 }; 1137 private static final int title_data[] = { 2, 5, 4, 12 }; 1138 private static final int GIVENNAME_DATA[] = { 2, 5, 4, 42 }; 1139 private static final int INITIALS_DATA[] = { 2, 5, 4, 43 }; 1140 private static final int GENERATIONQUALIFIER_DATA[] = { 2, 5, 4, 44 }; 1141 private static final int DNQUALIFIER_DATA[] = { 2, 5, 4, 46 }; 1142 1143 private static final int ipAddress_data[] = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; 1144 private static final int DOMAIN_COMPONENT_DATA[] = 1145 { 0, 9, 2342, 19200300, 100, 1, 25 }; 1146 private static final int userid_data[] = 1147 { 0, 9, 2342, 19200300, 100, 1, 1 }; 1148 1149 1150 public static final ObjectIdentifier commonName_oid; 1151 public static final ObjectIdentifier countryName_oid; 1152 public static final ObjectIdentifier localityName_oid; 1153 public static final ObjectIdentifier orgName_oid; 1154 public static final ObjectIdentifier orgUnitName_oid; 1155 public static final ObjectIdentifier stateName_oid; 1156 public static final ObjectIdentifier streetAddress_oid; 1157 public static final ObjectIdentifier title_oid; 1158 public static final ObjectIdentifier DNQUALIFIER_OID; 1159 public static final ObjectIdentifier SURNAME_OID; 1160 public static final ObjectIdentifier GIVENNAME_OID; 1161 public static final ObjectIdentifier INITIALS_OID; 1162 public static final ObjectIdentifier GENERATIONQUALIFIER_OID; 1163 public static final ObjectIdentifier ipAddress_oid; 1164 public static final ObjectIdentifier DOMAIN_COMPONENT_OID; 1165 public static final ObjectIdentifier userid_oid; 1166 public static final ObjectIdentifier SERIALNUMBER_OID; 1167 1168 static { 1169 /** OID for the "CN=" attribute, denoting a person's common name. */ 1170 commonName_oid = intern(ObjectIdentifier.newInternal(commonName_data)); 1171 1172 /** OID for the "SERIALNUMBER=" attribute, denoting a serial number for. 1173 a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the 1174 certificate serial number. */ 1175 SERIALNUMBER_OID = intern(ObjectIdentifier.newInternal(SERIALNUMBER_DATA)); 1176 1177 /** OID for the "C=" attribute, denoting a country. */ 1178 countryName_oid = intern(ObjectIdentifier.newInternal(countryName_data)); 1179 1180 /** OID for the "L=" attribute, denoting a locality (such as a city) */ 1181 localityName_oid = intern(ObjectIdentifier.newInternal(localityName_data)); 1182 1183 /** OID for the "O=" attribute, denoting an organization name */ 1184 orgName_oid = intern(ObjectIdentifier.newInternal(orgName_data)); 1185 1186 /** OID for the "OU=" attribute, denoting an organizational unit name */ 1187 orgUnitName_oid = intern(ObjectIdentifier.newInternal(orgUnitName_data)); 1188 1189 /** OID for the "S=" attribute, denoting a state (such as Delaware) */ 1190 stateName_oid = intern(ObjectIdentifier.newInternal(stateName_data)); 1191 1192 /** OID for the "STREET=" attribute, denoting a street address. */ 1193 streetAddress_oid = intern(ObjectIdentifier.newInternal(streetAddress_data)); 1194 1195 /** OID for the "T=" attribute, denoting a person's title. */ 1196 title_oid = intern(ObjectIdentifier.newInternal(title_data)); 1197 1198 /** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN 1199 disambiguating information.*/ 1200 DNQUALIFIER_OID = intern(ObjectIdentifier.newInternal(DNQUALIFIER_DATA)); 1201 1202 /** OID for the "SURNAME=" attribute, denoting a person's surname.*/ 1203 SURNAME_OID = intern(ObjectIdentifier.newInternal(SURNAME_DATA)); 1204 1205 /** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/ 1206 GIVENNAME_OID = intern(ObjectIdentifier.newInternal(GIVENNAME_DATA)); 1207 1208 /** OID for the "INITIALS=" attribute, denoting a person's initials.*/ 1209 INITIALS_OID = intern(ObjectIdentifier.newInternal(INITIALS_DATA)); 1210 1211 /** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/ 1212 GENERATIONQUALIFIER_OID = 1213 intern(ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA)); 1214 1215 /* 1216 * OIDs from other sources which show up in X.500 names we 1217 * expect to deal with often 1218 */ 1219 /** OID for "IP=" IP address attributes, used with SKIP. */ 1220 ipAddress_oid = intern(ObjectIdentifier.newInternal(ipAddress_data)); 1221 1222 /* 1223 * Domain component OID from RFC 1274, RFC 2247, RFC 5280 1224 */ 1225 1226 /* 1227 * OID for "DC=" domain component attributes, used with DNS names in DN 1228 * format 1229 */ 1230 DOMAIN_COMPONENT_OID = 1231 intern(ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA)); 1232 1233 /** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */ 1234 userid_oid = intern(ObjectIdentifier.newInternal(userid_data)); 1235 } 1236 1237 /** 1238 * Return constraint type:<ul> 1239 * <li>NAME_DIFF_TYPE = -1: input name is different type from this name 1240 * (i.e. does not constrain) 1241 * <li>NAME_MATCH = 0: input name matches this name 1242 * <li>NAME_NARROWS = 1: input name narrows this name 1243 * <li>NAME_WIDENS = 2: input name widens this name 1244 * <li>NAME_SAME_TYPE = 3: input name does not match or narrow this name, 1245 & but is same type 1246 * </ul>. These results are used in checking NameConstraints during 1247 * certification path verification. 1248 * 1249 * @param inputName to be checked for being constrained 1250 * @returns constraint type above 1251 * @throws UnsupportedOperationException if name is not exact match, but 1252 * narrowing and widening are not supported for this name type. 1253 */ 1254 public int constrains(GeneralNameInterface inputName) 1255 throws UnsupportedOperationException { 1256 int constraintType; 1257 if (inputName == null) { 1258 constraintType = NAME_DIFF_TYPE; 1259 } else if (inputName.getType() != NAME_DIRECTORY) { 1260 constraintType = NAME_DIFF_TYPE; 1261 } else { // type == NAME_DIRECTORY 1262 X500Name inputX500 = (X500Name)inputName; 1263 if (inputX500.equals(this)) { 1264 constraintType = NAME_MATCH; 1265 } else if (inputX500.names.length == 0) { 1266 constraintType = NAME_WIDENS; 1267 } else if (this.names.length == 0) { 1268 constraintType = NAME_NARROWS; 1269 } else if (inputX500.isWithinSubtree(this)) { 1270 constraintType = NAME_NARROWS; 1271 } else if (isWithinSubtree(inputX500)) { 1272 constraintType = NAME_WIDENS; 1273 } else { 1274 constraintType = NAME_SAME_TYPE; 1275 } 1276 } 1277 return constraintType; 1278 } 1279 1280 /** 1281 * Compares this name with another and determines if 1282 * it is within the subtree of the other. Useful for 1283 * checking against the name constraints extension. 1284 * 1285 * @return true iff this name is within the subtree of other. 1286 */ 1287 private boolean isWithinSubtree(X500Name other) { 1288 if (this == other) { 1289 return true; 1290 } 1291 if (other == null) { 1292 return false; 1293 } 1294 if (other.names.length == 0) { 1295 return true; 1296 } 1297 if (this.names.length == 0) { 1298 return false; 1299 } 1300 if (names.length < other.names.length) { 1301 return false; 1302 } 1303 for (int i = 0; i < other.names.length; i++) { 1304 if (!names[i].equals(other.names[i])) { 1305 return false; 1306 } 1307 } 1308 return true; 1309 } 1310 1311 /** 1312 * Return subtree depth of this name for purposes of determining 1313 * NameConstraints minimum and maximum bounds and for calculating 1314 * path lengths in name subtrees. 1315 * 1316 * @returns distance of name from root 1317 * @throws UnsupportedOperationException if not supported for this name type 1318 */ 1319 public int subtreeDepth() throws UnsupportedOperationException { 1320 return names.length; 1321 } 1322 1323 /** 1324 * Return lowest common ancestor of this name and other name 1325 * 1326 * @param other another X500Name 1327 * @return X500Name of lowest common ancestor; null if none 1328 */ 1329 public X500Name commonAncestor(X500Name other) { 1330 1331 if (other == null) { 1332 return null; 1333 } 1334 int otherLen = other.names.length; 1335 int thisLen = this.names.length; 1336 if (thisLen == 0 || otherLen == 0) { 1337 return null; 1338 } 1339 int minLen = (thisLen < otherLen) ? thisLen: otherLen; 1340 1341 //Compare names from highest RDN down the naming tree 1342 //Note that these are stored in RDN[0]... 1343 int i=0; 1344 for (; i < minLen; i++) { 1345 if (!names[i].equals(other.names[i])) { 1346 if (i == 0) { 1347 return null; 1348 } else { 1349 break; 1350 } 1351 } 1352 } 1353 1354 //Copy matching RDNs into new RDN array 1355 RDN[] ancestor = new RDN[i]; 1356 for (int j=0; j < i; j++) { 1357 ancestor[j] = names[j]; 1358 } 1359 1360 X500Name commonAncestor = null; 1361 try { 1362 commonAncestor = new X500Name(ancestor); 1363 } catch (IOException ioe) { 1364 return null; 1365 } 1366 return commonAncestor; 1367 } 1368 1369 /** 1370 * Constructor object for use by asX500Principal(). 1371 */ 1372 private static final Constructor<X500Principal> principalConstructor; 1373 1374 /** 1375 * Field object for use by asX500Name(). 1376 */ 1377 private static final Field principalField; 1378 1379 /** 1380 * Retrieve the Constructor and Field we need for reflective access 1381 * and make them accessible. 1382 */ 1383 static { 1384 PrivilegedExceptionAction<Object[]> pa = 1385 new PrivilegedExceptionAction<>() { 1386 public Object[] run() throws Exception { 1387 Class<X500Principal> pClass = X500Principal.class; 1388 Class<?>[] args = new Class<?>[] { X500Name.class }; 1389 Constructor<X500Principal> cons = pClass.getDeclaredConstructor(args); 1390 cons.setAccessible(true); 1391 Field field = pClass.getDeclaredField("thisX500Name"); 1392 field.setAccessible(true); 1393 return new Object[] {cons, field}; 1394 } 1395 }; 1396 try { 1397 Object[] result = AccessController.doPrivileged(pa); 1398 @SuppressWarnings("unchecked") 1399 Constructor<X500Principal> constr = 1400 (Constructor<X500Principal>)result[0]; 1401 principalConstructor = constr; 1402 principalField = (Field)result[1]; 1403 } catch (Exception e) { 1404 throw new InternalError("Could not obtain X500Principal access", e); 1405 } 1406 } 1407 1408 /** 1409 * Get an X500Principal backed by this X500Name. 1410 * 1411 * Note that we are using privileged reflection to access the hidden 1412 * package private constructor in X500Principal. 1413 */ 1414 public X500Principal asX500Principal() { 1415 if (x500Principal == null) { 1416 try { 1417 Object[] args = new Object[] {this}; 1418 x500Principal = principalConstructor.newInstance(args); 1419 } catch (Exception e) { 1420 throw new RuntimeException("Unexpected exception", e); 1421 } 1422 } 1423 return x500Principal; 1424 } 1425 1426 /** 1427 * Get the X500Name contained in the given X500Principal. 1428 * 1429 * Note that the X500Name is retrieved using reflection. 1430 */ 1431 public static X500Name asX500Name(X500Principal p) { 1432 try { 1433 X500Name name = (X500Name)principalField.get(p); 1434 name.x500Principal = p; 1435 return name; 1436 } catch (Exception e) { 1437 throw new RuntimeException("Unexpected exception", e); 1438 } 1439 } 1440 1441 }