JDK-4528677 : can't connect to server where SSLv2/SSLv3/TLS combined ClientHello not supported
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 1.0.2
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2001-11-17
  • Updated: 2001-11-17
  • Resolved: 2001-11-17
Description

Name: nt126004			Date: 11/16/2001


java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)

Some old servers have problems with the combined SSLv2/SSLv3/TLS ClientHello, I
believe it only supports the SSLv2 ClientHello, but I'm not positive. When the
server recieves the combined ClientHello, it just closes the socket. I have been
unable to find a workaround for this.

There are several of these machines around the net, the one I'm trying to
conncet to is https://padlock.netnation.com/ though this is not my server, and
is not afiliated with my company. It's just an example.

I've included code below that builds an SSL connection to a server.

Here's what I get when I run my program to a server that does support the
ClientHello:

java ConnectJSSE https://www.paygateway.com/
Opening stream
Got Not Found
Received from host: read: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>404 Not Found</TITLE>
</HEAD><BODY>
<H1>Not Found</H1>
The requested URL / was not found on this server.<P>
</BODY></HTML>

Here's what I get when I run my program to a server that does NOT support the
ClientHello:

java ConnectJSSE https://padlock.netnation.com/

java.net.SocketException: Socket closed
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a([DashoPro-V1.2-120198])
        at
com.sun.net.ssl.internal.ssl.AppOutputStream.write([DashoPro-V1.2-120198])
        at java.io.OutputStream.write(OutputStream.java:61)
        at
com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake([DashoPro-V1.2-120198])
        at
com.sun.net.ssl.internal.www.protocol.https.HttpsClient.doConnect([DashoPro-V1.2-1201
98])
        at
com.sun.net.ssl.internal.www.protocol.https.NetworkClient.openServer([DashoPro-V1.2-1
20198])
        at
com.sun.net.ssl.internal.www.protocol.https.HttpClient.l([DashoPro-V1.2-120198])
        at
com.sun.net.ssl.internal.www.protocol.https.HttpClient.<init>([DashoPro-V1.2-120198])

        at
com.sun.net.ssl.internal.www.protocol.https.HttpsClient.<init>([DashoPro-V1.2-120198]
)
        at
com.sun.net.ssl.internal.www.protocol.https.HttpsClient.a([DashoPro-V1.2-120198])
        at
com.sun.net.ssl.internal.www.protocol.https.HttpsClient.a([DashoPro-V1.2-120198])
        at
com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnection.connect([DashoPro-V1.2
-120198])
        at
com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnection.getInputStream([DashoP
ro-V1.2-120198])
        at ConnectJSSE.connect(ConnectJSSE.java:39)
        at ConnectJSSE.main(ConnectJSSE.java:82)
Received from host: null


So you see, the server just closes the socket.

I've tried getting the SSLContext for a specific protocol (SSLv3, SSL, SSLV2)
and   using the context to set the SocketFactories, but I've been unable to
correct the problem.



my code:

import java.net.URL;
import java.net.HttpURLConnection;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.EOFException;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.security.Security;

/**
 *
 * @author  zjacobson
 * @version
 */
public class ConnectJSSE {
    private String site = null;

    /**
     * Creates new ConnectJSSE
     */
    public ConnectJSSE( String site ) {
        this.site = site;
    }

    public void connect( ) {
        URL url = null;
        HttpURLConnection connection = null;
        BufferedReader in = null;
        String responseString = null;
        try {
            url = new URL( site );
            connection = ( HttpURLConnection )url.openConnection( );

            connection.setRequestMethod( "GET" );
            connection.setDoInput( true );
            connection.setDoOutput( false );
            connection.setUseCaches( false );

            System.err.println( "Opening stream" );
            in = new BufferedReader( new InputStreamReader(
connection.getInputStream( ) ) );

            System.err.println( "Got " + connection.getResponseMessage( ) );
            String tempString = null;
            responseString = "read: ";
            try {
                while( ( tempString = in.readLine( ) ) != null ) {
                    responseString += tempString + '\n';
                }
            } catch( EOFException e ) {
                if( tempString == null ) {
                    throw e;
                }
            }
        } catch( Exception e ) {
            e.printStackTrace( );
        } finally {
            try {
                if( in != null ) {
                    in.close( );
                }
                if( connection != null ) {
                    connection.disconnect( );
                }
            } catch( Exception e ) {
                e.printStackTrace( );
            }
        }

        System.out.println( "Received from host: " + responseString );
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main( String args[ ] ){
        String pkgs = System.getProperty( "java.protocol.handler.pkgs" );
        System.setProperty( "java.protocol.handler.pkgs",
                            ( pkgs == null ? "" : pkgs + "|" ) +
                            "com.sun.net.ssl.internal.www.protocol" );
        Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider( ) );

        ConnectJSSE connection = new ConnectJSSE ( args[ 0 ] );
        connection.connect( );

    }
}
(Review ID: 135838) 
======================================================================

Comments
EVALUATION The site described does not accept TLS at all. Any attempt to talk TLS should be negotiated down to the lowest level you understand, which should be 3.0. You must configure the protocols to support only V3, with or without sslv2 client hello. No TLS. In JSSE in merlin, you do this by using the SSLSocket.setEnabledProtocols, or by setting the https.protocols variable for HttpsURLConnections. This method does not exist in JSSE 1.0.2, so this particular user is out of luck unless they wish to move to merlin. We currently do not plan to backport this functionality. public static void main( String args[ ] ){ // This is the default. // System.setProperty("https.protocols", "TLSv1,SSLv3,SSLv2Hello" ); System.setProperty("https.protocols", "SSLv3, SSLv2Hello" ); This works just fine. Note SSLContext.getInstance() returns an instance of a context that supports *AT LEAST* the protocol requests, however, it may support additional protocols if desired. SunJSSE supports a hybrid, but you can use the Enabled Protocols for more fine grained control. ###@###.### 2001-11-16
16-11-2001