001: /*
002: * @(#)SubjectAlternativeNameExtension.java 1.21 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: import java.io.InputStream;
032: import java.io.OutputStream;
033: import java.lang.reflect.Array;
034: import java.util.Enumeration;
035:
036: import sun.security.util.*;
037:
038: /**
039: * This represents the Subject Alternative Name Extension.
040: *
041: * This extension, if present, allows the subject to specify multiple
042: * alternative names.
043: *
044: * <p>Extensions are represented as a sequence of the extension identifier
045: * (Object Identifier), a boolean flag stating whether the extension is to
046: * be treated as being critical and the extension value itself (this is again
047: * a DER encoding of the extension value).
048: * <p>
049: * The ASN.1 syntax for this is:
050: * <pre>
051: * SubjectAltName ::= GeneralNames
052: * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
053: * </pre>
054: * @author Amit Kapoor
055: * @author Hemma Prafullchandra
056: * @version 1.14
057: * @see Extension
058: * @see CertAttrSet
059: */
060: public class SubjectAlternativeNameExtension extends Extension
061: implements CertAttrSet {
062: /**
063: * Identifier for this attribute, to be used with the
064: * get, set, delete methods of Certificate, x509 type.
065: */
066: public static final String IDENT = "x509.info.extensions.SubjectAlternativeName";
067: /**
068: * Attribute names.
069: */
070: public static final String NAME = "SubjectAlternativeName";
071: public static final String SUBJECT_NAME = "subject_name";
072:
073: // private data members
074: GeneralNames names = null;
075:
076: // Encode this extension
077: private void encodeThis() throws IOException {
078: if (names == null || names.isEmpty()) {
079: this .extensionValue = null;
080: return;
081: }
082: DerOutputStream os = new DerOutputStream();
083: names.encode(os);
084: this .extensionValue = os.toByteArray();
085: }
086:
087: /**
088: * Create a SubjectAlternativeNameExtension with the passed GeneralNames.
089: * The extension is marked non-critical.
090: *
091: * @param names the GeneralNames for the subject.
092: * @exception IOException on error.
093: */
094: public SubjectAlternativeNameExtension(GeneralNames names)
095: throws IOException {
096: this (Boolean.FALSE, names);
097: }
098:
099: /**
100: * Create a SubjectAlternativeNameExtension with the specified
101: * criticality and GeneralNames.
102: *
103: * @param critical true if the extension is to be treated as critical.
104: * @param names the GeneralNames for the subject.
105: * @exception IOException on error.
106: */
107: public SubjectAlternativeNameExtension(Boolean critical,
108: GeneralNames names) throws IOException {
109: this .names = names;
110: this .extensionId = PKIXExtensions.SubjectAlternativeName_Id;
111: this .critical = critical.booleanValue();
112: encodeThis();
113: }
114:
115: /**
116: * Create a default SubjectAlternativeNameExtension. The extension
117: * is marked non-critical.
118: */
119: public SubjectAlternativeNameExtension() {
120: extensionId = PKIXExtensions.SubjectAlternativeName_Id;
121: critical = false;
122: names = new GeneralNames();
123: }
124:
125: /**
126: * Create the extension from the passed DER encoded value.
127: *
128: * @param critical true if the extension is to be treated as critical.
129: * @param value Array of DER encoded bytes of the actual value.
130: * @exception IOException on error.
131: */
132: public SubjectAlternativeNameExtension(Boolean critical,
133: Object value) throws IOException {
134: this .extensionId = PKIXExtensions.SubjectAlternativeName_Id;
135: this .critical = critical.booleanValue();
136:
137: if (!(value instanceof byte[]))
138: throw new IOException("SubjectAlternativeName: "
139: + "Illegal argument type");
140:
141: int len = Array.getLength(value);
142: byte[] extValue = new byte[len];
143: System.arraycopy(value, 0, extValue, 0, len);
144:
145: this .extensionValue = extValue;
146: DerValue val = new DerValue(extValue);
147: if (val.data == null) {
148: names = new GeneralNames();
149: return;
150: }
151:
152: names = new GeneralNames(val);
153: }
154:
155: /**
156: * Returns a printable representation of the SubjectAlternativeName.
157: */
158: public String toString() {
159: return super .toString() + "SubjectAlternativeName [\n"
160: + String.valueOf(names) + "]\n";
161: }
162:
163: /**
164: * Decode the extension from the InputStream.
165: *
166: * @param in the InputStream to unmarshal the contents from.
167: * @exception IOException on decoding or validity errors.
168: */
169: public void decode(InputStream in) throws IOException {
170: throw new IOException("Method not to be called directly.");
171: }
172:
173: /**
174: * Write the extension to the OutputStream.
175: *
176: * @param out the OutputStream to write the extension to.
177: * @exception IOException on encoding errors.
178: */
179: public void encode(OutputStream out) throws IOException {
180: DerOutputStream tmp = new DerOutputStream();
181: if (extensionValue == null) {
182: extensionId = PKIXExtensions.SubjectAlternativeName_Id;
183: critical = false;
184: encodeThis();
185: }
186: super .encode(tmp);
187: out.write(tmp.toByteArray());
188: }
189:
190: /**
191: * Set the attribute value.
192: */
193: public void set(String name, Object obj) throws IOException {
194: if (name.equalsIgnoreCase(SUBJECT_NAME)) {
195: if (!(obj instanceof GeneralNames)) {
196: throw new IOException("Attribute value should be of "
197: + "type GeneralNames.");
198: }
199: names = (GeneralNames) obj;
200: } else {
201: throw new IOException("Attribute name not recognized by "
202: + "CertAttrSet:SubjectAlternativeName.");
203: }
204: encodeThis();
205: }
206:
207: /**
208: * Get the attribute value.
209: */
210: public Object get(String name) throws IOException {
211: if (name.equalsIgnoreCase(SUBJECT_NAME)) {
212: return (names);
213: } else {
214: throw new IOException("Attribute name not recognized by "
215: + "CertAttrSet:SubjectAlternativeName.");
216: }
217: }
218:
219: /**
220: * Delete the attribute value.
221: */
222: public void delete(String name) throws IOException {
223: if (name.equalsIgnoreCase(SUBJECT_NAME)) {
224: names = null;
225: } else {
226: throw new IOException("Attribute name not recognized by "
227: + "CertAttrSet:SubjectAlternativeName.");
228: }
229: encodeThis();
230: }
231:
232: /**
233: * Return an enumeration of names of attributes existing within this
234: * attribute.
235: */
236: public Enumeration getElements() {
237: AttributeNameEnumeration elements = new AttributeNameEnumeration();
238: elements.addElement(SUBJECT_NAME);
239:
240: return (elements.elements());
241: }
242:
243: /**
244: * Return the name of this attribute.
245: */
246: public String getName() {
247: return (NAME);
248: }
249: }
|