/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.api.security.tls; import java.io.IOException; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Move a {@link TlsConfiguration} to and from Properties (typically System Properties). This can be used to store TLS/SSL * configuration for a library (eg. Javamail, which reads java.mail properties) or for later retrieval by * {@link TlsPropertiesSocketFactory}. */ public class TlsPropertiesMapper { private static final String TRUST_NAME_SUFFIX = ".ssl.trustStore"; private static final String TRUST_TYPE_SUFFIX = ".ssl.trustStoreType"; private static final String TRUST_PASSWORD_SUFFIX = ".ssl.trustStorePassword"; private static final String TRUST_ALGORITHM_SUFFIX = ".ssl.trustManagerAlgorithm"; private static final String KEY_NAME_SUFFIX = ".ssl.keyStore"; private static final String KEY_TYPE_SUFFIX = ".ssl.keyStoreType"; private static final String KEY_PASSWORD_SUFFIX = ".ssl.keyStorePassword"; private Logger logger = LoggerFactory.getLogger(getClass()); private String namespace; public TlsPropertiesMapper(String namespace) { this.namespace = namespace; } public void writeToProperties(Properties properties, TlsConfiguration configuration) { writeTrustStoreToProperties(properties, configuration); writeKeyStoreToProperties(properties, configuration); } public void readFromProperties(TlsConfiguration configuration, Properties properties) throws IOException { readTrustStoreFromProperties(configuration, properties); readKeyStoreFromProperties(configuration, properties); } private void writeTrustStoreToProperties(Properties properties, TlsConfiguration configuration) { String trustStoreName = configuration.getTrustStore(); String trustStorePassword = configuration.getTrustStorePassword(); if (null == trustStoreName && !configuration.isExplicitTrustStoreOnly()) { logger.info("Defaulting " + namespace + " trust store to client Key Store"); trustStoreName = configuration.getClientKeyStore(); trustStorePassword = configuration.getClientKeyStorePassword(); } if (null != trustStoreName) { synchronized (properties) { setProperty(properties, TRUST_NAME_SUFFIX, trustStoreName); setProperty(properties, TRUST_TYPE_SUFFIX, configuration.getTrustStoreType()); setProperty(properties, TRUST_PASSWORD_SUFFIX, trustStorePassword); setProperty(properties, TRUST_ALGORITHM_SUFFIX, configuration.getTrustManagerAlgorithm()); } logger.debug("Set Trust Store: " + namespace + TRUST_NAME_SUFFIX + " = " + trustStoreName); } } private void readTrustStoreFromProperties(TlsConfiguration configuration, Properties properties) throws IOException { configuration.setTrustStore(getProperty(properties, TRUST_NAME_SUFFIX, configuration.getTrustStore())); configuration.setTrustStoreType(getProperty(properties, TRUST_TYPE_SUFFIX, configuration.getTrustStoreType())); configuration.setTrustStorePassword(getProperty(properties, TRUST_PASSWORD_SUFFIX, configuration.getTrustStorePassword())); configuration .setTrustManagerAlgorithm(getProperty(properties, TRUST_ALGORITHM_SUFFIX, configuration.getTrustManagerAlgorithm())); } private void writeKeyStoreToProperties(Properties properties, TlsConfiguration configuration) { if (null != configuration.getClientKeyStore()) { synchronized (properties) { setProperty(properties, KEY_NAME_SUFFIX, configuration.getClientKeyStore()); setProperty(properties, KEY_TYPE_SUFFIX, configuration.getClientKeyStoreType()); setProperty(properties, KEY_PASSWORD_SUFFIX, configuration.getClientKeyStorePassword()); } logger.info("Set Key Store: " + namespace + KEY_NAME_SUFFIX + " = " + configuration.getClientKeyStore()); } } // note the asymmetry here. this preserves the semantics of the original implementation. // originally, the "client" keystore data were written to system properties (only) and // used implicitly to construct sockets, while "non-client" keystore information was // used explicitly. // now we construct some of those implicit sockets explicitly (as part of avoiding global // configuration for tls across all transports). in these cases we read the data needed // from (namespaced) proeprties. if we read that information back into "non-client" keystore // data, even though it was written from "client" data, then we can use the same code in // TlsConfiguration to generate the sockets in both cases. private void readKeyStoreFromProperties(TlsConfiguration configuration, Properties properties) throws IOException { configuration.setKeyStore(getProperty(properties, KEY_NAME_SUFFIX, configuration.getKeyStore())); configuration.setKeyStoreType(getProperty(properties, KEY_TYPE_SUFFIX, configuration.getKeyStoreType())); configuration.setKeyStorePassword(getProperty(properties, KEY_PASSWORD_SUFFIX, configuration.getKeyStorePassword())); } private void setProperty(Properties properties, String suffix, String value) { if (null != value) { properties.setProperty(namespace + suffix, value); if (logger.isDebugEnabled()) { logger.debug(namespace + suffix + " <- " + value); } } } private String getProperty(Properties properties, String suffix, String deflt) { String value = properties.getProperty(namespace + suffix); if (null == value) { value = deflt; } if (logger.isDebugEnabled()) { logger.debug(namespace + suffix + " -> " + value); } return value; } }