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.KeyStore; 021 import java.security.KeyStoreException; 022 import java.security.NoSuchAlgorithmException; 023 import java.security.UnrecoverableKeyException; 024 025 import javax.net.ssl.KeyManager; 026 import javax.net.ssl.KeyManagerFactory; 027 import javax.net.ssl.SSLContext; 028 import javax.net.ssl.SSLServerSocketFactory; 029 import javax.net.ssl.SSLSocketFactory; 030 import javax.net.ssl.TrustManager; 031 import javax.net.ssl.TrustManagerFactory; 032 033 import org.apache.logging.log4j.core.config.plugins.Plugin; 034 import org.apache.logging.log4j.core.config.plugins.PluginAttribute; 035 import org.apache.logging.log4j.core.config.plugins.PluginElement; 036 import org.apache.logging.log4j.core.config.plugins.PluginFactory; 037 import org.apache.logging.log4j.status.StatusLogger; 038 039 /** 040 * SSL Configuration 041 */ 042 @Plugin(name = "Ssl", category = "Core", printObject = true) 043 public 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(String protocol, KeyStoreConfiguration keyStoreConfig, 051 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 public SSLSocketFactory getSslSocketFactory() { 059 return sslContext.getSocketFactory(); 060 } 061 062 public SSLServerSocketFactory getSslServerSocketFactory() { 063 return sslContext.getServerSocketFactory(); 064 } 065 066 private SSLContext createSslContext() { 067 SSLContext context = null; 068 069 try { 070 context = createSslContextBasedOnConfiguration(); 071 LOGGER.debug("Creating SSLContext with the given parameters"); 072 } 073 catch (TrustStoreConfigurationException e) { 074 context = createSslContextWithTrustStoreFailure(); 075 } 076 catch (KeyStoreConfigurationException e) { 077 context = createSslContextWithKeyStoreFailure(); 078 } 079 return context; 080 } 081 082 private SSLContext createSslContextWithTrustStoreFailure() { 083 SSLContext context; 084 085 try { 086 context = createSslContextWithDefaultTrustManagerFactory(); 087 LOGGER.debug("Creating SSLContext with default truststore"); 088 } 089 catch (KeyStoreConfigurationException e) { 090 context = createDefaultSslContext(); 091 LOGGER.debug("Creating SSLContext with default configuration"); 092 } 093 return context; 094 } 095 096 private SSLContext createSslContextWithKeyStoreFailure() { 097 SSLContext context; 098 099 try { 100 context = createSslContextWithDefaultKeyManagerFactory(); 101 LOGGER.debug("Creating SSLContext with default keystore"); 102 } 103 catch (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 (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 (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 (NoSuchAlgorithmException e) { 137 LOGGER.error("Failed to create an SSLContext with default configuration"); 138 return null; 139 } 140 } 141 142 private SSLContext createSslContext(boolean loadDefaultKeyManagerFactory, boolean loadDefaultTrustManagerFactory) 143 throws KeyStoreConfigurationException, TrustStoreConfigurationException { 144 try { 145 KeyManager[] kManagers = null; 146 TrustManager[] tManagers = null; 147 148 SSLContext newSslContext = SSLContext.getInstance(this.protocol); 149 if (!loadDefaultKeyManagerFactory) { 150 KeyManagerFactory kmFactory = loadKeyManagerFactory(); 151 kManagers = kmFactory.getKeyManagers(); 152 } 153 if (!loadDefaultTrustManagerFactory) { 154 TrustManagerFactory tmFactory = loadTrustManagerFactory(); 155 tManagers = tmFactory.getTrustManagers(); 156 } 157 158 newSslContext.init(kManagers, tManagers, null); 159 return newSslContext; 160 } 161 catch (NoSuchAlgorithmException e) { 162 LOGGER.error("No Provider supports a TrustManagerFactorySpi implementation for the specified protocol"); 163 throw new TrustStoreConfigurationException(e); 164 } 165 catch (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 (NoSuchAlgorithmException e) { 180 LOGGER.error("The specified algorithm is not available from the specified provider"); 181 throw new TrustStoreConfigurationException(e); 182 } catch (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 (NoSuchAlgorithmException e) { 197 LOGGER.error("The specified algorithm is not available from the specified provider"); 198 throw new KeyStoreConfigurationException(e); 199 } catch (KeyStoreException e) { 200 LOGGER.error("Failed to initialize the TrustManagerFactory"); 201 throw new KeyStoreConfigurationException(e); 202 } catch (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(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 * Creates an SslConfiguration from a KeyStoreConfiguration and a TrustStoreConfiguration. 233 * @param protocol The protocol, see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext 234 * @param keyStoreConfig The KeyStoreConfiguration. 235 * @param trustStoreConfig The TrustStoreConfiguration. 236 * @return a new SslConfiguration 237 */ 238 @PluginFactory 239 public static SslConfiguration createSSLConfiguration( 240 // @formatter:off 241 @PluginAttribute("protocol") String protocol, 242 @PluginElement("KeyStore") KeyStoreConfiguration keyStoreConfig, 243 @PluginElement("TrustStore") TrustStoreConfiguration trustStoreConfig) { 244 // @formatter:on 245 return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig); 246 } 247 }