/* * -----------------------------------------------------------------------\ * PerfCake *   * Copyright (C) 2010 - 2016 the original author or authors. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * -----------------------------------------------------------------------/ */ package org.perfcake.util; import org.perfcake.PerfCakeConst; import org.perfcake.PerfCakeException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; /** * Factory to create pre-configured SSL socket factories. * Searches for the file in the directory specified in the property called like the value of {@link PerfCakeConst#KEYSTORES_DIR_PROPERTY}, then in * <code>keystores</code> directory and then in current working directory or the full path specified in the location parameters. * * @author <a href="mailto:marvenec@gmail.com">Martin Večeřa</a> */ public class SslSocketFactoryFactory { private static final Logger log = LogManager.getLogger(SslSocketFactoryFactory.class); /** * Initializes key store from the given location and password. * * @param keyStoreLocation * Key store location. * @param keyStorePassword * Key store password. * @return The key store initialized from the provided location and password. * @throws GeneralSecurityException * When it was not possible to initialize the key store. * @throws IOException * When it was not possible to read the provided location. */ private static KeyStore initKeyStore(final String keyStoreLocation, final String keyStorePassword) throws GeneralSecurityException, IOException { final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); try (InputStream is = Utils.locationToUrl(keyStoreLocation, PerfCakeConst.KEYSTORES_DIR_PROPERTY, Utils.determineDefaultLocation("keystores"), "").openStream()) { keyStore.load(is, keyStorePassword == null ? null : keyStorePassword.toCharArray()); } return keyStore; } /** * Gets a new SSL socket factory configured with the provided key and trust store using TLS protocol. * * @param keyStoreLocation * Key store location. * @param keyStorePassword * Key store password. * @param trustStoreLocation * Trust store location. * @param trustStorePassword * Trust store password. * @return The new SSL socket factory configured with the provided key and trust store. * @throws PerfCakeException * When it was not possible to create the SSL socket factory. */ public static SSLSocketFactory newSslSocketFactory(final String keyStoreLocation, final String keyStorePassword, final String trustStoreLocation, final String trustStorePassword) throws PerfCakeException { return newSslSocketFactory(keyStoreLocation, keyStorePassword, trustStoreLocation, trustStorePassword, "TLS"); } /** * Gets a new SSL socket factory configured with the provided key and trust store. * * @param keyStoreLocation * Key store location. * @param keyStorePassword * Key store password. * @param trustStoreLocation * Trust store location. * @param trustStorePassword * Trust store password. * @param protocol * Protocol for the factory (TLS, SSL...). * @return The new SSL socket factory configured with the provided key and trust store. * @throws PerfCakeException * When it was not possible to create the SSL socket factory. */ public static SSLSocketFactory newSslSocketFactory(final String keyStoreLocation, final String keyStorePassword, final String trustStoreLocation, final String trustStorePassword, final String protocol) throws PerfCakeException { return newSslContext(keyStoreLocation, keyStorePassword, trustStoreLocation, trustStorePassword, protocol).getSocketFactory(); } /** * Gets a new SSL context configured with the provided key and trust store using TLS protocol. * * @param keyStoreLocation * Key store location. * @param keyStorePassword * Key store password. * @param trustStoreLocation * Trust store location. * @param trustStorePassword * Trust store password. * @return The new SSL context configured with the provided key and trust store. * @throws PerfCakeException * When it was not possible to create the SSL context. */ public static SSLContext newSslContext(final String keyStoreLocation, final String keyStorePassword, final String trustStoreLocation, final String trustStorePassword) throws PerfCakeException { return newSslContext(keyStoreLocation, keyStorePassword, trustStoreLocation, trustStorePassword, "TLS"); } /** * Gets a new SSL context configured with the provided key and trust store. * * @param keyStoreLocation * Key store location. * @param keyStorePassword * Key store password. * @param trustStoreLocation * Trust store location. * @param trustStorePassword * Trust store password. * @param protocol * Protocol for the factory (TLS, SSL...). * @return The new SSL context configured with the provided key and trust store. * @throws PerfCakeException * When it was not possible to create the SSL context. */ public static SSLContext newSslContext(final String keyStoreLocation, final String keyStorePassword, final String trustStoreLocation, final String trustStorePassword, final String protocol) throws PerfCakeException { KeyStore keyStore; KeyStore trustStore; KeyManagerFactory keyManager = null; TrustManagerFactory trustManager = null; try { if (keyStoreLocation != null) { if (keyStorePassword == null) { log.warn("Empty keystore password."); } keyStore = initKeyStore(keyStoreLocation, keyStorePassword); keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManager.init(keyStore, keyStorePassword == null ? null : keyStorePassword.toCharArray()); } if (trustStoreLocation != null) { if (trustStorePassword == null) { log.warn("Empty trust store password."); } trustStore = initKeyStore(trustStoreLocation, trustStorePassword); trustManager = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManager.init(trustStore); } final SSLContext ctx = SSLContext.getInstance(protocol); ctx.init(keyManager == null ? null : keyManager.getKeyManagers(), trustManager == null ? null : trustManager.getTrustManagers(), null); return ctx; } catch (GeneralSecurityException | IOException e) { throw new PerfCakeException("Unable to prepare SSL context: ", e); } } }