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