View Javadoc

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  package org.apache.logging.log4j.core.net.ssl;
18  
19  import org.apache.logging.log4j.core.config.plugins.Plugin;
20  import org.apache.logging.log4j.core.config.plugins.PluginElement;
21  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
22  import org.apache.logging.log4j.status.StatusLogger;
23  
24  import javax.net.ssl.*;
25  import java.security.*;
26  
27  /**
28   *  SSL Configuration
29   */
30  @Plugin(name = "ssl", category = "Core", printObject = true)
31  public class SSLConfiguration {
32      private static final StatusLogger LOGGER = StatusLogger.getLogger();
33      private KeyStoreConfiguration keyStoreConfig;
34      private TrustStoreConfiguration trustStoreConfig;
35      private SSLContext sslContext;
36  
37      private SSLConfiguration(KeyStoreConfiguration keyStoreConfig, TrustStoreConfiguration trustStoreConfig) {
38          this.keyStoreConfig = keyStoreConfig;
39          this.trustStoreConfig = trustStoreConfig;
40          this.sslContext = null;
41      }
42  
43      public SSLSocketFactory getSSLSocketFactory() {
44          if (sslContext == null) {
45              this.sslContext = createSSLContext();
46          }
47          return sslContext.getSocketFactory();
48      }
49  
50      public SSLServerSocketFactory getSSLServerSocketFactory() {
51              if (sslContext == null) {
52                  this.sslContext = createSSLContext();
53              }
54              return sslContext.getServerSocketFactory();
55      }
56  
57      private SSLContext createSSLContext() {
58          SSLContext context = null;
59  
60          try {
61              context = createSSLContextBasedOnConfiguration();
62              LOGGER.debug("Creating SSLContext with the given parameters");
63          }
64          catch (TrustStoreConfigurationException e) {
65              context = createSSLContextWithTrustStoreFailure();
66          }
67          catch (KeyStoreConfigurationException e) {
68              context = createSSLContextWithKeyStoreFailure();
69          }
70          return context;
71      }
72  
73      private SSLContext createSSLContextWithTrustStoreFailure() {
74          SSLContext context;
75  
76          try {
77              context = createSSLContextWithDefaultTrustManagerFactory();
78              LOGGER.debug("Creating SSLContext with default truststore");
79          }
80          catch (KeyStoreConfigurationException e) {
81              context = createDefaultSSLContext();
82              LOGGER.debug("Creating SSLContext with default configuration");
83          }
84          return context;
85      }
86  
87      private SSLContext createSSLContextWithKeyStoreFailure() {
88          SSLContext context;
89  
90          try {
91              context = createSSLContextWithDefaultKeyManagerFactory();
92              LOGGER.debug("Creating SSLContext with default keystore");
93          }
94          catch (TrustStoreConfigurationException e) {
95              context = createDefaultSSLContext();
96              LOGGER.debug("Creating SSLContext with default configuration");
97          }
98          return context;
99      }
100 
101     private SSLContext createSSLContextBasedOnConfiguration() throws KeyStoreConfigurationException, TrustStoreConfigurationException {
102         return createSSLContext(false, false);
103     }
104 
105     private SSLContext createSSLContextWithDefaultKeyManagerFactory() throws TrustStoreConfigurationException {
106         try {
107             return createSSLContext(true, false);
108         } catch (KeyStoreConfigurationException dummy) {
109              LOGGER.debug("Exception occured while using default keystore. This should be a BUG");
110              return null;
111         }
112     }
113 
114     private SSLContext createSSLContextWithDefaultTrustManagerFactory() throws KeyStoreConfigurationException {
115         try {
116             return createSSLContext(false, true);
117         }
118         catch (TrustStoreConfigurationException dummy) {
119             LOGGER.debug("Exception occured while using default truststore. This should be a BUG");
120             return null;
121         }
122     }
123 
124     private SSLContext createDefaultSSLContext() {
125         try {
126             return SSLContext.getDefault();
127         } catch (NoSuchAlgorithmException e) {
128             LOGGER.error("Failed to create an SSLContext with default configuration");
129             return null;
130         }
131     }
132 
133     private SSLContext createSSLContext(boolean loadDefaultKeyManagerFactory, boolean loadDefaultTrustManagerFactory)
134             throws KeyStoreConfigurationException, TrustStoreConfigurationException {
135         try {
136             KeyManager[] kManagers = null;
137             TrustManager[] tManagers = null;
138 
139             SSLContext sslContext = SSLContext.getInstance(SSLConfigurationDefaults.PROTOCOL);
140             if (!loadDefaultKeyManagerFactory) {
141                 KeyManagerFactory kmFactory = loadKeyManagerFactory();
142                 kManagers = kmFactory.getKeyManagers();
143             }
144             if (!loadDefaultTrustManagerFactory) {
145                 TrustManagerFactory tmFactory = loadTrustManagerFactory();
146                 tManagers = tmFactory.getTrustManagers();
147             }
148 
149             sslContext.init(kManagers, tManagers, null);
150             return sslContext;
151         }
152         catch (NoSuchAlgorithmException e) {
153             LOGGER.error("No Provider supports a TrustManagerFactorySpi implementation for the specified protocol");
154             throw new TrustStoreConfigurationException(e);
155         }
156         catch (KeyManagementException e) {
157             LOGGER.error("Failed to initialize the SSLContext");
158             throw new KeyStoreConfigurationException(e);
159         }
160     }
161 
162     private TrustManagerFactory loadTrustManagerFactory() throws TrustStoreConfigurationException {
163         KeyStore trustStore = null;
164         TrustManagerFactory tmFactory = null;
165 
166         if (trustStoreConfig == null) {
167             throw new TrustStoreConfigurationException(new Exception("The trustStoreConfiguration is null"));
168         }
169 
170         try {
171             trustStore = trustStoreConfig.getTrustStore();
172             tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
173             tmFactory.init(trustStore);
174         }
175         catch (NoSuchAlgorithmException e) {
176             LOGGER.error("The specified algorithm is not available from the specified provider");
177             throw new TrustStoreConfigurationException(e);
178         } catch (KeyStoreException e) {
179             LOGGER.error("Failed to initialize the TrustManagerFactory");
180             throw new TrustStoreConfigurationException(e);
181         } catch (StoreConfigurationException e) {
182             throw new TrustStoreConfigurationException(e);
183         }
184 
185         return tmFactory;
186     }
187 
188     private KeyManagerFactory loadKeyManagerFactory() throws KeyStoreConfigurationException {
189         KeyStore keyStore = null;
190         KeyManagerFactory kmFactory = null;
191 
192         if (keyStoreConfig == null) {
193             throw new KeyStoreConfigurationException(new Exception("The keyStoreConfiguration is null"));
194         }
195 
196         try {
197             keyStore = keyStoreConfig.getKeyStore();
198             kmFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
199             kmFactory.init(keyStore, keyStoreConfig.getPasswordAsCharArray());
200         }
201         catch (NoSuchAlgorithmException e) {
202             LOGGER.error("The specified algorithm is not available from the specified provider");
203             throw new KeyStoreConfigurationException(e);
204         } catch (KeyStoreException e) {
205             LOGGER.error("Failed to initialize the TrustManagerFactory");
206             throw new KeyStoreConfigurationException(e);
207         } catch (StoreConfigurationException e) {
208             throw new KeyStoreConfigurationException(e);
209         } catch (UnrecoverableKeyException e) {
210             LOGGER.error("The key cannot be recovered (e.g. the given password is wrong)");
211             throw new KeyStoreConfigurationException(e);
212         }
213 
214         return kmFactory;
215     }
216 
217     public boolean equals(SSLConfiguration config) {
218         if (config == null) {
219             return false;
220         }
221 
222         boolean keyStoreEquals = false;
223         boolean trustStoreEquals = false;
224 
225         if (keyStoreConfig != null) {
226             keyStoreEquals = keyStoreConfig.equals(config.keyStoreConfig);
227         } else {
228             keyStoreEquals = keyStoreConfig == config.keyStoreConfig;
229         }
230 
231         if (trustStoreConfig != null) {
232             trustStoreEquals = trustStoreConfig.equals(config.trustStoreConfig);
233         } else {
234             trustStoreEquals = trustStoreConfig == config.trustStoreConfig;
235         }
236 
237         return keyStoreEquals && trustStoreEquals;
238     }
239 
240     /**
241      * Create an SSLConfiguration from a KeyStoreConfiguration and a TrustStoreConfiguration.
242      * @param keyStoreConfig The KeyStoreConfiguration.
243      * @param trustStoreConfig The TrustStoreConfiguration.
244      * @return
245      */
246     @PluginFactory
247     public static SSLConfiguration createSSLConfiguration(
248             @PluginElement("keyStore") KeyStoreConfiguration keyStoreConfig,
249             @PluginElement("trustStore") TrustStoreConfiguration trustStoreConfig) {
250         return new SSLConfiguration(keyStoreConfig, trustStoreConfig);
251     }
252 }