Home | History | Annotate | Download | only in x509
      1 /*
      2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 package sun.security.x509;
     26 
     27 import java.io.IOException;
     28 import java.io.OutputStream;
     29 import java.security.cert.*;
     30 import java.util.Date;
     31 import java.util.Enumeration;
     32 
     33 import sun.security.util.*;
     34 
     35 /**
     36  * This class defines the interval for which the certificate is valid.
     37  *
     38  * @author Amit Kapoor
     39  * @author Hemma Prafullchandra
     40  * @see CertAttrSet
     41  */
     42 public class CertificateValidity implements CertAttrSet<String> {
     43     /**
     44      * Identifier for this attribute, to be used with the
     45      * get, set, delete methods of Certificate, x509 type.
     46      */
     47     public static final String IDENT = "x509.info.validity";
     48     /**
     49      * Sub attributes name for this CertAttrSet.
     50      */
     51     public static final String NAME = "validity";
     52     public static final String NOT_BEFORE = "notBefore";
     53     public static final String NOT_AFTER = "notAfter";
     54     private static final long YR_2050 = 2524636800000L;
     55 
     56     // Private data members
     57     private Date        notBefore;
     58     private Date        notAfter;
     59 
     60     // Returns the first time the certificate is valid.
     61     private Date getNotBefore() {
     62         return (new Date(notBefore.getTime()));
     63     }
     64 
     65     // Returns the last time the certificate is valid.
     66     private Date getNotAfter() {
     67        return (new Date(notAfter.getTime()));
     68     }
     69 
     70     // Construct the class from the DerValue
     71     private void construct(DerValue derVal) throws IOException {
     72         if (derVal.tag != DerValue.tag_Sequence) {
     73             throw new IOException("Invalid encoded CertificateValidity, " +
     74                                   "starting sequence tag missing.");
     75         }
     76         // check if UTCTime encoded or GeneralizedTime
     77         if (derVal.data.available() == 0)
     78             throw new IOException("No data encoded for CertificateValidity");
     79 
     80         DerInputStream derIn = new DerInputStream(derVal.toByteArray());
     81         DerValue[] seq = derIn.getSequence(2);
     82         if (seq.length != 2)
     83             throw new IOException("Invalid encoding for CertificateValidity");
     84 
     85         if (seq[0].tag == DerValue.tag_UtcTime) {
     86             notBefore = derVal.data.getUTCTime();
     87         } else if (seq[0].tag == DerValue.tag_GeneralizedTime) {
     88             notBefore = derVal.data.getGeneralizedTime();
     89         } else {
     90             throw new IOException("Invalid encoding for CertificateValidity");
     91         }
     92 
     93         if (seq[1].tag == DerValue.tag_UtcTime) {
     94             notAfter = derVal.data.getUTCTime();
     95         } else if (seq[1].tag == DerValue.tag_GeneralizedTime) {
     96             notAfter = derVal.data.getGeneralizedTime();
     97         } else {
     98             throw new IOException("Invalid encoding for CertificateValidity");
     99         }
    100     }
    101 
    102     /**
    103      * Default constructor for the class.
    104      */
    105     public CertificateValidity() { }
    106 
    107     /**
    108      * The default constructor for this class for the specified interval.
    109      *
    110      * @param notBefore the date and time before which the certificate
    111      *                   is not valid.
    112      * @param notAfter the date and time after which the certificate is
    113      *                  not valid.
    114      */
    115     public CertificateValidity(Date notBefore, Date notAfter) {
    116         this.notBefore = notBefore;
    117         this.notAfter = notAfter;
    118     }
    119 
    120     /**
    121      * Create the object, decoding the values from the passed DER stream.
    122      *
    123      * @param in the DerInputStream to read the CertificateValidity from.
    124      * @exception IOException on decoding errors.
    125      */
    126     public CertificateValidity(DerInputStream in) throws IOException {
    127         DerValue derVal = in.getDerValue();
    128         construct(derVal);
    129     }
    130 
    131     /**
    132      * Return the validity period as user readable string.
    133      */
    134     public String toString() {
    135         if (notBefore == null || notAfter == null)
    136             return "";
    137         return ("Validity: [From: " + notBefore.toString() +
    138              ",\n               To: " + notAfter.toString() + "]");
    139     }
    140 
    141     /**
    142      * Encode the CertificateValidity period in DER form to the stream.
    143      *
    144      * @param out the OutputStream to marshal the contents to.
    145      * @exception IOException on errors.
    146      */
    147     public void encode(OutputStream out) throws IOException {
    148 
    149         // in cases where default constructor is used check for
    150         // null values
    151         if (notBefore == null || notAfter == null) {
    152             throw new IOException("CertAttrSet:CertificateValidity:" +
    153                                   " null values to encode.\n");
    154         }
    155         DerOutputStream pair = new DerOutputStream();
    156 
    157         if (notBefore.getTime() < YR_2050) {
    158             pair.putUTCTime(notBefore);
    159         } else
    160             pair.putGeneralizedTime(notBefore);
    161 
    162         if (notAfter.getTime() < YR_2050) {
    163             pair.putUTCTime(notAfter);
    164         } else {
    165             pair.putGeneralizedTime(notAfter);
    166         }
    167         DerOutputStream seq = new DerOutputStream();
    168         seq.write(DerValue.tag_Sequence, pair);
    169 
    170         out.write(seq.toByteArray());
    171     }
    172 
    173     /**
    174      * Set the attribute value.
    175      */
    176     public void set(String name, Object obj) throws IOException {
    177         if (!(obj instanceof Date)) {
    178             throw new IOException("Attribute must be of type Date.");
    179         }
    180         if (name.equalsIgnoreCase(NOT_BEFORE)) {
    181             notBefore = (Date)obj;
    182         } else if (name.equalsIgnoreCase(NOT_AFTER)) {
    183             notAfter = (Date)obj;
    184         } else {
    185             throw new IOException("Attribute name not recognized by " +
    186                             "CertAttrSet: CertificateValidity.");
    187         }
    188     }
    189 
    190     /**
    191      * Get the attribute value.
    192      */
    193     public Date get(String name) throws IOException {
    194         if (name.equalsIgnoreCase(NOT_BEFORE)) {
    195             return (getNotBefore());
    196         } else if (name.equalsIgnoreCase(NOT_AFTER)) {
    197             return (getNotAfter());
    198         } else {
    199             throw new IOException("Attribute name not recognized by " +
    200                             "CertAttrSet: CertificateValidity.");
    201         }
    202     }
    203 
    204     /**
    205      * Delete the attribute value.
    206      */
    207     public void delete(String name) throws IOException {
    208         if (name.equalsIgnoreCase(NOT_BEFORE)) {
    209             notBefore = null;
    210         } else if (name.equalsIgnoreCase(NOT_AFTER)) {
    211             notAfter = null;
    212         } else {
    213             throw new IOException("Attribute name not recognized by " +
    214                             "CertAttrSet: CertificateValidity.");
    215         }
    216     }
    217 
    218     /**
    219      * Return an enumeration of names of attributes existing within this
    220      * attribute.
    221      */
    222     public Enumeration<String> getElements() {
    223         AttributeNameEnumeration elements = new AttributeNameEnumeration();
    224         elements.addElement(NOT_BEFORE);
    225         elements.addElement(NOT_AFTER);
    226 
    227         return (elements.elements());
    228     }
    229 
    230     /**
    231      * Return the name of this attribute.
    232      */
    233     public String getName() {
    234         return (NAME);
    235     }
    236 
    237     /**
    238      * Verify that the current time is within the validity period.
    239      *
    240      * @exception CertificateExpiredException if the certificate has expired.
    241      * @exception CertificateNotYetValidException if the certificate is not
    242      * yet valid.
    243      */
    244     public void valid()
    245     throws CertificateNotYetValidException, CertificateExpiredException {
    246         Date now = new Date();
    247         valid(now);
    248     }
    249 
    250     /**
    251      * Verify that the passed time is within the validity period.
    252      * @param now the Date against which to compare the validity
    253      * period.
    254      *
    255      * @exception CertificateExpiredException if the certificate has expired
    256      * with respect to the <code>Date</code> supplied.
    257      * @exception CertificateNotYetValidException if the certificate is not
    258      * yet valid with respect to the <code>Date</code> supplied.
    259      *
    260      */
    261     public void valid(Date now)
    262     throws CertificateNotYetValidException, CertificateExpiredException {
    263         /*
    264          * we use the internal Dates rather than the passed in Date
    265          * because someone could override the Date methods after()
    266          * and before() to do something entirely different.
    267          */
    268         if (notBefore.after(now)) {
    269             throw new CertificateNotYetValidException("NotBefore: " +
    270                                                       notBefore.toString());
    271         }
    272         if (notAfter.before(now)) {
    273             throw new CertificateExpiredException("NotAfter: " +
    274                                                   notAfter.toString());
    275         }
    276     }
    277 }
    278