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