Proxied https connection reuse by sun.net.www.http.HttpClient can send CONNECT to the destination server

Steven Lawrance slawrance at salesforce.com
Mon Dec 23 15:41:34 PST 2013


Hi net-dev,

I filed this on September 26 at bugs.sun.com, which assigned bug ID 9007104
to it, but that bug still does not appear to be visible. I'm emailing in
case if that system malfunctioned. I now see that OpenJDK has a Bugzilla
system, but I don't have an account to file this bug.

Bug details:

Proxied https connection reuse by sun.net.www.http.HttpClient can send
CONNECT to the destination server

Linux slawrance-wsl 2.6.32-45-generic #104-Ubuntu SMP Tue Feb 19 21:20:09
UTC 2013 x86_64 GNU/Linux
This also happens in RedHat Enterprise Linux 4 and 5, at least

This bug occurs in an environment where a HTTP proxy server is used for
outbound connections.

java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)

This bug also exists in 1.6.0_34 and 1.7.0_21:

java version "1.6.0_34"
Java(TM) SE Runtime Environment (build 1.6.0_34-b04)
Java HotSpot(TM) 64-Bit Server VM (build 20.9-b04, mixed mode)

java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)


When a proxied https request is reused in the JDK's built-in
HttpsURLConnection, a closed connection will cause the retry code to
inadvertently send the 'CONNECT' request meant for the proxy to the remote
endpoint via the new proxied connection.

>From a high level, the second request in a reused request where the remote
endpoint had closed down its output stream causes an error handler in
sun.net.www.http.HttpClient to try it again within a new proxy connection.
It does establish a new proxied connection, but it ends up sending the
wrong request through the established proxied connection. Instead of
sending the intended request, it sends the http request that was used to
establish the second connection to the proxy.

That bug in the error handler in HttpsURLConnection is very subtle. It
appears that a part of it was coded it in a way that was intended to
mitigate this issue, but it unfortunately wasn't sufficient.

In sun.net.www.http.HttpClient.parseHTTPHeader:765 (in 1.7.0u40's source
code), the call to httpuc.doTunneling() backs up the 'requests' field and
then restores it by the end of that method, but that's just in httpuc. When
httpud.doTunneling() writes the 'CONNECT' request, it ends up calling the
sun.net.www.http.HttpClient's writeRequests:598 method, which sets the
'requests' field of sun.net.www.http.HttpClient to the 'CONNECT' request's
values. After httpuc.doTunneling() returns, it proceeds to retry the
request with the newly established proxy connection, but it's unfortunately
using the 'requests' field that was overwritten by the writeRequests() call
from the 'CONNECT' request. Consequently, the remote endpoint sees a
'CONNECT' request instead of the intended request.

Fortunately, it is possible to override sun.net.www.http.HttpClient by
using the endorsed jar mechanism. I tried that out and was able to verify
that it successfully fixes the issue. The patch that fixed this issue is
the following:

---
/home/slawrance/dev/tools/Linux/jdk/jdk1.7.0_40_x64/src/jdk/src/share/classes/sun/net/www/http/HttpClient.java
2013-09-06 11:28:38.000000000 -0700
+++ HttpClient.java     2013-09-25 23:14:19.693524881 -0700
@@ -651,7 +634,9 @@
                     // try once more
                     openServer();
                     if (needsTunneling()) {
+                        final MessageHeader origRequests = requests;
                         httpuc.doTunneling();
+                        requests = origRequests;
                     }
                     afterConnect();
                     writeRequests(requests, poster);
@@ -762,7 +747,9 @@
                         cachedHttpClient = false;
                         openServer();
                         if (needsTunneling()) {
+                            final MessageHeader origRequests = requests;
                             httpuc.doTunneling();
+                            requests = origRequests;
                         }
                         afterConnect();
                         writeRequests(requests, poster);


Reproduction steps:

Run the test case code. The Test.java class starts up a https server and a
proxy server so that it can make two requests via the proxy to the https
server in a manner that triggers reuse of the first connection.

I was able to verify that this test fails without the fix and passes with
the fix. Details exist in the expected and actual results below.


Expected results:

After the fix is applied via the endorsed jar mechanism, the test passes:

$ ~/dev/tools/Linux/jdk/jdk1.7.0_40_x64/bin/java
-Djava.endorsed.dirs=/home/slawrance/dev/system/ext/sun_misc/HttpClientFix/jars
Test
Client: Requesting https://slawrance-wsl.internal.salesforce.com:7517/ via
HTTP @ slawrance-wsl.internal.salesforce.com/10.0.63.231:47856 (attempt 1
of 2)
Proxy: NEW CONNECTION
Server: NEW CONNECTION
Client: Requesting https://slawrance-wsl.internal.salesforce.com:7517/ via
HTTP @ slawrance-wsl.internal.salesforce.com/10.0.63.231:47856 (attempt 2
of 2)
Proxy: NEW CONNECTION
Server: NEW CONNECTION
TEST PASSED


Failure (current) output:

$ ~/dev/tools/Linux/jdk/jdk1.7.0_40_x64/bin/java Test
Client: Requesting https://slawrance-wsl.internal.salesforce.com:10318/ via
HTTP @ slawrance-wsl.internal.salesforce.com/10.0.63.231:5445 (attempt 1 of
2)
Proxy: NEW CONNECTION
Server: NEW CONNECTION
Client: Requesting https://slawrance-wsl.internal.salesforce.com:10318/ via
HTTP @ slawrance-wsl.internal.salesforce.com/10.0.63.231:5445 (attempt 2 of
2)
Proxy: NEW CONNECTION
Server: NEW CONNECTION
Server: BUG! HTTP CONNECT encountered: CONNECT
slawrance-wsl.internal.salesforce.com:10318 HTTP/1.1
TEST FAILED


Test case code:

import java.io.*;
import java.net.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.*;

import
com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;

/**
 * Test case for the bug where a closed connection will cause the retry
code to inadvertently send the 'CONNECT' request
 * meant for the proxy to the remote endpoint via the new proxied
connection when a proxied https request is reused in
 * the JDK's built-in HttpsURLConnection.
 *
 * @author Steven Lawrance
 */
public class Test {
    private final InetSocketAddress serverSocketAddress, proxySocketAddress;
    private final Thread serverThread, proxyThread;
    private final AtomicBoolean keepRunning = new AtomicBoolean(true);
    private final AtomicBoolean connectObservedInServer = new
AtomicBoolean();

    /** Key and certificate for the https server in this test, expressed as
base64 (not a "real" cert; it's a test cert) */
    private final String TEST_PKCS12_FILE =
"MIIKZgIBAzCCCjAGCSqGSIb3DQEHAaCCCiEEggodMIIKGTCCBJ8GCSqGSIb3DQEHBqCCBJAwggSM"
            +
"AgEAMIIEhQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIwqUBH+SDbMYCAggAgIIEWFyrRsMm"
            +
"PxJ7mqJ6EEK63TLrcjfpbc+jEK3w5nWB8NfuILFy1fvCX3Z5VfOrU0SV+ZSrbFzXL52XKItwq7nD"
            +
"WcDPAoBybKQZcOjTkTPKUlIQJdU+oovOS69ER52wOAu3FySEYCXVjVO4xQ9Jr9fmx0wbScI6ramT"
            +
"+oOJs9woi12/NQ2zLj0cIk1x84kD4Lw/vMe/2q6D6XjxZWrWCJaZNo4VJwssLBuSquM6VuW3q63r"
            +
"L8NedZ4BId6CyR0Ft/4JVQM+kpMDshhj5wnUUfPDjvldhHP1c1MSiI/gNxwbn/Ielh1zMjffitIZ"
            +
"WY2UUmVFlpg3CElA1gJKylQnXvSuXu1jw/Vnd4raI32tOqlovEx2/Iey/W0ZBj8vXzKqcYW7sCzf"
            +
"i2qEyWYvSLyqCVdOMc6wkbK5a3QInamV+2fcl3z3/l//4/yzZ6xhNQ7+9LlZs7YuMreR6og+dfWK"
            +
"FsIaZDz1sr1bHdAEJNE5YcaJkRqkT74eyKMalRa9HBHZXCG5y06JgwO6h7P4MtOltIPi/HHhHvs5"
            +
"VXZsLljLj/JyinDNNKPvhw3SxF1r4XMF2sNN+6eSGuWNjmWp1mXP/Pio8vgQH/epWlhee3b6WYYu"
            +
"bpSvHHRBdYqfdnUd4SKvgi074SFxJ7r/8XykAr7lpxqjuxPMExcEh/BsmNaXBAB3uv5B3E83tU49"
            +
"nQ+kas+QNdx08D8EOLKYhUGOsa3iMMtrmlD643Zd031uBB5JLcBRK6ZgBg16I8pBv0PjWRe3Bg7X"
            +
"rOemfUZySfsDVRIiZqvy0DbkvqvhiAMOIkWmQW6gfV/1/KeSm4NV12MCRL4B68xPn+t1Ok3O0TG2"
            +
"HkSmGUTwuLkv9dn4dW2rz1fr+9LJk27nr9+Ecn4hUfDx8xIp9rsqd3wJSqSWC55uafCq3zC5CvOY"
            +
"7DoLehM8w3GiAscZupIhG34HIt9NbQcN1RQus6TgkNWMh3s8fGM7ypWCmptN8V1wTMb1E+9zwlFg"
            +
"NQHhqg0hGwSwaF5R7+w1+QzP38Xiss5Es+Qxi2DPjhNNzHTb33JKo6VoPHUgAdHAT2VtHjhnIb6G"
            +
"PRhKI0NxrSrsfZZY2x1JnwfH0UhbDGJheObeGLplzZYvHcUw+dDRS+nPvt8faCos3Mmdz9Ux4FiX"
            +
"trXvp/3PadFduC/mKBC7/aAyu1HW0dCJd0djZbn0+VzOfr8TRPI5j1/uaELzSF67PlKr1L/PVFlL"
            +
"GdlwhMLDLPthUt3Wu7aHOOxkRZuXsHCveSIh+y4VsWH2u4SQEYEd8xASf6D/p4MtC1JIe+vapoEN"
            +
"7uLdIuG75Td2Qh12/VDbCAHFaRFqeDpdlz7qG5hrQbrSnTuGFxVEJM9tMYxshDeK0+IJ44cSQBNi"
            +
"FD3Cko281Pcgoeiqp3a43q7o12reaXU5smHLJ5BgCz1jrbBVagmX4WYIOy9iq2QjWa0Fh7aHIfAi"
            +
"Vf8BB4aeGBUUpFyNzOOHaSBfWtFWF75TMIIFcgYJKoZIhvcNAQcBoIIFYwSCBV8wggVbMIIFVwYL"
            +
"KoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECFiQCKVgBtWJAgIIAASCBMi1w33Q"
            +
"cFzrSVWzSo8fBb74biRDlMAhVFUYyQt3uU7i9ss7/Eqetvg+2erZXx4ywhlwSy7p3lQ5+rJvRYPk"
            +
"ayxzoMLYP3Q102OHtGANwhRGFbX+PKEyB9o6qBj1CfcuEptkpCvdxYbnZ8AThzyBDwWEyVJX81Zw"
            +
"0r8GpuTg6sFtfdd1Ytjzxr2MpJsrqukFD5D9/8YCHYNab3A8JrkudvHNUUlgmHH4hmEEMOxnSlc6"
            +
"tIGoWqSi3KhCZjVDiZB6dzUih2TwDkklfwa5r65/lpp9xgBKK1wf6Q3cbhwrncn9kNbnBBH/nQxO"
            +
"qsvFRzypBnU7u9XmRdBIZox9yM8Vgt+Elf90E44xiMF+RV8mzGOvogQ2QUpLsZ8JCcmMq7z3Rpth"
            +
"HDmHl067VhAll7qAZcUqtEvgutLx6QX/UmFBumdWjrNqn4S3EpaiZhe4qQKlaIHZJvnvrGpAwxGt"
            +
"0VRuDFH9B98hx7k7Rfuw4nz/AcQf3v51dY950SoAIHtbk6xQ11Ad0YJ0lUsdck4uhMpvrM4OjtG4"
            +
"UEv4ywo6JVsjXQ9bo2j6asR4NnGR5Gs7PkyEn6Yz4DTjj/hW9m8uqUjcNbxPlASx+owNsEkL9IqW"
            +
"XV7KRcPQFd1dsWttMnBh9yfr62yGBCzEj7FNcDNOpzjZFUbbe8X55GHeBQN82BHZglA1A6rD6a1H"
            +
"QXUHkXcPrh8xpRsh5MRKMf0LgV5bd2XnwQgbeq3EFbyYdx+uz7RwxNOhp5OHHasSMjAbLNNBRIUH"
            +
"YGoWH6NxQIZ7WiGpno9ZnfBLY32b9MQKJMRRiv93CGtjo2wtKZyEeVvJI99UBBz2+ateeNknG054"
            +
"oi1qENiDc8iU0lYyTP4acNKjcso0m5X4X1PJLNlj6DOzmG8x2XeESXM2FtHLpqWtbtGhRsJPsPJE"
            +
"KqWpUZ1l148i7XbJkixLhgUdpJhT69Bubcc7JkdOKbpvIW3ipPXS9GbSwhJVN95nRot8sEjM8uqe"
            +
"6kJ1/VV250Cw2ZJj2BDhK/Teq9GKm27YbC7YWUSo5YOQSfaL2k3zD5ejDTMCiWjK2FDaFQ4fHvBw"
            +
"UQyYeX3IdPo5HdwTcfrGzVCYMUxKN3eUbcYMZajC25mkd7IvPNDvezUyb0KmAAip+xnXfb0Z9zGF"
            +
"c1lzv7MkwPFI0ceYwCX49d4NDGMZ67rG+zhYR0UgxnzyMav5u4c+9gz9PZLdZRqooNpusY3A21v5"
            +
"iXRY32u7UcY2QYMR4tquJ3lKKFY9OWaOnC2cLK/fuK+3IEBdK6ZejXXmS7a5g6HCHBEFb+wOjOiT"
            +
"P795XuB6d9m2tqED4WojxnP+shagD9DU7cRcDpwYiEqhIh44OE5m9vpoX1IIk7Y89QES9tcfmEFS"
            +
"EEF1FblMZC0LjYOEuqvStRxFOoa0SuD1vEUnJdGQXrRAlvOrQK+Hx128wSO5cC895D7/MKmRenRp"
            +
"sIjuKG9nFHnzagQ5kR9Q4II5Y73qCf9894KMCp5MdK/IEZoY/yhWKHgwE9iDL53URstRoqD2OfqO"
            +
"sjxKYlOsC52IoL9xlqFVm2ahsaP+9lOzrgNo43D8GMNuGRuZ9UEJAKoi7QTknt2vEktnA5gj0TyT"
            +
"7aZYdO2sAVFRydlRsT8oiOhYhZoXMrExVjAjBgkqhkiG9w0BCRUxFgQUr8hoZhCTn3Jpm5tZ1GOM"
            +
"396ULBkwLwYJKoZIhvcNAQkUMSIeIABUAGUAcwB0ACAAQwBlAHIAdABpAGYAaQBjAGEAdABlMC0w"
            +
"ITAJBgUrDgMCGgUABBQb3xdMv5tvFY0Qi7geGD1SBoG5JwQIAcFtrXRzzmA=";

    public static void main(String[] args) {
        try {
            final Test test = new Test();
            test.runTest();
            test.keepRunning.set(false);
            test.serverThread.interrupt();
            test.serverThread.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.exit(0);
    }

    private void runTest() throws IOException {
        final URL url = new URL("https", serverSocketAddress.getHostName(),
serverSocketAddress.getPort(), "/");
        final Proxy proxy = new Proxy(Proxy.Type.HTTP, proxySocketAddress);
        HttpsURLConnection.setDefaultHostnameVerifier(new
HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession sslSession) {
                return serverSocketAddress.getHostName().equals(hostname);
// ignore the cert's CN; it's not important to this test
            }
        });

HttpsURLConnection.setDefaultSSLSocketFactory(createTestSSLSocketFactory());

        // Make two connections. The bug occurs when the second request is
made
        for (int i = 0; i < 2; i++) {
            System.out.println("Client: Requesting " + url.toExternalForm()
+ " via " + proxy.toString() + " (attempt " + (i + 1) + " of 2)");
            HttpsURLConnection connection = (HttpsURLConnection)
url.openConnection(proxy);
            connection.setRequestMethod("POST");
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestProperty("User-Agent", "Test/1.0");
            connection.getOutputStream().write("Hello,
world!".getBytes("UTF-8"));
            if (connection.getResponseCode() != 200) {
                System.err.println("Client: Unexpected response code " +
connection.getResponseCode());
                break;
            }
            final BufferedReader reader = new BufferedReader(new
InputStreamReader(connection.getInputStream(), "UTF-8"));
            final String response = reader.readLine();
            if (!"Hi!".equals(response)) {
                System.err.println("Client: Unexpected response body: " +
response);
            }
        }
        if (connectObservedInServer.get()) {
            System.err.println("TEST FAILED");
        } else {
            System.out.println("TEST PASSED");
        }
    }

    private Test() throws IOException, NoSuchAlgorithmException,
KeyStoreException, CertificateException, KeyManagementException,
UnrecoverableKeyException {
        KeyStore ks = openKeyStore(TEST_PKCS12_FILE, "testing123",
"PKCS12");
        KeyManagerFactory factory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        factory.init(ks, "testing123".toCharArray());
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(factory.getKeyManagers(), null, null);
        final SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();

        // Create the server that the test wants to connect to via the proxy
        final ServerSocket serverSocket =
ServerSocketFactory.getDefault().createServerSocket();
        serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(),
0 /* ephemeral port */));
        serverSocketAddress = (InetSocketAddress)
serverSocket.getLocalSocketAddress();
        serverThread = new Thread("ServerThread") {
            @Override
            public void run() {
                try {
                    while (keepRunning.get()) {
                        final Socket socket = serverSocket.accept();
                        System.out.println("Server: NEW CONNECTION");
                        if (socket != null) {
                            try {
                                final SSLSocket sslSocket = (SSLSocket)
sslSocketFactory.createSocket(socket, null, serverSocketAddress.getPort(),
false);
                                sslSocket.setUseClientMode(false);
                                sslSocket.startHandshake();
                                final BufferedReader reader = new
BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
                                String line;
                                while (!sslSocket.isInputShutdown()) {
                                    try {
                                        String firstLine = null;
                                        while ((line = reader.readLine())
!= null && line.length() > 0) {
                                            if (firstLine == null) {
                                                firstLine = line;
                                            }
                                        }
                                        if (line == null) {
                                            break;
                                        }
                                        if (firstLine != null &&
firstLine.contains("CONNECT")) {
                                            System.out.println("Server:
BUG! HTTP CONNECT encountered: " + firstLine);

connectObservedInServer.set(true);
                                        }
                                        final String response = "HTTP/1.1
200 OK\r\nContent-Type: text/plain\r\nContent-Length: 3\r\n\r\nHi!";
                                        final OutputStream out =
sslSocket.getOutputStream();

out.write(response.getBytes("UTF-8"));
                                        out.flush();

                                        // Close the underlying
connection's output writer after a second to ensure that the client and
proxy
                                        // think that this connection is
still open in both directions for the second request.
                                        try {
                                            Thread.sleep(1000);
                                        } catch (InterruptedException e) {
                                        }
                                        socket.shutdownOutput();
                                        break;
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                        break;
                                    }
                                }
                            } catch (Exception e) {
                                try {
                                    socket.close();
                                } catch (IOException e2) {
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        serverThread.start();

        // Create the http proxy server
        final ServerSocket proxySocket =
ServerSocketFactory.getDefault().createServerSocket();
        proxySocket.bind(new InetSocketAddress(InetAddress.getLocalHost(),
0 /* ephemeral port */));
        proxySocketAddress = (InetSocketAddress)
proxySocket.getLocalSocketAddress();
        proxyThread = new Thread("ProxyThread") {
            @Override
            public void run() {
                try {
                    final Pattern connectLinePattern =
Pattern.compile("^CONNECT ([^: ]+):([0-9]+) HTTP/[0-9.]+$");
                    int proxyConnectionCount = 0;
                    while (keepRunning.get()) {
                        final Socket clientSocket = proxySocket.accept();
                        System.out.println("Proxy: NEW CONNECTION");
                        final int proxyThreadCount = ++proxyConnectionCount;
                        new Thread("ProxySocket" + proxyThreadCount) {
                            @Override
                            public void run() {
                                if (clientSocket != null) {
                                    try {
                                        final InputStream clientIn =
clientSocket.getInputStream();
                                        String line;
                                        try {
                                            String firstLine = null;
                                            while ((line =
readLineFromInputStream(clientIn)) != null && line.length() > 0) {
                                                if (firstLine == null) {
                                                    firstLine = line;
                                                }
                                            }
                                            if (line == null || firstLine
== null) {
                                                return;
                                            }
                                            final Matcher
connectLineMatcher = connectLinePattern.matcher(firstLine);
                                            if
(!connectLineMatcher.matches()) {
                                                System.out.println("Proxy:
Unexpected request to the proxy: " + firstLine);
                                                return;
                                            }
                                            final String host =
connectLineMatcher.group(1);
                                            final String portStr =
connectLineMatcher.group(2);
                                            final int port =
Integer.parseInt(portStr);
                                            final Socket serverSocket =
SocketFactory.getDefault().createSocket(host, port);
                                            final InputStream serverIn =
serverSocket.getInputStream();
                                            final OutputStream serverOut =
serverSocket.getOutputStream();
                                            final OutputStream clientOut =
clientSocket.getOutputStream();
                                            clientOut.write("HTTP/1.0 200
Connection Established\r\nProxy-Agent:
TestProxy/1.0\r\n\r\n".getBytes("UTF-8"));
                                            final Thread toServerCopier =
new Thread("ProxyCopierToServer" + proxyThreadCount) {
                                                @Override
                                                public void run() {
                                                    try {
                                                        final byte[] b =
new byte[1024];
                                                        int byteCount;
                                                        while ((byteCount =
clientIn.read(b)) > 0) {

serverOut.write(b, 0, byteCount);
                                                        }
                                                    } catch (IOException e)
{
                                                        // Socket is
probably closed
                                                    } catch (Exception e) {
                                                        e.printStackTrace();
                                                    }
                                                    try {

serverSocket.shutdownOutput();
                                                    } catch (IOException e)
{
                                                        // Socket is
probably closed
                                                    } catch (Exception e) {
                                                        e.printStackTrace();
                                                    }
                                                }
                                            };
                                            toServerCopier.start();
                                            try {
                                                final byte[] b = new
byte[1024];
                                                int byteCount;
                                                while ((byteCount =
serverIn.read(b)) > 0) {
                                                    clientOut.write(b, 0,
byteCount);
                                                }
                                            } catch (IOException e) {
                                                // Socket is probably closed
                                            }
                                            try {

clientSocket.shutdownOutput();
                                            } catch (IOException e) {
                                                // Socket is probably closed
                                            } catch (Exception e) {
                                                e.printStackTrace();
                                            }
                                            toServerCopier.join();
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }
                                    } catch (Exception e) {
                                        try {
                                            e.printStackTrace();
                                            clientSocket.close();
                                        } catch (IOException e2) {
                                        }
                                    }
                                }
                            }
                        }.start();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        proxyThread.start();
    }

    private String readLineFromInputStream(InputStream in) throws
IOException {
        final StringBuilder s = new StringBuilder();
        int ch;
        while ((ch = in.read()) >= 0) {
            if (ch == '\r') {
                continue;
            }
            if (ch == '\n') {
                break;
            }
            s.append((char) ch);
        }
        return s.toString();
    }

    private KeyStore openKeyStore(String pkcs12FileBase64, String password,
String type) throws IOException, NoSuchAlgorithmException,
KeyStoreException, CertificateException {
        ByteArrayInputStream fin = null;
        char[] passphrase = password.toCharArray();
        KeyStore ks = KeyStore.getInstance(type);
        try {
            fin = new ByteArrayInputStream(Base64.decode(pkcs12FileBase64));
        } catch (Base64DecodingException e) {
            throw new RuntimeException(e);
        }
        ks.load(fin, passphrase);
        return ks;
    }

    private SSLSocketFactory createTestSSLSocketFactory() {

        // Set up the socket factory to use a trust manager that trusts all
certs, since trust validation isn't important to this test
        final TrustManager[] trustAllCertChains = new TrustManager[] { new
X509TrustManager() {
            @Override
            public java.security.cert.X509Certificate[]
getAcceptedIssuers() {
                return null;
            }

            @Override
            public void
checkClientTrusted(java.security.cert.X509Certificate[] certs, String
authType) {}

            @Override
            public void
checkServerTrusted(java.security.cert.X509Certificate[] certs, String
authType) {}
        } };
        final SSLContext sc;
        try {
            sc = SSLContext.getInstance("TLS");
        }
        catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        try {
            sc.init(null, trustAllCertChains, new
java.security.SecureRandom());
        }
        catch (KeyManagementException e) {
            throw new RuntimeException(e);
        }
        return sc.getSocketFactory();
    }
}


Thanks, and please feel free to let me know if you have any questions.

Steven Lawrance
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/net-dev/attachments/20131223/608b5ab6/attachment.html 


More information about the net-dev mailing list