Home | History | Annotate | Download | only in x509
      1 /*
      2  * Copyright (c) 2003, 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.util.Enumeration;
     30 
     31 import sun.security.util.DerValue;
     32 import sun.security.util.DerOutputStream;
     33 
     34 /**
     35  * Represents the CRL Certificate Issuer Extension (OID = 2.5.29.29).
     36  * <p>
     37  * The CRL certificate issuer extension identifies the certificate issuer
     38  * associated with an entry in an indirect CRL, i.e. a CRL that has the
     39  * indirectCRL indicator set in its issuing distribution point extension. If
     40  * this extension is not present on the first entry in an indirect CRL, the
     41  * certificate issuer defaults to the CRL issuer. On subsequent entries
     42  * in an indirect CRL, if this extension is not present, the certificate
     43  * issuer for the entry is the same as that for the preceding entry.
     44  * <p>
     45  * If used by conforming CRL issuers, this extension is always
     46  * critical.  If an implementation ignored this extension it could not
     47  * correctly attribute CRL entries to certificates.  PKIX (RFC 3280)
     48  * RECOMMENDS that implementations recognize this extension.
     49  * <p>
     50  * The ASN.1 definition for this is:
     51  * <pre>
     52  * id-ce-certificateIssuer   OBJECT IDENTIFIER ::= { id-ce 29 }
     53  *
     54  * certificateIssuer ::=     GeneralNames
     55  * </pre>
     56  *
     57  * @author Anne Anderson
     58  * @author Sean Mullan
     59  * @since 1.5
     60  * @see Extension
     61  * @see CertAttrSet
     62  */
     63 public class CertificateIssuerExtension extends Extension
     64     implements CertAttrSet<String> {
     65 
     66     /**
     67      * Attribute names.
     68      */
     69     public static final String NAME = "CertificateIssuer";
     70     public static final String ISSUER = "issuer";
     71 
     72     private GeneralNames names;
     73 
     74     /**
     75      * Encode this extension
     76      */
     77     private void encodeThis() throws IOException {
     78         if (names == null || names.isEmpty()) {
     79             this.extensionValue = null;
     80             return;
     81         }
     82         DerOutputStream os = new DerOutputStream();
     83         names.encode(os);
     84         this.extensionValue = os.toByteArray();
     85     }
     86 
     87     /**
     88      * Create a CertificateIssuerExtension containing the specified issuer name.
     89      * Criticality is automatically set to true.
     90      *
     91      * @param issuer the certificate issuer
     92      * @throws IOException on error
     93      */
     94     public CertificateIssuerExtension(GeneralNames issuer) throws IOException {
     95         this.extensionId = PKIXExtensions.CertificateIssuer_Id;
     96         this.critical = true;
     97         this.names = issuer;
     98         encodeThis();
     99     }
    100 
    101     /**
    102      * Create a CertificateIssuerExtension from the specified DER encoded
    103      * value of the same.
    104      *
    105      * @param critical true if the extension is to be treated as critical.
    106      * @param value an array of DER encoded bytes of the actual value
    107      * @throws ClassCastException if value is not an array of bytes
    108      * @throws IOException on error
    109      */
    110     public CertificateIssuerExtension(Boolean critical, Object value)
    111         throws IOException {
    112         this.extensionId = PKIXExtensions.CertificateIssuer_Id;
    113         this.critical = critical.booleanValue();
    114 
    115         this.extensionValue = (byte[]) value;
    116         DerValue val = new DerValue(this.extensionValue);
    117         this.names = new GeneralNames(val);
    118     }
    119 
    120     /**
    121      * Set the attribute value.
    122      *
    123      * @throws IOException on error
    124      */
    125     public void set(String name, Object obj) throws IOException {
    126         if (name.equalsIgnoreCase(ISSUER)) {
    127             if (!(obj instanceof GeneralNames)) {
    128                 throw new IOException("Attribute value must be of type " +
    129                     "GeneralNames");
    130             }
    131             this.names = (GeneralNames)obj;
    132         } else {
    133             throw new IOException("Attribute name not recognized by " +
    134                 "CertAttrSet:CertificateIssuer");
    135         }
    136         encodeThis();
    137     }
    138 
    139     /**
    140      * Gets the attribute value.
    141      *
    142      * @throws IOException on error
    143      */
    144     public GeneralNames get(String name) throws IOException {
    145         if (name.equalsIgnoreCase(ISSUER)) {
    146             return names;
    147         } else {
    148             throw new IOException("Attribute name not recognized by " +
    149                 "CertAttrSet:CertificateIssuer");
    150         }
    151     }
    152 
    153     /**
    154      * Deletes the attribute value.
    155      *
    156      * @throws IOException on error
    157      */
    158     public void delete(String name) throws IOException {
    159         if (name.equalsIgnoreCase(ISSUER)) {
    160             names = null;
    161         } else {
    162             throw new IOException("Attribute name not recognized by " +
    163                 "CertAttrSet:CertificateIssuer");
    164         }
    165         encodeThis();
    166     }
    167 
    168     /**
    169      * Returns a printable representation of the certificate issuer.
    170      */
    171     public String toString() {
    172         return super.toString() + "Certificate Issuer [\n" +
    173             String.valueOf(names) + "]\n";
    174     }
    175 
    176     /**
    177      * Write the extension to the OutputStream.
    178      *
    179      * @param out the OutputStream to write the extension to
    180      * @exception IOException on encoding errors
    181      */
    182     public void encode(OutputStream out) throws IOException {
    183         DerOutputStream  tmp = new DerOutputStream();
    184         if (extensionValue == null) {
    185             extensionId = PKIXExtensions.CertificateIssuer_Id;
    186             critical = true;
    187             encodeThis();
    188         }
    189         super.encode(tmp);
    190         out.write(tmp.toByteArray());
    191     }
    192 
    193     /**
    194      * Return an enumeration of names of attributes existing within this
    195      * attribute.
    196      */
    197     public Enumeration<String> getElements() {
    198         AttributeNameEnumeration elements = new AttributeNameEnumeration();
    199         elements.addElement(ISSUER);
    200         return elements.elements();
    201     }
    202 
    203     /**
    204      * Return the name of this attribute.
    205      */
    206     public String getName() {
    207         return NAME;
    208     }
    209 }
    210