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 java.security.KeyManagementException;
20 import java.security.KeyStoreException;
21 import java.security.NoSuchAlgorithmException;
22 import java.security.UnrecoverableKeyException;
23
24 import javax.net.ssl.KeyManager;
25 import javax.net.ssl.KeyManagerFactory;
26 import javax.net.ssl.SSLContext;
27 import javax.net.ssl.SSLServerSocketFactory;
28 import javax.net.ssl.SSLSocketFactory;
29 import javax.net.ssl.TrustManager;
30 import javax.net.ssl.TrustManagerFactory;
31
32 import org.apache.logging.log4j.core.Core;
33 import org.apache.logging.log4j.core.config.plugins.Plugin;
34 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
35 import org.apache.logging.log4j.core.config.plugins.PluginElement;
36 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
37 import org.apache.logging.log4j.status.StatusLogger;
38
39
40
41
42 @Plugin(name = "Ssl", category = Core.CATEGORY_NAME, printObject = true)
43 public class SslConfiguration {
44 private static final StatusLogger LOGGER = StatusLogger.getLogger();
45 private final KeyStoreConfiguration keyStoreConfig;
46 private final TrustStoreConfiguration trustStoreConfig;
47 private final SSLContext sslContext;
48 private final String protocol;
49 private final boolean verifyHostName;
50
51 private SslConfiguration(final String protocol, final KeyStoreConfiguration keyStoreConfig,
52 final TrustStoreConfiguration trustStoreConfig, boolean verifyHostName) {
53 this.keyStoreConfig = keyStoreConfig;
54 this.trustStoreConfig = trustStoreConfig;
55 this.protocol = protocol == null ? SslConfigurationDefaults.PROTOCOL : protocol;
56 this.sslContext = this.createSslContext();
57 this.verifyHostName = verifyHostName;
58 }
59
60
61
62
63 public void clearSecrets() {
64 if (this.keyStoreConfig != null) {
65 this.keyStoreConfig.clearSecrets();
66 }
67 if (this.trustStoreConfig != null) {
68 this.trustStoreConfig.clearSecrets();
69 }
70 }
71
72 public SSLSocketFactory getSslSocketFactory() {
73 return sslContext.getSocketFactory();
74 }
75
76 public SSLServerSocketFactory getSslServerSocketFactory() {
77 return sslContext.getServerSocketFactory();
78 }
79
80 private SSLContext createSslContext() {
81 SSLContext context = null;
82
83 try {
84 context = createSslContextBasedOnConfiguration();
85 LOGGER.debug("Creating SSLContext with the given parameters");
86 }
87 catch (final TrustStoreConfigurationException e) {
88 context = createSslContextWithTrustStoreFailure();
89 }
90 catch (final KeyStoreConfigurationException e) {
91 context = createSslContextWithKeyStoreFailure();
92 }
93 return context;
94 }
95
96 private SSLContext createSslContextWithTrustStoreFailure() {
97 SSLContext context;
98
99 try {
100 context = createSslContextWithDefaultTrustManagerFactory();
101 LOGGER.debug("Creating SSLContext with default truststore");
102 }
103 catch (final KeyStoreConfigurationException e) {
104 context = createDefaultSslContext();
105 LOGGER.debug("Creating SSLContext with default configuration");
106 }
107 return context;
108 }
109
110 private SSLContext createSslContextWithKeyStoreFailure() {
111 SSLContext context;
112
113 try {
114 context = createSslContextWithDefaultKeyManagerFactory();
115 LOGGER.debug("Creating SSLContext with default keystore");
116 }
117 catch (final TrustStoreConfigurationException e) {
118 context = createDefaultSslContext();
119 LOGGER.debug("Creating SSLContext with default configuration");
120 }
121 return context;
122 }
123
124 private SSLContext createSslContextBasedOnConfiguration() throws KeyStoreConfigurationException, TrustStoreConfigurationException {
125 return createSslContext(false, false);
126 }
127
128 private SSLContext createSslContextWithDefaultKeyManagerFactory() throws TrustStoreConfigurationException {
129 try {
130 return createSslContext(true, false);
131 } catch (final KeyStoreConfigurationException dummy) {
132 LOGGER.debug("Exception occurred while using default keystore. This should be a BUG");
133 return null;
134 }
135 }
136
137 private SSLContext createSslContextWithDefaultTrustManagerFactory() throws KeyStoreConfigurationException {
138 try {
139 return createSslContext(false, true);
140 }
141 catch (final TrustStoreConfigurationException dummy) {
142 LOGGER.debug("Exception occurred while using default truststore. This should be a BUG");
143 return null;
144 }
145 }
146
147 private SSLContext createDefaultSslContext() {
148 try {
149 return SSLContext.getDefault();
150 } catch (final NoSuchAlgorithmException e) {
151 LOGGER.error("Failed to create an SSLContext with default configuration", e);
152 return null;
153 }
154 }
155
156 private SSLContext createSslContext(final boolean loadDefaultKeyManagerFactory, final boolean loadDefaultTrustManagerFactory)
157 throws KeyStoreConfigurationException, TrustStoreConfigurationException {
158 try {
159 KeyManager[] kManagers = null;
160 TrustManager[] tManagers = null;
161
162 final SSLContext newSslContext = SSLContext.getInstance(this.protocol);
163 if (!loadDefaultKeyManagerFactory) {
164 final KeyManagerFactory kmFactory = loadKeyManagerFactory();
165 kManagers = kmFactory.getKeyManagers();
166 }
167 if (!loadDefaultTrustManagerFactory) {
168 final TrustManagerFactory tmFactory = loadTrustManagerFactory();
169 tManagers = tmFactory.getTrustManagers();
170 }
171
172 newSslContext.init(kManagers, tManagers, null);
173 return newSslContext;
174 }
175 catch (final NoSuchAlgorithmException e) {
176 LOGGER.error("No Provider supports a TrustManagerFactorySpi implementation for the specified protocol", e);
177 throw new TrustStoreConfigurationException(e);
178 }
179 catch (final KeyManagementException e) {
180 LOGGER.error("Failed to initialize the SSLContext", e);
181 throw new KeyStoreConfigurationException(e);
182 }
183 }
184
185 private TrustManagerFactory loadTrustManagerFactory() throws TrustStoreConfigurationException {
186 if (trustStoreConfig == null) {
187 throw new TrustStoreConfigurationException(new Exception("The trustStoreConfiguration is null"));
188 }
189
190 try {
191 return trustStoreConfig.initTrustManagerFactory();
192 }
193 catch (final NoSuchAlgorithmException e) {
194 LOGGER.error("The specified algorithm is not available from the specified provider", e);
195 throw new TrustStoreConfigurationException(e);
196 } catch (final KeyStoreException e) {
197 LOGGER.error("Failed to initialize the TrustManagerFactory", e);
198 throw new TrustStoreConfigurationException(e);
199 }
200 }
201
202 private KeyManagerFactory loadKeyManagerFactory() throws KeyStoreConfigurationException {
203 if (keyStoreConfig == null) {
204 throw new KeyStoreConfigurationException(new Exception("The keyStoreConfiguration is null"));
205 }
206
207 try {
208 return keyStoreConfig.initKeyManagerFactory();
209 }
210 catch (final NoSuchAlgorithmException e) {
211 LOGGER.error("The specified algorithm is not available from the specified provider", e);
212 throw new KeyStoreConfigurationException(e);
213 } catch (final KeyStoreException e) {
214 LOGGER.error("Failed to initialize the TrustManagerFactory", e);
215 throw new KeyStoreConfigurationException(e);
216 } catch (final UnrecoverableKeyException e) {
217 LOGGER.error("The key cannot be recovered (e.g. the given password is wrong)", e);
218 throw new KeyStoreConfigurationException(e);
219 }
220 }
221
222
223
224
225
226
227
228
229
230 @PluginFactory
231 public static SslConfiguration createSSLConfiguration(
232
233 @PluginAttribute("protocol") final String protocol,
234 @PluginElement("KeyStore") final KeyStoreConfiguration keyStoreConfig,
235 @PluginElement("TrustStore") final TrustStoreConfiguration trustStoreConfig) {
236
237 return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig, false);
238 }
239
240
241
242
243
244
245
246
247
248
249
250 public static SslConfiguration createSSLConfiguration(
251
252 @PluginAttribute("protocol") final String protocol,
253 @PluginElement("KeyStore") final KeyStoreConfiguration keyStoreConfig,
254 @PluginElement("TrustStore") final TrustStoreConfiguration trustStoreConfig,
255 @PluginAttribute("verifyHostName") final boolean verifyHostName) {
256
257 return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig, verifyHostName);
258 }
259
260 @Override
261 public int hashCode() {
262 final int prime = 31;
263 int result = 1;
264 result = prime * result + ((keyStoreConfig == null) ? 0 : keyStoreConfig.hashCode());
265 result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
266 result = prime * result + ((sslContext == null) ? 0 : sslContext.hashCode());
267 result = prime * result + ((trustStoreConfig == null) ? 0 : trustStoreConfig.hashCode());
268 return result;
269 }
270
271 @Override
272 public boolean equals(final Object obj) {
273 if (this == obj) {
274 return true;
275 }
276 if (obj == null) {
277 return false;
278 }
279 if (getClass() != obj.getClass()) {
280 return false;
281 }
282 final SslConfiguration other = (SslConfiguration) obj;
283 if (keyStoreConfig == null) {
284 if (other.keyStoreConfig != null) {
285 return false;
286 }
287 } else if (!keyStoreConfig.equals(other.keyStoreConfig)) {
288 return false;
289 }
290 if (protocol == null) {
291 if (other.protocol != null) {
292 return false;
293 }
294 } else if (!protocol.equals(other.protocol)) {
295 return false;
296 }
297 if (sslContext == null) {
298 if (other.sslContext != null) {
299 return false;
300 }
301 } else if (!sslContext.equals(other.sslContext)) {
302 return false;
303 }
304 if (trustStoreConfig == null) {
305 if (other.trustStoreConfig != null) {
306 return false;
307 }
308 } else if (!trustStoreConfig.equals(other.trustStoreConfig)) {
309 return false;
310 }
311 return true;
312 }
313
314 public KeyStoreConfiguration getKeyStoreConfig() {
315 return keyStoreConfig;
316 }
317
318 public TrustStoreConfiguration getTrustStoreConfig() {
319 return trustStoreConfig;
320 }
321
322 public SSLContext getSslContext() {
323 return sslContext;
324 }
325
326 public String getProtocol() {
327 return protocol;
328 }
329
330 public boolean isVerifyHostName() {
331 return verifyHostName;
332 }
333 }