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