001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.crypto;
018    
019    import java.io.ByteArrayInputStream;
020    import java.io.ByteArrayOutputStream;
021    import java.io.IOException;
022    import java.security.KeyStore;
023    import java.security.Provider;
024    import java.security.Security;
025    import java.security.cert.Certificate;
026    import java.security.cert.CertificateFactory;
027    import java.util.Collections;
028    import java.util.HashSet;
029    import java.util.Set;
030    import java.util.TreeSet;
031    
032    /**
033     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
034     */
035    public class KeystoreUtil {
036        /**
037         * All KeyStore types available.
038         */
039        public static final Set<String> keystoreTypes;
040        /**
041         * The keystore types which allow an empty keystore saved to disk.
042         */
043        public static final Set<String> emptyKeystoreTypes;
044        /**
045         * The keystore types which allow certificate entries.
046         */
047        public static final Set<String> certKeystoreTypes;
048        /**
049         * The default keystore type.
050         */
051        public static final String defaultType;
052    
053        static {
054            Set<String> ignoreKeystores = new HashSet<String>();
055            ignoreKeystores.add("windows-my");
056            ignoreKeystores.add("windows-root");
057            
058            TreeSet<String> tempKeystoreTypes = new TreeSet<String>();
059            TreeSet<String> tempEmptyKeystoreTypes = new TreeSet<String>();
060            TreeSet<String> tempCertKeystoreTypes = new TreeSet<String>();
061            String tempDefaultType = null;
062            Provider[] providers = Security.getProviders();
063            char[] password = "emptypassword".toCharArray();
064    
065            // Certificate used to check if a keystore allows storing trusted
066            String sampleCertText = "-----BEGIN CERTIFICATE-----\n"
067                +"MIIBpzCCAVECBgEV+CystzANBgkqhkiG9w0BAQQFADBcMQswCQYDVQQDEwJNZTEQMA4GA1UECxMH\n"
068                +"TXkgVW5pdDEPMA0GA1UEChMGTXkgT3JnMRAwDgYDVQQHEwdNeSBDaXR5MQswCQYDVQQIEwJBUDEL\n"
069                +"MAkGA1UEBhMCSU4wHhcNMDcxMDMxMjIyNjU4WhcNMTcxMDI4MjIyNjU4WjBcMQswCQYDVQQDEwJN\n"
070                +"ZTEQMA4GA1UECxMHTXkgVW5pdDEPMA0GA1UEChMGTXkgT3JnMRAwDgYDVQQHEwdNeSBDaXR5MQsw\n"
071                +"CQYDVQQIEwJBUDELMAkGA1UEBhMCSU4wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAlN7IscUYq5U9\n"
072                +"d1TYVJaj5RQJLg39Gz9R9hB0hhOULSHOxeE0utTJvgBQcf+f39FgbGIdriJniyoubtCXGfSpxwID\n"
073                +"AQABMA0GCSqGSIb3DQEBBAUAA0EACQN6ScbxzAjrrQ3Ciy8I7/qsgpQo4Nuhfo5cAU4rvcKnujs6\n"
074                +"uGHAJrHMF/ROGl6kPZvFeoGXk5qjyKs8Kx5MJA==\n"
075                +"-----END CERTIFICATE-----";
076            Certificate sampleCert = null;
077    
078            try {
079                CertificateFactory certFac = CertificateFactory.getInstance("X.509");
080                sampleCert = certFac.generateCertificate(new ByteArrayInputStream(sampleCertText.getBytes()));
081            } catch (Throwable ignored) {
082            }
083            for(Provider provider: providers) {
084                for(Provider.Service service: provider.getServices()) {
085                    String type = service.getAlgorithm();
086                    if (service.getType().equals("KeyStore") && 
087                        !ignoreKeystores.contains(type.toLowerCase())) {
088    
089                        tempKeystoreTypes.add(type);
090                        if(type.equalsIgnoreCase(KeyStore.getDefaultType())) {
091                            tempDefaultType = type;
092                        }
093    
094                        ByteArrayOutputStream baos = null;
095                        KeyStore ks = null;
096                        try {
097                            ks = KeyStore.getInstance(type);
098                            ks.load(null);
099                            baos = new ByteArrayOutputStream();
100                            // Check if an empty keystore can be saved.
101                            ks.store(baos, password);
102                            tempEmptyKeystoreTypes.add(type);
103                        } catch(Throwable ignored) {
104                        } finally {
105                            if(baos != null) {
106                                try {baos.close();} catch(IOException ignored){}
107                            }
108                        }
109    
110                        try {
111                            // Check if the keystore allows storing of certificate entries.
112                            ks.setCertificateEntry("samplecert", sampleCert);
113                            tempCertKeystoreTypes.add(type);
114                        } catch(Throwable ignored) {
115                        }
116                    }
117                }
118            }
119            
120            keystoreTypes = Collections.unmodifiableSortedSet(tempKeystoreTypes);
121            emptyKeystoreTypes = Collections.unmodifiableSortedSet(tempEmptyKeystoreTypes);
122            certKeystoreTypes = Collections.unmodifiableSortedSet(tempCertKeystoreTypes);
123            defaultType = tempDefaultType;
124        }
125    }