Skip to content

Commit e53d41b

Browse files
youurayychrjohn
andauthored
Add optional TLS SNI initiator support (#277)
* 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>
1 parent 697f2f4 commit e53d41b

File tree

5 files changed

+67
-7
lines changed

5 files changed

+67
-7
lines changed

quickfixj-core/src/main/doc/usermanual/usage/configuration.html

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,12 @@ <H3>QuickFIX Settings</H3>
692692
<TD></TD>
693693
<TD><a href="https://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html">Java default cipher suites</a></TD>
694694
</TR>
695+
<TR ALIGN="left" VALIGN="middle">
696+
<TD valign="top"> <I>UseSNI</I></TD>
697+
<TD>Configures the SSL engine to use Server Name Indication. This option is only useful to initiators.</TD>
698+
<TD>Y<BR>N</TD>
699+
<TD>N</TD>
700+
</TR>
695701

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

12811287
<H3><A NAME="Invalid vs Garbled Messages">Rejecting Invalid vs Garbled Messages</A></H3>
1282-
1288+
12831289
<p>
12841290
There are mainly two settings that influence QFJ's rejection behaviour:
12851291
</p>
@@ -1292,9 +1298,9 @@ <H3><A NAME="Invalid vs Garbled Messages">Rejecting Invalid vs Garbled Messages<
12921298
While the first applies to messages that fail data dictionary validation,
12931299
the latter applies to messages that fail basic validity checks on the FIX protocol level.
12941300
</p>
1295-
1301+
12961302
<H4>Setting RejectInvalidMessage</H4>
1297-
1303+
12981304
<p>
12991305
If RejectInvalidMessage is set to
13001306
</p>

quickfixj-core/src/main/java/quickfix/mina/initiator/IoSessionInitiator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ private SSLFilter installSslFilter(CompositeIoFilterChainBuilder ioFilterChainBu
192192
: SSLSupport.getDefaultCipherSuites(sslContext));
193193
sslFilter.setEnabledProtocols(sslConfig.getEnabledProtocols() != null ? sslConfig.getEnabledProtocols()
194194
: SSLSupport.getSupportedProtocols(sslContext));
195+
sslFilter.setUseSNI(sslConfig.isUseSNI());
195196
ioFilterChainBuilder.addLast(SSLSupport.FILTER_NAME, sslFilter);
196197
return sslFilter;
197198
}

quickfixj-core/src/main/java/quickfix/mina/ssl/SSLConfig.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class SSLConfig {
3636
private String[] enabledProtocols;
3737
private String[] enabledCipherSuites;
3838
private boolean needClientAuth;
39+
private boolean useSNI;
3940

4041
@Override
4142
public boolean equals(Object obj) {
@@ -81,6 +82,8 @@ public boolean equals(Object obj) {
8182
return false;
8283
if (!Arrays.equals(trustStorePassword, other.trustStorePassword))
8384
return false;
85+
if(useSNI != other.useSNI)
86+
return false;
8487
if (trustStoreType == null) {
8588
return other.trustStoreType == null;
8689
} else return trustStoreType.equals(other.trustStoreType);
@@ -149,6 +152,10 @@ public boolean isNeedClientAuth() {
149152
return needClientAuth;
150153
}
151154

155+
public boolean isUseSNI() {
156+
return useSNI;
157+
}
158+
152159
public void setEnabledCipherSuites(String[] enabledCipherSuites) {
153160
this.enabledCipherSuites = enabledCipherSuites;
154161
}
@@ -177,6 +184,10 @@ public void setNeedClientAuth(boolean needClientAuth) {
177184
this.needClientAuth = needClientAuth;
178185
}
179186

187+
public void setUseSNI(boolean useSNI) {
188+
this.useSNI = useSNI;
189+
}
190+
180191
public void setTrustManagerFactoryAlgorithm(String trustManagerFactoryAlgorithm) {
181192
this.trustManagerFactoryAlgorithm = trustManagerFactoryAlgorithm;
182193
}

quickfixj-core/src/main/java/quickfix/mina/ssl/SSLFilter.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,26 @@
1919

2020
package quickfix.mina.ssl;
2121

22+
import java.net.InetSocketAddress;
23+
import java.net.SocketAddress;
2224
import javax.net.ssl.SSLContext;
2325

26+
import javax.net.ssl.SSLException;
27+
import org.apache.mina.core.filterchain.IoFilterChain;
28+
import org.apache.mina.core.session.IoSession;
2429
import org.apache.mina.filter.ssl.SslFilter;
30+
import org.slf4j.Logger;
31+
import org.slf4j.LoggerFactory;
2532

2633
/**
27-
* An extended SSL filter based on MINA {@link SslFilter} that disables setting
28-
* enabled cipher suites via default method.
34+
* An extended SSL filter based on MINA {@link SslFilter} that applies
35+
* some adaptations.
2936
*/
3037
public class SSLFilter extends SslFilter {
3138

39+
private final Logger log = LoggerFactory.getLogger(getClass());
40+
private boolean useSNI;
41+
3242
public SSLFilter(SSLContext sslContext, boolean autoStart) {
3343
super(sslContext, autoStart);
3444
}
@@ -38,8 +48,8 @@ public SSLFilter(SSLContext sslContext) {
3848
}
3949

4050
/**
41-
* This method is called from {@link SslFilter#onPreAdd} every time new
42-
* session is created which makes impossible to override enabled cipher
51+
* Called from {@link SslFilter#onPreAdd} every time a new
52+
* session is created which makes it impossible to override enabled cipher
4353
* suites configuration.
4454
*/
4555
@Override
@@ -49,4 +59,30 @@ public void setEnabledCipherSuites(String[] cipherSuites) {
4959
public void setCipherSuites(String[] cipherSuites) {
5060
super.setEnabledCipherSuites(cipherSuites);
5161
}
62+
63+
/**
64+
* Called before filter is added into the chain.
65+
* We activate Server Name Indication if it is enabled in the session config.
66+
*/
67+
@Override
68+
public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter)
69+
throws SSLException {
70+
71+
if (useSNI) {
72+
IoSession session = parent.getSession();
73+
SocketAddress remoteAddress = session.getRemoteAddress();
74+
75+
if (remoteAddress instanceof InetSocketAddress) {
76+
// activate the SNI support in the JSSE SSLEngine
77+
log.info("Activating TLS SNI support for peer address: {}", remoteAddress);
78+
session.setAttribute(PEER_ADDRESS, remoteAddress);
79+
}
80+
}
81+
82+
super.onPreAdd(parent, name, nextFilter);
83+
}
84+
85+
public void setUseSNI(boolean useSNI) {
86+
this.useSNI = useSNI;
87+
}
5288
}

quickfixj-core/src/main/java/quickfix/mina/ssl/SSLSupport.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class SSLSupport {
3939
public static final String SETTING_TRUST_MANAGER_FACTORY_ALGORITHM = "TrustManagerFactoryAlgorithm";
4040
public static final String SETTING_TRUST_STORE_TYPE = "TrustStoreType";
4141
public static final String SETTING_NEED_CLIENT_AUTH = "NeedClientAuth";
42+
public static final String SETTING_USE_SNI = "UseSNI";
4243
public static final String SETTING_ENABLED_PROTOCOLS = "EnabledProtocols";
4344
public static final String SETTING_CIPHER_SUITES = "CipherSuites";
4445
static final String DEFAULT_STORE_TYPE = "JKS";
@@ -110,6 +111,7 @@ public static SSLConfig getSslConfig(SessionSettings sessionSettings, SessionID
110111
sslConfig.setEnabledCipherSuites(getEnabledCipherSuites(sessionSettings, sessionID));
111112
sslConfig.setEnabledProtocols(getEnabledProtocols(sessionSettings, sessionID));
112113
sslConfig.setNeedClientAuth(isNeedClientAuth(sessionSettings, sessionID));
114+
sslConfig.setUseSNI(isUseSNI(sessionSettings, sessionID));
113115

114116
return sslConfig;
115117
}
@@ -147,4 +149,8 @@ public static String getTrustStoreType(SessionSettings sessionSettings, SessionI
147149
public static boolean isNeedClientAuth(SessionSettings sessionSettings, SessionID sessionID) {
148150
return "Y".equals(getString(sessionSettings, sessionID, SETTING_NEED_CLIENT_AUTH, "N"));
149151
}
152+
153+
public static boolean isUseSNI(SessionSettings sessionSettings, SessionID sessionID) {
154+
return "Y".equals(getString(sessionSettings, sessionID, SETTING_USE_SNI, "N"));
155+
}
150156
}

0 commit comments

Comments
 (0)