[ 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: dev-unsubscr...@mina.apache.org For additional commands, e-mail: dev-h...@mina.apache.org