001: /*
002: * @(#)CertificateValidity.java 1.23 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: package sun.security.x509;
028:
029: import java.io.IOException;
030: import java.io.InputStream;
031: import java.io.OutputStream;
032: import java.security.cert.*;
033: import java.util.Date;
034: import java.util.Enumeration;
035:
036: import sun.security.util.*;
037:
038: /**
039: * This class defines the interval for which the certificate is valid.
040: *
041: * @author Amit Kapoor
042: * @author Hemma Prafullchandra
043: * @version 1.16
044: * @see CertAttrSet
045: */
046: public class CertificateValidity implements CertAttrSet {
047: /**
048: * Identifier for this attribute, to be used with the
049: * get, set, delete methods of Certificate, x509 type.
050: */
051: public static final String IDENT = "x509.info.validity";
052: /**
053: * Sub attributes name for this CertAttrSet.
054: */
055: public static final String NAME = "validity";
056: public static final String NOT_BEFORE = "notBefore";
057: public static final String NOT_AFTER = "notAfter";
058: private static final long YR_2050 = 2524636800000L;
059:
060: // Private data members
061: private Date notBefore;
062: private Date notAfter;
063:
064: // Returns the first time the certificate is valid.
065: private Date getNotBefore() {
066: return (new Date(notBefore.getTime()));
067: }
068:
069: // Returns the last time the certificate is valid.
070: private Date getNotAfter() {
071: return (new Date(notAfter.getTime()));
072: }
073:
074: // Construct the class from the DerValue
075: private void construct(DerValue derVal) throws IOException {
076: if (derVal.tag != DerValue.tag_Sequence) {
077: throw new IOException(
078: "Invalid encoded CertificateValidity, "
079: + "starting sequence tag missing.");
080: }
081: // check if UTCTime encoded or GeneralizedTime
082: if (derVal.data.available() == 0)
083: throw new IOException(
084: "No data encoded for CertificateValidity");
085:
086: DerInputStream derIn = new DerInputStream(derVal.toByteArray());
087: DerValue[] seq = derIn.getSequence(2);
088: if (seq.length != 2)
089: throw new IOException(
090: "Invalid encoding for CertificateValidity");
091:
092: if (seq[0].tag == DerValue.tag_UtcTime) {
093: notBefore = derVal.data.getUTCTime();
094: } else if (seq[0].tag == DerValue.tag_GeneralizedTime) {
095: notBefore = derVal.data.getGeneralizedTime();
096: } else {
097: throw new IOException(
098: "Invalid encoding for CertificateValidity");
099: }
100:
101: if (seq[1].tag == DerValue.tag_UtcTime) {
102: notAfter = derVal.data.getUTCTime();
103: } else if (seq[1].tag == DerValue.tag_GeneralizedTime) {
104: notAfter = derVal.data.getGeneralizedTime();
105: } else {
106: throw new IOException(
107: "Invalid encoding for CertificateValidity");
108: }
109: }
110:
111: /**
112: * Default constructor for the class.
113: */
114: public CertificateValidity() {
115: }
116:
117: /**
118: * The default constructor for this class for the specified interval.
119: *
120: * @param notBefore the date and time before which the certificate
121: * is not valid.
122: * @param notAfter the date and time after which the certificate is
123: * not valid.
124: */
125: public CertificateValidity(Date notBefore, Date notAfter) {
126: this .notBefore = notBefore;
127: this .notAfter = notAfter;
128: }
129:
130: /**
131: * Create the object, decoding the values from the passed DER stream.
132: *
133: * @param in the DerInputStream to read the CertificateValidity from.
134: * @exception IOException on decoding errors.
135: */
136: public CertificateValidity(DerInputStream in) throws IOException {
137: DerValue derVal = in.getDerValue();
138: construct(derVal);
139: }
140:
141: /**
142: * Return the validity period as user readable string.
143: */
144: public String toString() {
145: if (notBefore == null || notAfter == null)
146: return "";
147: return ("Validity: [From: " + notBefore.toString()
148: + ",\n To: " + notAfter.toString() + "]");
149: }
150:
151: /**
152: * Decode the CertificateValidity period from the InputStream.
153: *
154: * @param in the InputStream to unmarshal the contents from.
155: * @exception IOException on errors.
156: */
157: public void decode(InputStream in) throws IOException {
158: DerValue derVal = new DerValue(in);
159: construct(derVal);
160: }
161:
162: /**
163: * Encode the CertificateValidity period in DER form to the stream.
164: *
165: * @param out the OutputStream to marshal the contents to.
166: * @exception IOException on errors.
167: */
168: public void encode(OutputStream out) throws IOException {
169:
170: // in cases where default constructor is used check for
171: // null values
172: if (notBefore == null || notAfter == null) {
173: throw new IOException("CertAttrSet:CertificateValidity:"
174: + " null values to encode.\n");
175: }
176: DerOutputStream pair = new DerOutputStream();
177:
178: if (notBefore.getTime() < YR_2050) {
179: pair.putUTCTime(notBefore);
180: } else
181: pair.putGeneralizedTime(notBefore);
182:
183: if (notAfter.getTime() < YR_2050) {
184: pair.putUTCTime(notAfter);
185: } else {
186: pair.putGeneralizedTime(notAfter);
187: }
188: DerOutputStream seq = new DerOutputStream();
189: seq.write(DerValue.tag_Sequence, pair);
190:
191: out.write(seq.toByteArray());
192: }
193:
194: /**
195: * Set the attribute value.
196: */
197: public void set(String name, Object obj) throws IOException {
198: if (!(obj instanceof Date)) {
199: throw new IOException("Attribute must be of type Date.");
200: }
201: if (name.equalsIgnoreCase(NOT_BEFORE)) {
202: notBefore = (Date) obj;
203: } else if (name.equalsIgnoreCase(NOT_AFTER)) {
204: notAfter = (Date) obj;
205: } else {
206: throw new IOException("Attribute name not recognized by "
207: + "CertAttrSet: CertificateValidity.");
208: }
209: }
210:
211: /**
212: * Get the attribute value.
213: */
214: public Object get(String name) throws IOException {
215: if (name.equalsIgnoreCase(NOT_BEFORE)) {
216: return (getNotBefore());
217: } else if (name.equalsIgnoreCase(NOT_AFTER)) {
218: return (getNotAfter());
219: } else {
220: throw new IOException("Attribute name not recognized by "
221: + "CertAttrSet: CertificateValidity.");
222: }
223: }
224:
225: /**
226: * Delete the attribute value.
227: */
228: public void delete(String name) throws IOException {
229: if (name.equalsIgnoreCase(NOT_BEFORE)) {
230: notBefore = null;
231: } else if (name.equalsIgnoreCase(NOT_AFTER)) {
232: notAfter = null;
233: } else {
234: throw new IOException("Attribute name not recognized by "
235: + "CertAttrSet: CertificateValidity.");
236: }
237: }
238:
239: /**
240: * Return an enumeration of names of attributes existing within this
241: * attribute.
242: */
243: public Enumeration getElements() {
244: AttributeNameEnumeration elements = new AttributeNameEnumeration();
245: elements.addElement(NOT_BEFORE);
246: elements.addElement(NOT_AFTER);
247:
248: return (elements.elements());
249: }
250:
251: /**
252: * Return the name of this attribute.
253: */
254: public String getName() {
255: return (NAME);
256: }
257:
258: /**
259: * Verify that the current time is within the validity period.
260: *
261: * @exception CertificateExpiredException if the certificate has expired.
262: * @exception CertificateNotYetValidException if the certificate is not
263: * yet valid.
264: */
265: public void valid() throws CertificateNotYetValidException,
266: CertificateExpiredException {
267: Date now = new Date();
268: valid(now);
269: }
270:
271: /**
272: * Verify that the passed time is within the validity period.
273: * @param now the Date against which to compare the validity
274: * period.
275: *
276: * @exception CertificateExpiredException if the certificate has expired
277: * with respect to the <code>Date</code> supplied.
278: * @exception CertificateNotYetValidException if the certificate is not
279: * yet valid with respect to the <code>Date</code> supplied.
280: *
281: */
282: public void valid(Date now) throws CertificateNotYetValidException,
283: CertificateExpiredException {
284: /*
285: * we use the internal Dates rather than the passed in Date
286: * because someone could override the Date methods after()
287: * and before() to do something entirely different.
288: */
289: if (notBefore.after(now)) {
290: throw new CertificateNotYetValidException("NotBefore: "
291: + notBefore.toString());
292: }
293: if (notAfter.before(now)) {
294: throw new CertificateExpiredException("NotAfter: "
295: + notAfter.toString());
296: }
297: }
298: }
|