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 java.security.KeyStoreException; 020import java.security.NoSuchAlgorithmException; 021import java.security.UnrecoverableKeyException; 022import java.util.Arrays; 023 024import javax.net.ssl.KeyManagerFactory; 025 026import org.apache.logging.log4j.core.Core; 027import org.apache.logging.log4j.core.config.plugins.Plugin; 028import org.apache.logging.log4j.core.config.plugins.PluginAttribute; 029import org.apache.logging.log4j.core.config.plugins.PluginFactory; 030 031/** 032 * Configuration of the KeyStore 033 */ 034@Plugin(name = "KeyStore", category = Core.CATEGORY_NAME, printObject = true) 035public class KeyStoreConfiguration extends AbstractKeyStoreConfiguration { 036 037 private final String keyManagerFactoryAlgorithm; 038 039 /** 040 * 041 * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore. 042 */ 043 public KeyStoreConfiguration(final String location, 044 final PasswordProvider passwordProvider, 045 final String keyStoreType, 046 final String keyManagerFactoryAlgorithm) throws StoreConfigurationException { 047 super(location, passwordProvider, keyStoreType); 048 this.keyManagerFactoryAlgorithm = keyManagerFactoryAlgorithm == null ? KeyManagerFactory.getDefaultAlgorithm() 049 : keyManagerFactoryAlgorithm; 050 } 051 052 /** 053 * 054 * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore. 055 * @deprecated use {@link #KeyStoreConfiguration(String, PasswordProvider, String, String)} instead 056 */ 057 public KeyStoreConfiguration(final String location, 058 final char[] password, 059 final String keyStoreType, 060 final String keyManagerFactoryAlgorithm) throws StoreConfigurationException { 061 this(location, new MemoryPasswordProvider(password), keyStoreType, keyManagerFactoryAlgorithm); 062 if (password != null) { 063 Arrays.fill(password, '\0'); 064 } 065 } 066 067 /** 068 * 069 * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore. 070 * @deprecated Use {@link #KeyStoreConfiguration(String, PasswordProvider, String, String)} instead 071 */ 072 @Deprecated 073 public KeyStoreConfiguration(final String location, final String password, final String keyStoreType, 074 final String keyManagerFactoryAlgorithm) throws StoreConfigurationException { 075 this(location, new MemoryPasswordProvider(password == null ? null : password.toCharArray()), keyStoreType, 076 keyManagerFactoryAlgorithm); 077 } 078 079 /** 080 * Creates a KeyStoreConfiguration. 081 * 082 * @param location 083 * The location of the KeyStore, a file path, URL or resource. 084 * @param password 085 * The password to access the KeyStore. 086 * @param keyStoreType 087 * The KeyStore type, null defaults to {@code "JKS"}. 088 * @param keyManagerFactoryAlgorithm 089 * The standard name of the requested algorithm. See the Java Secure Socket Extension Reference Guide for information about these names. 090 * @return a new KeyStoreConfiguration 091 * @throws StoreConfigurationException Thrown if this call cannot load the KeyStore. 092 */ 093 @PluginFactory 094 public static KeyStoreConfiguration createKeyStoreConfiguration( 095 // @formatter:off 096 @PluginAttribute("location") final String location, 097 @PluginAttribute(value = "password", sensitive = true) final char[] password, 098 @PluginAttribute("passwordEnvironmentVariable") final String passwordEnvironmentVariable, 099 @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}