Commit f3c3d13e authored by Guus der Kinderen's avatar Guus der Kinderen

OF-946: Jetty SslContextFactory instantion should not be duplicated.

SSLConfig can now be used to get a consistently configured Jetty SSL configuration.
parent 938c0f26
......@@ -148,23 +148,10 @@ public class AdminConsolePlugin implements Plugin {
Log.warn("Admin console: Using RSA certificates but they are not valid for the hosted domain");
}
final TrustStoreConfig trustStoreConfig = SSLConfig.getInstance().getTrustStoreConfig( Purpose.WEBADMIN );
final SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setTrustStorePath( trustStoreConfig.getCanonicalPath() );
sslContextFactory.setTrustStorePassword( trustStoreConfig.getPassword() );
sslContextFactory.setTrustStoreType( trustStoreConfig.getType() );
sslContextFactory.setKeyStorePath( identityStoreConfig.getCanonicalPath() );
sslContextFactory.setKeyStorePassword( identityStoreConfig.getPassword() );
sslContextFactory.setKeyStoreType( identityStoreConfig.getType() );
sslContextFactory.addExcludeProtocols( "SSLv3" );
sslContextFactory.setNeedClientAuth( false );
sslContextFactory.setWantClientAuth( false );
final SslContextFactory sslContextFactory = SSLConfig.getSslContextFactory( Purpose.WEBADMIN );
final ServerConnector httpsConnector;
if ("npn".equals(JiveGlobals.getXMLProperty("spdy.protocol", "")))
{
if ("npn".equals(JiveGlobals.getXMLProperty("spdy.protocol", ""))) {
httpsConnector = new HTTPSPDYServerConnector(adminServer, sslContextFactory);
} else {
......
......@@ -64,6 +64,7 @@ import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.keystore.IdentityStoreConfig;
import org.jivesoftware.openfire.keystore.Purpose;
import org.jivesoftware.openfire.keystore.CertificateStoreConfig;
import org.jivesoftware.openfire.keystore.TrustStoreConfig;
import org.jivesoftware.openfire.net.SSLConfig;
import org.jivesoftware.openfire.session.ConnectionSettings;
import org.jivesoftware.util.CertificateEventListener;
......@@ -259,38 +260,15 @@ public final class HttpBindManager {
"the hosted domain");
}
final TrustStoreConfig trustStoreConfig = SSLConfig.getInstance().getTrustStoreConfig( Purpose.BOSH_C2S );
final SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setTrustStorePath( trustStoreConfig.getCanonicalPath() );
sslContextFactory.setTrustStorePassword( trustStoreConfig.getPassword() );
sslContextFactory.setTrustStoreType( trustStoreConfig.getType() );
sslContextFactory.setKeyStorePath( identityStoreConfig.getCanonicalPath() );
sslContextFactory.setKeyStorePassword( identityStoreConfig.getPassword() );
sslContextFactory.setKeyStoreType( identityStoreConfig.getType() );
sslContextFactory.addExcludeProtocols( "SSLv3" );
// Set policy for checking client certificates
String certPol = JiveGlobals.getProperty(HTTP_BIND_AUTH_PER_CLIENTCERT_POLICY, "disabled");
if(certPol.equals("needed")) {
sslContextFactory.setNeedClientAuth(true);
sslContextFactory.setWantClientAuth(true);
} else if(certPol.equals("wanted")) {
sslContextFactory.setNeedClientAuth(false);
sslContextFactory.setWantClientAuth(true);
} else {
sslContextFactory.setNeedClientAuth(false);
sslContextFactory.setWantClientAuth(false);
}
final SslContextFactory sslContextFactory = SSLConfig.getSslContextFactory( Purpose.BOSH_C2S );
HttpConfiguration httpsConfig = new HttpConfiguration();
final HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.setSecureScheme("https");
httpsConfig.setSecurePort(securePort);
configureProxiedConnector(httpsConfig);
httpsConfig.addCustomizer(new SecureRequestCustomizer());
ServerConnector sslConnector = null;
final ServerConnector sslConnector;
if ("npn".equals(JiveGlobals.getXMLProperty("spdy.protocol", "")))
{
......
......@@ -4,6 +4,7 @@ import org.jivesoftware.util.JiveGlobals;
import java.io.File;
import java.io.IOException;
import java.util.Set;
/**
* Potential intended usages (for TLS connectivity).
......@@ -138,7 +139,7 @@ public enum Purpose
public String getIdentityStoreLocation() throws IOException
{
return canonicalize( getIdentityStoreLocation() );
return canonicalize( getIdentityStoreLocationNonCanonicalized() );
}
public String getIdentityStoreLocationNonCanonicalized()
......@@ -158,7 +159,7 @@ public enum Purpose
public String getTrustStoreLocation() throws IOException
{
return canonicalize( getTrustStoreLocation() );
return canonicalize( getTrustStoreLocationNonCanonicalized() );
}
public String getTrustStoreLocationNonCanonicalized()
......@@ -176,6 +177,67 @@ public enum Purpose
}
}
public String getProtocolsEnabled()
{
final String propertyName = prefix + "protocols.enabled";
final String defaultValue = "TLSv1,TLSv1.1,TLSv1.2";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getProtocolsEnabled() ).trim();
}
}
public String getProtocolsDisabled()
{
final String propertyName = prefix + "protocols.disabled";
final String defaultValue = "SSLv1,SSLv2,SSLv2Hello,SSLv3";
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getProtocolsDisabled() ).trim();
}
}
public String getCipherSuitesEnabled()
{
final String propertyName = prefix + "ciphersuites.enabled";
final String defaultValue = "";
final String result;
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue );
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getCipherSuitesEnabled() );
}
}
public String getCipherSuitesDisabled()
{
final String propertyName = prefix + "ciphersuites.disabled";
final String defaultValue = null;
if ( fallback == null )
{
return JiveGlobals.getProperty( propertyName, defaultValue ).trim();
}
else
{
return JiveGlobals.getProperty( propertyName, fallback.getCipherSuitesDisabled() ).trim();
}
}
public static String canonicalize( String path ) throws IOException
{
File file = new File( path );
......
......@@ -21,6 +21,7 @@
package org.jivesoftware.openfire.net;
import org.apache.mina.filter.ssl.SslFilter;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.keystore.*;
import org.jivesoftware.openfire.session.ConnectionSettings;
......@@ -406,7 +407,6 @@ public class SSLConfig
final SSLContext sslContext = SSLContext.getInstance( purpose.getIdentityStoreType() );
sslContext.init( keyManagers, trustManagers, new SecureRandom() );
return sslContext;
}
......@@ -473,12 +473,89 @@ public class SSLConfig
final SSLContext sslContext = getSSLContext( purpose );
final SSLEngine sslEngine = sslContext.createSSLEngine();
configureProtocols( sslEngine, purpose );
configureCipherSuites( sslEngine, purpose );
// Configure protocol support.
if ( purpose.getProtocolsEnabled() != null && !purpose.getProtocolsEnabled().isEmpty() )
{
// When an explicit list of enabled protocols is defined, use only those.
sslEngine.setEnabledProtocols( purpose.getProtocolsEnabled().split( "," ) );
}
else if ( purpose.getProtocolsDisabled() != null && !purpose.getProtocolsDisabled().isEmpty() )
{
// Otherwise, use all supported protocols (except for the ones that are explicitly disabled).
final List<String> disabled = Arrays.asList( purpose.getProtocolsDisabled() );
final ArrayList<String> supported = new ArrayList<>( );
for ( final String candidate : sslEngine.getSupportedProtocols() ) {
if ( !disabled.contains( candidate ) ) {
supported.add( candidate );
}
}
sslEngine.setEnabledProtocols( supported.toArray( new String[ supported.size()] ) );
}
// Configure cipher suite support.
if ( purpose.getCipherSuitesEnabled() != null && !purpose.getCipherSuitesEnabled().isEmpty() )
{
// When an explicit list of enabled protocols is defined, use only those.
sslEngine.setEnabledCipherSuites( purpose.getCipherSuitesEnabled().split( "," ) );
}
else if ( purpose.getCipherSuitesDisabled() != null && !purpose.getCipherSuitesDisabled().isEmpty() )
{
// Otherwise, use all supported cipher suites (except for the ones that are explicitly disabled).
final List<String> disabled = Arrays.asList( purpose.getCipherSuitesDisabled() );
final ArrayList<String> supported = new ArrayList<>( );
for ( final String candidate : sslEngine.getSupportedCipherSuites() ) {
if ( !disabled.contains( candidate ) ) {
supported.add( candidate );
}
}
sslEngine.setEnabledCipherSuites( supported.toArray( new String[ supported.size() ] ) );
}
// TODO: Set policy for checking client certificates
return sslEngine;
}
public static SslContextFactory getSslContextFactory( final Purpose purpose )
{
final SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setTrustStore( SSLConfig.getTrustStore( purpose ) );
sslContextFactory.setKeyStore( SSLConfig.getIdentityStore( purpose ) );
// Configure protocol and cipher suite support.
if ( purpose.getProtocolsEnabled() != null ) {
sslContextFactory.setIncludeProtocols( purpose.getProtocolsEnabled().split( "," ) );
}
if ( purpose.getProtocolsDisabled() != null ) {
sslContextFactory.setExcludeProtocols( purpose.getProtocolsDisabled().split( "," ) );
}
if ( purpose.getCipherSuitesEnabled() != null) {
sslContextFactory.setIncludeCipherSuites( purpose.getCipherSuitesEnabled().split( "," ) );
}
if ( purpose.getCipherSuitesDisabled() != null ) {
sslContextFactory.setExcludeCipherSuites( purpose.getCipherSuitesDisabled().split( "," ) );
}
// TODO: Set policy for checking client certificates
// String certPol = JiveGlobals.getProperty(HTTP_BIND_AUTH_PER_CLIENTCERT_POLICY, "disabled");
// if(certPol.equals("needed")) {
// sslContextFactory.setNeedClientAuth(true);
// sslContextFactory.setWantClientAuth(true);
// } else if(certPol.equals("wanted")) {
// sslContextFactory.setNeedClientAuth(false);
// sslContextFactory.setWantClientAuth(true);
// } else {
// sslContextFactory.setNeedClientAuth(false);
// sslContextFactory.setWantClientAuth(false);
// }
return sslContextFactory;
}
/**
* Enables a specific set of protocols in an SSLEngine instance.
*
......@@ -493,7 +570,7 @@ public class SSLConfig
*
* @param sslEngine The instance to configure. Cannot be null.
* @param purpose The type of configuration to use (used to select the relevent property). Cannot be null.
*/
private static void configureProtocols( SSLEngine sslEngine, Purpose purpose )
{
// Find configuration, using fallback where applicable.
......@@ -530,6 +607,7 @@ public class SSLConfig
sslEngine.setEnabledProtocols( defaultEnabled.toArray( new String[ defaultEnabled.size()] ) );
}
}
*/
/**
* Enables a specific set of cipher suites in an SSLEngine instance.
......@@ -545,7 +623,7 @@ public class SSLConfig
*
* @param sslEngine The instance to configure. Cannot be null.
* @param purpose The type of configuration to use (used to select the relevent property). Cannot be null.
*/
private static void configureCipherSuites( SSLEngine sslEngine, Purpose purpose )
{
String enabledCipherSuites = JiveGlobals.getProperty( purpose.getPrefix() + "enabled.ciphersuites" );
......@@ -588,6 +666,7 @@ public class SSLConfig
sslEngine.setEnabledCipherSuites( defaultEnabled.toArray( new String[ defaultEnabled.size()] ) );
}
}
*/
/**
* Creates an Apache MINA SslFilter that is configured to use server mode when handshaking.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment