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