001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j.core.net.ssl; 018 019import java.security.KeyManagementException; 020import java.security.KeyStoreException; 021import java.security.NoSuchAlgorithmException; 022import java.security.UnrecoverableKeyException; 023 024import javax.net.ssl.KeyManager; 025import javax.net.ssl.KeyManagerFactory; 026import javax.net.ssl.SSLContext; 027import javax.net.ssl.SSLServerSocketFactory; 028import javax.net.ssl.SSLSocketFactory; 029import javax.net.ssl.TrustManager; 030import javax.net.ssl.TrustManagerFactory; 031 032import org.apache.logging.log4j.core.Core; 033import org.apache.logging.log4j.core.config.plugins.Plugin; 034import org.apache.logging.log4j.core.config.plugins.PluginAttribute; 035import org.apache.logging.log4j.core.config.plugins.PluginElement; 036import org.apache.logging.log4j.core.config.plugins.PluginFactory; 037import org.apache.logging.log4j.status.StatusLogger; 038 039/** 040 * SSL Configuration 041 */ 042@Plugin(name = "Ssl", category = Core.CATEGORY_NAME, printObject = true) 043public class SslConfiguration { 044 private static final StatusLogger LOGGER = StatusLogger.getLogger(); 045 private final KeyStoreConfiguration keyStoreConfig; 046 private final TrustStoreConfiguration trustStoreConfig; 047 private final SSLContext sslContext; 048 private final String protocol; 049 050 private SslConfiguration(final String protocol, final KeyStoreConfiguration keyStoreConfig, 051 final TrustStoreConfiguration trustStoreConfig) { 052 this.keyStoreConfig = keyStoreConfig; 053 this.trustStoreConfig = trustStoreConfig; 054 this.protocol = protocol == null ? SslConfigurationDefaults.PROTOCOL : protocol; 055 this.sslContext = this.createSslContext(); 056 } 057 058 /** 059 * Clears the secret fields in this object but still allow it to operate normally. 060 */ 061 public void clearSecrets() { 062 if (this.keyStoreConfig != null) { 063 this.keyStoreConfig.clearSecrets(); 064 } 065 if (this.trustStoreConfig != null) { 066 this.trustStoreConfig.clearSecrets(); 067 } 068 } 069 070 public SSLSocketFactory getSslSocketFactory() { 071 return sslContext.getSocketFactory(); 072 } 073 074 public SSLServerSocketFactory getSslServerSocketFactory() { 075 return sslContext.getServerSocketFactory(); 076 } 077 078 private SSLContext createSslContext() { 079 SSLContext context = null; 080 081 try { 082 context = createSslContextBasedOnConfiguration(); 083 LOGGER.debug("Creating SSLContext with the given parameters"); 084 } 085 catch (final TrustStoreConfigurationException e) { 086 context = createSslContextWithTrustStoreFailure(); 087 } 088 catch (final KeyStoreConfigurationException e) { 089 context = createSslContextWithKeyStoreFailure(); 090 } 091 return context; 092 } 093 094 private SSLContext createSslContextWithTrustStoreFailure() { 095 SSLContext context; 096 097 try { 098 context = createSslContextWithDefaultTrustManagerFactory(); 099 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 * Creates an SslConfiguration from a KeyStoreConfiguration and a TrustStoreConfiguration. 222 * 223 * @param protocol The protocol, see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext 224 * @param keyStoreConfig The KeyStoreConfiguration. 225 * @param trustStoreConfig The TrustStoreConfiguration. 226 * @return a new SslConfiguration 227 */ 228 @PluginFactory 229 public static SslConfiguration createSSLConfiguration( 230 // @formatter:off 231 @PluginAttribute("protocol") final String protocol, 232 @PluginElement("KeyStore") final KeyStoreConfiguration keyStoreConfig, 233 @PluginElement("TrustStore") final TrustStoreConfiguration trustStoreConfig) { 234 // @formatter:on 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}