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 */ 017 package org.apache.logging.log4j.core.net.ssl; 018 019 import java.security.KeyManagementException; 020 import java.security.KeyStoreException; 021 import java.security.NoSuchAlgorithmException; 022 import java.security.UnrecoverableKeyException; 023 024 import javax.net.ssl.KeyManager; 025 import javax.net.ssl.KeyManagerFactory; 026 import javax.net.ssl.SSLContext; 027 import javax.net.ssl.SSLServerSocketFactory; 028 import javax.net.ssl.SSLSocketFactory; 029 import javax.net.ssl.TrustManager; 030 import javax.net.ssl.TrustManagerFactory; 031 032 import org.apache.logging.log4j.core.config.plugins.Plugin; 033 import org.apache.logging.log4j.core.config.plugins.PluginAttribute; 034 import org.apache.logging.log4j.core.config.plugins.PluginElement; 035 import org.apache.logging.log4j.core.config.plugins.PluginFactory; 036 import org.apache.logging.log4j.status.StatusLogger; 037 038 /** 039 * SSL Configuration 040 */ 041 @Plugin(name = "Ssl", category = "Core", printObject = true) 042 public class SslConfiguration { 043 private static final StatusLogger LOGGER = StatusLogger.getLogger(); 044 private final KeyStoreConfiguration keyStoreConfig; 045 private final TrustStoreConfiguration trustStoreConfig; 046 private final SSLContext sslContext; 047 private final String protocol; 048 049 private SslConfiguration(final String protocol, final KeyStoreConfiguration keyStoreConfig, 050 final TrustStoreConfiguration trustStoreConfig) { 051 this.keyStoreConfig = keyStoreConfig; 052 this.trustStoreConfig = trustStoreConfig; 053 this.protocol = protocol == null ? SslConfigurationDefaults.PROTOCOL : protocol; 054 this.sslContext = this.createSslContext(); 055 } 056 057 public SSLSocketFactory getSslSocketFactory() { 058 return sslContext.getSocketFactory(); 059 } 060 061 public SSLServerSocketFactory getSslServerSocketFactory() { 062 return sslContext.getServerSocketFactory(); 063 } 064 065 private SSLContext createSslContext() { 066 SSLContext context = null; 067 068 try { 069 context = createSslContextBasedOnConfiguration(); 070 LOGGER.debug("Creating SSLContext with the given parameters"); 071 } 072 catch (final TrustStoreConfigurationException e) { 073 context = createSslContextWithTrustStoreFailure(); 074 } 075 catch (final KeyStoreConfigurationException e) { 076 context = createSslContextWithKeyStoreFailure(); 077 } 078 return context; 079 } 080 081 private SSLContext createSslContextWithTrustStoreFailure() { 082 SSLContext context; 083 084 try { 085 context = createSslContextWithDefaultTrustManagerFactory(); 086 LOGGER.debug("Creating SSLContext with default truststore"); 087 } 088 catch (final KeyStoreConfigurationException e) { 089 context = createDefaultSslContext(); 090 LOGGER.debug("Creating SSLContext with default configuration"); 091 } 092 return context; 093 } 094 095 private SSLContext createSslContextWithKeyStoreFailure() { 096 SSLContext context; 097 098 try { 099 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"); 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"); 162 throw new TrustStoreConfigurationException(e); 163 } 164 catch (final KeyManagementException e) { 165 LOGGER.error("Failed to initialize the SSLContext"); 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"); 180 throw new TrustStoreConfigurationException(e); 181 } catch (final KeyStoreException e) { 182 LOGGER.error("Failed to initialize the TrustManagerFactory"); 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"); 197 throw new KeyStoreConfigurationException(e); 198 } catch (final KeyStoreException e) { 199 LOGGER.error("Failed to initialize the TrustManagerFactory"); 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)"); 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 * Creates an SslConfiguration from a KeyStoreConfiguration and a TrustStoreConfiguration. 232 * @param protocol The protocol, see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext 233 * @param keyStoreConfig The KeyStoreConfiguration. 234 * @param trustStoreConfig The TrustStoreConfiguration. 235 * @return a new SslConfiguration 236 */ 237 @PluginFactory 238 public static SslConfiguration createSSLConfiguration( 239 // @formatter:off 240 @PluginAttribute("protocol") final String protocol, 241 @PluginElement("KeyStore") final KeyStoreConfiguration keyStoreConfig, 242 @PluginElement("TrustStore") final TrustStoreConfiguration trustStoreConfig) { 243 // @formatter:on 244 return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig); 245 } 246 }