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