4 Replies Latest reply: Oct 22, 2013 3:40 PM by DrewS RSS

    can't import certificates through a Proxy

    DrewS

      I am beginning to work with SSL Socket connections and have a question regarding SSLSocket connections while behind a proxy (or multiple proxies).

       

      One of the applications I'm working on requires the import of root certificates prior to use.  I know how to do this via keytool after manually downloading the certificate, but was also interested in using ImportCert.java (one version found at:  https://gist.github.com/philipsorst/438037 ) to do the import.

      ImportCert works fine when not behind a proxy.  However, while behind a Proxy, I get errors when connecting to https sites: 

       

      javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

      at sun.security.ssl.InputRecord.handleUnknownRecord(InputRecord.java:671)

      at sun.security.ssl.InputRecord.read(InputRecord.java:504)

      at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)

      at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)

      at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)

      at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)

      at com.aw.ad.util.InstallCert.main(InstallCert.java:98)

      Could not obtain server certificate chain


      those sites are fine when using a browser through the proxy. 


      The connection logic in question from ImportCert.java:


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

      TrustManagerFactory tmf =  TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

      tmf.init(ks);

      X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];

      SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);

      context.init(null, new TrustManager[] {tm}, null);

      SSLSocketFactory factory = context.getSocketFactory();

       

      System.out.println("Opening connection to " + host + ":" + port + "...");

      SSLSocket socket = (SSLSocket)factory.createSocket(host, port);

      socket.setSoTimeout(10000);

      try {

      System.out.println("Starting SSL handshake...");

      socket.startHandshake();

      socket.close();

      System.out.println();

      System.out.println("No errors, certificate is already trusted");

      } catch (SSLException e) {

      e.printStackTrace();

      }

       


      I have tried updating the code with:

      System.setProperty("http.proxyHost", "172.23.0.1");

      System.setProperty("http.proxyPort", "8080");

      System.setProperty("https.proxyHost", "172.23.0.1");

      System.setProperty("https.proxyPort", "8080");

       

      or running the jvm with -Dhttp.proxyHost=172.23.0.1 -Dhttp.proxyPort=8080 -Dhttps.proxyHost=172.23.0.1 -Dhttps.proxyPort=8080 ImportCert website.example.com:443

       

      but neither have any effect, as seen by monitoring the erros and a tcpdump of the connection.

       

      I did modify the code to make a URL connection instead of an SSL Socket Connection with something like: 

      URL url = new URL("https://websitetoconnecto.com/");

      InputStream in = url.openStream();

       

      which does honor the proxy settings.

       

      So the question is, why does the SSLSocket connection method not appear to honor the proxy settings?  A little digging suggests that an HTTP CONNECT request may be needed first... but I'm totally lost at this moment.

       

      Thanks for any suggestions!