View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements. See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache license, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License. You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the license for the specific language governing permissions and
    15   * limitations under the license.
    16   */
    17  package org.apache.logging.log4j.core.net.ssl;
    18
    19  import java.security.KeyManagementException;
    20  import java.security.KeyStoreException;
    21  import java.security.NoSuchAlgorithmException;
    22  import java.security.UnrecoverableKeyException;
    23
    24  import javax.net.ssl.KeyManager;
    25  import javax.net.ssl.KeyManagerFactory;
    26  import javax.net.ssl.SSLContext;
    27  import javax.net.ssl.SSLServerSocketFactory;
    28  import javax.net.ssl.SSLSocketFactory;
    29  import javax.net.ssl.TrustManager;
    30  import javax.net.ssl.TrustManagerFactory;
    31
    32  import org.apache.logging.log4j.core.config.plugins.Plugin;
    33  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
    34  import org.apache.logging.log4j.core.config.plugins.PluginElement;
    35  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
    36  import org.apache.logging.log4j.status.StatusLogger;
    37
    38  /**
    39   *  SSL Configuration
    40   */
    41  @Plugin(name = "Ssl", category = "Core", printObject = true)
    42  public class SslConfiguration {
    43      private static final StatusLogger LOGGER = StatusLogger.getLogger();
    44      private final KeyStoreConfiguration keyStoreConfig;
    45      private final TrustStoreConfiguration trustStoreConfig;
    46      private final SSLContext sslContext;
    47      private final String protocol;
    48
    49      private SslConfiguration(final String protocol, final KeyStoreConfiguration keyStoreConfig,
    50              final TrustStoreConfiguration trustStoreConfig) {
    51          this.keyStoreConfig = keyStoreConfig;
    52          this.trustStoreConfig = trustStoreConfig;
    53          this.protocol = protocol == null ? SslConfigurationDefaults.PROTOCOL : protocol;
    54          this.sslContext = this.createSslContext();
    55      }
    56
    57      public SSLSocketFactory getSslSocketFactory() {
    58          return sslContext.getSocketFactory();
    59      }
    60
    61      public SSLServerSocketFactory getSslServerSocketFactory() {
    62          return sslContext.getServerSocketFactory();
    63      }
    64
    65      private SSLContext createSslContext() {
    66          SSLContext context = null;
    67
    68          try {
    69              context = createSslContextBasedOnConfiguration();
    70              LOGGER.debug("Creating SSLContext with the given parameters");
    71          }
    72          catch (final TrustStoreConfigurationException e) {
    73              context = createSslContextWithTrustStoreFailure();
    74          }
    75          catch (final KeyStoreConfigurationException e) {
    76              context = createSslContextWithKeyStoreFailure();
    77          }
    78          return context;
    79      }
    80
    81      private SSLContext createSslContextWithTrustStoreFailure() {
    82          SSLContext context;
    83
    84          try {
    85              context = createSslContextWithDefaultTrustManagerFactory();
    86              LOGGER.debug("Creating SSLContext with default truststore");
    87          }
    88          catch (final KeyStoreConfigurationException e) {
    89              context = createDefaultSslContext();
    90              LOGGER.debug("Creating SSLContext with default configuration");
    91          }
    92          return context;
    93      }
    94
    95      private SSLContext createSslContextWithKeyStoreFailure() {
    96          SSLContext context;
    97
    98          try {
    99              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 }