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 }