summaryrefslogtreecommitdiffstats
path: root/base/util/src/netscape/security/x509/CRLExtensions.java
blob: bdadcc12eb3440ab8d88be32d591808f4dcbcd3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package netscape.security.x509;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import netscape.security.util.DerInputStream;
import netscape.security.util.DerOutputStream;
import netscape.security.util.DerValue;

/**
 * This class defines the CRL Extensions.
 * 
 * @author Hemma Prafullchandra
 * @version 1.4
 */
public class CRLExtensions extends Vector<Extension> {

    /**
     *
     */
    private static final long serialVersionUID = 365767738692986418L;
    private Hashtable<String, Extension> map;

    // Parse the encoded extension
    private void parseExtension(Extension ext) throws X509ExtensionException {
        try {
            Class<?> extClass = OIDMap.getClass(ext.getExtensionId());
            if (extClass == null) { // Unsupported extension
                if (ext.isCritical()) {
                    throw new IOException("Unsupported CRITICAL extension: "
                                          + ext.getExtensionId());
                } else {
                    map.put(ext.getExtensionId().toString(), ext);
                    addElement(ext);
                    return;
                }
            }
            Class<?>[] params = { Boolean.class, Object.class };
            Constructor<?> cons = extClass.getConstructor(params);
            byte[] extData = ext.getExtensionValue();
            int extLen = extData.length;
            Object value = Array.newInstance(byte.class, extLen);

            for (int i = 0; i < extLen; i++) {
                Array.setByte(value, i, extData[i]);
            }
            Object[] passed = new Object[] { new Boolean(ext.isCritical()),
                                                        value };
            CertAttrSet crlExt = (CertAttrSet) cons.newInstance(passed);
            map.put(crlExt.getName(), (Extension) crlExt);
            addElement((Extension) crlExt);

        } catch (InvocationTargetException invk) {
            throw new X509ExtensionException(
                                 invk.getTargetException().getMessage());

        } catch (Exception e) {
            throw new X509ExtensionException(e.toString());
        }
    }

    /**
     * Default constructor.
     */
    public CRLExtensions() {
        map = new Hashtable<String, Extension>();
    }

    /**
     * Create the object, decoding the values from the passed DER stream.
     * 
     * @param in the DerInputStream to read the Extension from.
     * @exception CRLException on decoding errors.
     * @exception X509ExtensionException on extension handling errors.
     */
    public CRLExtensions(DerInputStream in)
            throws CRLException, X509ExtensionException {

        map = new Hashtable<String, Extension>();
        try {
            DerValue[] exts = in.getSequence(5);

            for (int i = 0; i < exts.length; i++) {
                Extension ext = new Extension(exts[i]);
                parseExtension(ext);
            }
        } catch (IOException e) {
            throw new CRLException("Parsing error: " + e.toString());
        }
    }

    /**
     * Decode the extensions from the InputStream.
     * 
     * @param in the InputStream to unmarshal the contents from.
     * @exception CRLException on decoding or validity errors.
     * @exception X509ExtensionException on extension handling errors.
     */
    public void decode(InputStream in)
            throws CRLException, X509ExtensionException {
        try {
            DerValue val = new DerValue(in);
            DerInputStream str = val.toDerInputStream();

            map = new Hashtable<String, Extension>();
            DerValue[] exts = str.getSequence(5);

            for (int i = 0; i < exts.length; i++) {
                Extension ext = new Extension(exts[i]);
                parseExtension(ext);
            }
        } catch (IOException e) {
            throw new CRLException("Parsing error: " + e.toString());
        }
    }

    /**
     * Encode the extensions in DER form to the stream.
     * 
     * @param out the DerOutputStream to marshal the contents to.
     * @param isExplicit the tag indicating whether this is an entry
     *            extension or a CRL extension.
     * @exception CRLException on encoding errors.
     */
    public void encode(OutputStream out, boolean isExplicit)
            throws CRLException {
        try {
            // #381559
            if (size() == 0)
                return;
            DerOutputStream extOut = new DerOutputStream();
            for (int i = 0; i < size(); i++) {
                Object thisOne = elementAt(i);
                if (thisOne instanceof CertAttrSet)
                    ((CertAttrSet) thisOne).encode(extOut);
                else if (thisOne instanceof Extension)
                    ((Extension) thisOne).encode(extOut);
                else
                    throw new CRLException("Illegal extension object");
            }

            DerOutputStream seq = new DerOutputStream();
            seq.write(DerValue.tag_Sequence, extOut);

            DerOutputStream tmp = new DerOutputStream();
            if (isExplicit)
                tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
                                             true, (byte) 0), seq);
            else
                tmp = seq;

            out.write(tmp.toByteArray());
        } catch (IOException e) {
            throw new CRLException("Encoding error: " + e.toString());
        } catch (CertificateException e) {
            throw new CRLException("Encoding error: " + e.toString());
        }
    }

    /**
     * Get the extension with this alias.
     * 
     * @param alias the identifier string for the extension to retrieve.
     * @exception X509ExtensionException on extension handling errors.
     */
    public Extension get(String alias) throws X509ExtensionException {
        X509AttributeName attr = new X509AttributeName(alias);
        String name;
        String id = attr.getPrefix();
        if (id.equalsIgnoreCase(X509CertImpl.NAME)) { // fully qualified
            int index = alias.lastIndexOf(".");
            name = alias.substring(index + 1);
        } else
            name = alias;
        Extension ext = (Extension) map.get(name);
        if (ext == null)
            throw new X509ExtensionException("No extension found with name: "
                                             + alias);
        return ext;
    }

    /**
     * Set the extension value with this alias.
     * 
     * @param alias the identifier string for the extension to set.
     * @param obj the Object to set the extension identified by the
     *            alias.
     * @exception IOException on errors.
     */
    public void set(String alias, Extension obj) throws IOException {
        map.put(alias, obj);
        addElement(obj);
    }

    /**
     * Return an enumeration of names of the extensions.
     * 
     * @return an enumeration of the names of the extensions in this CRL.
     */
    public Enumeration<Extension> getElements() {
        return (map.elements());
    }
}