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