/*
* JacORB - a free Java ORB
*
* Copyright (C) 1999-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.
*
*/
package org.jacorb.security.ssl.sun_jsse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.CRL;
import java.security.cert.CertPathParameters;
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.X509CertSelector;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import javax.net.ServerSocketFactory;
import javax.net.ssl.CertPathTrustManagerParameters;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.jacorb.config.Configurable;
import org.jacorb.config.Configuration;
import org.jacorb.config.ConfigurationException;
/**
* @author Nicolas Noffke
*/
public class SSLServerSocketFactory
extends SSLRandom
implements org.jacorb.orb.factory.ServerSocketFactory, Configurable
{
private ServerSocketFactory factory = null;
private boolean require_mutual_auth = false;
private boolean request_mutual_auth = false;
private boolean trusteesFromKS = false;
private String[] cipher_suites = null;
private String[] enabledProtocols = null;
private TrustManager trustManager = null;
private int serverSupportedOptions = 0;
private int serverRequiredOptions = 0;
private String keystore_location = null;
private String keystore_passphrase = null;
private String keystore_type = null;
private String keyManagerAlgorithm = null;
private String trustManagerAlgorithm = null;
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 void configure(Configuration configuration)
throws ConfigurationException
{
super.configure(configuration);
final org.jacorb.config.Configuration config = (org.jacorb.config.Configuration) configuration;
trusteesFromKS =
configuration.getAttributeAsBoolean("jacorb.security.jsse.trustees_from_ks", false);
serverSupportedOptions = configuration.getAttributeAsInteger("jacorb.security.ssl.server.supported_options", 0x20, 16); // 16 is the base as we take the string value as hex!
serverRequiredOptions = configuration.getAttributeAsInteger("jacorb.security.ssl.server.required_options", 0, 16);
if( (serverSupportedOptions & 0x40) != 0 )
{
// would prefer to establish trust in client. If client can
// support authentication, it will, otherwise we will continue
if (logger.isInfoEnabled())
logger.info("Will create SSL sockets that request client authentication" );
request_mutual_auth = true;
}
if( (serverRequiredOptions & 0x40) != 0 )
{
//required: establish trust in client
//--> force other side to authenticate
require_mutual_auth = true;
request_mutual_auth = false;
if (logger.isInfoEnabled())
logger.info("Will create SSL sockets that require client authentication" );
}
keystore_location =
configuration.getAttribute("jacorb.security.keystore");
keystore_passphrase =
configuration.getAttribute("jacorb.security.keystore_password");
keystore_type=
configuration.getAttribute("jacorb.security.keystore_type", "JKS");
keyManagerAlgorithm =
configuration.getAttribute("jacorb.security.jsse.server.key_manager_algorithm","SunX509");
trustManagerAlgorithm =
configuration.getAttribute("jacorb.security.jsse.server.trust_manager_algorithm","SunX509");
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);
try
{
trustManager = (TrustManager) ((org.jacorb.config.Configuration)configuration).getAttributeAsObject
("jacorb.security.ssl.server.trust_manager");
}
catch (ConfigurationException ce)
{
if (logger.isErrorEnabled())
{
logger.error("TrustManager object creation failed. Please check value of property "
+ "'jacorb.security.ssl.server.trust_manager'. Current value: "
+ configuration.getAttribute("jacorb.security.ssl.server.trust_manager", ""), ce);
}
}
enabledProtocols = configuration.getAttributeAsStringsArray ("jacorb.security.ssl.server.protocols");
if (enabledProtocols != null && logger.isDebugEnabled())
{
logger.debug("Setting user specified server enabled protocols : " +
configuration.getAttribute("jacorb.security.ssl.server.protocols", ""));
}
try
{
factory = createServerSocketFactory();
}
catch(Exception e)
{
logger.warn("Unable to create ServerSocketFactory : {}", e.getMessage (), e);
throw new ConfigurationException("Unable to create ServerSocketFactory!", e);
}
// Andrew T. Finnell
// We need to obtain all the cipher suites to use from the
// properties file.
cipher_suites = config.getAttributeAsStringsArray ("jacorb.security.ssl.server.cipher_suites");
}
public ServerSocket createServerSocket( int port )
throws IOException
{
SSLServerSocket s = (SSLServerSocket)
factory.createServerSocket( port );
if (request_mutual_auth)
{
s.setWantClientAuth (request_mutual_auth);
}
else if (require_mutual_auth)
{
s.setNeedClientAuth( require_mutual_auth );
}
// Andrew T. Finnell / Change made for e-Security Inc. 2002
// 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)
{
s.setEnabledCipherSuites ( cipher_suites );
}
if (enabledProtocols != null)
{
s.setEnabledProtocols (enabledProtocols);
}
return s;
}
public ServerSocket createServerSocket( int port, int backlog )
throws IOException
{
SSLServerSocket s = (SSLServerSocket)
factory.createServerSocket( port, backlog );
if (request_mutual_auth)
{
s.setWantClientAuth (request_mutual_auth);
}
else if (require_mutual_auth)
{
s.setNeedClientAuth( require_mutual_auth );
}
// Andrew T. Finnell / Change made for e-Security Inc. 2002
// 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)
{
s.setEnabledCipherSuites (cipher_suites);
}
if (enabledProtocols != null)
{
s.setEnabledProtocols (enabledProtocols);
}
return s;
}
public ServerSocket createServerSocket (int port,
int backlog,
InetAddress ifAddress)
throws IOException
{
SSLServerSocket s = (SSLServerSocket)
factory.createServerSocket( port, backlog, ifAddress );
if (request_mutual_auth)
{
s.setWantClientAuth (request_mutual_auth);
}
else if (require_mutual_auth)
{
s.setNeedClientAuth( require_mutual_auth );
}
// Andrew T. Finnell / Change made for e-Security Inc. 2002
// 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)
{
s.setEnabledCipherSuites (cipher_suites);
}
if (enabledProtocols != null)
{
s.setEnabledProtocols (enabledProtocols);
}
return s;
}
public boolean isSSL( java.net.ServerSocket s )
{
return (s instanceof SSLServerSocket);
}
private ServerSocketFactory createServerSocketFactory()
throws IOException, java.security.GeneralSecurityException
{
KeyStore key_store =
KeyStoreUtil.getKeyStore( keystore_location,
keystore_passphrase.toCharArray(),
keystore_type,
keystore_provider);
KeyManagerFactory 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 = null;
KeyStore trust_store = null;
//only add trusted certs, if establish trust in client
//is required
if(( serverRequiredOptions & 0x40) != 0 ||
( serverSupportedOptions & 0x40) != 0)
{
tmf = TrustManagerFactory.getInstance (trustManagerAlgorithm);
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);
}
logger.debug ("SSLServerSocketFactory: loaded trust store: "
+ ((trust_store != null) ? trust_store.getProvider() : "default (null)"));
}
if( trust_store != null && support_crl )
{
CertPathParameters pkixParams = null;
//create the selector to filter the trusted CA from others.
X509CertSelector x509CertSelector = new X509CertSelector();
x509CertSelector.setCertificateValid( new Date() );
PKIXBuilderParameters xparams = new PKIXBuilderParameters( trust_store, x509CertSelector );
Collection<? extends CRL> crls = getCRLs();
CertStoreParameters cparam = new CollectionCertStoreParameters( crls );
CertStore cs = CertStore.getInstance( "Collection", cparam );
//Specify that revocation checking is to be enabled
xparams.setRevocationEnabled( true );
//add the certificate store
xparams.addCertStore( cs );
pkixParams = xparams;
//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 == null) ? null : tmf.getTrustManagers();
}
else
{
trustManagers = new TrustManager[] { trustManager };
if (logger.isDebugEnabled())
{
logger.debug("Setting user specified server TrustManger : " + trustManager.getClass().toString());
}
}
SSLContext ctx = SSLContext.getInstance( "TLS" );
ctx.init( kmf.getKeyManagers(),
trustManagers,
getSecureRandom());
return ctx.getServerSocketFactory();
}
private Collection<? extends CRL> getCRLs () throws IOException, GeneralSecurityException
{
logger.debug( "SSLServerSocketFactory: Loading the CRLs from file: " + crl_file );
File crlFile = new File( crl_file );
Collection <? extends CRL> crls = null;
InputStream is = null;
try
{
CertificateFactory cf = CertificateFactory.getInstance( "X.509" );
is = new FileInputStream( crlFile );
crls = cf.generateCRLs( is );
if (logger.isDebugEnabled ())
{
logger.debug ("SSLServerSocketFactory: Found CLRs:");
Iterator <? extends CRL> it = crls.iterator ();
while (it.hasNext ())
{
logger.debug (it.next().toString ());
}
}
}
catch ( IOException ex )
{
logger.error ("SSLServerSocketFactory: CLRs loading failed: ", ex);
throw ex;
}
catch (GeneralSecurityException gse)
{
logger.error ("SSLServerSocketFactory: CLRs security error: ", gse);
throw gse;
}
finally
{
if (is != null)
{
try
{
is.close ();
}
catch (Exception ex) { /* ignored */ }
}
}
return crls;
}
}