001: /*
002: * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.security.x509;
027:
028: import java.io.IOException;
029:
030: import sun.security.util.*;
031:
032: /**
033: * This class implements the ASN.1 GeneralName object class.
034: * <p>
035: * The ASN.1 syntax for this is:
036: * <pre>
037: * GeneralName ::= CHOICE {
038: * otherName [0] OtherName,
039: * rfc822Name [1] IA5String,
040: * dNSName [2] IA5String,
041: * x400Address [3] ORAddress,
042: * directoryName [4] Name,
043: * ediPartyName [5] EDIPartyName,
044: * uniformResourceIdentifier [6] IA5String,
045: * iPAddress [7] OCTET STRING,
046: * registeredID [8] OBJECT IDENTIFIER
047: * }
048: * </pre>
049: * @author Amit Kapoor
050: * @author Hemma Prafullchandra
051: * @version 1.27, 05/05/07
052: */
053: public class GeneralName {
054:
055: // Private data members
056: private GeneralNameInterface name = null;
057:
058: /**
059: * Default constructor for the class.
060: *
061: * @param name the selected CHOICE from the list.
062: * @throws NullPointerException if name is null
063: */
064: public GeneralName(GeneralNameInterface name) {
065: if (name == null) {
066: throw new NullPointerException(
067: "GeneralName must not be null");
068: }
069: this .name = name;
070: }
071:
072: /**
073: * Create the object from its DER encoded value.
074: *
075: * @param encName the DER encoded GeneralName.
076: */
077: public GeneralName(DerValue encName) throws IOException {
078: this (encName, false);
079: }
080:
081: /**
082: * Create the object from its DER encoded value.
083: *
084: * @param encName the DER encoded GeneralName.
085: * @param nameConstraint true if general name is a name constraint
086: */
087: public GeneralName(DerValue encName, boolean nameConstraint)
088: throws IOException {
089: short tag = (byte) (encName.tag & 0x1f);
090:
091: // All names except for NAME_DIRECTORY should be encoded with the
092: // IMPLICIT tag.
093: switch (tag) {
094: case GeneralNameInterface.NAME_ANY:
095: if (encName.isContextSpecific() && encName.isConstructed()) {
096: encName.resetTag(DerValue.tag_Sequence);
097: name = new OtherName(encName);
098: } else {
099: throw new IOException("Invalid encoding of Other-Name");
100: }
101: break;
102:
103: case GeneralNameInterface.NAME_RFC822:
104: if (encName.isContextSpecific() && !encName.isConstructed()) {
105: encName.resetTag(DerValue.tag_IA5String);
106: name = new RFC822Name(encName);
107: } else {
108: throw new IOException("Invalid encoding of RFC822 name");
109: }
110: break;
111:
112: case GeneralNameInterface.NAME_DNS:
113: if (encName.isContextSpecific() && !encName.isConstructed()) {
114: encName.resetTag(DerValue.tag_IA5String);
115: name = new DNSName(encName);
116: } else {
117: throw new IOException("Invalid encoding of DNS name");
118: }
119: break;
120:
121: case GeneralNameInterface.NAME_URI:
122: if (encName.isContextSpecific() && !encName.isConstructed()) {
123: encName.resetTag(DerValue.tag_IA5String);
124: name = (nameConstraint ? URIName
125: .nameConstraint(encName) : new URIName(encName));
126: } else {
127: throw new IOException("Invalid encoding of URI");
128: }
129: break;
130:
131: case GeneralNameInterface.NAME_IP:
132: if (encName.isContextSpecific() && !encName.isConstructed()) {
133: encName.resetTag(DerValue.tag_OctetString);
134: name = new IPAddressName(encName);
135: } else {
136: throw new IOException("Invalid encoding of IP address");
137: }
138: break;
139:
140: case GeneralNameInterface.NAME_OID:
141: if (encName.isContextSpecific() && !encName.isConstructed()) {
142: encName.resetTag(DerValue.tag_ObjectId);
143: name = new OIDName(encName);
144: } else {
145: throw new IOException("Invalid encoding of OID name");
146: }
147: break;
148:
149: case GeneralNameInterface.NAME_DIRECTORY:
150: if (encName.isContextSpecific() && encName.isConstructed()) {
151: name = new X500Name(encName.getData());
152: } else {
153: throw new IOException(
154: "Invalid encoding of Directory name");
155: }
156: break;
157:
158: case GeneralNameInterface.NAME_EDI:
159: if (encName.isContextSpecific() && encName.isConstructed()) {
160: encName.resetTag(DerValue.tag_Sequence);
161: name = new EDIPartyName(encName);
162: } else {
163: throw new IOException("Invalid encoding of EDI name");
164: }
165: break;
166:
167: default:
168: throw new IOException("Unrecognized GeneralName tag, ("
169: + tag + ")");
170: }
171: }
172:
173: /**
174: * Return the type of the general name.
175: */
176: public int getType() {
177: return name.getType();
178: }
179:
180: /**
181: * Return the GeneralNameInterface name.
182: */
183: public GeneralNameInterface getName() {
184: //XXXX May want to consider cloning this
185: return name;
186: }
187:
188: /**
189: * Return the name as user readable string
190: */
191: public String toString() {
192: return name.toString();
193: }
194:
195: /**
196: * Compare this GeneralName with another
197: *
198: * @param other GeneralName to compare to this
199: * @returns true if match
200: */
201: public boolean equals(Object other) {
202: if (this == other) {
203: return true;
204: }
205: if (!(other instanceof GeneralName))
206: return false;
207: GeneralNameInterface otherGNI = ((GeneralName) other).name;
208: try {
209: return name.constrains(otherGNI) == GeneralNameInterface.NAME_MATCH;
210: } catch (UnsupportedOperationException ioe) {
211: return false;
212: }
213: }
214:
215: /**
216: * Returns the hash code for this GeneralName.
217: *
218: * @return a hash code value.
219: */
220: public int hashCode() {
221: return name.hashCode();
222: }
223:
224: /**
225: * Encode the name to the specified DerOutputStream.
226: *
227: * @param out the DerOutputStream to encode the the GeneralName to.
228: * @exception IOException on encoding errors.
229: */
230: public void encode(DerOutputStream out) throws IOException {
231: DerOutputStream tmp = new DerOutputStream();
232: name.encode(tmp);
233: int nameType = name.getType();
234: if (nameType == GeneralNameInterface.NAME_ANY
235: || nameType == GeneralNameInterface.NAME_X400
236: || nameType == GeneralNameInterface.NAME_EDI) {
237:
238: // implicit, constructed form
239: out.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
240: true, (byte) nameType), tmp);
241: } else if (nameType == GeneralNameInterface.NAME_DIRECTORY) {
242: // explicit, constructed form since underlying tag is CHOICE
243: // (see X.680 section 30.6, part c)
244: out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
245: (byte) nameType), tmp);
246: } else {
247: // implicit, primitive form
248: out.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
249: false, (byte) nameType), tmp);
250: }
251: }
252: }
|