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