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.util.Arrays;
022import java.util.Objects;
023
024import javax.net.ssl.TrustManagerFactory;
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 TrustStore
033 */
034@Plugin(name = "TrustStore", category = Core.CATEGORY_NAME, printObject = true)
035public class TrustStoreConfiguration extends AbstractKeyStoreConfiguration {
036
037    private final String trustManagerFactoryAlgorithm;
038
039    public TrustStoreConfiguration(final String location,
040                                   final PasswordProvider passwordProvider,
041                                   final String keyStoreType,
042                                   final String trustManagerFactoryAlgorithm) throws StoreConfigurationException {
043        super(location, passwordProvider, keyStoreType);
044        this.trustManagerFactoryAlgorithm = trustManagerFactoryAlgorithm == null ? TrustManagerFactory
045                .getDefaultAlgorithm() : trustManagerFactoryAlgorithm;
046    }
047
048    /**
049     * @deprecated Use {@link #TrustStoreConfiguration(String, PasswordProvider, String, String)} instead
050     */
051    @Deprecated
052    public TrustStoreConfiguration(final String location, final char[] password, final String keyStoreType,
053            final String trustManagerFactoryAlgorithm) throws StoreConfigurationException {
054        this(location, new MemoryPasswordProvider(password), keyStoreType, trustManagerFactoryAlgorithm);
055        if (password != null) {
056            Arrays.fill(password, '\0');
057        }
058    }
059
060    /**
061     * @deprecated Use {@link #TrustStoreConfiguration(String, PasswordProvider, String, String)} instead
062     */
063    @Deprecated
064    public TrustStoreConfiguration(final String location, final String password, final String keyStoreType,
065            final String trustManagerFactoryAlgorithm) throws StoreConfigurationException {
066        this(location, new MemoryPasswordProvider(password == null ? null : password.toCharArray()), keyStoreType,
067                trustManagerFactoryAlgorithm);
068    }
069
070    /**
071     * Creates a KeyStoreConfiguration.
072     *
073     * @param location
074     *        The location of the KeyStore, a file path, URL or resource.
075     * @param password
076     *        The password to access the KeyStore.
077     * @param keyStoreType
078     *        The KeyStore type, null defaults to {@code "JKS"}.
079     * @param trustManagerFactoryAlgorithm
080     *        The standard name of the requested trust management algorithm. See the Java Secure Socket Extension Reference Guide for information these names.
081     * @return a new TrustStoreConfiguration
082     * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore.
083     */
084    @PluginFactory
085    public static TrustStoreConfiguration createKeyStoreConfiguration(
086            // @formatter:off
087            @PluginAttribute("location") final String location,
088            @PluginAttribute(value = "password", sensitive = true) final char[] password,
089            @PluginAttribute("passwordEnvironmentVariable") final String passwordEnvironmentVariable,
090            @PluginAttribute("passwordFile") final String passwordFile,
091            @PluginAttribute("type") final String keyStoreType,
092            @PluginAttribute("trustManagerFactoryAlgorithm") final String trustManagerFactoryAlgorithm) throws StoreConfigurationException {
093            // @formatter:on
094
095        if (password != null && passwordEnvironmentVariable != null && passwordFile != null) {
096            throw new IllegalStateException("You MUST set only one of 'password', 'passwordEnvironmentVariable' or 'passwordFile'.");
097        }
098        try {
099            // @formatter:off
100            final PasswordProvider provider = passwordFile != null
101                    ? new FilePasswordProvider(passwordFile)
102                    : passwordEnvironmentVariable != null
103                            ? new EnvironmentPasswordProvider(passwordEnvironmentVariable)
104                            // the default is memory char[] array, which may be null
105                            : new MemoryPasswordProvider(password);
106            // @formatter:on
107            if (password != null) {
108                Arrays.fill(password, '\0');
109            }
110            return new TrustStoreConfiguration(location, provider, keyStoreType, trustManagerFactoryAlgorithm);
111        } catch (final Exception ex) {
112            throw new StoreConfigurationException("Could not configure TrustStore", ex);
113        }
114    }
115
116    /**
117     * @deprecated Use {@link #createKeyStoreConfiguration(String, char[], String, String, String, String)}
118     */
119    @Deprecated
120    public static TrustStoreConfiguration createKeyStoreConfiguration(
121            // @formatter:off
122            final String location,
123            final char[] password,
124            final String keyStoreType,
125            final String trustManagerFactoryAlgorithm) throws StoreConfigurationException {
126        // @formatter:on
127        return createKeyStoreConfiguration(location, password, null, null, keyStoreType, trustManagerFactoryAlgorithm);
128    }
129
130    /**
131     * Creates a KeyStoreConfiguration.
132     *
133     * @param location The location of the KeyStore, a file path, URL or resource.
134     * @param password The password to access the KeyStore.
135     * @param keyStoreType The KeyStore type, null defaults to {@code "JKS"}.
136     * @param trustManagerFactoryAlgorithm The standard name of the requested trust management algorithm. See the Java
137     * Secure Socket Extension Reference Guide for information these names.
138     * @return a new TrustStoreConfiguration
139     * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore.
140     * @deprecated Use createKeyStoreConfiguration(String, char[], String, String)
141     */
142    @Deprecated
143    public static TrustStoreConfiguration createKeyStoreConfiguration(
144            // @formatter:off
145            final String location,
146            final String password,
147            final String keyStoreType,
148            final String trustManagerFactoryAlgorithm) throws StoreConfigurationException {
149            // @formatter:on
150        return createKeyStoreConfiguration(location, (password == null ? null : password.toCharArray()),
151                null, null, keyStoreType, trustManagerFactoryAlgorithm);
152    }
153
154    public TrustManagerFactory initTrustManagerFactory() throws NoSuchAlgorithmException, KeyStoreException {
155        final TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(this.trustManagerFactoryAlgorithm);
156        tmFactory.init(this.getKeyStore());
157        return tmFactory;
158    }
159
160    @Override
161    public int hashCode() {
162        final int prime = 31;
163        int result = super.hashCode();
164        result = prime * result
165                + ((trustManagerFactoryAlgorithm == null) ? 0 : trustManagerFactoryAlgorithm.hashCode());
166        return result;
167    }
168
169    @Override
170    public boolean equals(final Object obj) {
171        if (this == obj) {
172            return true;
173        }
174        if (!super.equals(obj)) {
175            return false;
176        }
177        if (getClass() != obj.getClass()) {
178            return false;
179        }
180        final TrustStoreConfiguration other = (TrustStoreConfiguration) obj;
181        if (!Objects.equals(trustManagerFactoryAlgorithm, other.trustManagerFactoryAlgorithm)) {
182            return false;
183        }
184        return true;
185    }
186
187    public String getTrustManagerFactoryAlgorithm() {
188        return trustManagerFactoryAlgorithm;
189    }
190}