package org.jacorb.security.ssl.sun_jsse;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 2000-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.cert.CertStore;
import java.security.cert.CertStoreParameters;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.X509CRL;
import java.security.cert.X509CertSelector;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.net.SocketFactory;
import javax.net.ssl.CertPathTrustManagerParameters;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.jacorb.config.Configuration;
import org.jacorb.config.ConfigurationException;
import org.jacorb.orb.ORB;
import org.jacorb.orb.factory.AbstractSocketFactory;
import org.jacorb.orb.listener.SSLHandshakeListener;
import org.jacorb.orb.listener.SSLSessionListener;
/**
* a SocketFactory implementation that allows
* to create sockets that support SSL.
*
* @author Nicolas Noffke
*/
public class SSLSocketFactory
extends AbstractSocketFactory
{
private SocketFactory factory = null;
private String[] cipher_suites = null;
private String[] enabledProtocols = null;
private TrustManager trustManager = null;
private boolean trusteesFromKS = false;
private int clientSupportedOptions = 0;
private String keystore_location = null;
private String keystore_passphrase = null;
private final SSLSessionListener sslListener;
private SSLRandom sslRandom;
private String keystore_type = null;
private String keyManagerAlgorithm = null;
private String trustManagerAlgorithm = null;
// Bugzilla#883: added the PKCS11 and CRL support
private String keystore_provider = null; // e.g.: SunPKCS11-NSS
private String truststore_type = null;
private String truststore_location = null;
private String truststore_passphrase = null;
private String truststore_provider = null;
private boolean support_crl = false; // CRL support on/off
private String crl_file = null; // absolute path to the CRL file
public SSLSocketFactory(ORB orb)
{
sslListener = orb.getTransportManager().getSocketFactoryManager().getSSLListener();
}
public void configure(Configuration configuration)
throws ConfigurationException
{
super.configure(configuration);
sslRandom = new SSLRandom();
sslRandom.configure(configuration);
trusteesFromKS =
configuration.getAttributeAsBoolean("jacorb.security.jsse.trustees_from_ks", false);
keystore_location =
configuration.getAttribute("jacorb.security.keystore");
keystore_passphrase =
configuration.getAttribute("jacorb.security.keystore_password");
keystore_type=
configuration.getAttribute("jacorb.security.keystore_type", "JKS");
keystore_provider =
configuration.getAttribute("jacorb.security.keystore_provider", null);
truststore_type =
configuration.getAttribute("jacorb.security.truststore_type", null);
truststore_location =
configuration.getAttribute("jacorb.security.truststore", null);
truststore_passphrase =
configuration.getAttribute("jacorb.security.truststore_password", null);
truststore_provider =
configuration.getAttribute("jacorb.security.truststore_provider", null);
crl_file =
configuration.getAttribute("jacorb.security.crl_file", null);
support_crl =
configuration.getAttributeAsBoolean("jacorb.security.support_crl", false);
keyManagerAlgorithm =
configuration.getAttribute("jacorb.security.jsse.client.key_manager_algorithm","SunX509");
trustManagerAlgorithm =
configuration.getAttribute("jacorb.security.jsse.client.trust_manager_algorithm","SunX509");
clientSupportedOptions = configuration.getAttributeAsInteger("jacorb.security.ssl.client.supported_options", 0, 16);
try
{
trustManager = (TrustManager) ((org.jacorb.config.Configuration)configuration).getAttributeAsObject
("jacorb.security.ssl.client.trust_manager");
}
catch (ConfigurationException e)
{
if (logger.isErrorEnabled())
{
logger.error("TrustManager object creation failed. Please check value of property "
+ "'jacorb.security.ssl.client.trust_manager'. Current value: "
+ configuration.getAttribute("jacorb.security.ssl.client.trust_manager", ""), e);
}
}
if (configuration.getAttribute("jacorb.security.ssl.client.protocols", null) != null)
{
enabledProtocols =
configuration.getAttributeAsStringsArray ("jacorb.security.ssl.server.protocols");
if (logger.isDebugEnabled())
{
logger.debug("Setting user specified client enabled protocols : "
+ configuration.getAttribute("jacorb.security.ssl.client.protocols", ""));
}
}
try
{
factory = createSocketFactory();
}
catch( Exception e )
{
logger.error("Unable to create SSLSocketFactory!", e);
throw new ConfigurationException("Unable to create SSLSocketFactory!", e);
}
// Andrew T. Finnell / Change made for e-Security Inc. 2002
// We need to obtain all the cipher suites to use from the
// properties file.
cipher_suites =
configuration.getAttributeAsStringsArray ("jacorb.security.ssl.client.cipher_suites");
}
public Socket createSocket( String host,
int port )
throws IOException, UnknownHostException
{
SSLSocket socket = (SSLSocket)factory.createSocket( host, port );
initSSLSocket(socket);
return socket;
}
protected Socket doCreateSocket(String host, int port, int timeout) throws IOException
{
SSLSocket socket = (SSLSocket)factory.createSocket();
socket.connect(new InetSocketAddress(host, port), timeout);
initSSLSocket(socket);
return socket;
}
/**
* common ssl socket initialization
* @param socket
*/
private void initSSLSocket(SSLSocket socket)
{
// Andrew T. Finnell
// We need a way to enable the cipher suites that we would like to use
// We should obtain these from the properties file
if ( cipher_suites != null )
{
socket.setEnabledCipherSuites( cipher_suites );
}
if (enabledProtocols != null)
{
socket.setEnabledProtocols (enabledProtocols);
}
socket.addHandshakeCompletedListener(new SSLHandshakeListener(logger, sslListener));
}
public boolean isSSL( java.net.Socket socket )
{
return (socket instanceof SSLSocket);
}
private SocketFactory createSocketFactory()
throws IOException, java.security.GeneralSecurityException
{
KeyManagerFactory kmf = null;
KeyStore key_store = null;
if( trusteesFromKS || ( clientSupportedOptions & 0x40) != 0 )
{
key_store =
KeyStoreUtil.getKeyStore( keystore_location,
keystore_passphrase.toCharArray(),
keystore_type,
keystore_provider );
//only add own credentials, if establish trust in
//client is supported
if( ( clientSupportedOptions & 0x40) != 0 )
{
kmf = KeyManagerFactory.getInstance( keyManagerAlgorithm );
// Bugzilla #883: PKCS 11 and CRL support for SSL
// Password for "WINDOWS-MY" store type doesn't need to be set
if ( "WINDOWS-MY".equalsIgnoreCase( keystore_type ) )
{
kmf.init( key_store, null );
}
else
{
kmf.init( key_store, keystore_passphrase.toCharArray() );
}
}
}
TrustManagerFactory tmf =
TrustManagerFactory.getInstance( trustManagerAlgorithm );
KeyStore trust_store = null;
if ( trusteesFromKS )
{
trust_store = key_store;
}
else
{
if ( "PKCS11".equalsIgnoreCase( truststore_type ) )
{
trust_store = KeyStore.getInstance( truststore_type, truststore_provider );
trust_store.load( null, truststore_passphrase.toCharArray() );
}
else if ( "WINDOWS-ROOT".equalsIgnoreCase( truststore_type ) )
{
trust_store = KeyStore.getInstance( "WINDOWS-ROOT" );
trust_store.load( null, null );
}
else if (truststore_location != null && truststore_passphrase != null)
{
trust_store = KeyStoreUtil.getKeyStore( truststore_location,
truststore_passphrase.toCharArray(),
truststore_type,
truststore_provider);
}
}
if (trust_store != null)
{
//take trusted certificates from keystore
if (logger.isInfoEnabled())
{
logger.info("Loading trusted certs from keystore " + trust_store.getType() );
}
}
if ( trust_store != null && support_crl )
{
PKIXBuilderParameters pkixParams = null;
//create the selector to filter the trusted CA from others.
X509CertSelector x509CertSelector = new X509CertSelector();
x509CertSelector.setCertificateValid( new Date() );
pkixParams = new PKIXBuilderParameters( trust_store, x509CertSelector );
//the CRL file
InputStream crlFileStream = new FileInputStream( crl_file );
//the usage of the certificate
boolean[] keyUsage = {true};
x509CertSelector.setKeyUsage( keyUsage );
CertificateFactory crlf = CertificateFactory.getInstance( "X.509" );
X509CRL x509crl = (X509CRL) crlf.generateCRL( crlFileStream );
List list = new ArrayList();
list.add( x509crl );
CertStoreParameters cparam = new CollectionCertStoreParameters( list );
CertStore cs = CertStore.getInstance( "Collection", cparam );
//Specify that revocation checking is to be enabled
pkixParams.setRevocationEnabled( true );
//add the certificate store
pkixParams.addCertStore( cs );
//Wrap them as trust manager parameters
ManagerFactoryParameters trustParams = new CertPathTrustManagerParameters( pkixParams );
//Pass parameters to factory to be passed to CertPath implementation
tmf.init( trustParams );
}
else
{
tmf.init( trust_store );
}
TrustManager[] trustManagers;
if (trustManager == null)
{
trustManagers = tmf.getTrustManagers();
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("Setting user specified TrustManager for the client: " + trustManager.getClass().getName());
}
trustManagers = new TrustManager[] { trustManager };
}
SSLContext ctx = SSLContext.getInstance( "TLS" );
ctx.init( (kmf == null)? null : kmf.getKeyManagers(),
trustManagers,
sslRandom.getSecureRandom() );
return ctx.getSocketFactory();
}
}