1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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
242
243
244
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 }