diff --git a/quickfixj-core/src/main/doc/usermanual/usage/configuration.html b/quickfixj-core/src/main/doc/usermanual/usage/configuration.html index 8b614b62b..b9be7ad2d 100644 --- a/quickfixj-core/src/main/doc/usermanual/usage/configuration.html +++ b/quickfixj-core/src/main/doc/usermanual/usage/configuration.html @@ -692,6 +692,12 @@
There are mainly two settings that influence QFJ's rejection behaviour:
@@ -1292,9 +1298,9 @@If RejectInvalidMessage is set to
diff --git a/quickfixj-core/src/main/java/quickfix/mina/initiator/IoSessionInitiator.java b/quickfixj-core/src/main/java/quickfix/mina/initiator/IoSessionInitiator.java index e70e6325d..fa93ac682 100644 --- a/quickfixj-core/src/main/java/quickfix/mina/initiator/IoSessionInitiator.java +++ b/quickfixj-core/src/main/java/quickfix/mina/initiator/IoSessionInitiator.java @@ -192,6 +192,7 @@ private SSLFilter installSslFilter(CompositeIoFilterChainBuilder ioFilterChainBu : SSLSupport.getDefaultCipherSuites(sslContext)); sslFilter.setEnabledProtocols(sslConfig.getEnabledProtocols() != null ? sslConfig.getEnabledProtocols() : SSLSupport.getSupportedProtocols(sslContext)); + sslFilter.setUseSNI(sslConfig.isUseSNI()); ioFilterChainBuilder.addLast(SSLSupport.FILTER_NAME, sslFilter); return sslFilter; } diff --git a/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLConfig.java b/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLConfig.java index ca27d3ba9..667750f34 100644 --- a/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLConfig.java +++ b/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLConfig.java @@ -36,6 +36,7 @@ public class SSLConfig { private String[] enabledProtocols; private String[] enabledCipherSuites; private boolean needClientAuth; + private boolean useSNI; @Override public boolean equals(Object obj) { @@ -81,6 +82,8 @@ public boolean equals(Object obj) { return false; if (!Arrays.equals(trustStorePassword, other.trustStorePassword)) return false; + if(useSNI != other.useSNI) + return false; if (trustStoreType == null) { return other.trustStoreType == null; } else return trustStoreType.equals(other.trustStoreType); @@ -149,6 +152,10 @@ public boolean isNeedClientAuth() { return needClientAuth; } + public boolean isUseSNI() { + return useSNI; + } + public void setEnabledCipherSuites(String[] enabledCipherSuites) { this.enabledCipherSuites = enabledCipherSuites; } @@ -177,6 +184,10 @@ public void setNeedClientAuth(boolean needClientAuth) { this.needClientAuth = needClientAuth; } + public void setUseSNI(boolean useSNI) { + this.useSNI = useSNI; + } + public void setTrustManagerFactoryAlgorithm(String trustManagerFactoryAlgorithm) { this.trustManagerFactoryAlgorithm = trustManagerFactoryAlgorithm; } diff --git a/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLFilter.java b/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLFilter.java index ba7d6e18b..b9c036f9d 100644 --- a/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLFilter.java +++ b/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLFilter.java @@ -19,16 +19,26 @@ package quickfix.mina.ssl; +import java.net.InetSocketAddress; +import java.net.SocketAddress; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; +import org.apache.mina.core.filterchain.IoFilterChain; +import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.ssl.SslFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * An extended SSL filter based on MINA {@link SslFilter} that disables setting - * enabled cipher suites via default method. + * An extended SSL filter based on MINA {@link SslFilter} that applies + * some adaptations. */ public class SSLFilter extends SslFilter { + private final Logger log = LoggerFactory.getLogger(getClass()); + private boolean useSNI; + public SSLFilter(SSLContext sslContext, boolean autoStart) { super(sslContext, autoStart); } @@ -38,8 +48,8 @@ public SSLFilter(SSLContext sslContext) { } /** - * This method is called from {@link SslFilter#onPreAdd} every time new - * session is created which makes impossible to override enabled cipher + * Called from {@link SslFilter#onPreAdd} every time a new + * session is created which makes it impossible to override enabled cipher * suites configuration. */ @Override @@ -49,4 +59,30 @@ public void setEnabledCipherSuites(String[] cipherSuites) { public void setCipherSuites(String[] cipherSuites) { super.setEnabledCipherSuites(cipherSuites); } + + /** + * Called before filter is added into the chain. + * We activate Server Name Indication if it is enabled in the session config. + */ + @Override + public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) + throws SSLException { + + if (useSNI) { + IoSession session = parent.getSession(); + SocketAddress remoteAddress = session.getRemoteAddress(); + + if (remoteAddress instanceof InetSocketAddress) { + // activate the SNI support in the JSSE SSLEngine + log.info("Activating TLS SNI support for peer address: {}", remoteAddress); + session.setAttribute(PEER_ADDRESS, remoteAddress); + } + } + + super.onPreAdd(parent, name, nextFilter); + } + + public void setUseSNI(boolean useSNI) { + this.useSNI = useSNI; + } } diff --git a/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLSupport.java b/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLSupport.java index 35d6af15b..d821f2f64 100644 --- a/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLSupport.java +++ b/quickfixj-core/src/main/java/quickfix/mina/ssl/SSLSupport.java @@ -39,6 +39,7 @@ public class SSLSupport { public static final String SETTING_TRUST_MANAGER_FACTORY_ALGORITHM = "TrustManagerFactoryAlgorithm"; public static final String SETTING_TRUST_STORE_TYPE = "TrustStoreType"; public static final String SETTING_NEED_CLIENT_AUTH = "NeedClientAuth"; + public static final String SETTING_USE_SNI = "UseSNI"; public static final String SETTING_ENABLED_PROTOCOLS = "EnabledProtocols"; public static final String SETTING_CIPHER_SUITES = "CipherSuites"; static final String DEFAULT_STORE_TYPE = "JKS"; @@ -110,6 +111,7 @@ public static SSLConfig getSslConfig(SessionSettings sessionSettings, SessionID sslConfig.setEnabledCipherSuites(getEnabledCipherSuites(sessionSettings, sessionID)); sslConfig.setEnabledProtocols(getEnabledProtocols(sessionSettings, sessionID)); sslConfig.setNeedClientAuth(isNeedClientAuth(sessionSettings, sessionID)); + sslConfig.setUseSNI(isUseSNI(sessionSettings, sessionID)); return sslConfig; } @@ -147,4 +149,8 @@ public static String getTrustStoreType(SessionSettings sessionSettings, SessionI public static boolean isNeedClientAuth(SessionSettings sessionSettings, SessionID sessionID) { return "Y".equals(getString(sessionSettings, sessionID, SETTING_NEED_CLIENT_AUTH, "N")); } + + public static boolean isUseSNI(SessionSettings sessionSettings, SessionID sessionID) { + return "Y".equals(getString(sessionSettings, sessionID, SETTING_USE_SNI, "N")); + } }