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