Bug 56780 - IBM Java: server.startup gives error "java.lang.IllegalArgumentException: Only TLS1.2 protocol can be enabl ed in SP800_131 strict mode"
IBM Java: server.startup gives error "java.lang.IllegalArgumentException: Onl...
Status: RESOLVED FIXED
Product: Tomcat 7
Classification: Unclassified
Component: Catalina
7.0.39
PC Mac OS X 10.4
: P2 major with 1 vote (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2014-07-28 17:38 UTC by Richard Watts
Modified: 2014-11-13 17:41 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Watts 2014-07-28 17:38:05 UTC
The problem is a change made in Tomcat 7.0.39. 

The offending code is in org.apache.tomcat.util.net.jsse.JSSESocketFactory.{...}:

        try {
            context = SSLContext.getInstance("TLS");
            ...

            SSLServerSocket socket = (SSLServerSocket) ssf.createServerSocket();
           ...
        } catch (NoSuchAlgorithmException e) {
            // Assume no RFC 5746 support
        } catch (KeyManagementException e) {
            // Assume no RFC 5746 support
        } catch (IOException e) {
            // Unable to determine default ciphers/protocols so use none
        }
        
With the IBM JVM configured for strict SP800-131a mode, the ssf.createServerSocket() will throw an IllegalArgumentException, which is a very bad thing to have happen in a class initializer.

IBM JRE: 6.0 (SR16) : Email me direct for the JRE if you want to test it.
Comment 1 Mark Thomas 2014-07-28 21:59:10 UTC
What value(s) will the IBM JRE accept there?

As an aside, if you can provide a IBM JRE for Windows to test with (preferably 64-bit) to markt@apache.org that would be great.
Comment 2 Karl Freburger 2014-07-29 15:29:45 UTC
If the IBM JVM is configured for strict SP800-131a mode, the only acceptable value (currently) for the protocol would be "TLSv1.2". If strict SP800-131a mode is NOT on, many other values are acceptable ("TLS", etc).

Note that if there was ever a TLSv1.3, then that would also become an acceptable value for the protocol.

If I read the code correctly (that's a big IF), the appropriate action here is to catch IllegalArgumentException and treat it like IOException.
Comment 3 Mark Thomas 2014-08-05 15:51:09 UTC
Handling it the same way as IOException should work, yes. That fix has been applied to 8.0.x for 8.0.11 onwards and to 7.0.x for 7.0.56 onwards.
Comment 4 Richard Watts 2014-10-20 14:37:31 UTC
looking at 7.0.56... it does not look like this made it into that release. Can someone comment?
Comment 5 Karl Freburger 2014-10-20 14:53:40 UTC
Unfortunately, the fix doesn't work...now we see this:

Throwable occurred: org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-9443]]
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
        at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
        at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:821)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:638)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:663)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:280)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:454)
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
        at org.apache.catalina.connector.Connector.initInternal(Connector.java:980)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
        ... 12 more
Caused by: java.io.IOException: Protocols may not be null
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.init(JSSESocketFactory.java:465)
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.createSocket(JSSESocketFactory.java:187)
        at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:398)
        at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:646)
        at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:434)
        at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
        at org.apache.catalina.connector.Connector.initInternal(Connector.java:978)
        ... 13 more
Caused by: java.lang.IllegalArgumentException: Protocols may not be null
        at com.ibm.jsse2.zb.a(zb.java:86)
        at com.ibm.jsse2.zb.<init>(zb.java:55)
        at com.ibm.jsse2.cd.setEnabledProtocols(cd.java:8)
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.initServerSocket(JSSESocketFactory.java:753)
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.checkConfig(JSSESocketFactory.java:768)
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.init(JSSESocketFactory.java:460)
        ... 19 more

It's triggered by the same place in org.apache.tomcat.util.net.jsse.JSSESocketFactory.{...}:

            context = SSLContext.getInstance("TLS");

Now DEFAULT_SERVER_PROTOCOLS is set to null because of the exception.

Is there a way to get the sslProtocol attribute specified for the connector in the server.xml? That has the value that should be used to create the SSLContext.
Comment 6 Hariharan, R 2014-10-21 08:13:29 UTC
@Mark Thomas: I am able to see the bug fix in 7.0.56.

@Karl Freburger:  Can you mail a 64-bit IBM JRE for Windows to cloakcavalier@gmail.com?
Comment 7 Mark Thomas 2014-10-22 20:59:47 UTC
> Is there a way to get the sslProtocol attribute specified for the connector
> in the server.xml? That has the value that should be used to create the
> SSLContext.

That is what is used. If you set sslProtocol="TLSv1.2" and sslEnabledProtocols="TLSv1.2" you should get past the exception you are currently seeing.

I now see a problem with cipher suites in my test environment. I'm still looking at whether this is a configuration problem or a Tomcat bug. The jury is out at this point so I am leaving this issue open.
Comment 8 Mark Thomas 2014-10-22 21:37:03 UTC
I have confirmed that this is a configuration issue.

A side effect of configuring strict SP800-131a mode and how Tomcat determines the available ciphers is that the default set of configured ciphers ends up being null. The simplest workaround to get to a working system is to use ciphers="ALL". In strict SP800-131a mode that should be a safe option. If you want to further restrict the ciphers list you can configure an explicit list of ciphetrs.

I am restoring this issue to FIXED since the additional issues raised since the original bug was fixed in 7.0.56 are configuration issues not coding bugs.
Comment 9 Konstantin Kolinko 2014-10-22 22:44:28 UTC
1. If IllegalArgumentException is thrown from static{} block of a class,  is it fatal for the class or not?

If it were fatal, the static{} block should have try/catch for IllegalArgumentException.

OK - JSSESocketFactory in Tomcat 7 has such catch, but Tomcat 6 does not have it yet.

2. This affects RFC_5746_SUPPORTED flag as well, as it will not be initialized and will remain in the state of "false".

3. Is it possible to try several names in turn in "SSLContext.getInstance("TLS");"
such as "TLS", "TLSv1.1" and "TLSv1.2"?

4. If this results in null value for DEFAULT_SERVER_PROTOCOLS then maybe

a) Report some error when DEFAULT_SERVER_PROTOCOLS is null?

From comment 5 we are lucky that passing the null to JRE API call results in an IllegalArgumentException with some decent message. I feared that it would be a NullPointerException.

b) Replace it with an empty String[] array. I think the message from JRE will be more near to the actual problem.
Comment 10 Konstantin Kolinko 2014-10-23 08:27:59 UTC
> 3. Is it possible to try several names in turn in
> "SSLContext.getInstance("TLS");" such as "TLS", "TLSv1.1" and "TLSv1.2"?

Other ideas:
A) Use JSSESocketFactory.defaultProtocol field here and allow it to be configured via a system property.

B) Defer evaluation of DEFAULT_SERVER_PROTOCOLS until there is a SSLContext instance that can be used to evaluate it, created from user-provided protocol name.

SSLContext.getProtocol() returns the protocol name and that allows to create a different SSLContext instance to test its defaults.
Comment 11 Mark Thomas 2014-10-23 09:24:06 UTC
(In reply to Konstantin Kolinko from comment #10)
> > 3. Is it possible to try several names in turn in
> > "SSLContext.getInstance("TLS");" such as "TLS", "TLSv1.1" and "TLSv1.2"?

Workable but ugly and not future proof for TLSv1.3 etc.

> Other ideas:
> A) Use JSSESocketFactory.defaultProtocol field here and allow it to be
> configured via a system property.

Yuck. I'm not a fan of system properties.

> B) Defer evaluation of DEFAULT_SERVER_PROTOCOLS until there is a SSLContext
> instance that can be used to evaluate it, created from user-provided
> protocol name.

I think this is possible. It looks as simple as moving the code from the static initializer to the constructor and having default per instance rather than at the class level (which makes more sense for protocols and ciphers since they may vary with connector configuration).

I'll take a look...
Comment 12 Mark Thomas 2014-10-23 10:21:26 UTC
Improved init code applied to 8.0.x for 8.0.15 onwards and to 7.0.x for 7.0.57 onwards.

The original issue has not been addressed in 6.0.x so the improved init code hasn't been applied either. The refactoring between 6.0.x and 7.0.x makes it more complex to backport and without an explicit user request, I do not plan to do so.
Comment 13 Konstantin Kolinko 2014-11-13 17:41:18 UTC
Fixed in Tomcat 6 by r1639415. The fix will be in 6.0.43 onwards.