com.tangosol.internal.net.ssl.LegacyXmlSSLSocketProviderDependencies Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of coherence Show documentation
Show all versions of coherence Show documentation
Oracle Coherence Community Edition
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.internal.net.ssl;
import com.oracle.coherence.common.net.SSLSocketProvider;
import com.oracle.coherence.common.net.SocketProvider;
import com.tangosol.coherence.config.ParameterMacroExpressionParser;
import com.tangosol.coherence.config.builder.ParameterizedBuilder;
import com.tangosol.coherence.config.xml.OperationalConfigNamespaceHandler;
import com.tangosol.coherence.config.xml.processor.PasswordProviderBuilderProcessor;
import com.tangosol.config.xml.DefaultProcessingContext;
import com.tangosol.config.xml.DocumentProcessor;
import com.tangosol.net.PasswordProvider;
import com.tangosol.net.SocketProviderFactory;
import com.tangosol.run.xml.XmlElement;
import com.tangosol.run.xml.XmlHelper;
import com.tangosol.run.xml.XmlValue;
import com.tangosol.util.Base;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Provider;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
/**
* Dependency parses the ssl xml snippet that defines the
* SSL Socket Provider configuration.
*
* Replaced by injectable {@link SSLSocketProviderDefaultDependencies}.
*
* @author bb 2011.11.21
* @since Coherence 12.1.2
* @deprecated
*/
public class LegacyXmlSSLSocketProviderDependencies
extends SSLSocketProvider.DefaultDependencies
{
/**
* Construct LegacyXmlSSLSocketProviderDependencies object based on the given XMLElement
*
* @param xml XMLElement for ssl config
*/
public LegacyXmlSSLSocketProviderDependencies(XmlElement xml)
{
this(xml, null);
}
/**
* Construct LegacyXmlSSLSocketProviderDependencies object
*
* @param xml XMLElement for ssl config
* @param dependencies SocketProviderFactory dependencies
*/
public LegacyXmlSSLSocketProviderDependencies(XmlElement xml, SocketProviderFactory.Dependencies dependencies)
{
if (xml == null)
{
throw new IllegalArgumentException("Null xml");
}
m_xml = xml;
m_DependenciesProviderFactory = (dependencies == null)
? new SocketProviderFactory.DefaultDependencies()
: dependencies;
}
/**
* {@inheritDoc}
*/
@Override
public SocketProvider getDelegateSocketProvider()
{
ensureConfigured();
return super.getDelegateSocketProvider();
}
/**
* {@inheritDoc}
*/
@Override
public SSLContext getSSLContext()
{
ensureConfigured();
return super.getSSLContext();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isClientAuthenticationRequired()
{
ensureConfigured();
return super.isClientAuthenticationRequired();
}
/**
* {@inheritDoc}
*/
@Override
public HostnameVerifier getHostnameVerifier()
{
ensureConfigured();
return super.getHostnameVerifier();
}
/**
* {@inheritDoc}
*/
@Override
public String[] getEnabledCipherSuites()
{
ensureConfigured();
return super.getEnabledCipherSuites();
}
/**
* {@inheritDoc}
*/
@Override
public String[] getEnabledProtocolVersions()
{
ensureConfigured();
return super.getEnabledProtocolVersions();
}
/**
* {@inheritDoc}
*/
@Override
public Executor getExecutor()
{
ensureConfigured();
return super.getExecutor();
}
/**
* {@inheritDoc}
*/
@Override
public Logger getLogger()
{
ensureConfigured();
return super.getLogger();
}
/**
* Check if xml snippet has been parsed
*/
protected void ensureConfigured()
{
if (!m_fConfigured)
{
synchronized (m_xml)
{
applyConfig(m_xml);
m_fConfigured = true;
}
}
}
/**
*
* Parse XMLElement
*/
protected void applyConfig(XmlElement xml)
{
StringBuffer sbDesc = new StringBuffer();
try
{
SSLContext ctx = null;
KeyManager[] aKeyManager = null;
TrustManager[] aTrustManager = null;
// TLS
String sProtocol = xml.ensureElement("protocol").getString(
DEFAULT_SSL_PROTOCOL);
//
// MyProvider
// com.foo.bar.SSLProvider
// com.foo.bar.SSLProviderFactory
// createInstance
//
//
// String
// MyValue
//
//
//
XmlElement xmlChild = xml.getElement("provider");
if (xmlChild != null)
{
String sProvider = xmlChild.ensureElement("name").getString(null);
Provider provider = instantiateProvider(xmlChild);
if (provider == null)
{
if (sProvider != null)
{
ctx = SSLContext.getInstance(sProtocol, sProvider);
}
}
else
{
ctx = SSLContext.getInstance(sProtocol, provider);
}
}
if (ctx == null)
{
ctx = SSLContext.getInstance(sProtocol);
}
m_ctx = ctx;
//
// com.foo.bar.Executor
// com.foo.bar.ExecutorFactory
// createInstance
//
//
// String
// MyValue
//
//
//
xmlChild = xml.getElement("executor");
if (xmlChild != null)
{
if (XmlHelper.isInstanceConfigEmpty(xmlChild))
{
m_executor = SSLSocketProviderDefaultDependencies.DEFAULT_EXECUTOR;
}
else
{
m_executor = (Executor)
XmlHelper.createInstance(xmlChild, null, null);
}
}
//
// SunX509
//
// MyProvider
// com.foo.bar.SSLProvider
// com.foo.bar.SSLProviderFactory
// createInstance
//
//
// String
// MyValue
//
//
//
//
// file:.identity.jks
// password
// JKS
//
// password
//
xmlChild = xml.getElement("identity-manager");
if (xmlChild == null)
{
sbDesc.append("identity=unspecified");
}
else
{
sbDesc.append("identity=");
String sAlgorithm = xmlChild.ensureElement("algorithm")
.getString(DEFAULT_IDENTITY_ALGORITHM);
sbDesc.append(sAlgorithm);
KeyManagerFactory factory = null;
XmlElement xmlProvider = xmlChild.getElement("provider");
if (xmlProvider != null)
{
String sProvider = xmlProvider.ensureElement("name").getString(null);
Provider provider = instantiateProvider(xmlProvider);
if (provider == null)
{
if (sProvider != null)
{
factory = KeyManagerFactory.getInstance(sAlgorithm, sProvider);
}
}
else
{
factory = KeyManagerFactory.getInstance(sAlgorithm, provider);
}
}
if (factory == null)
{
factory = KeyManagerFactory.getInstance(sAlgorithm);
}
XmlElement xmlStore = xmlChild.ensureElement("key-store");
String sPassword = xmlChild.ensureElement("password").getString(null);
char[] achPassword = null;
if (sPassword == null)
{
achPassword = getPwdFromProvider(xmlChild);
}
else
{
achPassword = sPassword.toCharArray();
}
String sURL = xmlStore.ensureElement("url").getString(null);
String sStorePassword = xmlStore.ensureElement("password").getString(null);
char[] achStorePassword = null;
if (sStorePassword == null)
{
achStorePassword = getPwdFromProvider(xmlStore);
}
else
{
achStorePassword = sStorePassword.toCharArray();
}
KeyStore keyStore = loadKeyStore(sURL,
achStorePassword,
xmlStore.ensureElement("type").getString(DEFAULT_KEYSTORE_TYPE));
if (sURL != null && sURL.length() > 0)
{
sbDesc.append('/')
.append(sURL);
}
// clear out passwords
if (sPassword != null)
{
xmlChild.ensureElement("password").setString(null);
}
if (sStorePassword != null)
{
xmlStore.ensureElement("password").setString(null);
}
factory.init(keyStore, achPassword);
aKeyManager = factory.getKeyManagers();
}
//
// SunX509
//
// MyProvider
// com.foo.bar.SSLProvider
// com.foo.bar.SSLProviderFactory
// createInstance
//
//
// String
// MyValue
//
//
//
//
// file:.trust.jks
// password
// JKS
//
//
xmlChild = xml.getElement("trust-manager");
if (xmlChild == null || xmlChild.getElementList().isEmpty())
{
sbDesc.append(", trust=unspecified");
}
else
{
sbDesc.append(", trust=");
String sAlgorithm = xmlChild.ensureElement("algorithm")
.getString(DEFAULT_TRUST_ALGORITHM);
sbDesc.append(sAlgorithm);
TrustManagerFactory factory = null;
XmlElement xmlProvider = xmlChild.getElement("provider");
if (xmlProvider != null)
{
String sProvider = xmlProvider.ensureElement("name").getString(null);
Provider provider = instantiateProvider(xmlProvider);
if (provider == null)
{
if (sProvider != null)
{
factory = TrustManagerFactory.getInstance(sAlgorithm, sProvider);
}
}
else
{
factory = TrustManagerFactory.getInstance(sAlgorithm, provider);
}
}
if (factory == null)
{
factory = TrustManagerFactory.getInstance(sAlgorithm);
}
XmlElement xmlStore = xmlChild.ensureElement("key-store");
String sURL = xmlStore.ensureElement("url").getString(null);
String sTrustPassword = xmlStore.ensureElement("password").getString(null);
char[] achTrustPassword = null;
if (sTrustPassword == null)
{
achTrustPassword = getPwdFromProvider(xmlStore);
}
else
{
achTrustPassword = sTrustPassword.toCharArray();
}
KeyStore keyStore = loadKeyStore(sURL,
achTrustPassword,
xmlStore.ensureElement("type").getString(DEFAULT_KEYSTORE_TYPE));
if (sURL != null && sURL.length() > 0)
{
sbDesc.append('/')
.append(sURL);
}
// clear out passwords
if (sTrustPassword != null)
{
xmlStore.ensureElement("password").setString(null);
}
factory.init(keyStore);
aTrustManager = factory.getTrustManagers();
m_fClientAuthRequired = aTrustManager != null;
}
//
// com.foo.bar.HostnameVerifier
// com.foo.bar.HostnameVerifierFactory
// createInstance
//
//
// String
// MyValue
//
//
//
xmlChild = xml.getElement("hostname-verifier");
if (xmlChild != null)
{
m_hostnameVerifier = (HostnameVerifier)
XmlHelper.createInstance(xmlChild, null, null);
sbDesc.append(", hostname-verifier=enabled");
}
// intialize a random number source
SecureRandom random = new SecureRandom();
random.nextInt();
// initialize the SSLContext
ctx.init(aKeyManager, aTrustManager, random);
//
// cipher-1
// cipher-2
// ...
//
//
xmlChild = xml.getElement("cipher-suites");
if (xmlChild != null)
{
ArrayList listCipher = new ArrayList();
for (Iterator iter = xmlChild.getElements("name");
iter.hasNext(); )
{
listCipher.add(((XmlElement) iter.next()).getValue());
}
XmlValue xmlValue = xmlChild.getAttribute("usage");
if (xmlValue != null && xmlValue.getString().equals("black-list"))
{
SSLEngine engine = ctx.createSSLEngine();
ArrayList listDefaultCiphers = new ArrayList(Arrays.asList(engine.getEnabledCipherSuites()));
listDefaultCiphers.removeAll(listCipher);
listCipher = listDefaultCiphers;
}
m_asCipherSuitesEnabled = (String[]) listCipher.toArray(
new String[listCipher.size()]);
}
//
// protocol-version1
// protocol-version2
// ...
//
//
xmlChild = xml.getElement("protocol-versions");
if (xmlChild != null)
{
ArrayList listProtocol = new ArrayList();
for (Iterator iter = xmlChild.getElements("name");
iter.hasNext(); )
{
listProtocol.add(((XmlElement) iter.next()).getValue());
}
XmlValue xmlValue = xmlChild.getAttribute("usage");
if (xmlValue != null && xmlValue.getString().equals("black-list"))
{
SSLEngine engine = ctx.createSSLEngine();
ArrayList listDefaultProtocols = new ArrayList(Arrays.asList(engine.getEnabledProtocols()));
listDefaultProtocols.removeAll(listProtocol);
listProtocol = listDefaultProtocols;
}
m_asProtocolVersionsEnabled = (String[]) listProtocol.toArray(
new String[listProtocol.size()]);
}
// delegate socket-provider
// check if socket-provider element is present
xmlChild = xml.getElement("socket-provider");
if (xmlChild == null)
{
setDelegate(m_DependenciesProviderFactory.getSocketProviderFactory().DEFAULT_SOCKET_PROVIDER);
}
else
{
setDelegate(m_DependenciesProviderFactory.getSocketProviderFactory().getSocketProvider(xmlChild));
}
String sAuth =
aKeyManager == null && aTrustManager == null ? "none"
: aKeyManager == null && aTrustManager != null ? "one-way client"
: aKeyManager != null && aTrustManager == null ? "one-way server"
: "two-way";
m_sDescription = sbDesc.insert(0,"SSLSocketProvider(auth=" + sAuth + ", ")
.append(')').toString();
}
catch (GeneralSecurityException e)
{
throw new IllegalArgumentException("Invalid configuration: " + xml, e);
}
catch (IOException e)
{
throw Base.ensureRuntimeException(e);
}
}
// ----- helpers -----------------------------------------------------
/**
* Instantiate and return an instance of a security provider using an
* XML configuration of the following form:
*
*
* <provider>
* <class-name>com.foo.bar.Provider</class-name>
* <class-factory-name>com.foo.bar.ProviderFactory</class-factory-name>
* <method-name>createInstance</method-name>
* <init-params>
* <init-param>
* <param-type>String</param-type>
* <param-value>MyValue</param-value>
* </init-param>
* </init-params>
* </provider>
*
*
* @param xml the XML configuration describing the provider to instantiate
*
* @return a new security provider
*/
protected Provider instantiateProvider(XmlElement xml)
{
if (XmlHelper.isInstanceConfigEmpty(xml))
{
return null;
}
return (Provider) XmlHelper.createInstance(xml, null, null);
}
/**
* Utility method for loading a keystore.
*
* @param sURL the URL of the keystore to load
* @param sPassword the opitonal password for the keystore
* @param sType the keystore type
*
* @throws GeneralSecurityException on keystore access error
* @throws IOException on I/O error
*
* @return the keystore
*/
protected KeyStore loadKeyStore(String sURL, String sPassword, String sType)
throws GeneralSecurityException, IOException
{
return loadKeyStore(sURL,
sPassword == null || sPassword.length() == 0 ? null : sPassword.toCharArray(), sType);
}
/**
* Utility method for loading a keystore.
*
* @param sURL the URL of the keystore to load
* @param achPassword the opitonal password for the keystore
* @param sType the keystore type
*
* @throws GeneralSecurityException on keystore access error
* @throws IOException on I/O error
*
* @return the keystore
*/
protected KeyStore loadKeyStore(String sURL, char[] achPassword, String sType)
throws GeneralSecurityException, IOException
{
if (sURL == null || sURL.length() == 0)
{
return null;
}
KeyStore keyStore = KeyStore.getInstance(sType);
InputStream in = null;
try
{
ClassLoader loader = this.getClass().getClassLoader();
in = loader.getResourceAsStream(new URL(sURL).getFile());
if (in == null)
{
in = new URL(sURL).openStream();
}
keyStore.load(in, achPassword);
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException e) {}
}
}
return keyStore;
}
protected char[] getPwdFromProvider(XmlElement xmlProvider)
{
XmlElement xmlPwdProvider = xmlProvider.ensureElement("password-provider");
if (xmlPwdProvider != null)
{
OperationalConfigNamespaceHandler nsHandler = new OperationalConfigNamespaceHandler();
DocumentProcessor.Dependencies dependencies =
new DocumentProcessor.DefaultDependencies(nsHandler)
.setExpressionParser(new ParameterMacroExpressionParser());
DefaultProcessingContext ctx = new DefaultProcessingContext(dependencies, null);
ctx.ensureNamespaceHandler("", nsHandler);
ParameterizedBuilder bldr = new PasswordProviderBuilderProcessor().process(ctx, xmlPwdProvider);
return bldr.realize(null, null, null).get();
}
return null;
}
// ----- Object methods ----------------------------------------------
/**
* {@inheritDoc}
*/
public String toString()
{
return m_sDescription;
}
// ----- data members ------------------------------------------------
/**
* The description of the provider.
*/
protected String m_sDescription = "SSLSocketProvider()";
/**
* Check if the xml has been parsed
*/
protected volatile boolean m_fConfigured;
/**
* SSL Xml config snippet
*/
protected XmlElement m_xml;
/**
* SocketProviderFactory dependencies
*/
protected SocketProviderFactory.Dependencies m_DependenciesProviderFactory;
// ----- constants ------------------------------------------------------
/**
* The name of the XmlElement in which the provider configuration is
* specified.
*/
public static final String XML_NAME = "ssl";
/**
* The default SSL protocol.
*/
public static final String DEFAULT_SSL_PROTOCOL = "TLS";
/**
* The default identity management algorithm.
*/
public static final String DEFAULT_IDENTITY_ALGORITHM = "SunX509";
/**
* The default trust management algorithm.
*/
public static final String DEFAULT_TRUST_ALGORITHM = "SunX509";
/**
* The default keystore type.
*/
public static final String DEFAULT_KEYSTORE_TYPE = "JKS";
}