Home | History | Annotate | Download | only in x509
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package sun.security.x509;
     28 
     29 import java.lang.reflect.*;
     30 import java.io.IOException;
     31 import java.security.PrivilegedExceptionAction;
     32 import java.security.AccessController;
     33 import java.security.Principal;
     34 import java.util.*;
     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  * <p>
     89  * <li>attribute values in types other than PrintableString are case
     90  *    sensitive (this permits matching of attribute values as binary
     91  *    objects);
     92  * <p>
     93  * <li>attribute values in PrintableString are not case sensitive
     94  *    (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and
     95  * <p>
     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 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<AVA>();
    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 3280).
    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 3280
    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         // Android-added: refuse DN starting with new line or tab
    880         checkNoNewLinesNorTabsAtBeginningOfDN(input);
    881 
    882         List<RDN> dnVector = new ArrayList<>();
    883         int dnOffset = 0;
    884         int rdnEnd;
    885         String rdnString;
    886         int quoteCount = 0;
    887 
    888         String dnString = input;
    889 
    890         int searchOffset = 0;
    891         int nextComma = dnString.indexOf(',');
    892         int nextSemiColon = dnString.indexOf(';');
    893         while (nextComma >=0 || nextSemiColon >=0) {
    894 
    895             if (nextSemiColon < 0) {
    896                 rdnEnd = nextComma;
    897             } else if (nextComma < 0) {
    898                 rdnEnd = nextSemiColon;
    899             } else {
    900                 rdnEnd = Math.min(nextComma, nextSemiColon);
    901             }
    902             quoteCount += countQuotes(dnString, searchOffset, rdnEnd);
    903 
    904             /*
    905              * We have encountered an RDN delimiter (comma or a semicolon).
    906              * If the comma or semicolon in the RDN under consideration is
    907              * preceded by a backslash (escape), or by a double quote, it
    908              * is part of the RDN. Otherwise, it is used as a separator, to
    909              * delimit the RDN under consideration from any subsequent RDNs.
    910              */
    911             if (rdnEnd >= 0 && quoteCount != 1 &&
    912                 !escaped(rdnEnd, searchOffset, dnString)) {
    913 
    914                 /*
    915                  * Comma/semicolon is a separator
    916                  */
    917                 rdnString = dnString.substring(dnOffset, rdnEnd);
    918 
    919                 // Parse RDN, and store it in vector
    920                 RDN rdn = new RDN(rdnString, keywordMap);
    921                 dnVector.add(rdn);
    922 
    923                 // Increase the offset
    924                 dnOffset = rdnEnd + 1;
    925 
    926                 // Set quote counter back to zero
    927                 quoteCount = 0;
    928             }
    929 
    930             searchOffset = rdnEnd + 1;
    931             nextComma = dnString.indexOf(',', searchOffset);
    932             nextSemiColon = dnString.indexOf(';', searchOffset);
    933         }
    934 
    935         // Parse last or only RDN, and store it in vector
    936         rdnString = dnString.substring(dnOffset);
    937         RDN rdn = new RDN(rdnString, keywordMap);
    938         dnVector.add(rdn);
    939 
    940         /*
    941          * Store the vector elements as an array of RDNs
    942          * NOTE: It's only on output that little-endian ordering is used.
    943          */
    944         Collections.reverse(dnVector);
    945         names = dnVector.toArray(new RDN[dnVector.size()]);
    946     }
    947 
    948     // BEGIN Android-added: refuse DN starting with new line or tab
    949     /**
    950      * Disallow new lines and tabs at the beginning of DN.
    951      *
    952      * @throws java.lang.IllegalArgumentException if the DN starts with new line or tab.
    953      */
    954     private void checkNoNewLinesNorTabsAtBeginningOfDN(String input) {
    955         for (int i = 0; i < input.length(); i++) {
    956             char c = input.charAt(i);
    957             if (c != ' ') {
    958                 if (c == '\t' || c == '\n') {
    959                     throw new IllegalArgumentException("DN cannot start with newline nor tab");
    960                 }
    961                 break;
    962             }
    963         }
    964     }
    965     // END Android-added: refuse DN starting with new line or tab
    966 
    967     private void parseRFC2253DN(String dnString) throws IOException {
    968         if (dnString.length() == 0) {
    969             names = new RDN[0];
    970             return;
    971          }
    972 
    973          List<RDN> dnVector = new ArrayList<>();
    974          int dnOffset = 0;
    975          String rdnString;
    976          int searchOffset = 0;
    977          int rdnEnd = dnString.indexOf(',');
    978          while (rdnEnd >=0) {
    979              /*
    980               * We have encountered an RDN delimiter (comma).
    981               * If the comma in the RDN under consideration is
    982               * preceded by a backslash (escape), it
    983               * is part of the RDN. Otherwise, it is used as a separator, to
    984               * delimit the RDN under consideration from any subsequent RDNs.
    985               */
    986              if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) {
    987 
    988                  /*
    989                   * Comma is a separator
    990                   */
    991                  rdnString = dnString.substring(dnOffset, rdnEnd);
    992 
    993                  // Parse RDN, and store it in vector
    994                  RDN rdn = new RDN(rdnString, "RFC2253");
    995                  dnVector.add(rdn);
    996 
    997                  // Increase the offset
    998                  dnOffset = rdnEnd + 1;
    999              }
   1000 
   1001              searchOffset = rdnEnd + 1;
   1002              rdnEnd = dnString.indexOf(',', searchOffset);
   1003          }
   1004 
   1005          // Parse last or only RDN, and store it in vector
   1006          rdnString = dnString.substring(dnOffset);
   1007          RDN rdn = new RDN(rdnString, "RFC2253");
   1008          dnVector.add(rdn);
   1009 
   1010          /*
   1011           * Store the vector elements as an array of RDNs
   1012           * NOTE: It's only on output that little-endian ordering is used.
   1013           */
   1014          Collections.reverse(dnVector);
   1015          names = dnVector.toArray(new RDN[dnVector.size()]);
   1016     }
   1017 
   1018     /*
   1019      * Counts double quotes in string.
   1020      * Escaped quotes are ignored.
   1021      */
   1022     static int countQuotes(String string, int from, int to) {
   1023         int count = 0;
   1024 
   1025         // BEGIN Android-changed: Fix countQuotes in case of escaped backslashes: \\"
   1026         int escape = 0;
   1027         for (int i = from; i < to; i++) {
   1028             if (string.charAt(i) == '"' && escape % 2 == 0) {
   1029                 count++;
   1030             }
   1031             escape = (string.charAt(i) == '\\') ? escape + 1 : 0;
   1032         }
   1033         // END Android-changed: Fix countQuotes in case of escaped backslashes: \\"
   1034 
   1035         return count;
   1036     }
   1037 
   1038     private static boolean escaped
   1039                 (int rdnEnd, int searchOffset, String dnString) {
   1040 
   1041         if (rdnEnd == 1 && dnString.charAt(rdnEnd - 1) == '\\') {
   1042 
   1043             //  case 1:
   1044             //  \,
   1045 
   1046             return true;
   1047 
   1048         } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' &&
   1049                 dnString.charAt(rdnEnd - 2) != '\\') {
   1050 
   1051             //  case 2:
   1052             //  foo\,
   1053 
   1054             return true;
   1055 
   1056         } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' &&
   1057                 dnString.charAt(rdnEnd - 2) == '\\') {
   1058 
   1059             //  case 3:
   1060             //  foo\\\\\,
   1061 
   1062             int count = 0;
   1063             rdnEnd--;   // back up to last backSlash
   1064             while (rdnEnd >= searchOffset) {
   1065                 if (dnString.charAt(rdnEnd) == '\\') {
   1066                     count++;    // count consecutive backslashes
   1067                 }
   1068                 rdnEnd--;
   1069             }
   1070 
   1071             // if count is odd, then rdnEnd is escaped
   1072             return (count % 2) != 0 ? true : false;
   1073 
   1074         } else {
   1075             return false;
   1076         }
   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      */
   1086     private void generateDN() {
   1087         if (names.length == 1) {
   1088             dn = names[0].toString();
   1089             return;
   1090         }
   1091 
   1092         StringBuilder sb = new StringBuilder(48);
   1093         if (names != null) {
   1094             for (int i = names.length - 1; i >= 0; i--) {
   1095                 if (i != names.length - 1) {
   1096                     sb.append(", ");
   1097                 }
   1098                 sb.append(names[i].toString());
   1099             }
   1100         }
   1101         dn = sb.toString();
   1102     }
   1103 
   1104     /*
   1105      * Dump the printable form of a distinguished name.  Each relative
   1106      * name is separated from the next by a ",", and assertions in the
   1107      * relative names have "label=value" syntax.
   1108      *
   1109      * Uses RFC 1779 syntax (i.e. little-endian, comma separators)
   1110      * Valid keywords from RFC 1779 are used. Additional keywords can be
   1111      * specified in the OID/keyword map.
   1112      */
   1113     private String generateRFC1779DN(Map<String, String> oidMap) {
   1114         if (names.length == 1) {
   1115             return names[0].toRFC1779String(oidMap);
   1116         }
   1117 
   1118         StringBuilder sb = new StringBuilder(48);
   1119         if (names != null) {
   1120             for (int i = names.length - 1; i >= 0; i--) {
   1121                 if (i != names.length - 1) {
   1122                     sb.append(", ");
   1123                 }
   1124                 sb.append(names[i].toRFC1779String(oidMap));
   1125             }
   1126         }
   1127         return sb.toString();
   1128     }
   1129 
   1130     /****************************************************************/
   1131 
   1132     /*
   1133      * Maybe return a preallocated OID, to reduce storage costs
   1134      * and speed recognition of common X.500 attributes.
   1135      */
   1136     static ObjectIdentifier intern(ObjectIdentifier oid) {
   1137         ObjectIdentifier interned = internedOIDs.putIfAbsent(oid, oid);
   1138         return (interned == null) ? oid : interned;
   1139     }
   1140 
   1141     private static final Map<ObjectIdentifier,ObjectIdentifier> internedOIDs
   1142                         = new HashMap<ObjectIdentifier,ObjectIdentifier>();
   1143 
   1144     /*
   1145      * Selected OIDs from X.520
   1146      * Includes all those specified in RFC 3280 as MUST or SHOULD
   1147      * be recognized
   1148      */
   1149     private static final int commonName_data[] = { 2, 5, 4, 3 };
   1150     private static final int SURNAME_DATA[] = { 2, 5, 4, 4 };
   1151     private static final int SERIALNUMBER_DATA[] = { 2, 5, 4, 5 };
   1152     private static final int countryName_data[] = { 2, 5, 4, 6 };
   1153     private static final int localityName_data[] = { 2, 5, 4, 7 };
   1154     private static final int stateName_data[] = { 2, 5, 4, 8 };
   1155     private static final int streetAddress_data[] = { 2, 5, 4, 9 };
   1156     private static final int orgName_data[] = { 2, 5, 4, 10 };
   1157     private static final int orgUnitName_data[] = { 2, 5, 4, 11 };
   1158     private static final int title_data[] = { 2, 5, 4, 12 };
   1159     private static final int GIVENNAME_DATA[] = { 2, 5, 4, 42 };
   1160     private static final int INITIALS_DATA[] = { 2, 5, 4, 43 };
   1161     private static final int GENERATIONQUALIFIER_DATA[] = { 2, 5, 4, 44 };
   1162     private static final int DNQUALIFIER_DATA[] = { 2, 5, 4, 46 };
   1163 
   1164     private static final int ipAddress_data[] = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 };
   1165     private static final int DOMAIN_COMPONENT_DATA[] =
   1166         { 0, 9, 2342, 19200300, 100, 1, 25 };
   1167     private static final int userid_data[] =
   1168         { 0, 9, 2342, 19200300, 100, 1, 1 };
   1169 
   1170 
   1171     public static final ObjectIdentifier commonName_oid;
   1172     public static final ObjectIdentifier countryName_oid;
   1173     public static final ObjectIdentifier localityName_oid;
   1174     public static final ObjectIdentifier orgName_oid;
   1175     public static final ObjectIdentifier orgUnitName_oid;
   1176     public static final ObjectIdentifier stateName_oid;
   1177     public static final ObjectIdentifier streetAddress_oid;
   1178     public static final ObjectIdentifier title_oid;
   1179     public static final ObjectIdentifier DNQUALIFIER_OID;
   1180     public static final ObjectIdentifier SURNAME_OID;
   1181     public static final ObjectIdentifier GIVENNAME_OID;
   1182     public static final ObjectIdentifier INITIALS_OID;
   1183     public static final ObjectIdentifier GENERATIONQUALIFIER_OID;
   1184     public static final ObjectIdentifier ipAddress_oid;
   1185     public static final ObjectIdentifier DOMAIN_COMPONENT_OID;
   1186     public static final ObjectIdentifier userid_oid;
   1187     public static final ObjectIdentifier SERIALNUMBER_OID;
   1188 
   1189     static {
   1190     /** OID for the "CN=" attribute, denoting a person's common name. */
   1191         commonName_oid = intern(ObjectIdentifier.newInternal(commonName_data));
   1192 
   1193     /** OID for the "SERIALNUMBER=" attribute, denoting a serial number for.
   1194         a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the
   1195         certificate serial number. */
   1196         SERIALNUMBER_OID = intern(ObjectIdentifier.newInternal(SERIALNUMBER_DATA));
   1197 
   1198     /** OID for the "C=" attribute, denoting a country. */
   1199         countryName_oid = intern(ObjectIdentifier.newInternal(countryName_data));
   1200 
   1201     /** OID for the "L=" attribute, denoting a locality (such as a city) */
   1202         localityName_oid = intern(ObjectIdentifier.newInternal(localityName_data));
   1203 
   1204     /** OID for the "O=" attribute, denoting an organization name */
   1205         orgName_oid = intern(ObjectIdentifier.newInternal(orgName_data));
   1206 
   1207     /** OID for the "OU=" attribute, denoting an organizational unit name */
   1208         orgUnitName_oid = intern(ObjectIdentifier.newInternal(orgUnitName_data));
   1209 
   1210     /** OID for the "S=" attribute, denoting a state (such as Delaware) */
   1211         stateName_oid = intern(ObjectIdentifier.newInternal(stateName_data));
   1212 
   1213     /** OID for the "STREET=" attribute, denoting a street address. */
   1214         streetAddress_oid = intern(ObjectIdentifier.newInternal(streetAddress_data));
   1215 
   1216     /** OID for the "T=" attribute, denoting a person's title. */
   1217         title_oid = intern(ObjectIdentifier.newInternal(title_data));
   1218 
   1219     /** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN
   1220         disambiguating information.*/
   1221         DNQUALIFIER_OID = intern(ObjectIdentifier.newInternal(DNQUALIFIER_DATA));
   1222 
   1223     /** OID for the "SURNAME=" attribute, denoting a person's surname.*/
   1224         SURNAME_OID = intern(ObjectIdentifier.newInternal(SURNAME_DATA));
   1225 
   1226     /** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/
   1227         GIVENNAME_OID = intern(ObjectIdentifier.newInternal(GIVENNAME_DATA));
   1228 
   1229     /** OID for the "INITIALS=" attribute, denoting a person's initials.*/
   1230         INITIALS_OID = intern(ObjectIdentifier.newInternal(INITIALS_DATA));
   1231 
   1232     /** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/
   1233         GENERATIONQUALIFIER_OID =
   1234             intern(ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA));
   1235 
   1236     /*
   1237      * OIDs from other sources which show up in X.500 names we
   1238      * expect to deal with often
   1239      */
   1240     /** OID for "IP=" IP address attributes, used with SKIP. */
   1241         ipAddress_oid = intern(ObjectIdentifier.newInternal(ipAddress_data));
   1242 
   1243     /*
   1244      * Domain component OID from RFC 1274, RFC 2247, RFC 3280
   1245      */
   1246 
   1247     /*
   1248      * OID for "DC=" domain component attributes, used with DNS names in DN
   1249      * format
   1250      */
   1251         DOMAIN_COMPONENT_OID =
   1252             intern(ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA));
   1253 
   1254     /** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */
   1255         userid_oid = intern(ObjectIdentifier.newInternal(userid_data));
   1256     }
   1257 
   1258     /**
   1259      * Return constraint type:<ul>
   1260      *   <li>NAME_DIFF_TYPE = -1: input name is different type from this name
   1261      *       (i.e. does not constrain)
   1262      *   <li>NAME_MATCH = 0: input name matches this name
   1263      *   <li>NAME_NARROWS = 1: input name narrows this name
   1264      *   <li>NAME_WIDENS = 2: input name widens this name
   1265      *   <li>NAME_SAME_TYPE = 3: input name does not match or narrow this name,
   1266      &       but is same type
   1267      * </ul>.  These results are used in checking NameConstraints during
   1268      * certification path verification.
   1269      *
   1270      * @param inputName to be checked for being constrained
   1271      * @returns constraint type above
   1272      * @throws UnsupportedOperationException if name is not exact match, but
   1273      *         narrowing and widening are not supported for this name type.
   1274      */
   1275     public int constrains(GeneralNameInterface inputName)
   1276             throws UnsupportedOperationException {
   1277         int constraintType;
   1278         if (inputName == null) {
   1279             constraintType = NAME_DIFF_TYPE;
   1280         } else if (inputName.getType() != NAME_DIRECTORY) {
   1281             constraintType = NAME_DIFF_TYPE;
   1282         } else { // type == NAME_DIRECTORY
   1283             X500Name inputX500 = (X500Name)inputName;
   1284             if (inputX500.equals(this)) {
   1285                 constraintType = NAME_MATCH;
   1286             } else if (inputX500.names.length == 0) {
   1287                 constraintType = NAME_WIDENS;
   1288             } else if (this.names.length == 0) {
   1289                 constraintType = NAME_NARROWS;
   1290             } else if (inputX500.isWithinSubtree(this)) {
   1291                 constraintType = NAME_NARROWS;
   1292             } else if (isWithinSubtree(inputX500)) {
   1293                 constraintType = NAME_WIDENS;
   1294             } else {
   1295                 constraintType = NAME_SAME_TYPE;
   1296             }
   1297         }
   1298         return constraintType;
   1299     }
   1300 
   1301     /**
   1302      * Compares this name with another and determines if
   1303      * it is within the subtree of the other. Useful for
   1304      * checking against the name constraints extension.
   1305      *
   1306      * @return true iff this name is within the subtree of other.
   1307      */
   1308     private boolean isWithinSubtree(X500Name other) {
   1309         if (this == other) {
   1310             return true;
   1311         }
   1312         if (other == null) {
   1313             return false;
   1314         }
   1315         if (other.names.length == 0) {
   1316             return true;
   1317         }
   1318         if (this.names.length == 0) {
   1319             return false;
   1320         }
   1321         if (names.length < other.names.length) {
   1322             return false;
   1323         }
   1324         for (int i = 0; i < other.names.length; i++) {
   1325             if (!names[i].equals(other.names[i])) {
   1326                 return false;
   1327             }
   1328         }
   1329         return true;
   1330     }
   1331 
   1332     /**
   1333      * Return subtree depth of this name for purposes of determining
   1334      * NameConstraints minimum and maximum bounds and for calculating
   1335      * path lengths in name subtrees.
   1336      *
   1337      * @returns distance of name from root
   1338      * @throws UnsupportedOperationException if not supported for this name type
   1339      */
   1340     public int subtreeDepth() throws UnsupportedOperationException {
   1341         return names.length;
   1342     }
   1343 
   1344     /**
   1345      * Return lowest common ancestor of this name and other name
   1346      *
   1347      * @param other another X500Name
   1348      * @return X500Name of lowest common ancestor; null if none
   1349      */
   1350     public X500Name commonAncestor(X500Name other) {
   1351 
   1352         if (other == null) {
   1353             return null;
   1354         }
   1355         int otherLen = other.names.length;
   1356         int thisLen = this.names.length;
   1357         if (thisLen == 0 || otherLen == 0) {
   1358             return null;
   1359         }
   1360         int minLen = (thisLen < otherLen) ? thisLen: otherLen;
   1361 
   1362         //Compare names from highest RDN down the naming tree
   1363         //Note that these are stored in RDN[0]...
   1364         int i=0;
   1365         for (; i < minLen; i++) {
   1366             if (!names[i].equals(other.names[i])) {
   1367                 if (i == 0) {
   1368                     return null;
   1369                 } else {
   1370                     break;
   1371                 }
   1372             }
   1373         }
   1374 
   1375         //Copy matching RDNs into new RDN array
   1376         RDN[] ancestor = new RDN[i];
   1377         for (int j=0; j < i; j++) {
   1378             ancestor[j] = names[j];
   1379         }
   1380 
   1381         X500Name commonAncestor = null;
   1382         try {
   1383             commonAncestor = new X500Name(ancestor);
   1384         } catch (IOException ioe) {
   1385             return null;
   1386         }
   1387         return commonAncestor;
   1388     }
   1389 
   1390     /**
   1391      * Constructor object for use by asX500Principal().
   1392      */
   1393     private static final Constructor<X500Principal> principalConstructor;
   1394 
   1395     /**
   1396      * Field object for use by asX500Name().
   1397      */
   1398     private static final Field principalField;
   1399 
   1400     /**
   1401      * Retrieve the Constructor and Field we need for reflective access
   1402      * and make them accessible.
   1403      */
   1404     static {
   1405         PrivilegedExceptionAction<Object[]> pa =
   1406                 new PrivilegedExceptionAction<Object[]>() {
   1407             public Object[] run() throws Exception {
   1408                 Class<X500Principal> pClass = X500Principal.class;
   1409                 Class<?>[] args = new Class<?>[] { X500Name.class };
   1410                 Constructor<X500Principal> cons = pClass.getDeclaredConstructor(args);
   1411                 cons.setAccessible(true);
   1412                 Field field = pClass.getDeclaredField("thisX500Name");
   1413                 field.setAccessible(true);
   1414                 return new Object[] {cons, field};
   1415             }
   1416         };
   1417         try {
   1418             Object[] result = AccessController.doPrivileged(pa);
   1419             @SuppressWarnings("unchecked")
   1420             Constructor<X500Principal> constr =
   1421                     (Constructor<X500Principal>)result[0];
   1422             principalConstructor = constr;
   1423             principalField = (Field)result[1];
   1424         } catch (Exception e) {
   1425             throw new InternalError("Could not obtain X500Principal access", e);
   1426         }
   1427     }
   1428 
   1429     /**
   1430      * Get an X500Principal backed by this X500Name.
   1431      *
   1432      * Note that we are using privileged reflection to access the hidden
   1433      * package private constructor in X500Principal.
   1434      */
   1435     public X500Principal asX500Principal() {
   1436         if (x500Principal == null) {
   1437             try {
   1438                 Object[] args = new Object[] {this};
   1439                 x500Principal = principalConstructor.newInstance(args);
   1440             } catch (Exception e) {
   1441                 throw new RuntimeException("Unexpected exception", e);
   1442             }
   1443         }
   1444         return x500Principal;
   1445     }
   1446 
   1447     /**
   1448      * Get the X500Name contained in the given X500Principal.
   1449      *
   1450      * Note that the X500Name is retrieved using reflection.
   1451      */
   1452     public static X500Name asX500Name(X500Principal p) {
   1453         try {
   1454             X500Name name = (X500Name)principalField.get(p);
   1455             name.x500Principal = p;
   1456             return name;
   1457         } catch (Exception e) {
   1458             throw new RuntimeException("Unexpected exception", e);
   1459         }
   1460     }
   1461 
   1462 }
   1463