1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.conscrypt;
19
20import java.io.BufferedInputStream;
21import java.io.FileInputStream;
22import java.io.IOException;
23import java.io.InputStream;
24import java.security.GeneralSecurityException;
25import java.security.KeyManagementException;
26import java.security.KeyStore;
27import java.security.SecureRandom;
28
29import javax.net.ssl.KeyManager;
30import javax.net.ssl.KeyManagerFactory;
31import javax.net.ssl.TrustManager;
32import javax.net.ssl.TrustManagerFactory;
33
34/**
35 * Support class for this package.
36 */
37public final class DefaultSSLContextImpl extends OpenSSLContextImpl {
38
39    /**
40     * Accessed by SSLContextImpl(DefaultSSLContextImpl) holding the
41     * DefaultSSLContextImpl.class monitor
42     */
43    private static KeyManager[] KEY_MANAGERS;
44
45    /**
46     * Accessed by SSLContextImpl(DefaultSSLContextImpl) holding the
47     * DefaultSSLContextImpl.class monitor
48     */
49    private static TrustManager[] TRUST_MANAGERS;
50
51    /**
52     * DefaultSSLContextImpl delegates the work to the super class since there
53     * is no way to put a synchronized around both the call to super and the
54     * rest of this constructor to guarantee that we don't have races in
55     * creating the state shared between all default SSLContexts.
56     */
57    public DefaultSSLContextImpl() throws GeneralSecurityException, IOException {
58        super();
59    }
60
61    // TODO javax.net.ssl.keyStoreProvider system property
62    KeyManager[] getKeyManagers () throws GeneralSecurityException, IOException {
63        if (KEY_MANAGERS != null) {
64            return KEY_MANAGERS;
65        }
66        // find KeyStore, KeyManagers
67        String keystore = System.getProperty("javax.net.ssl.keyStore");
68        if (keystore == null) {
69            return null;
70        }
71        String keystorepwd = System.getProperty("javax.net.ssl.keyStorePassword");
72        char[] pwd = (keystorepwd == null) ? null : keystorepwd.toCharArray();
73
74        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
75        InputStream is = null;
76        try {
77            is = new BufferedInputStream(new FileInputStream(keystore));
78            ks.load(is, pwd);
79        } finally {
80            if (is != null) {
81                is.close();
82            }
83        }
84
85        String kmfAlg = KeyManagerFactory.getDefaultAlgorithm();
86        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlg);
87        kmf.init(ks, pwd);
88        KEY_MANAGERS = kmf.getKeyManagers();
89        return KEY_MANAGERS;
90    }
91
92    // TODO javax.net.ssl.trustStoreProvider system property
93    TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException {
94        if (TRUST_MANAGERS != null) {
95            return TRUST_MANAGERS;
96        }
97
98        // find TrustStore, TrustManagers
99        String keystore = System.getProperty("javax.net.ssl.trustStore");
100        if (keystore == null) {
101            return null;
102        }
103        String keystorepwd = System.getProperty("javax.net.ssl.trustStorePassword");
104        char[] pwd = (keystorepwd == null) ? null : keystorepwd.toCharArray();
105
106        // TODO Defaults: jssecacerts; cacerts
107        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
108        InputStream is = null;
109        try {
110            is = new BufferedInputStream(new FileInputStream(keystore));
111            ks.load(is, pwd);
112        } finally {
113            if (is != null) {
114                is.close();
115            }
116        }
117        String tmfAlg = TrustManagerFactory.getDefaultAlgorithm();
118        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlg);
119        tmf.init(ks);
120        TRUST_MANAGERS = tmf.getTrustManagers();
121        return TRUST_MANAGERS;
122    }
123
124    @Override
125    public void engineInit(KeyManager[] kms, TrustManager[] tms,
126            SecureRandom sr) throws KeyManagementException {
127        throw new KeyManagementException("Do not init() the default SSLContext ");
128    }
129}
130