Home | History | Annotate | Download | only in x509
      1 /*
      2  * Copyright (c) 1998, 2006, 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 
     26 package sun.security.x509;
     27 
     28 import java.io.IOException;
     29 import java.io.OutputStream;
     30 import java.util.*;
     31 
     32 import sun.security.util.*;
     33 
     34 /**
     35  * Represents Netscape Certificate Type Extension.
     36  * The details are defined
     37  * <a href=http://www.netscape.com/eng/security/comm4-cert-exts.html>
     38  * here </a>.
     39  *
     40  * <p>This extension, if present, defines both the purpose
     41  * (e.g., encipherment, signature, certificate signing) and the application
     42  * (e.g., SSL, S/Mime or Object Signing of the key contained in the
     43  * certificate. This extension has been superseded by IETF PKIX extensions
     44  * but is provided here for compatibility reasons.
     45  *
     46  * @author Hemma Prafullchandra
     47  * @see Extension
     48  * @see CertAttrSet
     49  */
     50 
     51 public class NetscapeCertTypeExtension extends Extension
     52 implements CertAttrSet<String> {
     53 
     54     /**
     55      * Identifier for this attribute, to be used with the
     56      * get, set, delete methods of Certificate, x509 type.
     57      */
     58     public static final String IDENT = "x509.info.extensions.NetscapeCertType";
     59 
     60     /**
     61      * Attribute names.
     62      */
     63     public static final String NAME = "NetscapeCertType";
     64     public static final String SSL_CLIENT = "ssl_client";
     65     public static final String SSL_SERVER = "ssl_server";
     66     public static final String S_MIME = "s_mime";
     67     public static final String OBJECT_SIGNING = "object_signing";
     68     public static final String SSL_CA = "ssl_ca";
     69     public static final String S_MIME_CA = "s_mime_ca";
     70     public static final String OBJECT_SIGNING_CA = "object_signing_ca";
     71 
     72     private static final int CertType_data[] = { 2, 16, 840, 1, 113730, 1, 1 };
     73 
     74     /**
     75      * Object identifier for the Netscape-Cert-Type extension.
     76      */
     77     public static ObjectIdentifier NetscapeCertType_Id;
     78 
     79     static {
     80         try {
     81             NetscapeCertType_Id = new ObjectIdentifier(CertType_data);
     82         } catch (IOException ioe) {
     83             // should not happen
     84         }
     85     }
     86 
     87     private boolean[] bitString;
     88 
     89     private static class MapEntry {
     90         String mName;
     91         int mPosition;
     92 
     93         MapEntry(String name, int position) {
     94             mName = name;
     95             mPosition = position;
     96         }
     97     }
     98 
     99     private static MapEntry[] mMapData = {
    100         new MapEntry(SSL_CLIENT, 0),
    101         new MapEntry(SSL_SERVER, 1),
    102         new MapEntry(S_MIME, 2),
    103         new MapEntry(OBJECT_SIGNING, 3),
    104         // note that bit 4 is reserved
    105         new MapEntry(SSL_CA, 5),
    106         new MapEntry(S_MIME_CA, 6),
    107         new MapEntry(OBJECT_SIGNING_CA, 7),
    108     };
    109 
    110     private static final Vector<String> mAttributeNames = new Vector<String>();
    111     static {
    112         for (MapEntry entry : mMapData) {
    113             mAttributeNames.add(entry.mName);
    114         }
    115     }
    116 
    117     private static int getPosition(String name) throws IOException {
    118         for (int i = 0; i < mMapData.length; i++) {
    119             if (name.equalsIgnoreCase(mMapData[i].mName))
    120                 return mMapData[i].mPosition;
    121         }
    122         throw new IOException("Attribute name [" + name
    123                              + "] not recognized by CertAttrSet:NetscapeCertType.");
    124     }
    125 
    126     // Encode this extension value
    127     private void encodeThis() throws IOException {
    128         DerOutputStream os = new DerOutputStream();
    129         os.putTruncatedUnalignedBitString(new BitArray(this.bitString));
    130         this.extensionValue = os.toByteArray();
    131     }
    132 
    133     /**
    134      * Check if bit is set.
    135      *
    136      * @param position the position in the bit string to check.
    137      */
    138     private boolean isSet(int position) {
    139         return bitString[position];
    140     }
    141 
    142     /**
    143      * Set the bit at the specified position.
    144      */
    145     private void set(int position, boolean val) {
    146         // enlarge bitString if necessary
    147         if (position >= bitString.length) {
    148             boolean[] tmp = new boolean[position+1];
    149             System.arraycopy(bitString, 0, tmp, 0, bitString.length);
    150             bitString = tmp;
    151         }
    152         bitString[position] = val;
    153     }
    154 
    155     /**
    156      * Create a NetscapeCertTypeExtension with the passed bit settings.
    157      * The criticality is set to true.
    158      *
    159      * @param bitString the bits to be set for the extension.
    160      */
    161     public NetscapeCertTypeExtension(byte[] bitString) throws IOException {
    162         this.bitString =
    163             new BitArray(bitString.length*8, bitString).toBooleanArray();
    164         this.extensionId = NetscapeCertType_Id;
    165         this.critical = true;
    166         encodeThis();
    167     }
    168 
    169     /**
    170      * Create a NetscapeCertTypeExtension with the passed bit settings.
    171      * The criticality is set to true.
    172      *
    173      * @param bitString the bits to be set for the extension.
    174      */
    175     public NetscapeCertTypeExtension(boolean[] bitString) throws IOException {
    176         this.bitString = bitString;
    177         this.extensionId = NetscapeCertType_Id;
    178         this.critical = true;
    179         encodeThis();
    180     }
    181 
    182     /**
    183      * Create the extension from the passed DER encoded value of the same.
    184      *
    185      * @param critical true if the extension is to be treated as critical.
    186      * @param value an array of DER encoded bytes of the actual value.
    187      * @exception ClassCastException if value is not an array of bytes
    188      * @exception IOException on error.
    189      */
    190     public NetscapeCertTypeExtension(Boolean critical, Object value)
    191     throws IOException {
    192         this.extensionId = NetscapeCertType_Id;
    193         this.critical = critical.booleanValue();
    194         this.extensionValue = (byte[]) value;
    195         DerValue val = new DerValue(this.extensionValue);
    196         this.bitString = val.getUnalignedBitString().toBooleanArray();
    197     }
    198 
    199     /**
    200      * Create a default key usage.
    201      */
    202     public NetscapeCertTypeExtension() {
    203         extensionId = NetscapeCertType_Id;
    204         critical = true;
    205         bitString = new boolean[0];
    206     }
    207 
    208     /**
    209      * Set the attribute value.
    210      */
    211     public void set(String name, Object obj) throws IOException {
    212         if (!(obj instanceof Boolean))
    213             throw new IOException("Attribute must be of type Boolean.");
    214 
    215         boolean val = ((Boolean)obj).booleanValue();
    216         set(getPosition(name), val);
    217         encodeThis();
    218     }
    219 
    220     /**
    221      * Get the attribute value.
    222      */
    223     public Object get(String name) throws IOException {
    224         return Boolean.valueOf(isSet(getPosition(name)));
    225     }
    226 
    227     /**
    228      * Delete the attribute value.
    229      */
    230     public void delete(String name) throws IOException {
    231         set(getPosition(name), false);
    232         encodeThis();
    233     }
    234 
    235     /**
    236      * Returns a printable representation of the NetscapeCertType.
    237      */
    238     public String toString() {
    239         String s = super.toString() + "NetscapeCertType [\n";
    240 
    241         try {
    242            if (isSet(getPosition(SSL_CLIENT)))
    243                s += "   SSL client\n";
    244            if (isSet(getPosition(SSL_SERVER)))
    245                s += "   SSL server\n";
    246            if (isSet(getPosition(S_MIME)))
    247                s += "   S/MIME\n";
    248            if (isSet(getPosition(OBJECT_SIGNING)))
    249                s += "   Object Signing\n";
    250            if (isSet(getPosition(SSL_CA)))
    251                s += "   SSL CA\n";
    252            if (isSet(getPosition(S_MIME_CA)))
    253                s += "   S/MIME CA\n";
    254            if (isSet(getPosition(OBJECT_SIGNING_CA)))
    255                s += "   Object Signing CA" ;
    256         } catch (Exception e) { }
    257 
    258         s += "]\n";
    259         return (s);
    260     }
    261 
    262     /**
    263      * Write the extension to the DerOutputStream.
    264      *
    265      * @param out the DerOutputStream to write the extension to.
    266      * @exception IOException on encoding errors.
    267      */
    268     public void encode(OutputStream out) throws IOException {
    269         DerOutputStream  tmp = new DerOutputStream();
    270 
    271         if (this.extensionValue == null) {
    272             this.extensionId = NetscapeCertType_Id;
    273             this.critical = true;
    274             encodeThis();
    275         }
    276         super.encode(tmp);
    277         out.write(tmp.toByteArray());
    278     }
    279 
    280     /**
    281      * Return an enumeration of names of attributes existing within this
    282      * attribute.
    283      */
    284     public Enumeration<String> getElements() {
    285         return mAttributeNames.elements();
    286     }
    287 
    288     /**
    289      * Return the name of this attribute.
    290      */
    291     public String getName() {
    292         return (NAME);
    293     }
    294 
    295     /**
    296      * Get a boolean array representing the bits of this extension,
    297      * as it maps to the KeyUsage extension.
    298      * @return the bit values of this extension mapped to the bit values
    299      * of the KeyUsage extension as an array of booleans.
    300      */
    301     public boolean[] getKeyUsageMappedBits() {
    302         KeyUsageExtension keyUsage = new KeyUsageExtension();
    303         Boolean val = Boolean.TRUE;
    304 
    305         try {
    306             if (isSet(getPosition(SSL_CLIENT)) ||
    307                 isSet(getPosition(S_MIME)) ||
    308                 isSet(getPosition(OBJECT_SIGNING)))
    309                 keyUsage.set(keyUsage.DIGITAL_SIGNATURE, val);
    310 
    311             if (isSet(getPosition(SSL_SERVER)))
    312                 keyUsage.set(keyUsage.KEY_ENCIPHERMENT, val);
    313 
    314             if (isSet(getPosition(SSL_CA)) ||
    315                 isSet(getPosition(S_MIME_CA)) ||
    316                 isSet(getPosition(OBJECT_SIGNING_CA)))
    317                 keyUsage.set(keyUsage.KEY_CERTSIGN, val);
    318         } catch (IOException e) { }
    319         return keyUsage.getBits();
    320     }
    321 }
    322