/* * 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; } }