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:
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?
What is the LayerType.LAYERED parameter and what does it mean?