Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/security/auth/x500/X500Principal.java
38918 views
1
/*
2
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package javax.security.auth.x500;
27
28
import java.io.*;
29
import java.security.Principal;
30
import java.util.Collections;
31
import java.util.Map;
32
import sun.security.x509.X500Name;
33
import sun.security.util.*;
34
35
/**
36
* <p> This class represents an X.500 {@code Principal}.
37
* {@code X500Principal}s are represented by distinguished names such as
38
* "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US".
39
*
40
* <p> This class can be instantiated by using a string representation
41
* of the distinguished name, or by using the ASN.1 DER encoded byte
42
* representation of the distinguished name. The current specification
43
* for the string representation of a distinguished name is defined in
44
* <a href="http://tools.ietf.org/html/rfc2253">RFC 2253: Lightweight
45
* Directory Access Protocol (v3): UTF-8 String Representation of
46
* Distinguished Names</a>. This class, however, accepts string formats from
47
* both RFC 2253 and <a href="http://tools.ietf.org/html/rfc1779">RFC 1779:
48
* A String Representation of Distinguished Names</a>, and also recognizes
49
* attribute type keywords whose OIDs (Object Identifiers) are defined in
50
* <a href="http://tools.ietf.org/html/rfc5280">RFC 5280: Internet X.509
51
* Public Key Infrastructure Certificate and CRL Profile</a>.
52
*
53
* <p> The string representation for this {@code X500Principal}
54
* can be obtained by calling the {@code getName} methods.
55
*
56
* <p> Note that the {@code getSubjectX500Principal} and
57
* {@code getIssuerX500Principal} methods of
58
* {@code X509Certificate} return X500Principals representing the
59
* issuer and subject fields of the certificate.
60
*
61
* @see java.security.cert.X509Certificate
62
* @since 1.4
63
*/
64
public final class X500Principal implements Principal, java.io.Serializable {
65
66
private static final long serialVersionUID = -500463348111345721L;
67
68
/**
69
* RFC 1779 String format of Distinguished Names.
70
*/
71
public static final String RFC1779 = "RFC1779";
72
/**
73
* RFC 2253 String format of Distinguished Names.
74
*/
75
public static final String RFC2253 = "RFC2253";
76
/**
77
* Canonical String format of Distinguished Names.
78
*/
79
public static final String CANONICAL = "CANONICAL";
80
81
/**
82
* The X500Name representing this principal.
83
*
84
* NOTE: this field is reflectively accessed from within X500Name.
85
*/
86
private transient X500Name thisX500Name;
87
88
/**
89
* Creates an X500Principal by wrapping an X500Name.
90
*
91
* NOTE: The constructor is package private. It is intended to be accessed
92
* using privileged reflection from classes in sun.security.*.
93
* Currently referenced from sun.security.x509.X500Name.asX500Principal().
94
*/
95
X500Principal(X500Name x500Name) {
96
thisX500Name = x500Name;
97
}
98
99
/**
100
* Creates an {@code X500Principal} from a string representation of
101
* an X.500 distinguished name (ex:
102
* "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").
103
* The distinguished name must be specified using the grammar defined in
104
* RFC 1779 or RFC 2253 (either format is acceptable).
105
*
106
* <p>This constructor recognizes the attribute type keywords
107
* defined in RFC 1779 and RFC 2253
108
* (and listed in {@link #getName(String format) getName(String format)}),
109
* as well as the T, DNQ or DNQUALIFIER, SURNAME, GIVENNAME, INITIALS,
110
* GENERATION, EMAILADDRESS, and SERIALNUMBER keywords whose Object
111
* Identifiers (OIDs) are defined in RFC 5280.
112
* Any other attribute type must be specified as an OID.
113
*
114
* <p>This implementation enforces a more restrictive OID syntax than
115
* defined in RFC 1779 and 2253. It uses the more correct syntax defined in
116
* <a href="http://www.ietf.org/rfc/rfc4512.txt">RFC 4512</a>, which
117
* specifies that OIDs contain at least 2 digits:
118
*
119
* <p>{@code numericoid = number 1*( DOT number ) }
120
*
121
* @param name an X.500 distinguished name in RFC 1779 or RFC 2253 format
122
* @exception NullPointerException if the {@code name}
123
* is {@code null}
124
* @exception IllegalArgumentException if the {@code name}
125
* is improperly specified
126
*/
127
public X500Principal(String name) {
128
this(name, Collections.<String, String>emptyMap());
129
}
130
131
/**
132
* Creates an {@code X500Principal} from a string representation of
133
* an X.500 distinguished name (ex:
134
* "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").
135
* The distinguished name must be specified using the grammar defined in
136
* RFC 1779 or RFC 2253 (either format is acceptable).
137
*
138
* <p> This constructor recognizes the attribute type keywords specified
139
* in {@link #X500Principal(String)} and also recognizes additional
140
* keywords that have entries in the {@code keywordMap} parameter.
141
* Keyword entries in the keywordMap take precedence over the default
142
* keywords recognized by {@code X500Principal(String)}. Keywords
143
* MUST be specified in all upper-case, otherwise they will be ignored.
144
* Improperly specified keywords are ignored; however if a keyword in the
145
* name maps to an improperly specified Object Identifier (OID), an
146
* {@code IllegalArgumentException} is thrown. It is permissible to
147
* have 2 different keywords that map to the same OID.
148
*
149
* <p>This implementation enforces a more restrictive OID syntax than
150
* defined in RFC 1779 and 2253. It uses the more correct syntax defined in
151
* <a href="http://www.ietf.org/rfc/rfc4512.txt">RFC 4512</a>, which
152
* specifies that OIDs contain at least 2 digits:
153
*
154
* <p>{@code numericoid = number 1*( DOT number ) }
155
*
156
* @param name an X.500 distinguished name in RFC 1779 or RFC 2253 format
157
* @param keywordMap an attribute type keyword map, where each key is a
158
* keyword String that maps to a corresponding object identifier in String
159
* form (a sequence of nonnegative integers separated by periods). The map
160
* may be empty but never {@code null}.
161
* @exception NullPointerException if {@code name} or
162
* {@code keywordMap} is {@code null}
163
* @exception IllegalArgumentException if the {@code name} is
164
* improperly specified or a keyword in the {@code name} maps to an
165
* OID that is not in the correct form
166
* @since 1.6
167
*/
168
public X500Principal(String name, Map<String, String> keywordMap) {
169
if (name == null) {
170
throw new NullPointerException
171
(sun.security.util.ResourcesMgr.getString
172
("provided.null.name"));
173
}
174
if (keywordMap == null) {
175
throw new NullPointerException
176
(sun.security.util.ResourcesMgr.getString
177
("provided.null.keyword.map"));
178
}
179
180
try {
181
thisX500Name = new X500Name(name, keywordMap);
182
} catch (Exception e) {
183
IllegalArgumentException iae = new IllegalArgumentException
184
("improperly specified input name: " + name);
185
iae.initCause(e);
186
throw iae;
187
}
188
}
189
190
/**
191
* Creates an {@code X500Principal} from a distinguished name in
192
* ASN.1 DER encoded form. The ASN.1 notation for this structure is as
193
* follows.
194
* <pre>{@code
195
* Name ::= CHOICE {
196
* RDNSequence }
197
*
198
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
199
*
200
* RelativeDistinguishedName ::=
201
* SET SIZE (1 .. MAX) OF AttributeTypeAndValue
202
*
203
* AttributeTypeAndValue ::= SEQUENCE {
204
* type AttributeType,
205
* value AttributeValue }
206
*
207
* AttributeType ::= OBJECT IDENTIFIER
208
*
209
* AttributeValue ::= ANY DEFINED BY AttributeType
210
* ....
211
* DirectoryString ::= CHOICE {
212
* teletexString TeletexString (SIZE (1..MAX)),
213
* printableString PrintableString (SIZE (1..MAX)),
214
* universalString UniversalString (SIZE (1..MAX)),
215
* utf8String UTF8String (SIZE (1.. MAX)),
216
* bmpString BMPString (SIZE (1..MAX)) }
217
* }</pre>
218
*
219
* @param name a byte array containing the distinguished name in ASN.1
220
* DER encoded form
221
* @throws IllegalArgumentException if an encoding error occurs
222
* (incorrect form for DN)
223
*/
224
public X500Principal(byte[] name) {
225
try {
226
thisX500Name = new X500Name(name);
227
} catch (Exception e) {
228
IllegalArgumentException iae = new IllegalArgumentException
229
("improperly specified input name");
230
iae.initCause(e);
231
throw iae;
232
}
233
}
234
235
/**
236
* Creates an {@code X500Principal} from an {@code InputStream}
237
* containing the distinguished name in ASN.1 DER encoded form.
238
* The ASN.1 notation for this structure is supplied in the
239
* documentation for
240
* {@link #X500Principal(byte[] name) X500Principal(byte[] name)}.
241
*
242
* <p> The read position of the input stream is positioned
243
* to the next available byte after the encoded distinguished name.
244
*
245
* @param is an {@code InputStream} containing the distinguished
246
* name in ASN.1 DER encoded form
247
*
248
* @exception NullPointerException if the {@code InputStream}
249
* is {@code null}
250
* @exception IllegalArgumentException if an encoding error occurs
251
* (incorrect form for DN)
252
*/
253
public X500Principal(InputStream is) {
254
if (is == null) {
255
throw new NullPointerException("provided null input stream");
256
}
257
258
try {
259
if (is.markSupported())
260
is.mark(is.available() + 1);
261
DerValue der = new DerValue(is);
262
thisX500Name = new X500Name(der.data);
263
} catch (Exception e) {
264
if (is.markSupported()) {
265
try {
266
is.reset();
267
} catch (IOException ioe) {
268
IllegalArgumentException iae = new IllegalArgumentException
269
("improperly specified input stream " +
270
("and unable to reset input stream"));
271
iae.initCause(e);
272
throw iae;
273
}
274
}
275
IllegalArgumentException iae = new IllegalArgumentException
276
("improperly specified input stream");
277
iae.initCause(e);
278
throw iae;
279
}
280
}
281
282
/**
283
* Returns a string representation of the X.500 distinguished name using
284
* the format defined in RFC 2253.
285
*
286
* <p>This method is equivalent to calling
287
* {@code getName(X500Principal.RFC2253)}.
288
*
289
* @return the distinguished name of this {@code X500Principal}
290
*/
291
public String getName() {
292
return getName(X500Principal.RFC2253);
293
}
294
295
/**
296
* Returns a string representation of the X.500 distinguished name
297
* using the specified format. Valid values for the format are
298
* "RFC1779", "RFC2253", and "CANONICAL" (case insensitive).
299
*
300
* <p> If "RFC1779" is specified as the format,
301
* this method emits the attribute type keywords defined in
302
* RFC 1779 (CN, L, ST, O, OU, C, STREET).
303
* Any other attribute type is emitted as an OID.
304
*
305
* <p> If "RFC2253" is specified as the format,
306
* this method emits the attribute type keywords defined in
307
* RFC 2253 (CN, L, ST, O, OU, C, STREET, DC, UID).
308
* Any other attribute type is emitted as an OID.
309
* Under a strict reading, RFC 2253 only specifies a UTF-8 string
310
* representation. The String returned by this method is the
311
* Unicode string achieved by decoding this UTF-8 representation.
312
*
313
* <p> If "CANONICAL" is specified as the format,
314
* this method returns an RFC 2253 conformant string representation
315
* with the following additional canonicalizations:
316
*
317
* <ol>
318
* <li> Leading zeros are removed from attribute types
319
* that are encoded as dotted decimal OIDs
320
* <li> DirectoryString attribute values of type
321
* PrintableString and UTF8String are not
322
* output in hexadecimal format
323
* <li> DirectoryString attribute values of types
324
* other than PrintableString and UTF8String
325
* are output in hexadecimal format
326
* <li> Leading and trailing white space characters
327
* are removed from non-hexadecimal attribute values
328
* (unless the value consists entirely of white space characters)
329
* <li> Internal substrings of one or more white space characters are
330
* converted to a single space in non-hexadecimal
331
* attribute values
332
* <li> Relative Distinguished Names containing more than one
333
* Attribute Value Assertion (AVA) are output in the
334
* following order: an alphabetical ordering of AVAs
335
* containing standard keywords, followed by a numeric
336
* ordering of AVAs containing OID keywords.
337
* <li> The only characters in attribute values that are escaped are
338
* those which section 2.4 of RFC 2253 states must be escaped
339
* (they are escaped using a preceding backslash character)
340
* <li> The entire name is converted to upper case
341
* using {@code String.toUpperCase(Locale.US)}
342
* <li> The entire name is converted to lower case
343
* using {@code String.toLowerCase(Locale.US)}
344
* <li> The name is finally normalized using normalization form KD,
345
* as described in the Unicode Standard and UAX #15
346
* </ol>
347
*
348
* <p> Additional standard formats may be introduced in the future.
349
*
350
* @param format the format to use
351
*
352
* @return a string representation of this {@code X500Principal}
353
* using the specified format
354
* @throws IllegalArgumentException if the specified format is invalid
355
* or null
356
*/
357
public String getName(String format) {
358
if (format != null) {
359
if (format.equalsIgnoreCase(RFC1779)) {
360
return thisX500Name.getRFC1779Name();
361
} else if (format.equalsIgnoreCase(RFC2253)) {
362
return thisX500Name.getRFC2253Name();
363
} else if (format.equalsIgnoreCase(CANONICAL)) {
364
return thisX500Name.getRFC2253CanonicalName();
365
}
366
}
367
throw new IllegalArgumentException("invalid format specified");
368
}
369
370
/**
371
* Returns a string representation of the X.500 distinguished name
372
* using the specified format. Valid values for the format are
373
* "RFC1779" and "RFC2253" (case insensitive). "CANONICAL" is not
374
* permitted and an {@code IllegalArgumentException} will be thrown.
375
*
376
* <p>This method returns Strings in the format as specified in
377
* {@link #getName(String)} and also emits additional attribute type
378
* keywords for OIDs that have entries in the {@code oidMap}
379
* parameter. OID entries in the oidMap take precedence over the default
380
* OIDs recognized by {@code getName(String)}.
381
* Improperly specified OIDs are ignored; however if an OID
382
* in the name maps to an improperly specified keyword, an
383
* {@code IllegalArgumentException} is thrown.
384
*
385
* <p> Additional standard formats may be introduced in the future.
386
*
387
* <p> Warning: additional attribute type keywords may not be recognized
388
* by other implementations; therefore do not use this method if
389
* you are unsure if these keywords will be recognized by other
390
* implementations.
391
*
392
* @param format the format to use
393
* @param oidMap an OID map, where each key is an object identifier in
394
* String form (a sequence of nonnegative integers separated by periods)
395
* that maps to a corresponding attribute type keyword String.
396
* The map may be empty but never {@code null}.
397
* @return a string representation of this {@code X500Principal}
398
* using the specified format
399
* @throws IllegalArgumentException if the specified format is invalid,
400
* null, or an OID in the name maps to an improperly specified keyword
401
* @throws NullPointerException if {@code oidMap} is {@code null}
402
* @since 1.6
403
*/
404
public String getName(String format, Map<String, String> oidMap) {
405
if (oidMap == null) {
406
throw new NullPointerException
407
(sun.security.util.ResourcesMgr.getString
408
("provided.null.OID.map"));
409
}
410
if (format != null) {
411
if (format.equalsIgnoreCase(RFC1779)) {
412
return thisX500Name.getRFC1779Name(oidMap);
413
} else if (format.equalsIgnoreCase(RFC2253)) {
414
return thisX500Name.getRFC2253Name(oidMap);
415
}
416
}
417
throw new IllegalArgumentException("invalid format specified");
418
}
419
420
/**
421
* Returns the distinguished name in ASN.1 DER encoded form. The ASN.1
422
* notation for this structure is supplied in the documentation for
423
* {@link #X500Principal(byte[] name) X500Principal(byte[] name)}.
424
*
425
* <p>Note that the byte array returned is cloned to protect against
426
* subsequent modifications.
427
*
428
* @return a byte array containing the distinguished name in ASN.1 DER
429
* encoded form
430
*/
431
public byte[] getEncoded() {
432
try {
433
return thisX500Name.getEncoded();
434
} catch (IOException e) {
435
throw new RuntimeException("unable to get encoding", e);
436
}
437
}
438
439
/**
440
* Return a user-friendly string representation of this
441
* {@code X500Principal}.
442
*
443
* @return a string representation of this {@code X500Principal}
444
*/
445
public String toString() {
446
return thisX500Name.toString();
447
}
448
449
/**
450
* Compares the specified {@code Object} with this
451
* {@code X500Principal} for equality.
452
*
453
* <p> Specifically, this method returns {@code true} if
454
* the {@code Object} <i>o</i> is an {@code X500Principal}
455
* and if the respective canonical string representations
456
* (obtained via the {@code getName(X500Principal.CANONICAL)} method)
457
* of this object and <i>o</i> are equal.
458
*
459
* <p> This implementation is compliant with the requirements of RFC 5280.
460
*
461
* @param o Object to be compared for equality with this
462
* {@code X500Principal}
463
*
464
* @return {@code true} if the specified {@code Object} is equal
465
* to this {@code X500Principal}, {@code false} otherwise
466
*/
467
public boolean equals(Object o) {
468
if (this == o) {
469
return true;
470
}
471
if (o instanceof X500Principal == false) {
472
return false;
473
}
474
X500Principal other = (X500Principal)o;
475
return this.thisX500Name.equals(other.thisX500Name);
476
}
477
478
/**
479
* Return a hash code for this {@code X500Principal}.
480
*
481
* <p> The hash code is calculated via:
482
* {@code getName(X500Principal.CANONICAL).hashCode()}
483
*
484
* @return a hash code for this {@code X500Principal}
485
*/
486
public int hashCode() {
487
return thisX500Name.hashCode();
488
}
489
490
/**
491
* Save the X500Principal object to a stream.
492
*
493
* @serialData this {@code X500Principal} is serialized
494
* by writing out its DER-encoded form
495
* (the value of {@code getEncoded} is serialized).
496
*/
497
private void writeObject(java.io.ObjectOutputStream s)
498
throws IOException {
499
s.writeObject(thisX500Name.getEncodedInternal());
500
}
501
502
/**
503
* Reads this object from a stream (i.e., deserializes it).
504
*/
505
private void readObject(java.io.ObjectInputStream s)
506
throws java.io.IOException,
507
java.io.NotActiveException,
508
ClassNotFoundException {
509
510
// re-create thisX500Name
511
thisX500Name = new X500Name((byte[])s.readObject());
512
}
513
}
514
515