2.2.x vs 2.1.x differences

The SSL/TLS handling has been totally rewritten in MINA 2.2. This has an impact in many areas.

Removal of the SslFilter.DISABLE_ENCRYPTION_ONCE attribute

This attribute was used in previous MINA versions to insure that we can send a clear text message to the remote peer while establishing the TLS connection when using the startTLS command.

The idea is that the startTLS command is sent by an application (an LDAP client, for instance), which tells the server it should establish the SSL/TLS layer. The problem is that the server should be able to inform the client that the SSL/TLS layer is up and running, in clear text, which is not possible as the SSL/TLS layer is already fonctionning…

This kind of chicken and egg problem was solved by giving the opportunity to the SSL/TLS layer to send back the startTLS response to the client in clear text, assuming it’s the server’s first message. A bit of a hack.

In MINA 2.2, this attribute has been removed and replaced by either a filter to be added, or by encapsulating the message that should not be encrypted into an instance that implements the DisableEncryptWriteRequest interface.

Typically, in Apache Directory, we use this filter:

public class StartTlsFilter extends IoFilterAdapter 
{
    /**
     * {@inheritDoc}
     */
    @Override
    public void filterWrite( NextFilter nextFilter, IoSession session, WriteRequest writeRequest ) throws Exception 
    {
        if ( writeRequest.getOriginalMessage() instanceof StartTlsResponse )
        {
            // We need to bypass the SslFilter
            IoFilterChain chain = session.getFilterChain();
            
            for ( IoFilterChain.Entry entry : chain.getAll() )
            {
                IoFilter filter = entry.getFilter();
                
                if ( filter instanceof SslFilter )
                {
                    entry.getNextFilter().filterWrite( session, writeRequest );
                }
            }
        }
        else
        {
            nextFilter.filterWrite( session, writeRequest );
        }
    }
}

As you can see in the code above, we check if the message is a startTLS response, and if so, we bypass the SSLFilter, which leads to the message to be sent in clear text.

Addition of the IoSession.isServer() method

This method tells if the underlaying service is an IoAcceptor or not. It’s useful to quickly find out if we have to set the Tls flag to client or server when initializing the SslEngine instance, we also use it for the SslFilter logs.

Removal of the SslFilter.getSslSession() method

This method is not used. Would you like to get the SSLSession instance, it’s a matter of calling the IoSession.getAttribute() method with SslFilter.SSL_SECURED as a parameter:

...
            SSLSession sslSession = SSLSession.class.cast(getAttribute(SslFilter.SSL_SECURED));
...

Why is it API incompatible ?

The removal of the SslFilter.DISABLE_ENCRYPTION_ONCE attribute makes it impossible for application that leverage the startTLS command to work, without some code change.

Migration

This is pretty straightforward :

  • Create a filter that bypasses the message that should not be encrypted, or encapsulate it into an instance that implements the DisableEncryptWriteRequest interface.

and that’s it !