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