Home » openjdk-7 » javax.security » auth » x500 » [javadoc | source]

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

Home » openjdk-7 » javax.security » auth » x500 » [javadoc | source]