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 import java.util.StringJoiner; 35 36 import sun.security.util.*; 37 import javax.security.auth.x500.X500Principal; 38 39 /** 40 * Note: As of 1.4, the public class, 41 * javax.security.auth.x500.X500Principal, 42 * should be used when parsing, generating, and comparing X.500 DNs. 43 * This class contains other useful methods for checking name constraints 44 * and retrieving DNs by keyword. 45 * 46 * <p> X.500 names are used to identify entities, such as those which are 47 * identified by X.509 certificates. They are world-wide, hierarchical, 48 * and descriptive. Entities can be identified by attributes, and in 49 * some systems can be searched for according to those attributes. 50 * <p> 51 * The ASN.1 for this is: 52 * <pre> 53 * GeneralName ::= CHOICE { 54 * .... 55 * directoryName [4] Name, 56 * .... 57 * Name ::= CHOICE { 58 * RDNSequence } 59 * 60 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 61 * 62 * RelativeDistinguishedName ::= 63 * SET OF AttributeTypeAndValue 64 * 65 * AttributeTypeAndValue ::= SEQUENCE { 66 * type AttributeType, 67 * value AttributeValue } 68 * 69 * AttributeType ::= OBJECT IDENTIFIER 70 * 71 * AttributeValue ::= ANY DEFINED BY AttributeType 72 * .... 73 * DirectoryString ::= CHOICE { 74 * teletexString TeletexString (SIZE (1..MAX)), 75 * printableString PrintableString (SIZE (1..MAX)), 76 * universalString UniversalString (SIZE (1..MAX)), 77 * utf8String UTF8String (SIZE (1.. MAX)), 78 * bmpString BMPString (SIZE (1..MAX)) } 79 * </pre> 80 * <p> 81 * This specification requires only a subset of the name comparison 82 * functionality specified in the X.500 series of specifications. The 83 * requirements for conforming implementations are as follows: 84 * <ol TYPE=a> 85 * <li>attribute values encoded in different types (e.g., 86 * PrintableString and BMPString) may be assumed to represent 87 * different strings; 88 * 89 * <li>attribute values in types other than PrintableString are case 90 * sensitive (this permits matching of attribute values as binary 91 * objects); 92 * 93 * <li>attribute values in PrintableString are not case sensitive 94 * (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and 95 * 96 * <li>attribute values in PrintableString are compared after 97 * removing leading and trailing white space and converting internal 98 * substrings of one or more consecutive white space characters to a 99 * single space. 100 * </ol> 101 * <p> 102 * These name comparison rules permit a certificate user to validate 103 * certificates issued using languages or encodings unfamiliar to the 104 * certificate user. 105 * <p> 106 * In addition, implementations of this specification MAY use these 107 * comparison rules to process unfamiliar attribute types for name 108 * chaining. This allows implementations to process certificates with 109 * unfamiliar attributes in the issuer name. 110 * <p> 111 * Note that the comparison rules defined in the X.500 series of 112 * specifications indicate that the character sets used to encode data 113 * in distinguished names are irrelevant. The characters themselves are 114 * compared without regard to encoding. Implementations of the profile 115 * are permitted to use the comparison algorithm defined in the X.500 116 * series. Such an implementation will recognize a superset of name 117 * matches recognized by the algorithm specified above. 118 * <p> 119 * Note that instances of this class are immutable. 120 * 121 * @author David Brownell 122 * @author Amit Kapoor 123 * @author Hemma Prafullchandra 124 * @see GeneralName 125 * @see GeneralNames 126 * @see GeneralNameInterface 127 */ 128 129 public class X500Name implements GeneralNameInterface, Principal { 130 131 private String dn; // roughly RFC 1779 DN, or null 132 private String rfc1779Dn; // RFC 1779 compliant DN, or null 133 private String rfc2253Dn; // RFC 2253 DN, or null 134 private String canonicalDn; // canonical RFC 2253 DN or null 135 private RDN[] names; // RDNs (never null) 136 private X500Principal x500Principal; 137 private byte[] encoded; 138 139 // cached immutable list of the RDNs and all the AVAs 140 private volatile List<RDN> rdnList; 141 private volatile List<AVA> allAvaList; 142 143 /** 144 * Constructs a name from a conventionally formatted string, such 145 * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US". 146 * (RFC 1779, 2253, or 4514 style). 147 * 148 * @param dname the X.500 Distinguished Name 149 */ 150 public X500Name(String dname) throws IOException { 151 this(dname, Collections.<String, String>emptyMap()); 152 } 153 154 /** 155 * Constructs a name from a conventionally formatted string, such 156 * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US". 157 * (RFC 1779, 2253, or 4514 style). 158 * 159 * @param dname the X.500 Distinguished Name 160 * @param keywordMap an additional keyword/OID map 161 */ 162 public X500Name(String dname, Map<String, String> keywordMap) 163 throws IOException { 164 parseDN(dname, keywordMap); 165 } 166 167 /** 168 * Constructs a name from a string formatted according to format. 169 * Currently, the formats DEFAULT and RFC2253 are supported. 170 * DEFAULT is the default format used by the X500Name(String) 171 * constructor. RFC2253 is the format strictly according to RFC2253 172 * without extensions. 173 * 174 * @param dname the X.500 Distinguished Name 175 * @param format the specified format of the String DN 176 */ 177 public X500Name(String dname, String format) throws IOException { 178 if (dname == null) { 179 throw new NullPointerException("Name must not be null"); 180 } 181 if (format.equalsIgnoreCase("RFC2253")) { 182 parseRFC2253DN(dname); 183 } else if (format.equalsIgnoreCase("DEFAULT")) { 184 parseDN(dname, Collections.<String, String>emptyMap()); 185 } else { 186 throw new IOException("Unsupported format " + format); 187 } 188 } 189 190 /** 191 * Constructs a name from fields common in enterprise application 192 * environments. 193 * 194 * <P><EM><STRONG>NOTE:</STRONG> The behaviour when any of 195 * these strings contain characters outside the ASCII range 196 * is unspecified in currently relevant standards.</EM> 197 * 198 * @param commonName common name of a person, e.g. "Vivette Davis" 199 * @param organizationUnit small organization name, e.g. "Purchasing" 200 * @param organizationName large organization name, e.g. "Onizuka, Inc." 201 * @param country two letter country code, e.g. "CH" 202 */ 203 public X500Name(String commonName, String organizationUnit, 204 String organizationName, String country) 205 throws IOException { 206 names = new RDN[4]; 207 /* 208 * NOTE: it's only on output that little-endian 209 * ordering is used. 210 */ 211 names[3] = new RDN(1); 212 names[3].assertion[0] = new AVA(commonName_oid, 213 new DerValue(commonName)); 214 names[2] = new RDN(1); 215 names[2].assertion[0] = new AVA(orgUnitName_oid, 216 new DerValue(organizationUnit)); 217 names[1] = new RDN(1); 218 names[1].assertion[0] = new AVA(orgName_oid, 219 new DerValue(organizationName)); 220 names[0] = new RDN(1); 221 names[0].assertion[0] = new AVA(countryName_oid, 222 new DerValue(country)); 223 } 224 225 /** 226 * Constructs a name from fields common in Internet application 227 * environments. 228 * 229 * <P><EM><STRONG>NOTE:</STRONG> The behaviour when any of 230 * these strings contain characters outside the ASCII range 231 * is unspecified in currently relevant standards.</EM> 232 * 233 * @param commonName common name of a person, e.g. "Vivette Davis" 234 * @param organizationUnit small organization name, e.g. "Purchasing" 235 * @param organizationName large organization name, e.g. "Onizuka, Inc." 236 * @param localityName locality (city) name, e.g. "Palo Alto" 237 * @param stateName state name, e.g. "California" 238 * @param country two letter country code, e.g. "CH" 239 */ 240 public X500Name(String commonName, String organizationUnit, 241 String organizationName, String localityName, 242 String stateName, String country) 243 throws IOException { 244 names = new RDN[6]; 245 /* 246 * NOTE: it's only on output that little-endian 247 * ordering is used. 248 */ 249 names[5] = new RDN(1); 250 names[5].assertion[0] = new AVA(commonName_oid, 251 new DerValue(commonName)); 252 names[4] = new RDN(1); 253 names[4].assertion[0] = new AVA(orgUnitName_oid, 254 new DerValue(organizationUnit)); 255 names[3] = new RDN(1); 256 names[3].assertion[0] = new AVA(orgName_oid, 257 new DerValue(organizationName)); 258 names[2] = new RDN(1); 259 names[2].assertion[0] = new AVA(localityName_oid, 260 new DerValue(localityName)); 261 names[1] = new RDN(1); 262 names[1].assertion[0] = new AVA(stateName_oid, 263 new DerValue(stateName)); 264 names[0] = new RDN(1); 265 names[0].assertion[0] = new AVA(countryName_oid, 266 new DerValue(country)); 267 } 268 269 /** 270 * Constructs a name from an array of relative distinguished names 271 * 272 * @param rdnArray array of relative distinguished names 273 * @throws IOException on error 274 */ 275 public X500Name(RDN[] rdnArray) throws IOException { 276 if (rdnArray == null) { 277 names = new RDN[0]; 278 } else { 279 names = rdnArray.clone(); 280 for (int i = 0; i < names.length; i++) { 281 if (names[i] == null) { 282 throw new IOException("Cannot create an X500Name"); 283 } 284 } 285 } 286 } 287 288 /** 289 * Constructs a name from an ASN.1 encoded value. The encoding 290 * of the name in the stream uses DER (a BER/1 subset). 291 * 292 * @param value a DER-encoded value holding an X.500 name. 293 */ 294 public X500Name(DerValue value) throws IOException { 295 //Note that toDerInputStream uses only the buffer (data) and not 296 //the tag, so an empty SEQUENCE (OF) will yield an empty DerInputStream 297 this(value.toDerInputStream()); 298 } 299 300 /** 301 * Constructs a name from an ASN.1 encoded input stream. The encoding 302 * of the name in the stream uses DER (a BER/1 subset). 303 * 304 * @param in DER-encoded data holding an X.500 name. 305 */ 306 public X500Name(DerInputStream in) throws IOException { 307 parseDER(in); 308 } 309 310 /** 311 * Constructs a name from an ASN.1 encoded byte array. 312 * 313 * @param name DER-encoded byte array holding an X.500 name. 314 */ 315 public X500Name(byte[] name) throws IOException { 316 DerInputStream in = new DerInputStream(name); 317 parseDER(in); 318 } 319 320 /** 321 * Return an immutable List of all RDNs in this X500Name. 322 */ 323 public List<RDN> rdns() { 324 List<RDN> list = rdnList; 325 if (list == null) { 326 list = Collections.unmodifiableList(Arrays.asList(names)); 327 rdnList = list; 328 } 329 return list; 330 } 331 332 /** 333 * Return the number of RDNs in this X500Name. 334 */ 335 public int size() { 336 return names.length; 337 } 338 339 /** 340 * Return an immutable List of the AVAs contained in all the 341 * RDNs of this X500Name. 342 */ 343 public List<AVA> allAvas() { 344 List<AVA> list = allAvaList; 345 if (list == null) { 346 list = new ArrayList<>(); 347 for (int i = 0; i < names.length; i++) { 348 list.addAll(names[i].avas()); 349 } 350 list = Collections.unmodifiableList(list); 351 allAvaList = list; 352 } 353 return list; 354 } 355 356 /** 357 * Return the total number of AVAs contained in all the RDNs of 358 * this X500Name. 359 */ 360 public int avaSize() { 361 return allAvas().size(); 362 } 363 364 /** 365 * Return whether this X500Name is empty. An X500Name is not empty 366 * if it has at least one RDN containing at least one AVA. 367 */ 368 public boolean isEmpty() { 369 int n = names.length; 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 StringJoiner sj = new StringJoiner(","); 693 for (int i = names.length - 1; i >= 0; i--) { 694 sj.add(names[i].toRFC2253String(oidMap)); 695 } 696 return sj.toString(); 697 } 698 699 public String getRFC2253CanonicalName() { 700 /* check for and return cached name */ 701 if (canonicalDn != null) { 702 return canonicalDn; 703 } 704 /* 705 * Section 2.1 : if the RDNSequence is an empty sequence 706 * the result is the empty or zero length string. 707 */ 708 if (names.length == 0) { 709 canonicalDn = ""; 710 return canonicalDn; 711 } 712 713 /* 714 * 2.1 (continued) : Otherwise, the output consists of the string 715 * encodings of each RelativeDistinguishedName in the RDNSequence 716 * (according to 2.2), starting with the last element of the sequence 717 * and moving backwards toward the first. 718 * 719 * The encodings of adjoining RelativeDistinguishedNames are separated 720 * by a comma character (',' ASCII 44). 721 */ 722 StringJoiner sj = new StringJoiner(","); 723 for (int i = names.length - 1; i >= 0; i--) { 724 sj.add(names[i].toRFC2253String(true)); 725 } 726 canonicalDn = sj.toString(); 727 return canonicalDn; 728 } 729 730 /** 731 * Returns the value of toString(). This call is needed to 732 * implement the java.security.Principal interface. 733 */ 734 public String getName() { return toString(); } 735 736 /** 737 * Find the first instance of this attribute in a "top down" 738 * search of all the attributes in the name. 739 */ 740 private DerValue findAttribute(ObjectIdentifier attribute) { 741 if (names != null) { 742 for (int i = 0; i < names.length; i++) { 743 DerValue value = names[i].findAttribute(attribute); 744 if (value != null) { 745 return value; 746 } 747 } 748 } 749 return null; 750 } 751 752 /** 753 * Find the most specific ("last") attribute of the given 754 * type. 755 */ 756 public DerValue findMostSpecificAttribute(ObjectIdentifier attribute) { 757 if (names != null) { 758 for (int i = names.length - 1; i >= 0; i--) { 759 DerValue value = names[i].findAttribute(attribute); 760 if (value != null) { 761 return value; 762 } 763 } 764 } 765 return null; 766 } 767 768 /****************************************************************/ 769 770 private void parseDER(DerInputStream in) throws IOException { 771 // 772 // X.500 names are a "SEQUENCE OF" RDNs, which means zero or 773 // more and order matters. We scan them in order, which 774 // conventionally is big-endian. 775 // 776 DerValue[] nameseq = null; 777 byte[] derBytes = in.toByteArray(); 778 779 try { 780 nameseq = in.getSequence(5); 781 } catch (IOException ioe) { 782 if (derBytes == null) { 783 nameseq = null; 784 } else { 785 DerValue derVal = new DerValue(DerValue.tag_Sequence, 786 derBytes); 787 derBytes = derVal.toByteArray(); 788 nameseq = new DerInputStream(derBytes).getSequence(5); 789 } 790 } 791 792 if (nameseq == null) { 793 names = new RDN[0]; 794 } else { 795 names = new RDN[nameseq.length]; 796 for (int i = 0; i < nameseq.length; i++) { 797 names[i] = new RDN(nameseq[i]); 798 } 799 } 800 } 801 802 /** 803 * Encodes the name in DER-encoded form. 804 * 805 * @deprecated Use encode() instead 806 * @param out where to put the DER-encoded X.500 name 807 */ 808 @Deprecated 809 public void emit(DerOutputStream out) throws IOException { 810 encode(out); 811 } 812 813 /** 814 * Encodes the name in DER-encoded form. 815 * 816 * @param out where to put the DER-encoded X.500 name 817 */ 818 public void encode(DerOutputStream out) throws IOException { 819 DerOutputStream tmp = new DerOutputStream(); 820 for (int i = 0; i < names.length; i++) { 821 names[i].encode(tmp); 822 } 823 out.write(DerValue.tag_Sequence, tmp); 824 } 825 826 /** 827 * Returned the encoding as an uncloned byte array. Callers must 828 * guarantee that they neither modify it not expose it to untrusted 829 * code. 830 */ 831 public byte[] getEncodedInternal() throws IOException { 832 if (encoded == null) { 833 DerOutputStream out = new DerOutputStream(); 834 DerOutputStream tmp = new DerOutputStream(); 835 for (int i = 0; i < names.length; i++) { 836 names[i].encode(tmp); 837 } 838 out.write(DerValue.tag_Sequence, tmp); 839 encoded = out.toByteArray(); 840 } 841 return encoded; 842 } 843 844 /** 845 * Gets the name in DER-encoded form. 846 * 847 * @return the DER encoded byte array of this name. 848 */ 849 public byte[] getEncoded() throws IOException { 850 return getEncodedInternal().clone(); 851 } 852 853 /* 854 * Parses a Distinguished Name (DN) in printable representation. 855 * 856 * According to RFC 1779, RDNs in a DN are separated by comma. 857 * The following examples show both methods of quoting a comma, so that it 858 * is not considered a separator: 859 * 860 * O="Sue, Grabbit and Runn" or 861 * O=Sue\, Grabbit and Runn 862 * 863 * This method can parse RFC 1779, 2253 or 4514 DNs and non-standard 5280 864 * keywords. Additional keywords can be specified in the keyword/OID map. 865 */ 866 private void parseDN(String input, Map<String, String> keywordMap) 867 throws IOException { 868 if (input == null || input.isEmpty()) { 869 names = new RDN[0]; 870 return; 871 } 872 873 List<RDN> dnVector = new ArrayList<>(); 874 int dnOffset = 0; 875 int rdnEnd; 876 String rdnString; 877 int quoteCount = 0; 878 879 String dnString = input; 880 881 int searchOffset = 0; 882 int nextComma = dnString.indexOf(','); 883 int nextSemiColon = dnString.indexOf(';'); 884 while (nextComma >=0 || nextSemiColon >=0) { 885 886 if (nextSemiColon < 0) { 887 rdnEnd = nextComma; 888 } else if (nextComma < 0) { 889 rdnEnd = nextSemiColon; 890 } else { 891 rdnEnd = Math.min(nextComma, nextSemiColon); 892 } 893 quoteCount += countQuotes(dnString, searchOffset, rdnEnd); 894 895 /* 896 * We have encountered an RDN delimiter (comma or a semicolon). 897 * If the comma or semicolon in the RDN under consideration is 898 * preceded by a backslash (escape), or by a double quote, it 899 * is part of the RDN. Otherwise, it is used as a separator, to 900 * delimit the RDN under consideration from any subsequent RDNs. 901 */ 902 if (rdnEnd >= 0 && quoteCount != 1 && 903 !escaped(rdnEnd, searchOffset, dnString)) { 904 905 /* 906 * Comma/semicolon is a separator 907 */ 908 rdnString = dnString.substring(dnOffset, rdnEnd); 909 910 // Parse RDN, and store it in vector 911 RDN rdn = new RDN(rdnString, keywordMap); 912 dnVector.add(rdn); 913 914 // Increase the offset 915 dnOffset = rdnEnd + 1; 916 917 // Set quote counter back to zero 918 quoteCount = 0; 919 } 920 921 searchOffset = rdnEnd + 1; 922 nextComma = dnString.indexOf(',', searchOffset); 923 nextSemiColon = dnString.indexOf(';', searchOffset); 924 } 925 926 // Parse last or only RDN, and store it in vector 927 rdnString = dnString.substring(dnOffset); 928 RDN rdn = new RDN(rdnString, keywordMap); 929 dnVector.add(rdn); 930 931 /* 932 * Store the vector elements as an array of RDNs 933 * NOTE: It's only on output that little-endian ordering is used. 934 */ 935 Collections.reverse(dnVector); 936 names = dnVector.toArray(new RDN[dnVector.size()]); 937 } 938 939 private void parseRFC2253DN(String dnString) throws IOException { 940 if (dnString.isEmpty()) { 941 names = new RDN[0]; 942 return; 943 } 944 945 List<RDN> dnVector = new ArrayList<>(); 946 int dnOffset = 0; 947 String rdnString; 948 int searchOffset = 0; 949 int rdnEnd = dnString.indexOf(','); 950 while (rdnEnd >=0) { 951 /* 952 * We have encountered an RDN delimiter (comma). 953 * If the comma in the RDN under consideration is 954 * preceded by a backslash (escape), it 955 * is part of the RDN. Otherwise, it is used as a separator, to 956 * delimit the RDN under consideration from any subsequent RDNs. 957 */ 958 if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) { 959 960 /* 961 * Comma is a separator 962 */ 963 rdnString = dnString.substring(dnOffset, rdnEnd); 964 965 // Parse RDN, and store it in vector 966 RDN rdn = new RDN(rdnString, "RFC2253"); 967 dnVector.add(rdn); 968 969 // Increase the offset 970 dnOffset = rdnEnd + 1; 971 } 972 973 searchOffset = rdnEnd + 1; 974 rdnEnd = dnString.indexOf(',', searchOffset); 975 } 976 977 // Parse last or only RDN, and store it in vector 978 rdnString = dnString.substring(dnOffset); 979 RDN rdn = new RDN(rdnString, "RFC2253"); 980 dnVector.add(rdn); 981 982 /* 983 * Store the vector elements as an array of RDNs 984 * NOTE: It's only on output that little-endian ordering is used. 985 */ 986 Collections.reverse(dnVector); 987 names = dnVector.toArray(new RDN[dnVector.size()]); 988 } 989 990 /* 991 * Counts double quotes in string. 992 * Escaped quotes are ignored. 993 */ 994 static int countQuotes(String string, int from, int to) { 995 int count = 0; 996 997 for (int i = from; i < to; i++) { 998 if ((string.charAt(i) == '"' && i == from) || 999 (string.charAt(i) == '"' && string.charAt(i-1) != '\\')) { 1000 count++; 1001 } 1002 } 1003 1004 return count; 1005 } 1006 1007 private static boolean escaped 1008 (int rdnEnd, int searchOffset, String dnString) { 1009 1010 if (rdnEnd == 1 && dnString.charAt(rdnEnd - 1) == '\\') { 1011 1012 // case 1: 1013 // \, 1014 1015 return true; 1016 1017 } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' && 1018 dnString.charAt(rdnEnd - 2) != '\\') { 1019 1020 // case 2: 1021 // foo\, 1022 1023 return true; 1024 1025 } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' && 1026 dnString.charAt(rdnEnd - 2) == '\\') { 1027 1028 // case 3: 1029 // foo\\\\\, 1030 1031 int count = 0; 1032 rdnEnd--; // back up to last backSlash 1033 while (rdnEnd >= searchOffset) { 1034 if (dnString.charAt(rdnEnd) == '\\') { 1035 count++; // count consecutive backslashes 1036 } 1037 rdnEnd--; 1038 } 1039 1040 // if count is odd, then rdnEnd is escaped 1041 return (count % 2) != 0 ? true : false; 1042 1043 } else { 1044 return false; 1045 } 1046 } 1047 1048 /* 1049 * Dump the printable form of a distinguished name. Each relative 1050 * name is separated from the next by a ",", and assertions in the 1051 * relative names have "label=value" syntax. 1052 * 1053 * Uses RFC 1779 syntax (i.e. little-endian, comma separators) 1054 */ 1055 private void generateDN() { 1056 if (names.length == 1) { 1057 dn = names[0].toString(); 1058 return; 1059 } 1060 1061 if (names == null) { 1062 dn = ""; 1063 return; 1064 } 1065 1066 StringJoiner sj = new StringJoiner(", "); 1067 for (int i = names.length - 1; i >= 0; i--) { 1068 sj.add(names[i].toString()); 1069 } 1070 dn = sj.toString(); 1071 } 1072 1073 /* 1074 * Dump the printable form of a distinguished name. Each relative 1075 * name is separated from the next by a ",", and assertions in the 1076 * relative names have "label=value" syntax. 1077 * 1078 * Uses RFC 1779 syntax (i.e. little-endian, comma separators) 1079 * Valid keywords from RFC 1779 are used. Additional keywords can be 1080 * specified in the OID/keyword map. 1081 */ 1082 private String generateRFC1779DN(Map<String, String> oidMap) { 1083 if (names.length == 1) { 1084 return names[0].toRFC1779String(oidMap); 1085 } 1086 1087 if (names == null) { 1088 return ""; 1089 } 1090 1091 StringJoiner sj = new StringJoiner(", "); 1092 for (int i = names.length - 1; i >= 0; i--) { 1093 sj.add(names[i].toRFC1779String(oidMap)); 1094 } 1095 return sj.toString(); 1096 } 1097 1098 /****************************************************************/ 1099 1100 /* 1101 * Maybe return a preallocated OID, to reduce storage costs 1102 * and speed recognition of common X.500 attributes. 1103 */ 1104 static ObjectIdentifier intern(ObjectIdentifier oid) { 1105 ObjectIdentifier interned = internedOIDs.putIfAbsent(oid, oid); 1106 return (interned == null) ? oid : interned; 1107 } 1108 1109 private static final Map<ObjectIdentifier,ObjectIdentifier> internedOIDs 1110 = new HashMap<ObjectIdentifier,ObjectIdentifier>(); 1111 1112 /* 1113 * Selected OIDs from X.520 1114 * Includes all those specified in RFC 5280 as MUST or SHOULD 1115 * be recognized 1116 */ 1117 private static final int[] commonName_data = { 2, 5, 4, 3 }; 1118 private static final int[] SURNAME_DATA = { 2, 5, 4, 4 }; 1119 private static final int[] SERIALNUMBER_DATA = { 2, 5, 4, 5 }; 1120 private static final int[] countryName_data = { 2, 5, 4, 6 }; 1121 private static final int[] localityName_data = { 2, 5, 4, 7 }; 1122 private static final int[] stateName_data = { 2, 5, 4, 8 }; 1123 private static final int[] streetAddress_data = { 2, 5, 4, 9 }; 1124 private static final int[] orgName_data = { 2, 5, 4, 10 }; 1125 private static final int[] orgUnitName_data = { 2, 5, 4, 11 }; 1126 private static final int[] title_data = { 2, 5, 4, 12 }; 1127 private static final int[] GIVENNAME_DATA = { 2, 5, 4, 42 }; 1128 private static final int[] INITIALS_DATA = { 2, 5, 4, 43 }; 1129 private static final int[] GENERATIONQUALIFIER_DATA = { 2, 5, 4, 44 }; 1130 private static final int[] DNQUALIFIER_DATA = { 2, 5, 4, 46 }; 1131 1132 private static final int[] ipAddress_data = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; 1133 private static final int[] DOMAIN_COMPONENT_DATA = 1134 { 0, 9, 2342, 19200300, 100, 1, 25 }; 1135 private static final int[] userid_data = 1136 { 0, 9, 2342, 19200300, 100, 1, 1 }; 1137 1138 1139 public static final ObjectIdentifier commonName_oid; 1140 public static final ObjectIdentifier countryName_oid; 1141 public static final ObjectIdentifier localityName_oid; 1142 public static final ObjectIdentifier orgName_oid; 1143 public static final ObjectIdentifier orgUnitName_oid; 1144 public static final ObjectIdentifier stateName_oid; 1145 public static final ObjectIdentifier streetAddress_oid; 1146 public static final ObjectIdentifier title_oid; 1147 public static final ObjectIdentifier DNQUALIFIER_OID; 1148 public static final ObjectIdentifier SURNAME_OID; 1149 public static final ObjectIdentifier GIVENNAME_OID; 1150 public static final ObjectIdentifier INITIALS_OID; 1151 public static final ObjectIdentifier GENERATIONQUALIFIER_OID; 1152 public static final ObjectIdentifier ipAddress_oid; 1153 public static final ObjectIdentifier DOMAIN_COMPONENT_OID; 1154 public static final ObjectIdentifier userid_oid; 1155 public static final ObjectIdentifier SERIALNUMBER_OID; 1156 1157 static { 1158 /** OID for the "CN=" attribute, denoting a person's common name. */ 1159 commonName_oid = intern(ObjectIdentifier.newInternal(commonName_data)); 1160 1161 /** OID for the "SERIALNUMBER=" attribute, denoting a serial number for. 1162 a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the 1163 certificate serial number. */ 1164 SERIALNUMBER_OID = intern(ObjectIdentifier.newInternal(SERIALNUMBER_DATA)); 1165 1166 /** OID for the "C=" attribute, denoting a country. */ 1167 countryName_oid = intern(ObjectIdentifier.newInternal(countryName_data)); 1168 1169 /** OID for the "L=" attribute, denoting a locality (such as a city) */ 1170 localityName_oid = intern(ObjectIdentifier.newInternal(localityName_data)); 1171 1172 /** OID for the "O=" attribute, denoting an organization name */ 1173 orgName_oid = intern(ObjectIdentifier.newInternal(orgName_data)); 1174 1175 /** OID for the "OU=" attribute, denoting an organizational unit name */ 1176 orgUnitName_oid = intern(ObjectIdentifier.newInternal(orgUnitName_data)); 1177 1178 /** OID for the "S=" attribute, denoting a state (such as Delaware) */ 1179 stateName_oid = intern(ObjectIdentifier.newInternal(stateName_data)); 1180 1181 /** OID for the "STREET=" attribute, denoting a street address. */ 1182 streetAddress_oid = intern(ObjectIdentifier.newInternal(streetAddress_data)); 1183 1184 /** OID for the "T=" attribute, denoting a person's title. */ 1185 title_oid = intern(ObjectIdentifier.newInternal(title_data)); 1186 1187 /** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN 1188 disambiguating information.*/ 1189 DNQUALIFIER_OID = intern(ObjectIdentifier.newInternal(DNQUALIFIER_DATA)); 1190 1191 /** OID for the "SURNAME=" attribute, denoting a person's surname.*/ 1192 SURNAME_OID = intern(ObjectIdentifier.newInternal(SURNAME_DATA)); 1193 1194 /** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/ 1195 GIVENNAME_OID = intern(ObjectIdentifier.newInternal(GIVENNAME_DATA)); 1196 1197 /** OID for the "INITIALS=" attribute, denoting a person's initials.*/ 1198 INITIALS_OID = intern(ObjectIdentifier.newInternal(INITIALS_DATA)); 1199 1200 /** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/ 1201 GENERATIONQUALIFIER_OID = 1202 intern(ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA)); 1203 1204 /* 1205 * OIDs from other sources which show up in X.500 names we 1206 * expect to deal with often 1207 */ 1208 /** OID for "IP=" IP address attributes, used with SKIP. */ 1209 ipAddress_oid = intern(ObjectIdentifier.newInternal(ipAddress_data)); 1210 1211 /* 1212 * Domain component OID from RFC 1274, RFC 2247, RFC 5280 1213 */ 1214 1215 /* 1216 * OID for "DC=" domain component attributes, used with DNSNames in DN 1217 * format 1218 */ 1219 DOMAIN_COMPONENT_OID = 1220 intern(ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA)); 1221 1222 /** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */ 1223 userid_oid = intern(ObjectIdentifier.newInternal(userid_data)); 1224 } 1225 1226 /** 1227 * Return constraint type:<ul> 1228 * <li>NAME_DIFF_TYPE = -1: input name is different type from this name 1229 * (i.e. does not constrain) 1230 * <li>NAME_MATCH = 0: input name matches this name 1231 * <li>NAME_NARROWS = 1: input name narrows this name 1232 * <li>NAME_WIDENS = 2: input name widens this name 1233 * <li>NAME_SAME_TYPE = 3: input name does not match or narrow this name, 1234 * but is same type. 1235 * </ul> 1236 * These results are used in checking NameConstraints during 1237 * certification path verification. 1238 * 1239 * @param inputName to be checked for being constrained 1240 * @return constraint type above 1241 * @throws UnsupportedOperationException if name is not exact match, but 1242 * narrowing and widening are not supported for this name type. 1243 */ 1244 public int constrains(GeneralNameInterface inputName) 1245 throws UnsupportedOperationException { 1246 int constraintType; 1247 if (inputName == null) { 1248 constraintType = NAME_DIFF_TYPE; 1249 } else if (inputName.getType() != NAME_DIRECTORY) { 1250 constraintType = NAME_DIFF_TYPE; 1251 } else { // type == NAME_DIRECTORY 1252 X500Name inputX500 = (X500Name)inputName; 1253 if (inputX500.equals(this)) { 1254 constraintType = NAME_MATCH; 1255 } else if (inputX500.names.length == 0) { 1256 constraintType = NAME_WIDENS; 1257 } else if (this.names.length == 0) { 1258 constraintType = NAME_NARROWS; 1259 } else if (inputX500.isWithinSubtree(this)) { 1260 constraintType = NAME_NARROWS; 1261 } else if (isWithinSubtree(inputX500)) { 1262 constraintType = NAME_WIDENS; 1263 } else { 1264 constraintType = NAME_SAME_TYPE; 1265 } 1266 } 1267 return constraintType; 1268 } 1269 1270 /** 1271 * Compares this name with another and determines if 1272 * it is within the subtree of the other. Useful for 1273 * checking against the name constraints extension. 1274 * 1275 * @return true iff this name is within the subtree of other. 1276 */ 1277 private boolean isWithinSubtree(X500Name other) { 1278 if (this == other) { 1279 return true; 1280 } 1281 if (other == null) { 1282 return false; 1283 } 1284 if (other.names.length == 0) { 1285 return true; 1286 } 1287 if (this.names.length == 0) { 1288 return false; 1289 } 1290 if (names.length < other.names.length) { 1291 return false; 1292 } 1293 for (int i = 0; i < other.names.length; i++) { 1294 if (!names[i].equals(other.names[i])) { 1295 return false; 1296 } 1297 } 1298 return true; 1299 } 1300 1301 /** 1302 * Return subtree depth of this name for purposes of determining 1303 * NameConstraints minimum and maximum bounds and for calculating 1304 * path lengths in name subtrees. 1305 * 1306 * @return distance of name from root 1307 * @throws UnsupportedOperationException if not supported for this name type 1308 */ 1309 public int subtreeDepth() throws UnsupportedOperationException { 1310 return names.length; 1311 } 1312 1313 /** 1314 * Return lowest common ancestor of this name and other name 1315 * 1316 * @param other another X500Name 1317 * @return X500Name of lowest common ancestor; null if none 1318 */ 1319 public X500Name commonAncestor(X500Name other) { 1320 1321 if (other == null) { 1322 return null; 1323 } 1324 int otherLen = other.names.length; 1325 int thisLen = this.names.length; 1326 if (thisLen == 0 || otherLen == 0) { 1327 return null; 1328 } 1329 int minLen = (thisLen < otherLen) ? thisLen: otherLen; 1330 1331 //Compare names from highest RDN down the naming tree 1332 //Note that these are stored in RDN[0]... 1333 int i=0; 1334 for (; i < minLen; i++) { 1335 if (!names[i].equals(other.names[i])) { 1336 if (i == 0) { 1337 return null; 1338 } else { 1339 break; 1340 } 1341 } 1342 } 1343 1344 //Copy matching RDNs into new RDN array 1345 RDN[] ancestor = new RDN[i]; 1346 for (int j=0; j < i; j++) { 1347 ancestor[j] = names[j]; 1348 } 1349 1350 X500Name commonAncestor = null; 1351 try { 1352 commonAncestor = new X500Name(ancestor); 1353 } catch (IOException ioe) { 1354 return null; 1355 } 1356 return commonAncestor; 1357 } 1358 1359 /** 1360 * Constructor object for use by asX500Principal(). 1361 */ 1362 private static final Constructor<X500Principal> principalConstructor; 1363 1364 /** 1365 * Field object for use by asX500Name(). 1366 */ 1367 private static final Field principalField; 1368 1369 /** 1370 * Retrieve the Constructor and Field we need for reflective access 1371 * and make them accessible. 1372 */ 1373 static { 1374 PrivilegedExceptionAction<Object[]> pa = 1375 new PrivilegedExceptionAction<>() { 1376 public Object[] run() throws Exception { 1377 Class<X500Principal> pClass = X500Principal.class; 1378 Class<?>[] args = new Class<?>[] { X500Name.class }; 1379 Constructor<X500Principal> cons = pClass.getDeclaredConstructor(args); 1380 cons.setAccessible(true); 1381 Field field = pClass.getDeclaredField("thisX500Name"); 1382 field.setAccessible(true); 1383 return new Object[] {cons, field}; 1384 } 1385 }; 1386 try { 1387 Object[] result = AccessController.doPrivileged(pa); 1388 @SuppressWarnings("unchecked") 1389 Constructor<X500Principal> constr = 1390 (Constructor<X500Principal>)result[0]; 1391 principalConstructor = constr; 1392 principalField = (Field)result[1]; 1393 } catch (Exception e) { 1394 throw new InternalError("Could not obtain X500Principal access", e); 1395 } 1396 } 1397 1398 /** 1399 * Get an X500Principal backed by this X500Name. 1400 * 1401 * Note that we are using privileged reflection to access the hidden 1402 * package private constructor in X500Principal. 1403 */ 1404 public X500Principal asX500Principal() { 1405 if (x500Principal == null) { 1406 try { 1407 Object[] args = new Object[] {this}; 1408 x500Principal = principalConstructor.newInstance(args); 1409 } catch (Exception e) { 1410 throw new RuntimeException("Unexpected exception", e); 1411 } 1412 } 1413 return x500Principal; 1414 } 1415 1416 /** 1417 * Get the X500Name contained in the given X500Principal. 1418 * 1419 * Note that the X500Name is retrieved using reflection. 1420 */ 1421 public static X500Name asX500Name(X500Principal p) { 1422 try { 1423 X500Name name = (X500Name)principalField.get(p); 1424 name.x500Principal = p; 1425 return name; 1426 } catch (Exception e) { 1427 throw new RuntimeException("Unexpected exception", e); 1428 } 1429 } 1430 1431 }