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
53     * since there is no way to put a synchronized around both the
54     * call to super and the rest of this constructor to guarantee
55     * that we don't have races in creating the state shared between
56     * all default SSLContexts.
57     */
58    public DefaultSSLContextImpl() throws GeneralSecurityException, IOException {
59        super(null);
60    }
61
62    // TODO javax.net.ssl.keyStoreProvider system property
63    KeyManager[] getKeyManagers () throws GeneralSecurityException, IOException {
64        if (KEY_MANAGERS != null) {
65            return KEY_MANAGERS;
66        }
67        // find KeyStore, KeyManagers
68        String keystore = System.getProperty("javax.net.ssl.keyStore");
69        if (keystore == null) {
70            return null;
71        }
72        String keystorepwd = System.getProperty("javax.net.ssl.keyStorePassword");
73        char[] pwd = (keystorepwd == null) ? null : keystorepwd.toCharArray();
74
75        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
76        InputStream is = null;
77        try {
78            is = new BufferedInputStream(new FileInputStream(keystore));
79            ks.load(is, pwd);
80        } finally {
81            if (is != null) {
82                is.close();
83            }
84        }
85
86        String kmfAlg = KeyManagerFactory.getDefaultAlgorithm();
87        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlg);
88        kmf.init(ks, pwd);
89        KEY_MANAGERS = kmf.getKeyManagers();
90        return KEY_MANAGERS;
91    }
92
93    // TODO javax.net.ssl.trustStoreProvider system property
94    TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException {
95        if (TRUST_MANAGERS != null) {
96            return TRUST_MANAGERS;
97        }
98
99        // find TrustStore, TrustManagers
100        String keystore = System.getProperty("javax.net.ssl.trustStore");
101        if (keystore == null) {
102            return null;
103        }
104        String keystorepwd = System.getProperty("javax.net.ssl.trustStorePassword");
105        char[] pwd = (keystorepwd == null) ? null : keystorepwd.toCharArray();
106
107        // TODO Defaults: jssecacerts; cacerts
108        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
109        InputStream is = null;
110        try {
111            is = new BufferedInputStream(new FileInputStream(keystore));
112            ks.load(is, pwd);
113        } finally {
114            if (is != null) {
115                is.close();
116            }
117        }
118        String tmfAlg = TrustManagerFactory.getDefaultAlgorithm();
119        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlg);
120        tmf.init(ks);
121        TRUST_MANAGERS = tmf.getTrustManagers();
122        return TRUST_MANAGERS;
123    }
124
125    @Override
126    public void engineInit(KeyManager[] kms, TrustManager[] tms,
127            SecureRandom sr) throws KeyManagementException {
128        throw new KeyManagementException("Do not init() the default SSLContext ");
129    }
130}
131