Bug 54690 - HTTPS BIO/NIO connector does not enable TLS 1.1 and TLS 1.2 by default
HTTPS BIO/NIO connector does not enable TLS 1.1 and TLS 1.2 by default
Product: Tomcat 7
Classification: Unclassified
Component: Connectors
PC Windows XP
: P2 normal (vote)
: ---
Assigned To: Tomcat Developers Mailing List
: 54619 (view as bug list)
Depends on:
  Show dependency tree
Reported: 2013-03-13 17:07 UTC by Ognjen Blagojevic
Modified: 2013-03-21 02:53 UTC (History)
1 user (show)

JSSE options on Oracle Java 7 (18.58 KB, text/plain)
2013-03-21 02:51 UTC, Tim Whittington
JSSE options on Oracle Java 6 (8.32 KB, text/plain)
2013-03-21 02:52 UTC, Tim Whittington
JSSE options on AIX Java 7 (18.19 KB, text/plain)
2013-03-21 02:53 UTC, Tim Whittington

Note You need to log in before you can comment on or make changes to this bug.
Description Ognjen Blagojevic 2013-03-13 17:07:20 UTC
As users already noted [1], default HTTPS BIO/NIO connector in Tomcat 7.0.37 enables only SSLv3 and TLSv1, while Tomcat 6.0.36 enables SSLv3, TLSv1, TLSv1.1 and TLSv1.2.

The reason for this change of behavior is that:

1. Tomcat 6, with default HTTPS connector configuration, does not call socket.setEnabledProtocols, thus enabling SSLv3, TLSv1, TLSv1.1 and TLSv1.2, while

2. Tomcat 7, with default HTTPS connector configuration, calls socket.setEnabledProtocols(enabledProtocols), where enabledProtocols is obtained with: context.getDefaultSSLParameters().getProtocols(). This, contrary to not calling setEnabledProtocols at all, results in enabling only SSLv3 and TLSv1.

I propose that Tomcat 7 mimics Tomcat 6 behavior, and if attribute sslEnabledProtocols (in HTTPS connector in server.xml) is not set, then method socket.setEnabledProtocols is not invoked.

Everything is tested with Oracle JDK 1.7.0_15.

More details on post on Tomcat dev list [2].

[1] https://twitter.com/ivanristic/status/303798231920431104
[2] http://www.mail-archive.com/dev@tomcat.apache.org/msg71522.html
Comment 1 Ognjen Blagojevic 2013-03-13 17:11:43 UTC
Here is a simple class to demonstrate Oracle JDK 7 behavior:

import java.net.ServerSocket;
import java.util.Arrays;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;

public class SSLProtocolsTest {

    public static void main(String[] args) throws Exception {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);
        SSLServerSocketFactory sslProxy = context.getServerSocketFactory();
        ServerSocket ssocket = sslProxy.createServerSocket(443);
        SSLServerSocket socket = (SSLServerSocket) ssocket;
        // Prints: [SSLv2Hello, SSLv3, TLSv1, TLSv1.1, TLSv1.2]
        System.out.println(" Socket enabled protocols: " + Arrays.asList(socket.getEnabledProtocols()));
        // Prints: [SSLv3, TLSv1]
        System.out.println("Default enabled protocols: " + Arrays.asList(socket.getEnabledProtocols()));

Comment 2 Mark Thomas 2013-03-13 23:16:48 UTC
Note hidden in the code comments is the fact that support for SSLv2Hello is also dropped.

Note that the change that triggered this bug was 54406.
Comment 3 Mark Thomas 2013-03-13 23:37:31 UTC
Some issues at $work have prompted me to look into this further.

Fundamentally, this is a JVM bug. I think the way forward is to use


to determine what the default protocols really are rather than using

That should then be JVM neutral. We can also add a test case that will pick up if this ever gets fixed in the JVM.

I'll look into patching this tomorrow.
Comment 4 Mark Thomas 2013-03-14 11:59:47 UTC
*** Bug 54619 has been marked as a duplicate of this bug. ***
Comment 5 Mark Thomas 2013-03-14 12:45:57 UTC
Digging into the OpenJDK source code it appears that the JVM behaviour is by design.

The defaults are different for client and server connections and SSLContext.getDefaultSSLParameters() returns the defaults for client connections not server connections.

We currently use SSLContext.getDefaultSSLParameters() to get the default ciphers and the default protocols. The protocols are different for clients and servers (this bug) and so are the ciphers (an additional issue no-one has reported). Both these issues need to be fixed.
Comment 6 Mark Thomas 2013-03-14 14:53:34 UTC
This has been fixed in trunk and 7.0.x and will be included in 7.0.39 onwards.
Comment 7 Ognjen Blagojevic 2013-03-14 17:00:09 UTC
Thank you.

Workaround for Tomcat 7.0.37 users: add 


to HTTPS BIO/NIO connector configuration.
Comment 8 Tim Whittington 2013-03-21 02:51:12 UTC
For posterity, the actual situation with JSSE is a bit more complicated than client vs server.
(The fix and workaround for this issue are correct - this is just to clarify the landscape in case it's ever come across again).

Testing on Java 7 on OS X/Linux/HP-UX:

There are 3 distinct sets of cipher suites obtainable from the 23! unique locations in the JSSE API that produce a list of cipher suites.
There are 4 distinct sets of protocol variants obtainable from the 15! unique locations in the JSSE API that produce a list of protocols.

I've attached a full report, but in summary:

The cipher suites obtained are grouped into 3 distinct sets of ciphers:
1. Default ciphers for client objects (SSLContext and SSLSocketFactory/SSLSocket) for default and <= TLSv1.1 engines
2. Supported ciphers for all engines (i.e. they're all the same)
3. Enabled ciphers from server objects (SSLEngine, SSLServerSocketFactory and SSLServerSocket) for all engines, and client object defaults for TLSv1.2 engine

The protocol variants are grouped into the following 4 sets:
1. Default for SSLContext and supported/default for SSLSocket in TLSv1.2 engine
2. Default for SSLContext and supported/default for SSLSocket in TLSv1.1 engine
3. Default for SSLContext and supported/default for all engines default and <= TLSv1 engines
4. Supported for SSLContext, supported/defaults for SSLEngine/SSLServerSocket in all engines

For Java 6 on OS X/Linux/HP-UX, the results are a bit simpler: 
- Cipher suites are split into 2 groups: supported cipher suites, and default/enabled cipher suites (on all client + server objects).
- For protocol variants, supported == enabled == default in all locations.

For Java 7 on AIX:
- Cipher suites are in 2 groups (supported and default/enabled), with client + server defaults the same.
- Protocol variants are in 6 groups:
1. Defaults for client objects in Default engine (SSLv3, TLSv1)
2. Supported/default for client objects for TLSv1.2 engine (TLSv1.2 only)
3. Supported/default for client objects for TLSv1.1 engine (TLSv1.1 only)
4. Supported/default for client objects for TLS and TLSv1 engines (TLSv1 only)
5. Supported/default for client objects for SSL and SSLv3 engines (SSLV3 only)
6. Supported protocols for SSLContext, SSLEngine and SSLServerSocket on all engines, and defaults for SSLServerSocket on default engine (SSLv3+)

(As an aside, all of this points out that in Java 7 switching the engine using the HTTPS connector protocol attribute will not only change defaults, but change the supported protocol variants that can be enabled).

Cutting across all this:
- Supported for SSLContext appears to be stable across the versions/platforms
- the only way to reliably detect the 'server' defaults in a JVM appear to be via an SSLEngine or a SSLServerSocket constructed from an SSLContext. Thankfully the defaults appear to be independant of the engine (the protocol argument to SSLContext.getInstance()).
Comment 9 Tim Whittington 2013-03-21 02:51:56 UTC
Created attachment 30088 [details]
JSSE options on Oracle Java 7
Comment 10 Tim Whittington 2013-03-21 02:52:14 UTC
Created attachment 30089 [details]
JSSE options on Oracle Java 6
Comment 11 Tim Whittington 2013-03-21 02:53:07 UTC
Created attachment 30090 [details]
JSSE options on AIX Java 7