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.KeyStoreException;
20  import java.security.NoSuchAlgorithmException;
21  import java.security.UnrecoverableKeyException;
22  import java.util.Arrays;
23  
24  import javax.net.ssl.KeyManagerFactory;
25  
26  import org.apache.logging.log4j.core.Core;
27  import org.apache.logging.log4j.core.config.plugins.Plugin;
28  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
29  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
30  
31  /**
32   * Configuration of the KeyStore
33   */
34  @Plugin(name = "KeyStore", category = Core.CATEGORY_NAME, printObject = true)
35  public class KeyStoreConfiguration extends AbstractKeyStoreConfiguration {
36  
37      private final String keyManagerFactoryAlgorithm;
38  
39      /**
40       *
41       * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore.
42       */
43      public KeyStoreConfiguration(final String location,
44                                   final PasswordProvider  passwordProvider,
45                                   final String keyStoreType,
46                                   final String keyManagerFactoryAlgorithm) throws StoreConfigurationException {
47          super(location, passwordProvider, keyStoreType);
48          this.keyManagerFactoryAlgorithm = keyManagerFactoryAlgorithm == null ? KeyManagerFactory.getDefaultAlgorithm()
49                  : keyManagerFactoryAlgorithm;
50      }
51  
52      /**
53       *
54       * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore.
55       * @deprecated use {@link #KeyStoreConfiguration(String, PasswordProvider, String, String)} instead
56       */
57      @Deprecated
58      public KeyStoreConfiguration(final String location,
59                                   final char[] password,
60                                   final String keyStoreType,
61                                   final String keyManagerFactoryAlgorithm) throws StoreConfigurationException {
62          this(location, new MemoryPasswordProvider(password), keyStoreType, keyManagerFactoryAlgorithm);
63          if (password != null) {
64              Arrays.fill(password, '\0');
65          }
66      }
67  
68      /**
69       *
70       * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore.
71       * @deprecated Use {@link #KeyStoreConfiguration(String, PasswordProvider, String, String)} instead
72       */
73      @Deprecated
74      public KeyStoreConfiguration(final String location, final String password, final String keyStoreType,
75              final String keyManagerFactoryAlgorithm) throws StoreConfigurationException {
76          this(location, new MemoryPasswordProvider(password == null ? null : password.toCharArray()), keyStoreType,
77                  keyManagerFactoryAlgorithm);
78      }
79  
80      /**
81       * Creates a KeyStoreConfiguration.
82       *
83       * @param location
84       *        The location of the KeyStore, a file path, URL or resource.
85       * @param password
86       *        The password to access the KeyStore.
87       * @param keyStoreType
88       *        The KeyStore type, null defaults to {@code "JKS"}.
89       * @param keyManagerFactoryAlgorithm
90       *         The standard name of the requested algorithm. See the Java Secure Socket Extension Reference Guide for information about these names.
91       * @return a new KeyStoreConfiguration
92       * @throws StoreConfigurationException Thrown if this call cannot load the KeyStore.
93       */
94      @PluginFactory
95      public static KeyStoreConfiguration createKeyStoreConfiguration(
96              // @formatter:off
97              @PluginAttribute("location") final String location,
98              @PluginAttribute(value = "password", sensitive = true) final char[] password,
99              @PluginAttribute("passwordEnvironmentVariable") final String passwordEnvironmentVariable,
100             @PluginAttribute("passwordFile") final String passwordFile,
101             @PluginAttribute("type") final String keyStoreType,
102             @PluginAttribute("keyManagerFactoryAlgorithm") final String keyManagerFactoryAlgorithm) throws StoreConfigurationException {
103             // @formatter:on
104 
105         if (password != null && passwordEnvironmentVariable != null && passwordFile != null) {
106             throw new StoreConfigurationException("You MUST set only one of 'password', 'passwordEnvironmentVariable' or 'passwordFile'.");
107         }
108         try {
109             // @formatter:off
110             final PasswordProvider provider = passwordFile != null
111                     ? new FilePasswordProvider(passwordFile)
112                     : passwordEnvironmentVariable != null
113                             ? new EnvironmentPasswordProvider(passwordEnvironmentVariable)
114                             // the default is memory char[] array, which may be null
115                             : new MemoryPasswordProvider(password);
116             // @formatter:on
117             if (password != null) {
118                 Arrays.fill(password, '\0');
119             }
120             return new KeyStoreConfiguration(location, provider, keyStoreType, keyManagerFactoryAlgorithm);
121         } catch (final Exception ex) {
122             throw new StoreConfigurationException("Could not configure KeyStore", ex);
123         }
124     }
125 
126     /**
127      * @deprecated use {@link #createKeyStoreConfiguration(String, char[], String, String, String, String)}
128      */
129     @Deprecated
130     public static KeyStoreConfiguration createKeyStoreConfiguration(
131             // @formatter:off
132             final String location,
133             final char[] password,
134             final String keyStoreType,
135             final String keyManagerFactoryAlgorithm) throws StoreConfigurationException {
136             // @formatter:on
137         return createKeyStoreConfiguration(location, password, null, null, keyStoreType, keyManagerFactoryAlgorithm);
138     }
139 
140     /**
141      * Creates a KeyStoreConfiguration.
142      *
143      * @param location The location of the KeyStore, a file path, URL or resource.
144      * @param password The password to access the KeyStore.
145      * @param keyStoreType The KeyStore type, null defaults to {@code "JKS"}.
146      * @param keyManagerFactoryAlgorithm The standard name of the requested algorithm. See the Java Secure Socket
147      * Extension Reference Guide for information about these names.
148      * @return a new KeyStoreConfiguration
149      * @throws StoreConfigurationException Thrown if this call cannot load the KeyStore.
150      * @deprecated Use createKeyStoreConfiguration(String, char[], String, String)
151      */
152     @Deprecated
153     public static KeyStoreConfiguration createKeyStoreConfiguration(
154             // @formatter:off
155             final String location,
156             final String password,
157             final String keyStoreType,
158             final String keyManagerFactoryAlgorithm) throws StoreConfigurationException {
159             // @formatter:on
160         return createKeyStoreConfiguration(location,
161                 (password == null ? null : password.toCharArray()),
162                 keyStoreType,
163                 keyManagerFactoryAlgorithm);
164     }
165 
166     public KeyManagerFactory initKeyManagerFactory() throws NoSuchAlgorithmException, UnrecoverableKeyException,
167             KeyStoreException {
168         final KeyManagerFactory kmFactory = KeyManagerFactory.getInstance(this.keyManagerFactoryAlgorithm);
169         final char[] password = this.getPasswordAsCharArray();
170         try {
171             kmFactory.init(this.getKeyStore(), password);
172         } finally {
173             if (password != null) {
174                 Arrays.fill(password, '\0');
175             }
176         }
177         return kmFactory;
178     }
179 
180     @Override
181     public int hashCode() {
182         final int prime = 31;
183         int result = super.hashCode();
184         result = prime * result + ((keyManagerFactoryAlgorithm == null) ? 0 : keyManagerFactoryAlgorithm.hashCode());
185         return result;
186     }
187 
188     @Override
189     public boolean equals(final Object obj) {
190         if (this == obj) {
191             return true;
192         }
193         if (!super.equals(obj)) {
194             return false;
195         }
196         if (getClass() != obj.getClass()) {
197             return false;
198         }
199         final KeyStoreConfiguration other = (KeyStoreConfiguration) obj;
200         if (keyManagerFactoryAlgorithm == null) {
201             if (other.keyManagerFactoryAlgorithm != null) {
202                 return false;
203             }
204         } else if (!keyManagerFactoryAlgorithm.equals(other.keyManagerFactoryAlgorithm)) {
205             return false;
206         }
207         return true;
208     }
209 
210     public String getKeyManagerFactoryAlgorithm() {
211         return keyManagerFactoryAlgorithm;
212     }
213 }