Make an SSL call through an HTTP proxy using HttpClient on a WebSphere server

1.8k views Asked by At

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.

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)

    // 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);

Passwords are temporarily written in the code, but they will be parametrized as soon as the solution will be working.

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)...

    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;
            }
        }
    };

... and send the message...

    DefaultHttpClient httpClient = new DefaultHttpClient(connManager);
    httpClient.setRoutePlanner(planner);

    HttpResponse resp = httpClient.execute(httpPost);

The answer is always the same: HTTP500, I'm not sure whether from the proxy or the SSL server I'm calling.

Some questions:

  1. 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?

  2. What is the LayerType.LAYERED parameter and what does it mean?

0

There are 0 answers