Home | History | Annotate | Download | only in x509
      1 /*
      2  * Copyright (c) 1997, 2004, 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.io.IOException;
     29 
     30 import sun.security.util.*;
     31 
     32 /**
     33  * This class implements the ASN.1 GeneralName object class.
     34  * <p>
     35  * The ASN.1 syntax for this is:
     36  * <pre>
     37  * GeneralName ::= CHOICE {
     38  *    otherName                       [0]     OtherName,
     39  *    rfc822Name                      [1]     IA5String,
     40  *    dNSName                         [2]     IA5String,
     41  *    x400Address                     [3]     ORAddress,
     42  *    directoryName                   [4]     Name,
     43  *    ediPartyName                    [5]     EDIPartyName,
     44  *    uniformResourceIdentifier       [6]     IA5String,
     45  *    iPAddress                       [7]     OCTET STRING,
     46  *    registeredID                    [8]     OBJECT IDENTIFIER
     47  * }
     48  * </pre>
     49  * @author Amit Kapoor
     50  * @author Hemma Prafullchandra
     51  */
     52 public class GeneralName {
     53 
     54     // Private data members
     55     private GeneralNameInterface name = null;
     56 
     57     /**
     58      * Default constructor for the class.
     59      *
     60      * @param name the selected CHOICE from the list.
     61      * @throws NullPointerException if name is null
     62      */
     63     public GeneralName(GeneralNameInterface name) {
     64         if (name == null) {
     65             throw new NullPointerException("GeneralName must not be null");
     66         }
     67         this.name = name;
     68     }
     69 
     70     /**
     71      * Create the object from its DER encoded value.
     72      *
     73      * @param encName the DER encoded GeneralName.
     74      */
     75     public GeneralName(DerValue encName) throws IOException {
     76         this(encName, false);
     77     }
     78 
     79     /**
     80      * Create the object from its DER encoded value.
     81      *
     82      * @param encName the DER encoded GeneralName.
     83      * @param nameConstraint true if general name is a name constraint
     84      */
     85     public GeneralName(DerValue encName, boolean nameConstraint)
     86         throws IOException {
     87         short tag = (byte)(encName.tag & 0x1f);
     88 
     89         // All names except for NAME_DIRECTORY should be encoded with the
     90         // IMPLICIT tag.
     91         switch (tag) {
     92         case GeneralNameInterface.NAME_ANY:
     93             if (encName.isContextSpecific() && encName.isConstructed()) {
     94                 encName.resetTag(DerValue.tag_Sequence);
     95                 name = new OtherName(encName);
     96             } else {
     97                 throw new IOException("Invalid encoding of Other-Name");
     98             }
     99             break;
    100 
    101         case GeneralNameInterface.NAME_RFC822:
    102             if (encName.isContextSpecific() && !encName.isConstructed()) {
    103                 encName.resetTag(DerValue.tag_IA5String);
    104                 name = new RFC822Name(encName);
    105             } else {
    106                 throw new IOException("Invalid encoding of RFC822 name");
    107             }
    108             break;
    109 
    110         case GeneralNameInterface.NAME_DNS:
    111             if (encName.isContextSpecific() && !encName.isConstructed()) {
    112                 encName.resetTag(DerValue.tag_IA5String);
    113                 name = new DNSName(encName);
    114             } else {
    115                 throw new IOException("Invalid encoding of DNS name");
    116             }
    117             break;
    118 
    119         case GeneralNameInterface.NAME_URI:
    120             if (encName.isContextSpecific() && !encName.isConstructed()) {
    121                 encName.resetTag(DerValue.tag_IA5String);
    122                 name = (nameConstraint ? URIName.nameConstraint(encName) :
    123                         new URIName(encName));
    124             } else {
    125                 throw new IOException("Invalid encoding of URI");
    126             }
    127             break;
    128 
    129         case GeneralNameInterface.NAME_IP:
    130             if (encName.isContextSpecific() && !encName.isConstructed()) {
    131                 encName.resetTag(DerValue.tag_OctetString);
    132                 name = new IPAddressName(encName);
    133             } else {
    134                 throw new IOException("Invalid encoding of IP address");
    135             }
    136             break;
    137 
    138         case GeneralNameInterface.NAME_OID:
    139             if (encName.isContextSpecific() && !encName.isConstructed()) {
    140                 encName.resetTag(DerValue.tag_ObjectId);
    141                 name = new OIDName(encName);
    142             } else {
    143                 throw new IOException("Invalid encoding of OID name");
    144             }
    145             break;
    146 
    147         case GeneralNameInterface.NAME_DIRECTORY:
    148             if (encName.isContextSpecific() && encName.isConstructed()) {
    149                 name = new X500Name(encName.getData());
    150             } else {
    151                 throw new IOException("Invalid encoding of Directory name");
    152             }
    153             break;
    154 
    155         case GeneralNameInterface.NAME_EDI:
    156             if (encName.isContextSpecific() && encName.isConstructed()) {
    157                 encName.resetTag(DerValue.tag_Sequence);
    158                 name = new EDIPartyName(encName);
    159             } else {
    160                 throw new IOException("Invalid encoding of EDI name");
    161             }
    162             break;
    163 
    164         default:
    165             throw new IOException("Unrecognized GeneralName tag, ("
    166                                   + tag +")");
    167         }
    168     }
    169 
    170     /**
    171      * Return the type of the general name.
    172      */
    173     public int getType() {
    174         return name.getType();
    175     }
    176 
    177     /**
    178      * Return the GeneralNameInterface name.
    179      */
    180     public GeneralNameInterface getName() {
    181         //XXXX May want to consider cloning this
    182         return name;
    183     }
    184 
    185     /**
    186      * Return the name as user readable string
    187      */
    188     public String toString() {
    189         return name.toString();
    190     }
    191 
    192     /**
    193      * Compare this GeneralName with another
    194      *
    195      * @param other GeneralName to compare to this
    196      * @returns true if match
    197      */
    198     public boolean equals(Object other) {
    199         if (this == other) {
    200             return true;
    201         }
    202         if (!(other instanceof GeneralName))
    203             return false;
    204         GeneralNameInterface otherGNI = ((GeneralName)other).name;
    205         try {
    206             return name.constrains(otherGNI) == GeneralNameInterface.NAME_MATCH;
    207         } catch (UnsupportedOperationException ioe) {
    208             return false;
    209         }
    210     }
    211 
    212     /**
    213      * Returns the hash code for this GeneralName.
    214      *
    215      * @return a hash code value.
    216      */
    217     public int hashCode() {
    218         return name.hashCode();
    219     }
    220 
    221     /**
    222      * Encode the name to the specified DerOutputStream.
    223      *
    224      * @param out the DerOutputStream to encode the the GeneralName to.
    225      * @exception IOException on encoding errors.
    226      */
    227     public void encode(DerOutputStream out) throws IOException {
    228         DerOutputStream tmp = new DerOutputStream();
    229         name.encode(tmp);
    230         int nameType = name.getType();
    231         if (nameType == GeneralNameInterface.NAME_ANY ||
    232             nameType == GeneralNameInterface.NAME_X400 ||
    233             nameType == GeneralNameInterface.NAME_EDI) {
    234 
    235             // implicit, constructed form
    236             out.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
    237                               true, (byte)nameType), tmp);
    238         } else if (nameType == GeneralNameInterface.NAME_DIRECTORY) {
    239             // explicit, constructed form since underlying tag is CHOICE
    240             // (see X.680 section 30.6, part c)
    241             out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
    242                                          true, (byte)nameType), tmp);
    243         } else {
    244             // implicit, primitive form
    245             out.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
    246                               false, (byte)nameType), tmp);
    247         }
    248     }
    249 }
    250