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 */ GeneralName(GeneralNameInterface name)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 */ GeneralName(DerValue encName)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 */ GeneralName(DerValue encName, boolean nameConstraint)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 */ getType()173 public int getType() { 174 return name.getType(); 175 } 176 177 /** 178 * Return the GeneralNameInterface name. 179 */ getName()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 */ toString()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 */ equals(Object other)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 */ hashCode()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 */ encode(DerOutputStream out)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