Random "peer not authenticated" exceptions with Java SSLContextImpl$TLS10Context
Asked Answered
C

2

50

I get connection failures that appear randomly when connecting to an HAProxy server using SSL. I have confirmed that these failures happen on JDK versions 1.7.0_21 and 1.7.0_25 but not with 1.7.0_04 or with 1.6.0_38.

The exception is

 Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)
    at SSLTest2.main(SSLTest2.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

These failures only happen when using the TLS SSL context and not with the default context. The following code is run in a loop a thousand times and failures happen before the loop completes (about 2% of the connections fail):

SSLContext sslcontext = SSLContext.getInstance("TLS");   
sslcontext.init(null, null, null);
SSLSocketFactory factory = sslcontext.getSocketFactory(); 
SSLSocket socket = (SSLSocket)factory.createSocket("myserver", 443);

//socket.startHandshake();
SSLSession session = socket.getSession();
session.getPeerCertificates();
socket.close();

If, however, I create the SSL context this way I have no connections failures on any of the Java versions I mentioned:

SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();

The first way uses SSLContextImpl$TLS10Context and the later uses SSLContextImpl$DefaultSSLContext. Looking at the code, I don't see any differences that would cause the exception to occur.

Why would I be getting the failures and what are the advantages/disadvantages of using the getDefault() call?

Note: The exceptions were first seen using the Apache HttpClient (version 4). This code is the smallest subset that reproduces the problem seen with HttpClient.

Here's the error I see when adding -Djavax.net.debug=ssl:

main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, bad_record_mac
%% Invalidated:  [Session-101, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLException: Received fatal alert:   bad_record_mac
main, IOException in getSession():  javax.net.ssl.SSLException: Received fatal alert: bad_record_mac

Another piece of information is that the errors do not occur if I turn off Diffie-Hellman on the proxy server.

Collation answered 15/8, 2013 at 22:34 Comment(7)
Please re-run with -Djavax.net.debug=ssl,handshake and post an output from a failing run.Groningen
Ran again with the debug option on. Updated the question with this information. Does anyone have any ideas?Collation
Why do you prefer four lines of code to one?Groningen
@EJP - could you explain what you mean with that comment? I'm confused.Wichern
Looks like this is a bug in the mentioned Java versions. I often got this error when connecting to the SVN server from within Eclipse (subclipse). However using the latest JVM 1.7.0_51 the code above does not trigger any exception here (executed 1000 times).Needs
You may want to read the comments in #10772858Office
@Zach You have one line of code that works, i.e. the one that calls getDefault(), and four lines that don't. I'm asking you why you prefer the second, when it is both longer and doesn't work.Groningen
R
1

Judging by the symptoms, I'm guessing this is related to browsers using TLS false start, which is a client-side trick Google introduced to reduce the back-and-forth in TLS:

False Start is largely controlled by the browser and works by reducing the two round-trip passes of data described in official SSL specifications to a single round-trip pass. It did this by instructing the client to send Finished and first ApplicationData messages in a single dispatch rather than putting them in two distinct packages and sending the second only after getting confirmation from the server.

Google proposed False Start as an official standard to make SSL more palatable to websites that currently find it too expensive to offer. By abbreviating the handshake that negotiates the encryption key and other variables needed to protect data passing between the end user and website, False Start was intended to lower the performance penalty that many say comes from using the protocol.

From the relevant issue raised in Mozilla Firefox: (emphasis mine)

So far, an incomplete list of products that are known to have current or previous compatibility problems with False Start include (AFAICT): F5, A10, Microsoft TMG, Cisco ASA, ServerIron ADX, ESET, NetNanny, some configurations of Java's SSL server implementation.

Roadrunner answered 19/5, 2014 at 15:6 Comment(2)
The connection, in the case of the OP and also in my case, is between a client written in JAVA and a server (proxy or http). No browser here...Declension
@LorenzoDematté Aah, of course, you're right. Can't believe I missed that.Roadrunner
T
-3

javax.net.ssl.SSLPeerUnverifiedException arise only because of http security you have to configure your connection as https else follow this code..

            SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, new TrustManager[]{tm}, null);
    SSLSocketFactory ssf = new SSLSocketFactory(ctx);
    ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    ClientConnectionManager ccm = client.getConnectionManager();
    SchemeRegistry sr = ccm.getSchemeRegistry();
    sr.register(new Scheme("https", ssf, 443));
    return new DefaultHttpClient(ccm, client.getParams());

use this. i hope it will help you

Touter answered 16/6, 2014 at 5:51 Comment(2)
You're just introducing a security vulnerability with ALLOW_ALL_HOSTNAME_VERIFIER, that's not helping.Scheelite
It doesn't 'arise only because of HTTP security' at all. It has nothing to do with HTTPS. It happens at the TLS layer.Groningen

© 2022 - 2024 — McMap. All rights reserved.