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