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