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 org.apache.logging.log4j.core.config.plugins.Plugin; 020import org.apache.logging.log4j.core.config.plugins.PluginElement; 021import org.apache.logging.log4j.core.config.plugins.PluginFactory; 022import org.apache.logging.log4j.status.StatusLogger; 023 024import javax.net.ssl.*; 025import java.security.*; 026 027/** 028 * SSL Configuration 029 */ 030@Plugin(name = "ssl", category = "Core", printObject = true) 031public class SSLConfiguration { 032 private static final StatusLogger LOGGER = StatusLogger.getLogger(); 033 private KeyStoreConfiguration keyStoreConfig; 034 private TrustStoreConfiguration trustStoreConfig; 035 private SSLContext sslContext; 036 037 private SSLConfiguration(KeyStoreConfiguration keyStoreConfig, TrustStoreConfiguration trustStoreConfig) { 038 this.keyStoreConfig = keyStoreConfig; 039 this.trustStoreConfig = trustStoreConfig; 040 this.sslContext = null; 041 } 042 043 public SSLSocketFactory getSSLSocketFactory() { 044 if (sslContext == null) { 045 this.sslContext = createSSLContext(); 046 } 047 return sslContext.getSocketFactory(); 048 } 049 050 public SSLServerSocketFactory getSSLServerSocketFactory() { 051 if (sslContext == null) { 052 this.sslContext = createSSLContext(); 053 } 054 return sslContext.getServerSocketFactory(); 055 } 056 057 private SSLContext createSSLContext() { 058 SSLContext context = null; 059 060 try { 061 context = createSSLContextBasedOnConfiguration(); 062 LOGGER.debug("Creating SSLContext with the given parameters"); 063 } 064 catch (TrustStoreConfigurationException e) { 065 context = createSSLContextWithTrustStoreFailure(); 066 } 067 catch (KeyStoreConfigurationException e) { 068 context = createSSLContextWithKeyStoreFailure(); 069 } 070 return context; 071 } 072 073 private SSLContext createSSLContextWithTrustStoreFailure() { 074 SSLContext context; 075 076 try { 077 context = createSSLContextWithDefaultTrustManagerFactory(); 078 LOGGER.debug("Creating SSLContext with default truststore"); 079 } 080 catch (KeyStoreConfigurationException e) { 081 context = createDefaultSSLContext(); 082 LOGGER.debug("Creating SSLContext with default configuration"); 083 } 084 return context; 085 } 086 087 private SSLContext createSSLContextWithKeyStoreFailure() { 088 SSLContext context; 089 090 try { 091 context = createSSLContextWithDefaultKeyManagerFactory(); 092 LOGGER.debug("Creating SSLContext with default keystore"); 093 } 094 catch (TrustStoreConfigurationException e) { 095 context = createDefaultSSLContext(); 096 LOGGER.debug("Creating SSLContext with default configuration"); 097 } 098 return context; 099 } 100 101 private SSLContext createSSLContextBasedOnConfiguration() throws KeyStoreConfigurationException, TrustStoreConfigurationException { 102 return createSSLContext(false, false); 103 } 104 105 private SSLContext createSSLContextWithDefaultKeyManagerFactory() throws TrustStoreConfigurationException { 106 try { 107 return createSSLContext(true, false); 108 } catch (KeyStoreConfigurationException dummy) { 109 LOGGER.debug("Exception occured while using default keystore. This should be a BUG"); 110 return null; 111 } 112 } 113 114 private SSLContext createSSLContextWithDefaultTrustManagerFactory() throws KeyStoreConfigurationException { 115 try { 116 return createSSLContext(false, true); 117 } 118 catch (TrustStoreConfigurationException dummy) { 119 LOGGER.debug("Exception occured while using default truststore. This should be a BUG"); 120 return null; 121 } 122 } 123 124 private SSLContext createDefaultSSLContext() { 125 try { 126 return SSLContext.getDefault(); 127 } catch (NoSuchAlgorithmException e) { 128 LOGGER.error("Failed to create an SSLContext with default configuration"); 129 return null; 130 } 131 } 132 133 private SSLContext createSSLContext(boolean loadDefaultKeyManagerFactory, boolean loadDefaultTrustManagerFactory) 134 throws KeyStoreConfigurationException, TrustStoreConfigurationException { 135 try { 136 KeyManager[] kManagers = null; 137 TrustManager[] tManagers = null; 138 139 SSLContext sslContext = SSLContext.getInstance(SSLConfigurationDefaults.PROTOCOL); 140 if (!loadDefaultKeyManagerFactory) { 141 KeyManagerFactory kmFactory = loadKeyManagerFactory(); 142 kManagers = kmFactory.getKeyManagers(); 143 } 144 if (!loadDefaultTrustManagerFactory) { 145 TrustManagerFactory tmFactory = loadTrustManagerFactory(); 146 tManagers = tmFactory.getTrustManagers(); 147 } 148 149 sslContext.init(kManagers, tManagers, null); 150 return sslContext; 151 } 152 catch (NoSuchAlgorithmException e) { 153 LOGGER.error("No Provider supports a TrustManagerFactorySpi implementation for the specified protocol"); 154 throw new TrustStoreConfigurationException(e); 155 } 156 catch (KeyManagementException e) { 157 LOGGER.error("Failed to initialize the SSLContext"); 158 throw new KeyStoreConfigurationException(e); 159 } 160 } 161 162 private TrustManagerFactory loadTrustManagerFactory() throws TrustStoreConfigurationException { 163 KeyStore trustStore = null; 164 TrustManagerFactory tmFactory = null; 165 166 if (trustStoreConfig == null) { 167 throw new TrustStoreConfigurationException(new Exception("The trustStoreConfiguration is null")); 168 } 169 170 try { 171 trustStore = trustStoreConfig.getTrustStore(); 172 tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 173 tmFactory.init(trustStore); 174 } 175 catch (NoSuchAlgorithmException e) { 176 LOGGER.error("The specified algorithm is not available from the specified provider"); 177 throw new TrustStoreConfigurationException(e); 178 } catch (KeyStoreException e) { 179 LOGGER.error("Failed to initialize the TrustManagerFactory"); 180 throw new TrustStoreConfigurationException(e); 181 } catch (StoreConfigurationException e) { 182 throw new TrustStoreConfigurationException(e); 183 } 184 185 return tmFactory; 186 } 187 188 private KeyManagerFactory loadKeyManagerFactory() throws KeyStoreConfigurationException { 189 KeyStore keyStore = null; 190 KeyManagerFactory kmFactory = null; 191 192 if (keyStoreConfig == null) { 193 throw new KeyStoreConfigurationException(new Exception("The keyStoreConfiguration is null")); 194 } 195 196 try { 197 keyStore = keyStoreConfig.getKeyStore(); 198 kmFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 199 kmFactory.init(keyStore, keyStoreConfig.getPasswordAsCharArray()); 200 } 201 catch (NoSuchAlgorithmException e) { 202 LOGGER.error("The specified algorithm is not available from the specified provider"); 203 throw new KeyStoreConfigurationException(e); 204 } catch (KeyStoreException e) { 205 LOGGER.error("Failed to initialize the TrustManagerFactory"); 206 throw new KeyStoreConfigurationException(e); 207 } catch (StoreConfigurationException e) { 208 throw new KeyStoreConfigurationException(e); 209 } catch (UnrecoverableKeyException e) { 210 LOGGER.error("The key cannot be recovered (e.g. the given password is wrong)"); 211 throw new KeyStoreConfigurationException(e); 212 } 213 214 return kmFactory; 215 } 216 217 public boolean equals(SSLConfiguration config) { 218 if (config == null) { 219 return false; 220 } 221 222 boolean keyStoreEquals = false; 223 boolean trustStoreEquals = false; 224 225 if (keyStoreConfig != null) { 226 keyStoreEquals = keyStoreConfig.equals(config.keyStoreConfig); 227 } else { 228 keyStoreEquals = keyStoreConfig == config.keyStoreConfig; 229 } 230 231 if (trustStoreConfig != null) { 232 trustStoreEquals = trustStoreConfig.equals(config.trustStoreConfig); 233 } else { 234 trustStoreEquals = trustStoreConfig == config.trustStoreConfig; 235 } 236 237 return keyStoreEquals && trustStoreEquals; 238 } 239 240 /** 241 * Create an SSLConfiguration from a KeyStoreConfiguration and a TrustStoreConfiguration. 242 * @param keyStoreConfig The KeyStoreConfiguration. 243 * @param trustStoreConfig The TrustStoreConfiguration. 244 * @return 245 */ 246 @PluginFactory 247 public static SSLConfiguration createSSLConfiguration( 248 @PluginElement("keyStore") KeyStoreConfiguration keyStoreConfig, 249 @PluginElement("trustStore") TrustStoreConfiguration trustStoreConfig) { 250 return new SSLConfiguration(keyStoreConfig, trustStoreConfig); 251 } 252}