/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Note: As of 1.4, the public class,
* javax.security.auth.x500.X500Principal,
* should be used when parsing, generating, and comparing X.500 DNs.
* This class contains other useful methods for checking name constraints
* and retrieving DNs by keyword.
*
* <p> X.500 names are used to identify entities, such as those which are
* identified by X.509 certificates. They are world-wide, hierarchical,
* and descriptive. Entities can be identified by attributes, and in
* some systems can be searched for according to those attributes.
* <p>
* The ASN.1 for this is:
* <pre>
* GeneralName ::= CHOICE {
* ....
* directoryName [4] Name,
* ....
* Name ::= CHOICE {
* RDNSequence }
*
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
*
* RelativeDistinguishedName ::=
* SET OF AttributeTypeAndValue
*
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
*
* AttributeType ::= OBJECT IDENTIFIER
*
* AttributeValue ::= ANY DEFINED BY AttributeType
* ....
* DirectoryString ::= CHOICE {
* teletexString TeletexString (SIZE (1..MAX)),
* printableString PrintableString (SIZE (1..MAX)),
* universalString UniversalString (SIZE (1..MAX)),
* utf8String UTF8String (SIZE (1.. MAX)),
* bmpString BMPString (SIZE (1..MAX)) }
* </pre>
* <p>
* This specification requires only a subset of the name comparison
* functionality specified in the X.500 series of specifications. The
* requirements for conforming implementations are as follows:
* <ol TYPE=a>
* <li>attribute values encoded in different types (e.g.,
* PrintableString and BMPString) may be assumed to represent
* different strings;
* <p>
* <li>attribute values in types other than PrintableString are case
* sensitive (this permits matching of attribute values as binary
* objects);
* <p>
* <li>attribute values in PrintableString are not case sensitive
* (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and
* <p>
* <li>attribute values in PrintableString are compared after
* removing leading and trailing white space and converting internal
* substrings of one or more consecutive white space characters to a
* single space.
* </ol>
* <p>
* These name comparison rules permit a certificate user to validate
* certificates issued using languages or encodings unfamiliar to the
* certificate user.
* <p>
* In addition, implementations of this specification MAY use these
* comparison rules to process unfamiliar attribute types for name
* chaining. This allows implementations to process certificates with
* unfamiliar attributes in the issuer name.
* <p>
* Note that the comparison rules defined in the X.500 series of
* specifications indicate that the character sets used to encode data
* in distinguished names are irrelevant. The characters themselves are
* compared without regard to encoding. Implementations of the profile
* are permitted to use the comparison algorithm defined in the X.500
* series. Such an implementation will recognize a superset of name
* matches recognized by the algorithm specified above.
* <p>
* Note that instances of this class are immutable.
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @see GeneralName
* @see GeneralNames
* @see GeneralNameInterface
*/
private byte[] encoded;
// cached immutable list of the RDNs and all the AVAs
/**
* Constructs a name from a conventionally formatted string, such
* as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US".
* (RFC 1779 or RFC 2253 style).
*
* @param DN X.500 Distinguished Name
*/
}
/**
* Constructs a name from a conventionally formatted string, such
* as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US".
* (RFC 1779 or RFC 2253 style).
*
* @param DN X.500 Distinguished Name
*/
throws IOException {
}
/**
* Constructs a name from a string formatted according to format.
* Currently, the formats DEFAULT and RFC2253 are supported.
* DEFAULT is the default format used by the X500Name(String)
* constructor. RFC2253 is format strictly according to RFC2253
* without extensions.
*
* @param DN X.500 Distinguished Name
*/
throw new NullPointerException("Name must not be null");
}
} else {
}
}
/**
* Constructs a name from fields common in enterprise application
* environments.
*
* <P><EM><STRONG>NOTE:</STRONG> The behaviour when any of
* these strings contain characters outside the ASCII range
* is unspecified in currently relevant standards.</EM>
*
* @param commonName common name of a person, e.g. "Vivette Davis"
* @param organizationUnit small organization name, e.g. "Purchasing"
* @param organizationName large organization name, e.g. "Onizuka, Inc."
* @param country two letter country code, e.g. "CH"
*/
throws IOException {
/*
* NOTE: it's only on output that little-endian
* ordering is used.
*/
new DerValue(commonName));
new DerValue(organizationUnit));
new DerValue(organizationName));
}
/**
* Constructs a name from fields common in Internet application
* environments.
*
* <P><EM><STRONG>NOTE:</STRONG> The behaviour when any of
* these strings contain characters outside the ASCII range
* is unspecified in currently relevant standards.</EM>
*
* @param commonName common name of a person, e.g. "Vivette Davis"
* @param organizationUnit small organization name, e.g. "Purchasing"
* @param organizationName large organization name, e.g. "Onizuka, Inc."
* @param localityName locality (city) name, e.g. "Palo Alto"
* @param stateName state name, e.g. "California"
* @param country two letter country code, e.g. "CH"
*/
throws IOException {
/*
* NOTE: it's only on output that little-endian
* ordering is used.
*/
new DerValue(commonName));
new DerValue(organizationUnit));
new DerValue(organizationName));
new DerValue(localityName));
}
/**
* Constructs a name from an array of relative distinguished names
*
* @param rdnArray array of relative distinguished names
* @throws IOException on error
*/
} else {
throw new IOException("Cannot create an X500Name");
}
}
}
}
/**
* Constructs a name from an ASN.1 encoded value. The encoding
* of the name in the stream uses DER (a BER/1 subset).
*
* @param value a DER-encoded value holding an X.500 name.
*/
//Note that toDerInputStream uses only the buffer (data) and not
//the tag, so an empty SEQUENCE (OF) will yield an empty DerInputStream
this(value.toDerInputStream());
}
/**
* Constructs a name from an ASN.1 encoded input stream. The encoding
* of the name in the stream uses DER (a BER/1 subset).
*
* @param in DER-encoded data holding an X.500 name.
*/
}
/**
* Constructs a name from an ASN.1 encoded byte array.
*
* @param name DER-encoded byte array holding an X.500 name.
*/
}
/**
* Return an immutable List of all RDNs in this X500Name.
*/
}
return list;
}
/**
* Return the number of RDNs in this X500Name.
*/
public int size() {
}
/**
* Return an immutable List of the the AVAs contained in all the
* RDNs of this X500Name.
*/
}
}
return list;
}
/**
* Return the total number of AVAs contained in all the RDNs of
* this X500Name.
*/
public int avaSize() {
}
/**
* Return whether this X500Name is empty. An X500Name is not empty
* if it has at least one RDN containing at least one AVA.
*/
public boolean isEmpty() {
if (n == 0) {
return true;
}
for (int i = 0; i < n; i++) {
return false;
}
}
return true;
}
/**
* Calculates a hash code value for the object. Objects
* which are equal will also have the same hashcode.
*/
public int hashCode() {
return getRFC2253CanonicalName().hashCode();
}
/**
* Compares this name with another, for equality.
*
* @return true iff the names are identical.
*/
if (this == obj) {
return true;
}
return false;
}
// if we already have the canonical forms, compare now
}
// quick check that number of RDNs and AVAs match before canonicalizing
return false;
}
for (int i = 0; i < n; i++) {
return false;
}
}
// definite check via canonical form
}
/*
* Returns the name component as a Java string, regardless of its
* encoding restrictions.
*/
return null;
throw new IOException("not a DER string encoding, "
else
return value;
}
/**
* Return type of GeneralName.
*/
public int getType() {
return (GeneralNameInterface.NAME_DIRECTORY);
}
/**
* Returns a "Country" name component. If more than one
* such attribute exists, the topmost one is returned.
*
* @return "C=" component of the name, if any.
*/
}
/**
* Returns an "Organization" name component. If more than
* one such attribute exists, the topmost one is returned.
*
* @return "O=" component of the name, if any.
*/
}
/**
* Returns an "Organizational Unit" name component. If more
* than one such attribute exists, the topmost one is returned.
*
* @return "OU=" component of the name, if any.
*/
}
/**
* Returns a "Common Name" component. If more than one such
* attribute exists, the topmost one is returned.
*
* @return "CN=" component of the name, if any.
*/
}
/**
* Returns a "Locality" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "L=" component of the name, if any.
*/
}
/**
* Returns a "State" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "S=" component of the name, if any.
*/
}
/**
* Returns a "Domain" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "DC=" component of the name, if any.
*/
}
/**
* Returns a "DN Qualifier" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "DNQ=" component of the name, if any.
*/
}
/**
* Returns a "Surname" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "SURNAME=" component of the name, if any.
*/
}
/**
* Returns a "Given Name" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "GIVENNAME=" component of the name, if any.
*/
}
/**
* Returns an "Initials" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "INITIALS=" component of the name, if any.
*/
}
/**
* Returns a "Generation Qualifier" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "GENERATION=" component of the name, if any.
*/
}
/**
* Returns an "IP address" name component. If more than one
* such component exists, the topmost one is returned.
*
* @return "IP=" component of the name, if any.
*/
}
/**
* Returns a string form of the X.500 distinguished name.
* The format of the string is from RFC 1779. The returned string
* may contain non-standardised keywords for more readability
* (keywords from RFCs 1779, 2253, and 3280).
*/
generateDN();
}
return dn;
}
/**
* Returns a string form of the X.500 distinguished name
* using the algorithm defined in RFC 1779. Only standard attribute type
* keywords defined in RFC 1779 are emitted.
*/
}
/**
* Returns a string form of the X.500 distinguished name
* using the algorithm defined in RFC 1779. Attribute type
* keywords defined in RFC 1779 are emitted, as well as additional
*/
throws IllegalArgumentException {
// return cached result
return rfc1779Dn;
} else {
return rfc1779Dn;
}
}
return generateRFC1779DN(oidMap);
}
/**
* Returns a string form of the X.500 distinguished name
* using the algorithm defined in RFC 2253. Only standard attribute type
* keywords defined in RFC 2253 are emitted.
*/
}
/**
* Returns a string form of the X.500 distinguished name
* using the algorithm defined in RFC 2253. Attribute type
* keywords defined in RFC 2253 are emitted, as well as additional
*/
/* check for and return cached name */
return rfc2253Dn;
} else {
return rfc2253Dn;
}
}
return generateRFC2253DN(oidMap);
}
/*
* Section 2.1 : if the RDNSequence is an empty sequence
* the result is the empty or zero length string.
*/
return "";
}
/*
* 2.1 (continued) : Otherwise, the output consists of the string
* encodings of each RelativeDistinguishedName in the RDNSequence
* (according to 2.2), starting with the last element of the sequence
* and moving backwards toward the first.
*
* The encodings of adjoining RelativeDistinguishedNames are separated
* by a comma character (',' ASCII 44).
*/
}
}
}
/* check for and return cached name */
if (canonicalDn != null) {
return canonicalDn;
}
/*
* Section 2.1 : if the RDNSequence is an empty sequence
* the result is the empty or zero length string.
*/
canonicalDn = "";
return canonicalDn;
}
/*
* 2.1 (continued) : Otherwise, the output consists of the string
* encodings of each RelativeDistinguishedName in the RDNSequence
* (according to 2.2), starting with the last element of the sequence
* and moving backwards toward the first.
*
* The encodings of adjoining RelativeDistinguishedNames are separated
* by a comma character (',' ASCII 44).
*/
}
}
return canonicalDn;
}
/**
* Returns the value of toString(). This call is needed to
* implement the java.security.Principal interface.
*/
/**
* Find the first instance of this attribute in a "top down"
* search of all the attributes in the name.
*/
return value;
}
}
}
return null;
}
/**
* Find the most specific ("last") attribute of the given
* type.
*/
return value;
}
}
}
return null;
}
/****************************************************************/
//
// X.500 names are a "SEQUENCE OF" RDNs, which means zero or
// more and order matters. We scan them in order, which
// conventionally is big-endian.
//
try {
} catch (IOException ioe) {
} else {
derBytes);
}
}
} else {
}
}
}
/**
* Encodes the name in DER-encoded form.
*
* @deprecated Use encode() instead
* @param out where to put the DER-encoded X.500 name
*/
}
/**
* Encodes the name in DER-encoded form.
*
* @param out where to put the DER-encoded X.500 name
*/
}
}
/**
* Returned the encoding as an uncloned byte array. Callers must
* guarantee that they neither modify it not expose it to untrusted
* code.
*/
}
}
return encoded;
}
/**
* Gets the name in DER-encoded form.
*
* @return the DER encoded byte array of this name.
*/
return getEncodedInternal().clone();
}
/*
* Parses a Distinguished Name (DN) in printable representation.
*
* According to RFC 1779, RDNs in a DN are separated by comma.
* The following examples show both methods of quoting a comma, so that it
* is not considered a separator:
*
* O="Sue, Grabbit and Runn" or
* O=Sue\, Grabbit and Runn
*
* This method can parse 1779 or 2253 DNs and non-standard 3280 keywords.
*/
throws IOException {
return;
}
int dnOffset = 0;
int rdnEnd;
int quoteCount = 0;
int searchOffset = 0;
if (nextSemiColon < 0) {
} else if (nextComma < 0) {
} else {
}
/*
* We have encountered an RDN delimiter (comma or a semicolon).
* If the comma or semicolon in the RDN under consideration is
* preceded by a backslash (escape), or by a double quote, it
* is part of the RDN. Otherwise, it is used as a separator, to
* delimit the RDN under consideration from any subsequent RDNs.
*/
/*
*/
// Parse RDN, and store it in vector
// Increase the offset
// Set quote counter back to zero
quoteCount = 0;
}
}
// Parse last or only RDN, and store it in vector
/*
* Store the vector elements as an array of RDNs
* NOTE: It's only on output that little-endian ordering is used.
*/
}
return;
}
int dnOffset = 0;
int searchOffset = 0;
while (rdnEnd >=0) {
/*
* We have encountered an RDN delimiter (comma).
* If the comma in the RDN under consideration is
* preceded by a backslash (escape), it
* is part of the RDN. Otherwise, it is used as a separator, to
* delimit the RDN under consideration from any subsequent RDNs.
*/
/*
* Comma is a separator
*/
// Parse RDN, and store it in vector
// Increase the offset
}
}
// Parse last or only RDN, and store it in vector
/*
* Store the vector elements as an array of RDNs
* NOTE: It's only on output that little-endian ordering is used.
*/
}
/*
* Counts double quotes in string.
* Escaped quotes are ignored.
*/
int count = 0;
count++;
}
}
return count;
}
private static boolean escaped
// case 1:
// \,
return true;
// case 2:
// foo\,
return true;
// case 3:
// foo\\\\\,
int count = 0;
rdnEnd--; // back up to last backSlash
while (rdnEnd >= searchOffset) {
count++; // count consecutive backslashes
}
rdnEnd--;
}
// if count is odd, then rdnEnd is escaped
} else {
return false;
}
}
/*
* Dump the printable form of a distinguished name. Each relative
* name is separated from the next by a ",", and assertions in the
* relative names have "label=value" syntax.
*
* Uses RFC 1779 syntax (i.e. little-endian, comma separators)
*/
private void generateDN() {
return;
}
}
}
}
}
/*
* Dump the printable form of a distinguished name. Each relative
* name is separated from the next by a ",", and assertions in the
* relative names have "label=value" syntax.
*
* Uses RFC 1779 syntax (i.e. little-endian, comma separators)
* Valid keywords from RFC 1779 are used. Additional keywords can be
*/
}
}
}
}
}
/****************************************************************/
/*
* Maybe return a preallocated OID, to reduce storage costs
* and speed recognition of common X.500 attributes.
*/
return interned;
}
return oid;
}
/*
* Selected OIDs from X.520
* Includes all those specified in RFC 3280 as MUST or SHOULD
* be recognized
*/
private static final int DOMAIN_COMPONENT_DATA[] =
{ 0, 9, 2342, 19200300, 100, 1, 25 };
private static final int userid_data[] =
{ 0, 9, 2342, 19200300, 100, 1, 1 };
static {
/** OID for the "CN=" attribute, denoting a person's common name. */
/** OID for the "SERIALNUMBER=" attribute, denoting a serial number for.
a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the
certificate serial number. */
/** OID for the "C=" attribute, denoting a country. */
/** OID for the "L=" attribute, denoting a locality (such as a city) */
/** OID for the "O=" attribute, denoting an organization name */
/** OID for the "OU=" attribute, denoting an organizational unit name */
/** OID for the "S=" attribute, denoting a state (such as Delaware) */
/** OID for the "STREET=" attribute, denoting a street address. */
/** OID for the "T=" attribute, denoting a person's title. */
/** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN
disambiguating information.*/
/** OID for the "SURNAME=" attribute, denoting a person's surname.*/
/** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/
/** OID for the "INITIALS=" attribute, denoting a person's initials.*/
/** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/
/*
* OIDs from other sources which show up in X.500 names we
* expect to deal with often
*/
/** OID for "IP=" IP address attributes, used with SKIP. */
/*
* Domain component OID from RFC 1274, RFC 2247, RFC 3280
*/
/*
* OID for "DC=" domain component attributes, used with DNS names in DN
* format
*/
/** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */
}
/**
* Return constraint type:<ul>
* <li>NAME_DIFF_TYPE = -1: input name is different type from this name
* (i.e. does not constrain)
* <li>NAME_MATCH = 0: input name matches this name
* <li>NAME_NARROWS = 1: input name narrows this name
* <li>NAME_WIDENS = 2: input name widens this name
* <li>NAME_SAME_TYPE = 3: input name does not match or narrow this name,
& but is same type
* </ul>. These results are used in checking NameConstraints during
* certification path verification.
*
* @param inputName to be checked for being constrained
* @returns constraint type above
* @throws UnsupportedOperationException if name is not exact match, but
* narrowing and widening are not supported for this name type.
*/
throws UnsupportedOperationException {
int constraintType;
} else { // type == NAME_DIRECTORY
} else if (inputX500.isWithinSubtree(this)) {
} else if (isWithinSubtree(inputX500)) {
} else {
}
}
return constraintType;
}
/**
* Compares this name with another and determines if
* it is within the subtree of the other. Useful for
* checking against the name constraints extension.
*
* @return true iff this name is within the subtree of other.
*/
if (this == other) {
return true;
}
return false;
}
return true;
}
return false;
}
return false;
}
return false;
}
}
return true;
}
/**
* Return subtree depth of this name for purposes of determining
* NameConstraints minimum and maximum bounds and for calculating
* path lengths in name subtrees.
*
* @returns distance of name from root
* @throws UnsupportedOperationException if not supported for this name type
*/
}
/**
* Return lowest common ancestor of this name and other name
*
* @param other another X500Name
* @return X500Name of lowest common ancestor; null if none
*/
return null;
}
return null;
}
//Compare names from highest RDN down the naming tree
//Note that these are stored in RDN[0]...
int i=0;
for (; i < minLen; i++) {
if (i == 0) {
return null;
} else {
break;
}
}
}
//Copy matching RDNs into new RDN array
for (int j=0; j < i; j++) {
}
try {
} catch (IOException ioe) {
return null;
}
return commonAncestor;
}
/**
* Constructor object for use by asX500Principal().
*/
/**
* Field object for use by asX500Name().
*/
/**
* Retrieve the Constructor and Field we need for reflective access
* and make them accessible.
*/
static {
new PrivilegedExceptionAction<Object[]>() {
cons.setAccessible(true);
field.setAccessible(true);
}
};
try {
} catch (Exception e) {
+ "X500Principal access").initCause(e);
}
}
/**
* Get an X500Principal backed by this X500Name.
*
* Note that we are using privileged reflection to access the hidden
* package private constructor in X500Principal.
*/
if (x500Principal == null) {
try {
} catch (Exception e) {
throw new RuntimeException("Unexpected exception", e);
}
}
return x500Principal;
}
/**
* Get the X500Name contained in the given X500Principal.
*
* Note that the X500Name is retrieved using reflection.
*/
try {
name.x500Principal = p;
return name;
} catch (Exception e) {
throw new RuntimeException("Unexpected exception", e);
}
}
}