title: Make an SSL call through an HTTP proxy using HttpClient on a WebSphere server
body: <p>I've tried to google for this problem for a couple of days but I'm still stuck, so I'll try to ask for some help here.</p>
  
  <p>Here is the situation. The EJB I'm developing must connect to a secure web service. The connection needs mutual authentication, so I have a public ID chain and a personal certificate. I load these informations from file, and build my own SSLSocketFactory (the Apache HttpClient one)</p>
  
  <pre><code>    // Queste proprietà servono perché senza di loro WebSphere 6.1 non
      // capisce un cazzo
      Security.setProperty("security.provider.1", "com.ibm.jsse2.IBMJSSEProvider2");
      Security.setProperty("security.provider.2", "com.ibm.crypto.fips.provider.IBMJCEFIPS");
      Security.setProperty("security.provider.3", "com.ibm.crypto.provider.IBMJCE");
      Security.setProperty("security.provider.4", "com.ibm.security.jgss.IBMJGSSProvider");
      Security.setProperty("security.provider.5", "com.ibm.security.cert.IBMCertPath");
      Security.setProperty("security.provider.6", "com.ibm.security.sasl.IBMSASL");
      Security.setProperty("ssl.SocketFactory.provider", "com.ibm.jsse2.SSLSocketFactoryImpl");
      Security.setProperty("ssl.ServerSocketFactory.provider", "com.ibm.jsse2.SSLServerSocketFactoryImpl");
  
      // d) SETUP KS, TS e SSL
      InitialContext ctx = new InitialContext();
  
      // keystore
      KeyManager[] keyManagers;
      TrustManager[] trustManagers;
      try {
          URI keyStoreUri = ((URL) ctx.lookup(JNDI_INPS_KEY_STORE_PATH))
                  .toURI();
          String keyStorePassword = "test2012";
  
          KeyStore keyStore = loadKeyStoreFromFile(keyStoreUri,
                  keyStorePassword);
  
          KeyManagerFactory keyManagerFactory = KeyManagerFactory
                  .getInstance("IBMX509");
          keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
  
          keyManagers = keyManagerFactory.getKeyManagers();
  
          URI trustStoreUri = ((URL) ctx.lookup(JNDI_INPS_TRUST_STORE_PATH))
                  .toURI();
          String trustStorePassword = "inpsChain";
  
          KeyStore trustStore = loadKeyStoreFromFile(trustStoreUri,
                  trustStorePassword);
  
          TrustManagerFactory trustManagerFactory = TrustManagerFactory
                  .getInstance("IBMX509");
          trustManagerFactory.init(trustStore);
  
          trustManagers = trustManagerFactory.getTrustManagers();
      } catch (NameNotFoundException ex) {
          throw new ErroreApplicativo("USINPS001", ErroreApplicativo.ERRORE,
                  "", null);
      }
  
      SSLContext sslCtx = SSLContext.getInstance("TLS");
      sslCtx.init(keyManagers,
              new TrustManager[] { new TrustfulTrustManager() }, null);
  
      SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslCtx);
      Scheme httpsScheme = new Scheme("https", HTTPS_PORT, sslSocketFactory);
      Scheme httpScheme = new Scheme("http", HTTP_PORT, sslSocketFactory); // Which socket factory should I use?
  
      final SchemeRegistry schemeRegistry = new SchemeRegistry();
      schemeRegistry.register(httpScheme);
      schemeRegistry.register(httpsScheme);
  
      PoolingClientConnectionManager connManager = new PoolingClientConnectionManager(
              schemeRegistry);
  </code></pre>
  
  <p>Passwords are temporarily written in the code, but they will be parametrized as soon as the solution will be working.</p>
  
  <p>I have to use a proxy to make the call. I've never done this kind of stuff, but I suppose that I have to use http tunneling since the certificates are in my server and not in the proxy. So I setup an HttpRoute (still an HttpClient class)...</p>
  
  <pre><code>    System.setProperty("java.net.useSystemProxies", "false");
  
      Resources res = new Resources();
      String proxyHost = res.get(PROXY_HOST);
      int proxyPort = Integer.parseInt(res.get(PROXY_PORT));
  
      final HttpHost proxy = new HttpHost(proxyHost, proxyPort, "http");
  
  
      String inpsProtocol = inpsHostURI.getScheme();
      String inpsHostName = inpsHostURI.getHost();
  
      final HttpHost inpsHost = new HttpHost(inpsHostName, HTTPS_PORT,
              inpsProtocol);
  
  
      HttpRoutePlanner planner = new HttpRoutePlanner() {
          public HttpRoute determineRoute(HttpHost arg0, HttpRequest arg1,
                  HttpContext arg2) throws HttpException {
              // TODO Stub di metodo generato automaticamente
              try {
                  return new HttpRoute(inpsHost, Inet4Address.getLocalHost(),
                          proxy, true, TunnelType.TUNNELLED,
                          LayerType.LAYERED);
              } catch (UnknownHostException e) {
                  return null;
              }
          }
      };
  </code></pre>
  
  <p>... and send the message...</p>
  
  <pre><code>    DefaultHttpClient httpClient = new DefaultHttpClient(connManager);
      httpClient.setRoutePlanner(planner);
  
      HttpResponse resp = httpClient.execute(httpPost);
  </code></pre>
  
  <p>The answer is always the same: HTTP500, I'm not sure whether from the proxy or the SSL server I'm calling.</p>
  
  <p>Some questions: </p>
  
  <ol>
  <li><p>Which socket factory should I use for HTTP scheme? Should I use the same SSL factory I use for the other socket or a plain socket factory shipped with HTTPClient?</p></li>
  <li><p>What is the LayerType.LAYERED parameter and what does it mean?</p></li>
  </ol>