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 occured 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 occured 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 public static SslConfiguration createSSLConfiguration(
250
251 @PluginAttribute("protocol") final String protocol,
252 @PluginElement("KeyStore") final KeyStoreConfiguration keyStoreConfig,
253 @PluginElement("TrustStore") final TrustStoreConfiguration trustStoreConfig,
254 @PluginElement("verifyHostName") final boolean verifyHostName) {
255
256 return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig, verifyHostName);
257 }
258
259 @Override
260 public int hashCode() {
261 final int prime = 31;
262 int result = 1;
263 result = prime * result + ((keyStoreConfig == null) ? 0 : keyStoreConfig.hashCode());
264 result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
265 result = prime * result + ((sslContext == null) ? 0 : sslContext.hashCode());
266 result = prime * result + ((trustStoreConfig == null) ? 0 : trustStoreConfig.hashCode());
267 return result;
268 }
269
270 @Override
271 public boolean equals(final Object obj) {
272 if (this == obj) {
273 return true;
274 }
275 if (obj == null) {
276 return false;
277 }
278 if (getClass() != obj.getClass()) {
279 return false;
280 }
281 final SslConfiguration other = (SslConfiguration) obj;
282 if (keyStoreConfig == null) {
283 if (other.keyStoreConfig != null) {
284 return false;
285 }
286 } else if (!keyStoreConfig.equals(other.keyStoreConfig)) {
287 return false;
288 }
289 if (protocol == null) {
290 if (other.protocol != null) {
291 return false;
292 }
293 } else if (!protocol.equals(other.protocol)) {
294 return false;
295 }
296 if (sslContext == null) {
297 if (other.sslContext != null) {
298 return false;
299 }
300 } else if (!sslContext.equals(other.sslContext)) {
301 return false;
302 }
303 if (trustStoreConfig == null) {
304 if (other.trustStoreConfig != null) {
305 return false;
306 }
307 } else if (!trustStoreConfig.equals(other.trustStoreConfig)) {
308 return false;
309 }
310 return true;
311 }
312
313 public KeyStoreConfiguration getKeyStoreConfig() {
314 return keyStoreConfig;
315 }
316
317 public TrustStoreConfiguration getTrustStoreConfig() {
318 return trustStoreConfig;
319 }
320
321 public SSLContext getSslContext() {
322 return sslContext;
323 }
324
325 public String getProtocol() {
326 return protocol;
327 }
328
329 public boolean isVerifyHostName() {
330 return verifyHostName;
331 }
332 }