📄 tlsconfiguration.java
字号:
/* * $Id: TlsConfiguration.java 10489 2008-01-23 17:53:38Z dfeist $ * -------------------------------------------------------------------------------------- * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.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.api.security.tls;import org.mule.api.lifecycle.CreateException;import org.mule.api.security.TlsDirectKeyStore;import org.mule.api.security.TlsDirectTrustStore;import org.mule.api.security.TlsIndirectKeyStore;import org.mule.api.security.TlsProtocolHandler;import org.mule.api.security.provider.AutoDiscoverySecurityProviderFactory;import org.mule.api.security.provider.SecurityProviderFactory;import org.mule.api.security.provider.SecurityProviderInfo;import org.mule.config.i18n.CoreMessages;import org.mule.util.FileUtils;import org.mule.util.IOUtils;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.security.KeyManagementException;import java.security.KeyStore;import java.security.NoSuchAlgorithmException;import java.security.Provider;import java.security.Security;import javax.net.ssl.KeyManager;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLServerSocketFactory;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.TrustManager;import javax.net.ssl.TrustManagerFactory;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * Support for configuring TLS/SSL connections. * <p/> * <h2>Introduction</h2> * <p/> * This class was introduced to centralise the work of TLS/SSL configuration. It is intended * to be backwards compatible with earlier code (as much as possible) and so is perhaps more * complex than would be necessary if starting from zero - the main source of confusion is the * distinction between direct and indirect creation of sockets and stores. * <p/> * <h2>Configuration</h2> * <p/> * The documentation in this class is intended more for programmers than end uses. If you are * configuring a connector the interfaces {@link org.mule.api.security.TlsIndirectTrustStore}, * {@link TlsDirectTrustStore}, * {@link TlsDirectKeyStore} and {@link TlsIndirectKeyStore} should provide guidance to individual * properties. In addition you should check the documentation for the specific protocol / connector * used and may also need to read the discussion on direct and indirect socket and store creation * below (or, more simply, just use whichever key store interface your connector implements!). * <p/> * <h2>Programming</h2> * <p/> * This class is intended to be used as a delegate as we typically want to add security to an * already existing connector (so we inherit from that connector, implement the appropriate * interfaces from {@link org.mule.api.security.TlsIndirectTrustStore}, {@link TlsDirectTrustStore}, * {@link TlsDirectKeyStore} and {@link TlsIndirectKeyStore}, and then forward calls to the * interfaces to an instance of this class). * <p/> * <p>For setting System properties (and reading them) use {@link TlsPropertiesMapper}. This * can take a "namespace" which can then be used by {@link TlsPropertiesSocketFactory} to * construct an appropriate socket factory. This approach (storing to proeprties and then * retrieving that information later in a socket factory) lets us pass TLS/SSL configuration * into libraries that are configured by specifying on the socket factory class.</p> * <p/> * <h2>Direct and Indirect Socket and Store Creation</h2> * <p/> * For the SSL transport, which historically defined parameters for many different secure * transports, the configuration interfaces worked as follows: * <p/> * <dl> * <dt>{@link TlsDirectTrustStore}</dt><dd>Used to generate trust store directly and indirectly * for all TLS/SSL conections via System properties</dd> * <dt>{@link TlsDirectKeyStore}</dt><dd>Used to generate key store directly</dd> * <dt>{@link TlsIndirectKeyStore}</dt><dd>Used to generate key store indirectly for all * TLS/SSL conections via System properties</dd> * </dl> * <p/> * Historically, many other transports relied on the indirect configurations defined above. * So they implemented {@link org.mule.api.security.TlsIndirectTrustStore} * (a superclass of {@link TlsDirectTrustStore}) * and relied on {@link TlsIndirectKeyStore} from the SSL configuration. For continuity these * interfaces continue to be used, even though * the configurations are now typically (see individual connector/protocol documentation) specific * to a protocol or connector. <em>Note - these interfaces are new, but the original code had * those methods, used as described. The new interfaces only make things explicit.</em> * <p/> * <p><em>Note for programmers</em> One way to understand the above is to see that many * protocols are handled by libraries that are configured by providing either properties or * a socket factory. In both cases (the latter via {@link TlsPropertiesSocketFactory}) we * continue to use properties and the "indirect" interface. Note also that the mapping * in {@link TlsPropertiesMapper} correctly handles the asymmetry, so an initial call to * {@link TlsConfiguration} uses the keystore defined via {@link TlsDirectKeyStore}, but * when a {@link TlsConfiguration} is retrieved from System proerties using * {@link TlsPropertiesMapper#readFromProperties(TlsConfiguration,java.util.Properties)} * the "indirect" properties are supplied as "direct" values, meaning that the "indirect" * socket factory can be retrieved from {@link #getKeyManagerFactory()}. It just works.</p> */public final class TlsConfiguration implements TlsDirectTrustStore, TlsDirectKeyStore, TlsIndirectKeyStore, TlsProtocolHandler{ public static final String DEFAULT_KEYSTORE = ".keystore"; public static final String DEFAULT_KEYSTORE_TYPE = KeyStore.getDefaultType(); public static final String DEFAULT_SSL_TYPE = "SSLv3"; public static final String JSSE_NAMESPACE = "javax.net"; private Log logger = LogFactory.getLog(getClass()); private SecurityProviderFactory spFactory = new AutoDiscoverySecurityProviderFactory(); private SecurityProviderInfo spInfo = spFactory.getSecurityProviderInfo(); private Provider provider = spFactory.getProvider(); private String sslType = DEFAULT_SSL_TYPE; // global private String protocolHandler = spInfo.getProtocolHandler(); // this is the key store that is generated in-memory and available to connectors explicitly. // it is local to the socket. private String keyStoreName = DEFAULT_KEYSTORE; // was default in https but not ssl private String keyPassword = null; private String keyStorePassword = null; private String keystoreType = DEFAULT_KEYSTORE_TYPE; private String keyManagerAlgorithm = spInfo.getKeyManagerAlgorithm(); private KeyManagerFactory keyManagerFactory = null; // this is the key store defined in system properties that is used implicitly. // note that some transports use different namespaces within system properties, // so this is typically global across a particular transport. // it is also used as the trust store defined in system properties if no other trust // store is given and explicitTrustStoreOnly is false private String clientKeyStoreName = null; private String clientKeyStorePassword = null; private String clientKeyStoreType = DEFAULT_KEYSTORE_TYPE; // this is the trust store used to construct sockets both explicitly // and globally (if not set, see client key above) via the jvm defaults. private String trustStoreName = null; private String trustStorePassword = null; private String trustStoreType = DEFAULT_KEYSTORE_TYPE; private String trustManagerAlgorithm = spInfo.getKeyManagerAlgorithm(); private TrustManagerFactory trustManagerFactory = null; private boolean explicitTrustStoreOnly = false; private boolean requireClientAuthentication = false; /** * Support for TLS connections with a given initial value for the key store * * @param keyStore initial value for the key store */ public TlsConfiguration(String keyStore) { this.keyStoreName = keyStore; } // note - in what follows i'm using "raw" variables rather than accessors because // i think the names are clearer. the API names for the accessors are historical // and not a close fit to actual use (imho). /** * @param anon If the connection is anonymous then we don't care about client keys * @param namespace Namespace to use for global properties (for JSSE use JSSE_NAMESPACE) * @throws CreateException ON initialisation problems */ public void initialise(boolean anon, String namespace) throws CreateException { if (logger.isDebugEnabled()) { logger.debug("initialising: anon " + anon); } validate(anon); Security.addProvider(provider); System.setProperty("java.protocol.handler.pkgs", protocolHandler); if (!anon) { initKeyManagerFactory(); } initTrustManagerFactory(); if (null != namespace) { new TlsPropertiesMapper(namespace).writeToProperties(System.getProperties(), this); } } private void validate(boolean anon) throws CreateException { assertNotNull(getProvider(), "The security provider cannot be null"); if (!anon) { assertNotNull(getKeyStore(), "The KeyStore location cannot be null"); assertNotNull(getKeyPassword(), "The Key password cannot be null"); assertNotNull(getKeyStorePassword(), "The KeyStore password cannot be null"); assertNotNull(getKeyManagerAlgorithm(), "The Key Manager Algorithm cannot be null"); } } private void initKeyManagerFactory() throws CreateException { if (logger.isDebugEnabled()) { logger.debug("initialising key manager factory from keystore data"); } KeyStore tempKeyStore; try { tempKeyStore = KeyStore.getInstance(keystoreType); InputStream is = IOUtils.getResourceAsStream(keyStoreName, getClass()); if (null == is) { throw new FileNotFoundException( CoreMessages.cannotLoadFromClasspath("Keystore: " + keyStoreName).getMessage()); } tempKeyStore.load(is, keyStorePassword.toCharArray()); } catch (Exception e) { throw new CreateException( CoreMessages.failedToLoad("KeyStore: " + keyStoreName), e, this); } try { keyManagerFactory = KeyManagerFactory.getInstance(getKeyManagerAlgorithm()); keyManagerFactory.init(tempKeyStore, keyPassword.toCharArray()); } catch (Exception e) { throw new CreateException(CoreMessages.failedToLoad("Key Manager"), e, this); } } private void initTrustManagerFactory() throws CreateException { if (null != trustStoreName) { trustStorePassword = null == trustStorePassword ? "" : trustStorePassword; KeyStore trustStore; try { trustStore = KeyStore.getInstance(trustStoreType); InputStream is = IOUtils.getResourceAsStream(trustStoreName, getClass()); if (null == is) { throw new FileNotFoundException( "Failed to load truststore from classpath or local file: " + trustStoreName); } trustStore.load(is, trustStorePassword.toCharArray()); } catch (Exception e) { throw new CreateException( CoreMessages.failedToLoad("TrustStore: " + trustStoreName), e, this); } try { trustManagerFactory = TrustManagerFactory.getInstance(trustManagerAlgorithm); trustManagerFactory.init(trustStore); } catch (Exception e) { throw new CreateException( CoreMessages.failedToLoad("Trust Manager (" + trustManagerAlgorithm + ")"), e, this);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -