Skip to content

Commit

Permalink
Add optional TLS SNI initiator support (quickfix-j#277)
Browse files Browse the repository at this point in the history
* add address to SNI init log output
* add UseSNI opt-in parameter
* add doc for the UseSNI config parameter
* change to parametrized logging
* minor changes to comments and logging
* corrected SNI (indication) in doc

Co-authored-by: Christoph John <christoph.john@macd.com>
  • Loading branch information
2 people authored and jieli committed Sep 22, 2020
1 parent e210319 commit a76376e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 7 deletions.
12 changes: 9 additions & 3 deletions quickfixj-core/src/main/doc/usermanual/usage/configuration.html
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,12 @@ <H3>QuickFIX Settings</H3>
<TD></TD>
<TD><a href="https://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html">Java default cipher suites</a></TD>
</TR>
<TR ALIGN="left" VALIGN="middle">
<TD valign="top"> <I>UseSNI</I></TD>
<TD>Configures the SSL engine to use Server Name Indication. This option is only useful to initiators.</TD>
<TD>Y<BR>N</TD>
<TD>N</TD>
</TR>

<TR ALIGN="center" VALIGN="middle">
<TD COLSPAN="4" class="subsection"><A NAME="Security">Socks Proxy Options (Initiator only)</A></TD>
Expand Down Expand Up @@ -1279,7 +1285,7 @@ <H3>QuickFIX Settings</H3>
</TABLE>

<H3><A NAME="Invalid vs Garbled Messages">Rejecting Invalid vs Garbled Messages</A></H3>

<p>
There are mainly two settings that influence QFJ's rejection behaviour:
</p>
Expand All @@ -1292,9 +1298,9 @@ <H3><A NAME="Invalid vs Garbled Messages">Rejecting Invalid vs Garbled Messages<
While the first applies to messages that fail data dictionary validation,
the latter applies to messages that fail basic validity checks on the FIX protocol level.
</p>

<H4>Setting RejectInvalidMessage</H4>

<p>
If RejectInvalidMessage is set to
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
11 changes: 11 additions & 0 deletions quickfixj-core/src/main/java/quickfix/mina/ssl/SSLConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -149,6 +152,10 @@ public boolean isNeedClientAuth() {
return needClientAuth;
}

public boolean isUseSNI() {
return useSNI;
}

public void setEnabledCipherSuites(String[] enabledCipherSuites) {
this.enabledCipherSuites = enabledCipherSuites;
}
Expand Down Expand Up @@ -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;
}
Expand Down
44 changes: 40 additions & 4 deletions quickfixj-core/src/main/java/quickfix/mina/ssl/SSLFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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
Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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"));
}
}

0 comments on commit a76376e

Please sign in to comment.