001: /*
002: *
003: *
004: * Copyright 1990-2007 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 com.sun.midp.publickeystore;
028:
029: // Explicit list of declarations to avoid CDC conflict
030: // with use of java.io.File
031: import java.io.IOException;
032: import java.io.InputStream;
033: import java.io.OutputStream;
034:
035: import java.util.*;
036:
037: import javax.microedition.io.*;
038: import com.sun.midp.io.j2me.storage.*;
039: import com.sun.midp.midlet.*;
040: import com.sun.midp.security.*;
041: import com.sun.midp.configurator.Constants;
042: import com.sun.midp.log.Logging;
043: import com.sun.midp.log.LogChannels;
044: import com.sun.midp.pki.*;
045:
046: /**
047: * A public keystore that can used with SSL.
048: * To work with SSL this class implements the SSL
049: * {@link CertStore} interface.
050: */
051: public class WebPublicKeyStore extends PublicKeyStore implements
052: CertStore {
053:
054: /**
055: * Inner class to request security token from SecurityInitializer.
056: * SecurityInitializer should be able to check this inner class name.
057: */
058: static private class SecurityTrusted implements
059: ImplicitlyTrustedClass {
060: };
061:
062: /** This class has a different security domain than the MIDlet suite */
063: private static SecurityToken classSecurityToken = SecurityInitializer
064: .requestToken(new SecurityTrusted());
065:
066: /** keystore this package uses for verifying descriptors */
067: private static WebPublicKeyStore trustedKeyStore;
068:
069: /** keystore this package uses for verifying descriptors */
070: private static Vector sharedKeyList;
071:
072: /**
073: * Load the certificate authorities for the MIDP from storage
074: * into the SSL keystore.
075: */
076: public static void loadCertificateAuthorities() {
077: RandomAccessStream storage;
078: InputStream tks;
079: WebPublicKeyStore ks;
080:
081: if (trustedKeyStore != null) {
082: return;
083: }
084:
085: try {
086: storage = new RandomAccessStream(classSecurityToken);
087: storage.connect(File
088: .getStorageRoot(Constants.INTERNAL_STORAGE_ID)
089: + "_main.ks", Connector.READ);
090: tks = storage.openInputStream();
091: } catch (Exception e) {
092: if (Logging.TRACE_ENABLED) {
093: Logging.trace(e,
094: "Could not open the trusted key store, "
095: + "cannot authenticate HTTPS servers");
096: }
097: return;
098: }
099:
100: try {
101: sharedKeyList = new Vector();
102: ks = new WebPublicKeyStore(tks, sharedKeyList);
103: } catch (Exception e) {
104: if (Logging.TRACE_ENABLED) {
105: Logging.trace(e, "Corrupt key store file, cannot"
106: + "authenticate HTTPS servers");
107: }
108: return;
109: } finally {
110: try {
111: storage.disconnect();
112: } catch (Exception e) {
113: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
114: Logging.report(Logging.WARNING,
115: LogChannels.LC_SECURITY,
116: "Exception during diconnect");
117: }
118: }
119: }
120:
121: WebPublicKeyStore.setTrustedKeyStore(ks);
122: }
123:
124: /**
125: * Disable a certificate authority in the trusted keystore.
126: *
127: * @param name name of the authority.
128: */
129: public static void disableCertAuthority(String name) {
130: setCertAuthorityEnabledField(name, false);
131: }
132:
133: /**
134: * Enable a certificate authority in the trusted keystore.
135: *
136: * @param name name of the authority.
137: */
138: public static void enableCertAuthority(String name) {
139: setCertAuthorityEnabledField(name, true);
140: }
141:
142: /**
143: * Disable a certificate authority in the trusted keystore.
144: *
145: * @param name name of the authority.
146: * @param enabled value of enable field
147: */
148: private static void setCertAuthorityEnabledField(String name,
149: boolean enabled) {
150: Vector keys;
151: PublicKeyInfo keyInfo;
152: MIDletSuite midletSuite = MIDletStateHandler
153: .getMidletStateHandler().getMIDletSuite();
154:
155: if (midletSuite == null) {
156: throw new IllegalStateException(
157: "This method can't be called before "
158: + "a suite is started.");
159: }
160:
161: midletSuite.checkIfPermissionAllowed(Permissions.AMS);
162:
163: keys = trustedKeyStore.findKeys(name);
164: if (keys == null || keys.size() <= 0) {
165: return;
166: }
167:
168: for (int i = 0; i < keys.size(); i++) {
169: keyInfo = (PublicKeyInfo) keys.elementAt(i);
170: keyInfo.enabled = enabled;
171: }
172:
173: saveKeyList();
174: }
175:
176: /** Saves the shared key list to main key store. */
177: private static void saveKeyList() {
178: PublicKeyStoreBuilderBase keystore;
179: RandomAccessStream storage;
180: OutputStream outputStream;
181:
182: if (trustedKeyStore == null) {
183: return;
184: }
185:
186: keystore = new PublicKeyStoreBuilderBase(sharedKeyList);
187: try {
188: storage = new RandomAccessStream(classSecurityToken);
189: storage.connect(File
190: .getStorageRoot(Constants.INTERNAL_STORAGE_ID)
191: + "_main.ks",
192: RandomAccessStream.READ_WRITE_TRUNCATE);
193: outputStream = storage.openOutputStream();
194: } catch (Exception e) {
195: if (Logging.TRACE_ENABLED) {
196: Logging.trace(e,
197: "Could not open the trusted key store, "
198: + "cannot authenticate HTTPS servers");
199: }
200: return;
201: }
202:
203: try {
204: keystore.serialize(outputStream);
205: } catch (Exception e) {
206: if (Logging.TRACE_ENABLED) {
207: Logging.trace(e, "Corrupt key store file, cannot"
208: + "authenticate HTTPS servers");
209: }
210:
211: return;
212: } finally {
213: try {
214: storage.disconnect();
215: } catch (Exception e) {
216: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
217: Logging.report(Logging.WARNING,
218: LogChannels.LC_SECURITY,
219: "Exception during diconnect");
220: }
221: }
222: }
223: }
224:
225: /**
226: * Establish the given keystore as the system trusted keystore.
227: * This is a one-shot method, it will only set the trusted keystore
228: * it there is no keystore set. For security purposes only
229: * read-only PublicKeyStores should be set.
230: * @param keyStore keystore to be the system trusted keystore
231: * @see #getTrustedKeyStore
232: */
233: private static void setTrustedKeyStore(WebPublicKeyStore keyStore) {
234: if (trustedKeyStore != null) {
235: return;
236: }
237:
238: trustedKeyStore = keyStore;
239: }
240:
241: /**
242: * Provides the keystore of resident public keys for
243: * security domain owners and other CA's. Loads the public key store if
244: * it has not already been loaded.
245: *
246: * @return keystore of domain owner and CA keys
247: * @see #setTrustedKeyStore
248: */
249: public static WebPublicKeyStore getTrustedKeyStore() {
250: if (trustedKeyStore == null) {
251: loadCertificateAuthorities();
252: }
253:
254: return trustedKeyStore;
255: }
256:
257: /**
258: * Constructs an keystore to initialize the class security token.
259: */
260: public WebPublicKeyStore() {
261: }
262:
263: /**
264: * Constructs an extendable keystore from a serialized keystore created
265: * by {@link PublicKeyStoreBuilder}.
266: * @param in stream to read a keystore serialized by
267: * {@link PublicKeyStoreBuilder#serialize(OutputStream)} from
268: * @exception IOException if the key storage was corrupted
269: */
270: public WebPublicKeyStore(InputStream in) throws IOException {
271: super (in);
272: }
273:
274: /**
275: * Constructs an extendable keystore from a serialized keystore created
276: * by {@link PublicKeyStoreBuilder}.
277: * @param in stream to read a keystore serialized by
278: * {@link PublicKeyStoreBuilder#serialize(OutputStream)} from
279: * @param sharedKeyList shared key list
280: * @exception IOException if the key storage was corrupted
281: */
282: public WebPublicKeyStore(InputStream in, Vector sharedKeyList)
283: throws IOException {
284: super (in, sharedKeyList);
285: }
286:
287: /**
288: * Returns the certificate(s) corresponding to a
289: * subject name string.
290: *
291: * @param subjectName subject name of the certificate in printable form.
292: *
293: * @return corresponding certificates or null (if not found)
294: */
295: public X509Certificate[] getCertificates(String subjectName) {
296: Vector keys;
297: X509Certificate[] certs;
298:
299: keys = findKeys(subjectName);
300: if (keys == null) {
301: return null;
302: }
303:
304: certs = new X509Certificate[keys.size()];
305: for (int i = 0; i < keys.size(); i++) {
306: certs[i] = createCertificate((PublicKeyInfo) keys
307: .elementAt(i));
308: }
309:
310: return certs;
311: }
312:
313: /**
314: * Creates an {@link X509Certificate} using the given public key
315: * information.
316: * @param keyInfo key information
317: * @return X509 certificate
318: */
319: public static X509Certificate createCertificate(
320: PublicKeyInfo keyInfo) {
321: if (keyInfo == null) {
322: return null;
323: }
324:
325: try {
326: X509Certificate cert;
327:
328: cert = new X509Certificate(
329: (byte) 0, // fixed at version 1 (raw 0)
330: new byte[0],
331: keyInfo.getOwner(),
332: keyInfo.getOwner(), // issuer same as subject
333: keyInfo.getNotBefore(), keyInfo.getNotAfter(),
334: keyInfo.getModulus(), keyInfo.getExponent(), null, // we don't use finger prints
335: 0);
336: return cert;
337: } catch (Exception e) {
338: return null;
339: }
340: }
341: }
|