HttpsURLConnection retry should not invoke X509TrustManager and HostnameVerifier more than once
Summary:
In 2.3, HttpsURLConnection was change to retry TLS connections as SSL
connections w/o compression to deal with servers that are TLS
intolerant. However, if the handshake proceeded to the point of
invoking the X509TrustManager, we should not retry. Similarly, if we
should not invoke the HostnameVerifier repeatedly, and need to wait
until the SSL handshake has completed.
Tested with (includes two new tests for this issue):
libcore/luni/src/test/java/libcore/javax/net/ssl/
libcore/luni/src/test/java/libcore/java/net/URLConnectionTest.java
libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
Details:
HttpConnection.setupSecureSocket has been broken into two
pieces. setupSecureSocket now just does the SSL
handshaking. verifySecureSocketHostname now does the
verification. The old HttpConnection code was careful never to
assign its sslSocket field until verification was complete. A new
unverifiedSocket field is added to store the sslSocket before
verification is completed by verifySecureSocketHostname.
luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
HttpsEngine.makeConnection now skips TLS intolerant retry if the
reason for the makeSslConnection failure was a
CertificateException, since that implies that we failed during
certification validation after initial handshaking. We also
prevent retrying hostname verification by moving it out of
makeSslConnection and only doing it on new SSL connections,
tracking the changes to HttpConnection.setupSecureSocket mentioned
above. We also now skip the redundant call to setUpTransportIO in
makeSslConnection on reused SSLSockets.
luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
Instead of throwing away the underlying CertificateExceptions, set
them as the cause of the SSLExceptions. This is what the RI does
in the case of X509TrustManager failures and is now used by
HttpsEngine.makeConnection.
luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
Added new testConnectViaHttpsToUntrustedServer which makes sure
that connections are not retried on certificate verification
failure.
luni/src/test/java/libcore/java/net/URLConnectionTest.java
Added new test_SSLSocket_untrustedServer that verifies that an
SSLHandshakeException is thown containing a CertificateException
is thrown on certificate verification problems.
luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
Added second test CA and a new TestKeyStore.getClientCA2 test key
store that does not trust the primary test key stores. This is
useful for negative testing and is used in the above two new
tests.
support/src/test/java/libcore/java/security/TestKeyStore.java
Issue: http://code.google.com/p/android/issues/detail?id=13178
Bug: 3292412
Change-Id: I37136bb65f04d2bceaf2f32f542d6432c8b76ad4