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
27package sun.security.x509;
28
29import java.lang.reflect.*;
30import java.io.IOException;
31import java.security.PrivilegedExceptionAction;
32import java.security.AccessController;
33import java.security.Principal;
34import java.util.*;
35
36import sun.security.util.*;
37import 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
129public 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        }
351        return list;
352    }
353
354    /**
355     * Return the total number of AVAs contained in all the RDNs of
356     * this X500Name.
357     */
358    public int avaSize() {
359        return allAvas().size();
360    }
361
362    /**
363     * Return whether this X500Name is empty. An X500Name is not empty
364     * if it has at least one RDN containing at least one AVA.
365     */
366    public boolean isEmpty() {
367        int n = names.length;
368        if (n == 0) {
369            return true;
370        }
371        for (int i = 0; i < n; i++) {
372            if (names[i].assertion.length != 0) {
373                return false;
374            }
375        }
376        return true;
377    }
378
379    /**
380     * Calculates a hash code value for the object.  Objects
381     * which are equal will also have the same hashcode.
382     */
383    public int hashCode() {
384        return getRFC2253CanonicalName().hashCode();
385    }
386
387    /**
388     * Compares this name with another, for equality.
389     *
390     * @return true iff the names are identical.
391     */
392    public boolean equals(Object obj) {
393        if (this == obj) {
394            return true;
395        }
396        if (obj instanceof X500Name == false) {
397            return false;
398        }
399        X500Name other = (X500Name)obj;
400        // if we already have the canonical forms, compare now
401        if ((this.canonicalDn != null) && (other.canonicalDn != null)) {
402            return this.canonicalDn.equals(other.canonicalDn);
403        }
404        // quick check that number of RDNs and AVAs match before canonicalizing
405        int n = this.names.length;
406        if (n != other.names.length) {
407            return false;
408        }
409        for (int i = 0; i < n; i++) {
410            RDN r1 = this.names[i];
411            RDN r2 = other.names[i];
412            if (r1.assertion.length != r2.assertion.length) {
413                return false;
414            }
415        }
416        // definite check via canonical form
417        String thisCanonical = this.getRFC2253CanonicalName();
418        String otherCanonical = other.getRFC2253CanonicalName();
419        return thisCanonical.equals(otherCanonical);
420    }
421
422    /*
423     * Returns the name component as a Java string, regardless of its
424     * encoding restrictions.
425     */
426    private String getString(DerValue attribute) throws IOException {
427        if (attribute == null)
428            return null;
429        String  value = attribute.getAsString();
430
431        if (value == null)
432            throw new IOException("not a DER string encoding, "
433                    + attribute.tag);
434        else
435            return value;
436    }
437
438    /**
439     * Return type of GeneralName.
440     */
441    public int getType() {
442        return (GeneralNameInterface.NAME_DIRECTORY);
443    }
444
445    /**
446     * Returns a "Country" name component.  If more than one
447     * such attribute exists, the topmost one is returned.
448     *
449     * @return "C=" component of the name, if any.
450     */
451    public String getCountry() throws IOException {
452        DerValue attr = findAttribute(countryName_oid);
453
454        return getString(attr);
455    }
456
457
458    /**
459     * Returns an "Organization" name component.  If more than
460     * one such attribute exists, the topmost one is returned.
461     *
462     * @return "O=" component of the name, if any.
463     */
464    public String getOrganization() throws IOException {
465        DerValue attr = findAttribute(orgName_oid);
466
467        return getString(attr);
468    }
469
470
471    /**
472     * Returns an "Organizational Unit" name component.  If more
473     * than one such attribute exists, the topmost one is returned.
474     *
475     * @return "OU=" component of the name, if any.
476     */
477    public String getOrganizationalUnit() throws IOException {
478        DerValue attr = findAttribute(orgUnitName_oid);
479
480        return getString(attr);
481    }
482
483
484    /**
485     * Returns a "Common Name" component.  If more than one such
486     * attribute exists, the topmost one is returned.
487     *
488     * @return "CN=" component of the name, if any.
489     */
490    public String getCommonName() throws IOException {
491        DerValue attr = findAttribute(commonName_oid);
492
493        return getString(attr);
494    }
495
496
497    /**
498     * Returns a "Locality" name component.  If more than one
499     * such component exists, the topmost one is returned.
500     *
501     * @return "L=" component of the name, if any.
502     */
503    public String getLocality() throws IOException {
504        DerValue attr = findAttribute(localityName_oid);
505
506        return getString(attr);
507    }
508
509    /**
510     * Returns a "State" name component.  If more than one
511     * such component exists, the topmost one is returned.
512     *
513     * @return "S=" component of the name, if any.
514     */
515    public String getState() throws IOException {
516      DerValue attr = findAttribute(stateName_oid);
517
518        return getString(attr);
519    }
520
521    /**
522     * Returns a "Domain" name component.  If more than one
523     * such component exists, the topmost one is returned.
524     *
525     * @return "DC=" component of the name, if any.
526     */
527    public String getDomain() throws IOException {
528        DerValue attr = findAttribute(DOMAIN_COMPONENT_OID);
529
530        return getString(attr);
531    }
532
533    /**
534     * Returns a "DN Qualifier" name component.  If more than one
535     * such component exists, the topmost one is returned.
536     *
537     * @return "DNQ=" component of the name, if any.
538     */
539    public String getDNQualifier() throws IOException {
540        DerValue attr = findAttribute(DNQUALIFIER_OID);
541
542        return getString(attr);
543    }
544
545    /**
546     * Returns a "Surname" name component.  If more than one
547     * such component exists, the topmost one is returned.
548     *
549     * @return "SURNAME=" component of the name, if any.
550     */
551    public String getSurname() throws IOException {
552        DerValue attr = findAttribute(SURNAME_OID);
553
554        return getString(attr);
555    }
556
557    /**
558     * Returns a "Given Name" name component.  If more than one
559     * such component exists, the topmost one is returned.
560     *
561     * @return "GIVENNAME=" component of the name, if any.
562     */
563    public String getGivenName() throws IOException {
564       DerValue attr = findAttribute(GIVENNAME_OID);
565
566       return getString(attr);
567    }
568
569    /**
570     * Returns an "Initials" name component.  If more than one
571     * such component exists, the topmost one is returned.
572     *
573     * @return "INITIALS=" component of the name, if any.
574     */
575    public String getInitials() throws IOException {
576        DerValue attr = findAttribute(INITIALS_OID);
577
578        return getString(attr);
579     }
580
581     /**
582      * Returns a "Generation Qualifier" name component.  If more than one
583      * such component exists, the topmost one is returned.
584      *
585      * @return "GENERATION=" component of the name, if any.
586      */
587    public String getGeneration() throws IOException {
588        DerValue attr = findAttribute(GENERATIONQUALIFIER_OID);
589
590        return getString(attr);
591    }
592
593    /**
594     * Returns an "IP address" name component.  If more than one
595     * such component exists, the topmost one is returned.
596     *
597     * @return "IP=" component of the name, if any.
598     */
599    public String getIP() throws IOException {
600        DerValue attr = findAttribute(ipAddress_oid);
601
602        return getString(attr);
603    }
604
605    /**
606     * Returns a string form of the X.500 distinguished name.
607     * The format of the string is from RFC 1779. The returned string
608     * may contain non-standardised keywords for more readability
609     * (keywords from RFCs 1779, 2253, and 3280).
610     */
611    public String toString() {
612        if (dn == null) {
613            generateDN();
614        }
615        return dn;
616    }
617
618    /**
619     * Returns a string form of the X.500 distinguished name
620     * using the algorithm defined in RFC 1779. Only standard attribute type
621     * keywords defined in RFC 1779 are emitted.
622     */
623    public String getRFC1779Name() {
624        return getRFC1779Name(Collections.<String, String>emptyMap());
625    }
626
627    /**
628     * Returns a string form of the X.500 distinguished name
629     * using the algorithm defined in RFC 1779. Attribute type
630     * keywords defined in RFC 1779 are emitted, as well as additional
631     * keywords contained in the OID/keyword map.
632     */
633    public String getRFC1779Name(Map<String, String> oidMap)
634        throws IllegalArgumentException {
635        if (oidMap.isEmpty()) {
636            // return cached result
637            if (rfc1779Dn != null) {
638                return rfc1779Dn;
639            } else {
640                rfc1779Dn = generateRFC1779DN(oidMap);
641                return rfc1779Dn;
642            }
643        }
644        return generateRFC1779DN(oidMap);
645    }
646
647    /**
648     * Returns a string form of the X.500 distinguished name
649     * using the algorithm defined in RFC 2253. Only standard attribute type
650     * keywords defined in RFC 2253 are emitted.
651     */
652    public String getRFC2253Name() {
653        return getRFC2253Name(Collections.<String, String>emptyMap());
654    }
655
656    /**
657     * Returns a string form of the X.500 distinguished name
658     * using the algorithm defined in RFC 2253. Attribute type
659     * keywords defined in RFC 2253 are emitted, as well as additional
660     * keywords contained in the OID/keyword map.
661     */
662    public String getRFC2253Name(Map<String, String> oidMap) {
663        /* check for and return cached name */
664        if (oidMap.isEmpty()) {
665            if (rfc2253Dn != null) {
666                return rfc2253Dn;
667            } else {
668                rfc2253Dn = generateRFC2253DN(oidMap);
669                return rfc2253Dn;
670            }
671        }
672        return generateRFC2253DN(oidMap);
673    }
674
675    private String generateRFC2253DN(Map<String, String> oidMap) {
676        /*
677         * Section 2.1 : if the RDNSequence is an empty sequence
678         * the result is the empty or zero length string.
679         */
680        if (names.length == 0) {
681            return "";
682        }
683
684        /*
685         * 2.1 (continued) : Otherwise, the output consists of the string
686         * encodings of each RelativeDistinguishedName in the RDNSequence
687         * (according to 2.2), starting with the last element of the sequence
688         * and moving backwards toward the first.
689         *
690         * The encodings of adjoining RelativeDistinguishedNames are separated
691         * by a comma character (',' ASCII 44).
692         */
693        StringBuilder fullname = new StringBuilder(48);
694        for (int i = names.length - 1; i >= 0; i--) {
695            if (i < names.length - 1) {
696                fullname.append(',');
697            }
698            fullname.append(names[i].toRFC2253String(oidMap));
699        }
700        return fullname.toString();
701    }
702
703    public String getRFC2253CanonicalName() {
704        /* check for and return cached name */
705        if (canonicalDn != null) {
706            return canonicalDn;
707        }
708        /*
709         * Section 2.1 : if the RDNSequence is an empty sequence
710         * the result is the empty or zero length string.
711         */
712        if (names.length == 0) {
713            canonicalDn = "";
714            return canonicalDn;
715        }
716
717        /*
718         * 2.1 (continued) : Otherwise, the output consists of the string
719         * encodings of each RelativeDistinguishedName in the RDNSequence
720         * (according to 2.2), starting with the last element of the sequence
721         * and moving backwards toward the first.
722         *
723         * The encodings of adjoining RelativeDistinguishedNames are separated
724         * by a comma character (',' ASCII 44).
725         */
726        StringBuilder fullname = new StringBuilder(48);
727        for (int i = names.length - 1; i >= 0; i--) {
728            if (i < names.length - 1) {
729                fullname.append(',');
730            }
731            fullname.append(names[i].toRFC2253String(true));
732        }
733        canonicalDn = fullname.toString();
734        return canonicalDn;
735    }
736
737    /**
738     * Returns the value of toString().  This call is needed to
739     * implement the java.security.Principal interface.
740     */
741    public String getName() { return toString(); }
742
743    /**
744     * Find the first instance of this attribute in a "top down"
745     * search of all the attributes in the name.
746     */
747    private DerValue findAttribute(ObjectIdentifier attribute) {
748        if (names != null) {
749            for (int i = 0; i < names.length; i++) {
750                DerValue value = names[i].findAttribute(attribute);
751                if (value != null) {
752                    return value;
753                }
754            }
755        }
756        return null;
757    }
758
759    /**
760     * Find the most specific ("last") attribute of the given
761     * type.
762     */
763    public DerValue findMostSpecificAttribute(ObjectIdentifier attribute) {
764        if (names != null) {
765            for (int i = names.length - 1; i >= 0; i--) {
766                DerValue value = names[i].findAttribute(attribute);
767                if (value != null) {
768                    return value;
769                }
770            }
771        }
772        return null;
773    }
774
775    /****************************************************************/
776
777    private void parseDER(DerInputStream in) throws IOException {
778        //
779        // X.500 names are a "SEQUENCE OF" RDNs, which means zero or
780        // more and order matters.  We scan them in order, which
781        // conventionally is big-endian.
782        //
783        DerValue[] nameseq = null;
784        byte[] derBytes = in.toByteArray();
785
786        try {
787            nameseq = in.getSequence(5);
788        } catch (IOException ioe) {
789            if (derBytes == null) {
790                nameseq = null;
791            } else {
792                DerValue derVal = new DerValue(DerValue.tag_Sequence,
793                                           derBytes);
794                derBytes = derVal.toByteArray();
795                nameseq = new DerInputStream(derBytes).getSequence(5);
796            }
797        }
798
799        if (nameseq == null) {
800            names = new RDN[0];
801        } else {
802            names = new RDN[nameseq.length];
803            for (int i = 0; i < nameseq.length; i++) {
804                names[i] = new RDN(nameseq[i]);
805            }
806        }
807    }
808
809    /**
810     * Encodes the name in DER-encoded form.
811     *
812     * @deprecated Use encode() instead
813     * @param out where to put the DER-encoded X.500 name
814     */
815    @Deprecated
816    public void emit(DerOutputStream out) throws IOException {
817        encode(out);
818    }
819
820    /**
821     * Encodes the name in DER-encoded form.
822     *
823     * @param out where to put the DER-encoded X.500 name
824     */
825    public void encode(DerOutputStream out) throws IOException {
826        DerOutputStream tmp = new DerOutputStream();
827        for (int i = 0; i < names.length; i++) {
828            names[i].encode(tmp);
829        }
830        out.write(DerValue.tag_Sequence, tmp);
831    }
832
833    /**
834     * Returned the encoding as an uncloned byte array. Callers must
835     * guarantee that they neither modify it not expose it to untrusted
836     * code.
837     */
838    public byte[] getEncodedInternal() throws IOException {
839        if (encoded == null) {
840            DerOutputStream     out = new DerOutputStream();
841            DerOutputStream     tmp = new DerOutputStream();
842            for (int i = 0; i < names.length; i++) {
843                names[i].encode(tmp);
844            }
845            out.write(DerValue.tag_Sequence, tmp);
846            encoded = out.toByteArray();
847        }
848        return encoded;
849    }
850
851    /**
852     * Gets the name in DER-encoded form.
853     *
854     * @return the DER encoded byte array of this name.
855     */
856    public byte[] getEncoded() throws IOException {
857        return getEncodedInternal().clone();
858    }
859
860    /*
861     * Parses a Distinguished Name (DN) in printable representation.
862     *
863     * According to RFC 1779, RDNs in a DN are separated by comma.
864     * The following examples show both methods of quoting a comma, so that it
865     * is not considered a separator:
866     *
867     *     O="Sue, Grabbit and Runn" or
868     *     O=Sue\, Grabbit and Runn
869     *
870     * This method can parse RFC 1779, 2253 or 4514 DNs and non-standard 3280
871     * keywords. Additional keywords can be specified in the keyword/OID map.
872     */
873    private void parseDN(String input, Map<String, String> keywordMap)
874        throws IOException {
875        if (input == null || input.length() == 0) {
876            names = new RDN[0];
877            return;
878        }
879
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    /**
949     * Disallow new lines and tabs at the beginning of DN.
950     *
951     * @throws java.lang.IllegalArgumentException if the DN starts with new line or tab.
952     */
953    private void checkNoNewLinesNorTabsAtBeginningOfDN(String input) {
954        for (int i = 0; i < input.length(); i++) {
955            char c = input.charAt(i);
956            if (c != ' ') {
957                if (c == '\t' || c == '\n') {
958                    throw new IllegalArgumentException("DN cannot start with newline nor tab");
959                }
960                break;
961            }
962        }
963    }
964
965    private void parseRFC2253DN(String dnString) throws IOException {
966        if (dnString.length() == 0) {
967            names = new RDN[0];
968            return;
969         }
970
971         List<RDN> dnVector = new ArrayList<>();
972         int dnOffset = 0;
973         String rdnString;
974         int searchOffset = 0;
975         int rdnEnd = dnString.indexOf(',');
976         while (rdnEnd >=0) {
977             /*
978              * We have encountered an RDN delimiter (comma).
979              * If the comma in the RDN under consideration is
980              * preceded by a backslash (escape), it
981              * is part of the RDN. Otherwise, it is used as a separator, to
982              * delimit the RDN under consideration from any subsequent RDNs.
983              */
984             if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) {
985
986                 /*
987                  * Comma is a separator
988                  */
989                 rdnString = dnString.substring(dnOffset, rdnEnd);
990
991                 // Parse RDN, and store it in vector
992                 RDN rdn = new RDN(rdnString, "RFC2253");
993                 dnVector.add(rdn);
994
995                 // Increase the offset
996                 dnOffset = rdnEnd + 1;
997             }
998
999             searchOffset = rdnEnd + 1;
1000             rdnEnd = dnString.indexOf(',', searchOffset);
1001         }
1002
1003         // Parse last or only RDN, and store it in vector
1004         rdnString = dnString.substring(dnOffset);
1005         RDN rdn = new RDN(rdnString, "RFC2253");
1006         dnVector.add(rdn);
1007
1008         /*
1009          * Store the vector elements as an array of RDNs
1010          * NOTE: It's only on output that little-endian ordering is used.
1011          */
1012         Collections.reverse(dnVector);
1013         names = dnVector.toArray(new RDN[dnVector.size()]);
1014    }
1015
1016    /*
1017     * Counts double quotes in string.
1018     * Escaped quotes are ignored.
1019     */
1020    static int countQuotes(String string, int from, int to) {
1021        int count = 0;
1022
1023        int escape = 0;
1024        for (int i = from; i < to; i++) {
1025            if (string.charAt(i) == '"' && escape % 2 == 0) {
1026                count++;
1027            }
1028            escape = (string.charAt(i) == '\\') ? escape + 1 : 0;
1029        }
1030
1031        return count;
1032    }
1033
1034    private static boolean escaped
1035                (int rdnEnd, int searchOffset, String dnString) {
1036
1037        if (rdnEnd == 1 && dnString.charAt(rdnEnd - 1) == '\\') {
1038
1039            //  case 1:
1040            //  \,
1041
1042            return true;
1043
1044        } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' &&
1045                dnString.charAt(rdnEnd - 2) != '\\') {
1046
1047            //  case 2:
1048            //  foo\,
1049
1050            return true;
1051
1052        } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\' &&
1053                dnString.charAt(rdnEnd - 2) == '\\') {
1054
1055            //  case 3:
1056            //  foo\\\\\,
1057
1058            int count = 0;
1059            rdnEnd--;   // back up to last backSlash
1060            while (rdnEnd >= searchOffset) {
1061                if (dnString.charAt(rdnEnd) == '\\') {
1062                    count++;    // count consecutive backslashes
1063                }
1064                rdnEnd--;
1065            }
1066
1067            // if count is odd, then rdnEnd is escaped
1068            return (count % 2) != 0 ? true : false;
1069
1070        } else {
1071            return false;
1072        }
1073    }
1074
1075    /*
1076     * Dump the printable form of a distinguished name.  Each relative
1077     * name is separated from the next by a ",", and assertions in the
1078     * relative names have "label=value" syntax.
1079     *
1080     * Uses RFC 1779 syntax (i.e. little-endian, comma separators)
1081     */
1082    private void generateDN() {
1083        if (names.length == 1) {
1084            dn = names[0].toString();
1085            return;
1086        }
1087
1088        StringBuilder sb = new StringBuilder(48);
1089        if (names != null) {
1090            for (int i = names.length - 1; i >= 0; i--) {
1091                if (i != names.length - 1) {
1092                    sb.append(", ");
1093                }
1094                sb.append(names[i].toString());
1095            }
1096        }
1097        dn = sb.toString();
1098    }
1099
1100    /*
1101     * Dump the printable form of a distinguished name.  Each relative
1102     * name is separated from the next by a ",", and assertions in the
1103     * relative names have "label=value" syntax.
1104     *
1105     * Uses RFC 1779 syntax (i.e. little-endian, comma separators)
1106     * Valid keywords from RFC 1779 are used. Additional keywords can be
1107     * specified in the OID/keyword map.
1108     */
1109    private String generateRFC1779DN(Map<String, String> oidMap) {
1110        if (names.length == 1) {
1111            return names[0].toRFC1779String(oidMap);
1112        }
1113
1114        StringBuilder sb = new StringBuilder(48);
1115        if (names != null) {
1116            for (int i = names.length - 1; i >= 0; i--) {
1117                if (i != names.length - 1) {
1118                    sb.append(", ");
1119                }
1120                sb.append(names[i].toRFC1779String(oidMap));
1121            }
1122        }
1123        return sb.toString();
1124    }
1125
1126    /****************************************************************/
1127
1128    /*
1129     * Maybe return a preallocated OID, to reduce storage costs
1130     * and speed recognition of common X.500 attributes.
1131     */
1132    static ObjectIdentifier intern(ObjectIdentifier oid) {
1133        ObjectIdentifier interned = internedOIDs.get(oid);
1134        if (interned != null) {
1135            return interned;
1136        }
1137        internedOIDs.put(oid, oid);
1138        return oid;
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