[
https://issues.apache.org/jira/browse/DIRMINA-1122?focusedWorklogId=861070&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-861070
]
ASF GitHub Bot logged work on DIRMINA-1122:
-------------------------------------------
Author: ASF GitHub Bot
Created on: 08/May/23 19:31
Start Date: 08/May/23 19:31
Worklog Time Spent: 10m
Work Description: elecharny commented on PR #26:
URL: https://github.com/apache/mina/pull/26#issuecomment-1538929098
Actually, all the handshakes are passing, which make the *shouldFailXXX*
tests failing.
Here is the modified test class for MINA 2.2.X:
```
package org.apache.mina.filter.ssl;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.filterchain.IoFilterChain;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.FilterEvent;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.apache.mina.util.AvailablePortFinder;
import org.junit.Before;
import org.junit.Test;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManagerFactory;
import java.net.InetSocketAddress;
import java.security.KeyStore;
import java.security.Security;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Test SNI matching scenarios. (tests for DIRMINA-1122)
*
* <pre>
* emptykeystore.sslTest - empty keystore
* server-cn.keystore - keystore with single certificate chain
(CN=mina)
* client-cn.truststore - keystore with trusted certificate
* server-san-ext.keystore - keystore with single certificate chain
(CN=mina;SAN=*.bbb.ccc,xxx.yyy)
* client-san-ext.truststore - keystore with trusted certificate
* </pre>
*/
public class SslIdentificationAlgorithmTest {
private static final String KEY_MANAGER_FACTORY_ALGORITHM;
static {
String algorithm =
Security.getProperty("ssl.KeyManagerFactory.algorithm");
if (algorithm == null) {
algorithm = KeyManagerFactory.getDefaultAlgorithm();
}
KEY_MANAGER_FACTORY_ALGORITHM = algorithm;
}
private int port;
private CountDownLatch handshakeDone;
@Before
public void setUp() {
port = AvailablePortFinder.getNextAvailable(5555);
handshakeDone = new CountDownLatch(2);
}
@Test
public void
shouldAuthenticateWhenServerCertificateCommonNameMatchesClientSNI() throws
Exception {
SSLContext acceptorContext = createSSLContext("server-cn.keystore",
"emptykeystore.sslTest");
SSLContext connectorContext =
createSSLContext("emptykeystore.sslTest", "client-cn.truststore");
startAcceptor(acceptorContext);
startConnector(connectorContext, "mina");
assertTrue(handshakeDone.await(10, TimeUnit.SECONDS));
}
@Test
public void
shouldFailAuthenticationWhenServerCertificateCommonNameDoesNotMatchClientSNI()
throws Exception {
SSLContext acceptorContext = createSSLContext("server-cn.keystore",
"emptykeystore.sslTest");
SSLContext connectorContext =
createSSLContext("emptykeystore.sslTest", "client-cn.truststore");
startAcceptor(acceptorContext);
startConnector(connectorContext, "example.com");
assertFalse(handshakeDone.await(10, TimeUnit.SECONDS));
}
@Test
public void
shouldFailAuthenticationWhenClientMissingSNIAndIdentificationAlgorithmProvided()
throws Exception {
SSLContext acceptorContext = createSSLContext("server-cn.keystore",
"emptykeystore.sslTest");
SSLContext connectorContext =
createSSLContext("emptykeystore.sslTest", "client-cn.truststore");
startAcceptor(acceptorContext);
startConnector(connectorContext, null);
assertFalse(handshakeDone.await(10, TimeUnit.SECONDS));
}
/**
* Subject Alternative Name (SAN) scenarios
*/
@Test
public void
shouldAuthenticateWhenServerCertificateAlternativeNameMatchesClientSNIExactly()
throws Exception {
SSLContext acceptorContext =
createSSLContext("server-san-ext.keystore", "emptykeystore.sslTest");
SSLContext connectorContext =
createSSLContext("emptykeystore.sslTest", "client-san-ext.truststore");
startAcceptor(acceptorContext);
startConnector(connectorContext, "xxx.yyy");
assertTrue(handshakeDone.await(10, TimeUnit.SECONDS));
}
@Test
public void
shouldAuthenticateWhenServerCertificateAlternativeNameMatchesClientSNIViaWildcard()
throws Exception {
SSLContext acceptorContext =
createSSLContext("server-san-ext.keystore", "emptykeystore.sslTest");
SSLContext connectorContext =
createSSLContext("emptykeystore.sslTest", "client-san-ext.truststore");
startAcceptor(acceptorContext);
startConnector(connectorContext, "aaa.bbb.ccc");
assertTrue(handshakeDone.await(10, TimeUnit.SECONDS));
}
@Test
public void
shouldFailAuthenticationWhenServerCommonNameMatchesSNIAndSNINotInAlternativeName()
throws Exception {
SSLContext acceptorContext =
createSSLContext("server-san-ext.keystore", "emptykeystore.sslTest");
SSLContext connectorContext =
createSSLContext("emptykeystore.sslTest", "client-san-ext.truststore");
startAcceptor(acceptorContext);
startConnector(connectorContext, "mina");
assertFalse(handshakeDone.await(10, TimeUnit.SECONDS));
}
@Test
public void
shouldFailAuthenticationWhenMatchingAlternativeNameWildcardExactly() throws
Exception {
SSLContext acceptorContext =
createSSLContext("server-san-ext.keystore", "emptykeystore.sslTest");
SSLContext connectorContext =
createSSLContext("emptykeystore.sslTest", "client-san-ext.truststore");
startAcceptor(acceptorContext);
startConnector(connectorContext, "*.bbb.ccc");
assertFalse(handshakeDone.await(10, TimeUnit.SECONDS));
}
@Test
public void
shouldFailAuthenticationWhenMatchingAlternativeNameWithTooManyLabels() throws
Exception {
SSLContext acceptorContext =
createSSLContext("server-san-ext.keystore", "emptykeystore.sslTest");
SSLContext connectorContext =
createSSLContext("emptykeystore.sslTest", "client-san-ext.truststore");
startAcceptor(acceptorContext);
startConnector(connectorContext, "mmm.nnn.bbb.ccc");
assertFalse(handshakeDone.await(10, TimeUnit.SECONDS));
}
private void startAcceptor(SSLContext sslContext) throws Exception {
NioSocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.setReuseAddress(true);
SslFilter sslFilter = new SslFilter(sslContext);
sslFilter.setEnabledProtocols(new String[] {"TLSv1.2"});
DefaultIoFilterChainBuilder filters = acceptor.getFilterChain();
filters.addLast("ssl", sslFilter);
filters.addLast("text", new ProtocolCodecFilter(new
TextLineCodecFactory()));
acceptor.setHandler(new IoHandlerAdapter() {
@Override
public void sessionOpened(IoSession session) {
session.write("acceptor write");
}
@Override
public void event(IoSession session, FilterEvent event) {
if (event == SslEvent.SECURED) {
handshakeDone.countDown();
}
}
});
acceptor.bind(new InetSocketAddress(port));
}
private void startConnector(SSLContext sslContext, final String sni) {
NioSocketConnector connector = new NioSocketConnector();
SslFilter sslFilter = new SslFilter(sslContext) {
@Override
public void onPreAdd(IoFilterChain parent, String name,
NextFilter nextFilter) throws SSLException {
if (sni != null) {
IoSession session = parent.getSession();
session.setAttribute(SslFilter.PEER_ADDRESS, new
InetSocketAddress(sni, port));
}
super.onPreAdd(parent, name, nextFilter);
}
};
sslFilter.setUseClientMode(true);
sslFilter.setEndpointIdentificationAlgorithm("HTTPS");
sslFilter.setEnabledProtocols(new String[] {"TLSv1.2"});
DefaultIoFilterChainBuilder filters = connector.getFilterChain();
filters.addLast("ssl", sslFilter);
filters.addLast("text", new ProtocolCodecFilter(new
TextLineCodecFactory()));
connector.setHandler(new IoHandlerAdapter() {
@Override
public void sessionOpened(IoSession session) {
session.write("connector write");
}
@Override
public void event(IoSession session, FilterEvent event) {
if (event == SslEvent.SECURED) {
handshakeDone.countDown();
}
}
});
connector.connect(new InetSocketAddress("localhost", port));
}
private SSLContext createSSLContext(String keyStorePath, String
trustStorePath) throws Exception {
char[] password = "password".toCharArray();
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(SslTest.class.getResourceAsStream(keyStorePath),
password);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
kmf.init(keyStore, password);
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(SslTest.class.getResourceAsStream(trustStorePath),
password);
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
tmf.init(trustStore);
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return ctx;
}
}
```
Issue Time Tracking
-------------------
Worklog Id: (was: 861070)
Time Spent: 1h 20m (was: 1h 10m)
> Add support for endpoint identification algorithm
> -------------------------------------------------
>
> Key: DIRMINA-1122
> URL: https://issues.apache.org/jira/browse/DIRMINA-1122
> Project: MINA
> Issue Type: Improvement
> Components: Filter, SSL
> Affects Versions: 2.0.22, 2.1.3
> Reporter: Marcin L
> Assignee: Jonathan Valliere
> Priority: Minor
> Fix For: 2.2.0
>
> Attachments:
> DIRMINA-1122_-_endpoint_identification_algorithm_support.patch
>
> Time Spent: 1h 20m
> Remaining Estimate: 0h
>
> Support for endpoint identification algorithm was added in Java 1.7.
> Currently MINA supports providing single SNI name via
> org.apache.mina.filter.ssl.SslFilter#PEER_ADDRESS session attribute, but
> there is no way verifying it matches the certificate received.
> It would be nice if we could provide endpoint identification algorithm to
> SslFilter so certificate's common name or subject alternative names are
> verified.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]