Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions quickfixj-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
<version>4.1.111.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.burningwave</groupId>
<artifactId>tools</artifactId>
<version>0.27.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
Expand Down
16 changes: 16 additions & 0 deletions quickfixj-core/src/main/doc/usermanual/usage/configuration.html
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,22 @@ <H3>QuickFIX Settings</H3>
<TD></TD>
<TD></TD>
</TR>
<TR ALIGN="left" VALIGN="middle">
<TD valign="top"> <I>UseSNI</I></TD>
<TD>
Enables the SSL engine to use Server Name Indication (SNI). This option is only applicable for initiators.
<p>If provided, <i>SNIHostName</i> will be used as the server name. Otherwise, <i>SocketConnectHost</i> or <i>SocketConnectHost&lt;n&gt;</i> will be used.</p>
<p>Note: When this option is disabled, the JVM may still implicitly send the SSL <code>server_name</code> extension.</p>
</TD>
<TD>Y<BR>N</TD>
<TD>N</TD>
</TR>
<TR ALIGN="left" VALIGN="middle">
<TD valign="top"> <I>SNIHostName</I></TD>
<TD>SNI host name to be used as desired Server Name Indication (SNI) parameter.</TD>
<TD></TD>
<TD></TD>
</TR>

<TR ALIGN="center" VALIGN="middle">
<TD COLSPAN="4" class="subsection"><A NAME="Security">Socks Proxy Options (Initiator only)</A></TD>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import quickfix.mina.ProtocolFactory;
import quickfix.mina.SessionConnector;
import quickfix.mina.message.FIXProtocolCodecFactory;
import quickfix.mina.ssl.InitiatorSslFilter;
import quickfix.mina.ssl.SSLConfig;
import quickfix.mina.ssl.SSLContextFactory;
import quickfix.mina.ssl.SSLSupport;
Expand Down Expand Up @@ -185,7 +186,7 @@ private void setupIoConnector() throws ConfigError, GeneralSecurityException {
private void installSslFilter(CompositeIoFilterChainBuilder ioFilterChainBuilder)
throws GeneralSecurityException {
final SSLContext sslContext = SSLContextFactory.getInstance(sslConfig);
final SslFilter sslFilter = new SslFilter(sslContext, false);
final SslFilter sslFilter = new InitiatorSslFilter(sslContext, getSniHostName(sslConfig));
sslFilter.setEnabledCipherSuites(sslConfig.getEnabledCipherSuites() != null ? sslConfig.getEnabledCipherSuites()
: SSLSupport.getDefaultCipherSuites(sslContext));
sslFilter.setEnabledProtocols(sslConfig.getEnabledProtocols() != null ? sslConfig.getEnabledProtocols()
Expand All @@ -194,6 +195,22 @@ private void installSslFilter(CompositeIoFilterChainBuilder ioFilterChainBuilder
ioFilterChainBuilder.addLast(SSLSupport.FILTER_NAME, sslFilter);
}

public String getSniHostName(SSLConfig sslConfig) {
if (!sslConfig.isUseSNI()) {
return null;
}

if (sslConfig.getSniHostName() != null) {
return sslConfig.getSniHostName();
}

if (socketAddresses[nextSocketAddressIndex] instanceof InetSocketAddress) {
return ((InetSocketAddress) socketAddresses[nextSocketAddressIndex]).getHostName();
}

return null;
}

@Override
public void run() {
resetIoConnector();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package quickfix.mina.ssl;

import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.ssl.SslFilter;

import javax.net.ssl.SNIHostName;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import java.net.InetSocketAddress;
import java.util.Arrays;

public final class InitiatorSslFilter extends SslFilter {

private final String sniHostName;

public InitiatorSslFilter(SSLContext sslContext, String sniHostName) {
super(sslContext, false);
this.sniHostName = sniHostName;
}

@Override
protected SSLEngine createEngine(IoSession session, InetSocketAddress addr) {
SSLEngine sslEngine;

if (addr != null) {
sslEngine = sslContext.createSSLEngine(addr.getHostName(), addr.getPort());
} else {
sslEngine = sslContext.createSSLEngine();
}

if (wantClientAuth) {
sslEngine.setWantClientAuth(true);
}

if (needClientAuth) {
sslEngine.setNeedClientAuth(true);
}

if (enabledCipherSuites != null) {
sslEngine.setEnabledCipherSuites(enabledCipherSuites);
}

if (enabledProtocols != null) {
sslEngine.setEnabledProtocols(enabledProtocols);
}

if (getEndpointIdentificationAlgorithm() != null) {
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm(getEndpointIdentificationAlgorithm());
sslEngine.setSSLParameters(sslParameters);
}

if (sniHostName != null) {
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setServerNames(Arrays.asList(new SNIHostName(sniHostName)));
sslEngine.setSSLParameters(sslParameters);
}

sslEngine.setUseClientMode(!session.isServer());

return sslEngine;
}
}
28 changes: 24 additions & 4 deletions quickfixj-core/src/main/java/quickfix/mina/ssl/SSLConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class SSLConfig {
private String[] enabledCipherSuites;
private boolean needClientAuth;
private String endpointIdentificationAlgorithm;
private boolean useSNI;
private String sniHostName;

public String[] getEnabledCipherSuites() {
return enabledCipherSuites;
Expand Down Expand Up @@ -87,7 +89,15 @@ public String getEndpointIdentificationAlgorithm() {
return endpointIdentificationAlgorithm;
}

public void setEnabledCipherSuites(String[] enabledCipherSuites) {
public boolean isUseSNI() {
return useSNI;
}

public String getSniHostName() {
return sniHostName;
}

public void setEnabledCipherSuites(String[] enabledCipherSuites) {
this.enabledCipherSuites = enabledCipherSuites;
}

Expand Down Expand Up @@ -119,7 +129,15 @@ public void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgo
this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm;
}

public void setTrustManagerFactoryAlgorithm(String trustManagerFactoryAlgorithm) {
public void setUseSNI(boolean useSNI) {
this.useSNI = useSNI;
}

public void setSniHostName(String sniHostName) {
this.sniHostName = sniHostName;
}

public void setTrustManagerFactoryAlgorithm(String trustManagerFactoryAlgorithm) {
this.trustManagerFactoryAlgorithm = trustManagerFactoryAlgorithm;
}

Expand Down Expand Up @@ -151,12 +169,14 @@ public boolean equals(Object o) {
Objects.equals(trustStoreType, sslConfig.trustStoreType) &&
Arrays.equals(enabledProtocols, sslConfig.enabledProtocols) &&
Arrays.equals(enabledCipherSuites, sslConfig.enabledCipherSuites) &&
Objects.equals(endpointIdentificationAlgorithm, sslConfig.endpointIdentificationAlgorithm);
Objects.equals(endpointIdentificationAlgorithm, sslConfig.endpointIdentificationAlgorithm) &&
Objects.equals(useSNI, sslConfig.useSNI) &&
Objects.equals(sniHostName, sslConfig.sniHostName);
}

@Override
public int hashCode() {
int result = Objects.hash(keyStoreName, keyManagerFactoryAlgorithm, keyStoreType, trustStoreName, trustManagerFactoryAlgorithm, trustStoreType, needClientAuth, endpointIdentificationAlgorithm);
int result = Objects.hash(keyStoreName, keyManagerFactoryAlgorithm, keyStoreType, trustStoreName, trustManagerFactoryAlgorithm, trustStoreType, needClientAuth, endpointIdentificationAlgorithm, useSNI, sniHostName);
result = 31 * result + Arrays.hashCode(keyStorePassword);
result = 31 * result + Arrays.hashCode(trustStorePassword);
result = 31 * result + Arrays.hashCode(enabledProtocols);
Expand Down
12 changes: 12 additions & 0 deletions quickfixj-core/src/main/java/quickfix/mina/ssl/SSLSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public class SSLSupport {
public static final String SETTING_TRUST_STORE_TYPE = "TrustStoreType";
public static final String SETTING_NEED_CLIENT_AUTH = "NeedClientAuth";
public static final String SETTING_ENDPOINT_IDENTIFICATION_ALGORITHM = "EndpointIdentificationAlgorithm";
public static final String SETTING_USE_SNI = "UseSNI";
public static final String SETTING_SNI_HOST_NAME = "SNIHostName";
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 @@ -112,6 +114,8 @@ public static SSLConfig getSslConfig(SessionSettings sessionSettings, SessionID
sslConfig.setEnabledProtocols(getEnabledProtocols(sessionSettings, sessionID));
sslConfig.setNeedClientAuth(isNeedClientAuth(sessionSettings, sessionID));
sslConfig.setEndpointIdentificationAlgorithm(getEndpointIdentificationAlgorithm(sessionSettings, sessionID));
sslConfig.setUseSNI(isUseSNI(sessionSettings, sessionID));
sslConfig.setSniHostName(getSNIHostName(sessionSettings, sessionID));

return sslConfig;
}
Expand Down Expand Up @@ -153,4 +157,12 @@ public static boolean isNeedClientAuth(SessionSettings sessionSettings, SessionI
public static String getEndpointIdentificationAlgorithm(SessionSettings sessionSettings, SessionID sessionID) {
return getString(sessionSettings, sessionID, SETTING_ENDPOINT_IDENTIFICATION_ALGORITHM, null);
}

public static boolean isUseSNI(SessionSettings sessionSettings, SessionID sessionID) {
return "Y".equals(getString(sessionSettings, sessionID, SETTING_USE_SNI, "N"));
}

public static String getSNIHostName(SessionSettings sessionSettings, SessionID sessionID) {
return getString(sessionSettings, sessionID, SETTING_SNI_HOST_NAME, null);
}
}
Loading
Loading