001: /*
002: * Copyright 2002-2006 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: import java.io.OutputStream;
030:
031: import java.util.*;
032:
033: import sun.security.util.DerOutputStream;
034: import sun.security.util.DerValue;
035: import sun.security.util.ObjectIdentifier;
036:
037: /**
038: * Represent the CRL Distribution Points Extension (OID = 2.5.29.31).
039: * <p>
040: * The CRL distribution points extension identifies how CRL information
041: * is obtained. The extension SHOULD be non-critical, but the PKIX profile
042: * recommends support for this extension by CAs and applications.
043: * <p>
044: * For PKIX, if the cRLDistributionPoints extension contains a
045: * DistributionPointName of type URI, the following semantics MUST be
046: * assumed: the URI is a pointer to the current CRL for the associated
047: * reasons and will be issued by the associated cRLIssuer. The
048: * expected values for the URI conform to the following rules. The
049: * name MUST be a non-relative URL, and MUST follow the URL syntax and
050: * encoding rules specified in [RFC 1738]. The name must include both
051: * a scheme (e.g., "http" or "ftp") and a scheme-specific-part. The
052: * scheme- specific-part must include a fully qualified domain name or
053: * IP address as the host. As specified in [RFC 1738], the scheme
054: * name is not case-sensitive (e.g., "http" is equivalent to "HTTP").
055: * The host part is also not case-sensitive, but other components of
056: * the scheme-specific-part may be case-sensitive. When comparing
057: * URIs, conforming implementations MUST compare the scheme and host
058: * without regard to case, but assume the remainder of the
059: * scheme-specific-part is case sensitive. Processing rules for other
060: * values are not defined by this specification. If the
061: * distributionPoint omits reasons, the CRL MUST include revocations
062: * for all reasons. If the distributionPoint omits cRLIssuer, the CRL
063: * MUST be issued by the CA that issued the certificate.
064: * <p>
065: * The ASN.1 definition for this is:
066: * <pre>
067: * id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 }
068: *
069: * cRLDistributionPoints ::= {
070: * CRLDistPointsSyntax }
071: *
072: * CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
073: * </pre>
074: * <p>
075: * @author Anne Anderson
076: * @author Andreas Sterbenz
077: * @version 1.13, 05/05/07
078: * @since 1.4.2
079: * @see DistributionPoint
080: * @see Extension
081: * @see CertAttrSet
082: */
083: public class CRLDistributionPointsExtension extends Extension implements
084: CertAttrSet<String> {
085:
086: /**
087: * Identifier for this attribute, to be used with the
088: * get, set, delete methods of Certificate, x509 type.
089: */
090: public static final String IDENT = "x509.info.extensions.CRLDistributionPoints";
091:
092: /**
093: * Attribute name.
094: */
095: public static final String NAME = "CRLDistributionPoints";
096: public static final String POINTS = "points";
097:
098: /**
099: * The List of DistributionPoint objects.
100: */
101: private List<DistributionPoint> distributionPoints;
102:
103: private String extensionName;
104:
105: /**
106: * Create a CRLDistributionPointsExtension from a List of
107: * DistributionPoint; the criticality is set to false.
108: *
109: * @param distributionPoints the list of distribution points
110: * @throws IOException on error
111: */
112: public CRLDistributionPointsExtension(
113: List<DistributionPoint> distributionPoints)
114: throws IOException {
115:
116: this (false, distributionPoints);
117: }
118:
119: /**
120: * Create a CRLDistributionPointsExtension from a List of
121: * DistributionPoint.
122: *
123: * @param isCritical the criticality setting.
124: * @param distributionPoints the list of distribution points
125: * @throws IOException on error
126: */
127: public CRLDistributionPointsExtension(boolean isCritical,
128: List<DistributionPoint> distributionPoints)
129: throws IOException {
130:
131: this (PKIXExtensions.CRLDistributionPoints_Id, isCritical,
132: distributionPoints, NAME);
133: }
134:
135: /**
136: * Creates the extension (also called by the subclass).
137: */
138: protected CRLDistributionPointsExtension(
139: ObjectIdentifier extensionId, boolean isCritical,
140: List<DistributionPoint> distributionPoints,
141: String extensionName) throws IOException {
142:
143: this .extensionId = extensionId;
144: this .critical = isCritical;
145: this .distributionPoints = distributionPoints;
146: encodeThis();
147: this .extensionName = extensionName;
148: }
149:
150: /**
151: * Create the extension from the passed DER encoded value of the same.
152: *
153: * @param critical true if the extension is to be treated as critical.
154: * @param value Array of DER encoded bytes of the actual value.
155: * @exception IOException on error.
156: */
157: public CRLDistributionPointsExtension(Boolean critical, Object value)
158: throws IOException {
159: this (PKIXExtensions.CRLDistributionPoints_Id, critical, value,
160: NAME);
161: }
162:
163: /**
164: * Creates the extension (also called by the subclass).
165: */
166: protected CRLDistributionPointsExtension(
167: ObjectIdentifier extensionId, Boolean critical,
168: Object value, String extensionName) throws IOException {
169:
170: this .extensionId = extensionId;
171: this .critical = critical.booleanValue();
172:
173: if (!(value instanceof byte[])) {
174: throw new IOException("Illegal argument type");
175: }
176:
177: extensionValue = (byte[]) value;
178: DerValue val = new DerValue(extensionValue);
179: if (val.tag != DerValue.tag_Sequence) {
180: throw new IOException("Invalid encoding for "
181: + extensionName + " extension.");
182: }
183: distributionPoints = new ArrayList<DistributionPoint>();
184: while (val.data.available() != 0) {
185: DerValue seq = val.data.getDerValue();
186: DistributionPoint point = new DistributionPoint(seq);
187: distributionPoints.add(point);
188: }
189: this .extensionName = extensionName;
190: }
191:
192: /**
193: * Return the name of this attribute.
194: */
195: public String getName() {
196: return extensionName;
197: }
198:
199: /**
200: * Write the extension to the DerOutputStream.
201: *
202: * @param out the DerOutputStream to write the extension to.
203: * @exception IOException on encoding errors.
204: */
205: public void encode(OutputStream out) throws IOException {
206: encode(out, PKIXExtensions.CRLDistributionPoints_Id, false);
207: }
208:
209: /**
210: * Write the extension to the DerOutputStream.
211: * (Also called by the subclass)
212: */
213: protected void encode(OutputStream out,
214: ObjectIdentifier extensionId, boolean isCritical)
215: throws IOException {
216:
217: DerOutputStream tmp = new DerOutputStream();
218: if (this .extensionValue == null) {
219: this .extensionId = extensionId;
220: this .critical = isCritical;
221: encodeThis();
222: }
223: super .encode(tmp);
224: out.write(tmp.toByteArray());
225: }
226:
227: /**
228: * Set the attribute value.
229: */
230: public void set(String name, Object obj) throws IOException {
231: if (name.equalsIgnoreCase(POINTS)) {
232: if (!(obj instanceof List)) {
233: throw new IOException(
234: "Attribute value should be of type List.");
235: }
236: distributionPoints = (List<DistributionPoint>) obj;
237: } else {
238: throw new IOException("Attribute name [" + name
239: + "] not recognized by " + "CertAttrSet:"
240: + extensionName + ".");
241: }
242: encodeThis();
243: }
244:
245: /**
246: * Get the attribute value.
247: */
248: public Object get(String name) throws IOException {
249: if (name.equalsIgnoreCase(POINTS)) {
250: return distributionPoints;
251: } else {
252: throw new IOException("Attribute name [" + name
253: + "] not recognized by " + "CertAttrSet:"
254: + extensionName + ".");
255: }
256: }
257:
258: /**
259: * Delete the attribute value.
260: */
261: public void delete(String name) throws IOException {
262: if (name.equalsIgnoreCase(POINTS)) {
263: distributionPoints = new ArrayList<DistributionPoint>();
264: } else {
265: throw new IOException("Attribute name [" + name
266: + "] not recognized by " + "CertAttrSet:"
267: + extensionName + ".");
268: }
269: encodeThis();
270: }
271:
272: /**
273: * Return an enumeration of names of attributes existing within this
274: * attribute.
275: */
276: public Enumeration<String> getElements() {
277: AttributeNameEnumeration elements = new AttributeNameEnumeration();
278: elements.addElement(POINTS);
279: return elements.elements();
280: }
281:
282: // Encode this extension value
283: private void encodeThis() throws IOException {
284: if (distributionPoints.isEmpty()) {
285: this .extensionValue = null;
286: } else {
287: DerOutputStream pnts = new DerOutputStream();
288: for (DistributionPoint point : distributionPoints) {
289: point.encode(pnts);
290: }
291: DerOutputStream seq = new DerOutputStream();
292: seq.write(DerValue.tag_Sequence, pnts);
293: this .extensionValue = seq.toByteArray();
294: }
295: }
296:
297: /**
298: * Return the extension as user readable string.
299: */
300: public String toString() {
301: return super .toString() + extensionName + " [\n "
302: + distributionPoints + "]\n";
303: }
304:
305: }
|