How to receive email using Apache Camel + SSL? - java

I am trying to read email using Apache Camel over IMAPS.
EDIT: The server is using a self-signed certificate. I have configured a keystore and have verified it working over JavaMail.
I have followed the information contained here and here to configure Apache Camel to use the keystore with the self signed certificate.
Here is my test code:
#Test
public void test() throws Exception {
System.setProperty("javax.net.debug", "all");
DefaultCamelContext camelContext;
KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("src/test/resources/config/ssl/keystore");
ksp.setPassword("password");
TrustManagersParameters tmp = new TrustManagersParameters();
tmp.setKeyStore(ksp);
SSLContextParameters scp = new SSLContextParameters();
scp.setTrustManagers(tmp);
SimpleRegistry registry = new SimpleRegistry();
registry.put("sslContextParameters", scp);
camelContext = new DefaultCamelContext(registry);
RouteBuilder route = new RouteBuilder() {
#Override
public void configure() throws Exception {
from(startEndpoint()).to("log:mail");
}
};
try {
camelContext.addRoutes(route);
} catch (Exception e) {
throw new RuntimeException(e);
}
camelContext.start();
Thread.sleep(60 * 1000);
}
private String startEndpoint() {
return "imaps://myserver.mydomain?username=myuser&password=mypassword&sslContextParameters=#sslContextParameters";
}
If fails with the following error:
Camel (camel-1) thread #0 - imaps://myserver.mydomain, SEND TLSv1 ALERT: fatal,
description = certificate_unknown
Camel (camel-1) thread #0 - imaps://myserver.mydomain, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 2E .......
Camel (camel-1) thread #0 - imaps://myserver.mydomain, called closeSocket()
Camel (camel-1) thread #0 - imaps://myserver.mydomain, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
May 27, 2014 2:23:17 PM com.liferay.portal.kernel.log.Jdk14LogImpl warn
WARNING: Consumer Consumer[imaps://myserver.mydomain?password=xxxxxx&sslContextParameters=%23sslContextParameters&username=myuser] failed polling endpoint: Endpoint[imaps://myserver.mydomain?password=xxxxxx&sslContextParameters=%23sslContextParameters&username=myuser]. Will try again at next poll. Caused by: [javax.mail.MessagingException - sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
javax.mail.MessagingException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target;
nested exception is:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:670)
<snipped>
I have tried adding mail.imaps.ssl.trust parameter to the URI.
I can see that the certificate is not known, but I don't understand why. I have also tried using the standard javax.net.ssl.trustStore parameters which doesn't work either.
What am I doing wrong?

I have tried adding mail.imaps.ssl.trust parameter to the URI.
Setting the mail.imaps.ssl.trust via Camel didn't work for me, too. I was using Java Mail 1.4.2 and had to find out that mail.imaps.ssl.trust support had been added in 1.4.3 (Changelog).

It looks like your server certificates may be "self-signed", please check out this document for solution.

Related

Soap on HTTPS Apache CFX with user certificate authentication not working

We have a server running on Tomcat. This server connects to several third part services.
I developed and tested the connection to a SOAP service. This service requires the client to identify using a certificate. The first version set the properties:
javax.net.ssl.trustStore
javax.net.ssl.trustStorePassword
javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword
javax.net.ssl.keyStoreType
My code worked when tested alone, but when my code was integrated to our server, it messed up the connection to other third part servers. Looking for a solution to this problem, I found Apache CFX. I noted that this library has an API to set the certificates without the need to change global properties. We donĀ“t use Spring and I would like to configure by code, but I am getting exceptions.
Code
public NotaFiscalServiceSoap getNotaFiscalServiceSoap() throws IOException, GeneralSecurityException {
if(notaFiscalServiceSoap==null){
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean() ;
factory.setWsdlURL(municipio.getUrlWsdl().toString());
factory.setServiceClass(NotaFiscalServiceSoap.class);
factory.setServiceName(Q_NAME);
factory.setConduitSelector(getConduitSelector());
notaFiscalServiceSoap = factory.create(NotaFiscalServiceSoap.class);
}
return notaFiscalServiceSoap;
}
private ConduitSelector getConduitSelector() throws IOException, GeneralSecurityException {
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setTargetNamespace(NAMESPACE);
EndpointInfo endpointInfo = new EndpointInfo();
endpointInfo.setService(serviceInfo);
endpointInfo.setName(Q_NAME);
endpointInfo.setAddress(municipio.getUrlWsdl().toString());
URLConnectionHTTPConduit conduit = new URLConnectionHTTPConduit(null, endpointInfo);
conduit.setTlsClientParameters(getTLSClientParameters());
ConduitSelector selector = new UpfrontConduitSelector(conduit);
return selector;
}
private TLSClientParameters getTLSClientParameters() throws GeneralSecurityException, IOException{
KeyStoreType trustKeyStore = new KeyStoreType();
trustKeyStore.setFile(pathCertWsdl);
trustKeyStore.setPassword(passCertWsdl);
trustKeyStore.setType("jks");
TrustManagersType trustManagerType = new TrustManagersType();
trustManagerType.setKeyStore(trustKeyStore);
KeyStoreType keyStoreType = new KeyStoreType();
keyStoreType.setFile(pathCertA1);
keyStoreType.setPassword(passCertA1);
keyStoreType.setType("pkcs12");
KeyManagersType keyManagerType = new KeyManagersType();
keyManagerType.setKeyStore(keyStoreType);
keyManagerType.setKeyPassword(passCertA1);
TLSClientParametersType clientParametersType = new TLSClientParametersType();
clientParametersType.setTrustManagers(trustManagerType);
clientParametersType.setKeyManagers(keyManagerType);
clientParametersType.setUseHttpsURLConnectionDefaultHostnameVerifier(true);
clientParametersType.setUseHttpsURLConnectionDefaultSslSocketFactory(true);
return TLSClientParametersConfig.createTLSClientParametersFromType(clientParametersType);
}
Exception
java.security.UnrecoverableKeyException: Password must not be null
at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:132)
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineGetKey(KeyStoreDelegator.java:96)
...
org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:87)
at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.buildServiceFromWSDL(ReflectionServiceFactoryBean.java:394)
...
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: Problem parsing 'https://issonline.vilavelha.es.gov.br/SistemaIss/WebService/NotaFiscalService.asmx?WSDL'.: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.ibm.wsdl.xml.WSDLReaderImpl.getDocument(WSDLReaderImpl.java:2198)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:2390)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:2422)
...
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
...
I found the solution to my problem.
I used this URL as reference: http://www.programcreek.com/java-api-examples/index.php?source_dir=support-examples-master/jaxws/cxfSsl.war/WEB-INF/classes/com/redhat/gss/jaxws/TestClient.java
I changed the way the soap service object was created. That way I could get the HTTPConduit and configure it, instead of having to create many auxiliary objects (probably I made a few mistakes here).
I created the keystores instead of configuring the certificates.

Multiple-thread access by Jersey client 2.25.1 with HTTPS(Certificate)

I meet a problem while using "javax.ws.rs.client.Client(Jersey client 2.25.1)" to send https request in multiple-thread context.
1) First I create a client like following:
Client client = ClientBuilder.newBuilder().sslContext(createSSLContext()).build();
private static SSLContext createSSLContext() throws Exception {
SSLContext sslcontext = SSLContext.getInstance(TLS);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
try (InputStream keyStoreSteam = new FileInputStream(keystoreFile)) {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(keyStoreSteam, keystorePwd.toCharArray());
kmf.init(ks, keystorePwd.toCharArray());
}
try (InputStream trustStoreSteam = new FileInputStream(trustStoreFile)) {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(trustStoreSteam, trustStorePwd.toCharArray());
tmf.init(trustStore);
sslcontext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new java.security.SecureRandom());
}
return sslcontext;
}
2) I'm using the "client" to send https request like following:
for(int i = 0; i < 3; i++){
public void run(){
while(true){
Builder request = client.target(url).request(theString);
Request request = request.get();
// other stuffs ...
Thread.current.sleep(5000);
}
}
}).start();
3) An Exception throws out in request.get(). Notice that there are 3 threads of invocation for request.get(), but only one thread successfully gets the response, and other 2 threads get exceptions like the following:
javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:287)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:252)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:411)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:311)
at com.mycode.RequestSender.send(RequestSender.java:37)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:399)
at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285)
... 15 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
... 30 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 36 more
It seems like 3 threads try to load the certification when they send request via https, but only 1 thread successes, the other 2 threads cannot find the valid certification path.
But after one request sends successfully, in the next loop after sleeping, all the 3 threads can send request successfully. So the exception only happens in first sending request in multiple-thread context.
So is this a bug in Jersey client or I use it incorrectly ?
This seems like a bug in Jersey - specifically all latest version (up until 26-b09).
Please see - https://github.com/jersey/jersey/issues/3293
Downgrading to version 2.21.1 resolved this issue for me..

How to do a POST call to secure site with restlet that is working fine with curl POST

My curl command is working fine:
curl -u "myusername":"mypassword" -X POST -H "Content-Type: application/json" -d '{
"data": [
{
"val": 867.8,
"date": "2014-06-18T09:56:21+00:00"
},
{
"val": 98.5432,
"date": "2014-06-18T09:58:21+00:00"
}
],
"user_id": "786733",
"pulse_id": "1",
}' https://www.myweb.com/Test/requests
Note that the connection is https i.e. it is using SSL and I didn't mentioned any certificate/keystore/truststore to be given.
However my java code is not working no matter if I add trustore code or not.
My code is working fine if I give the URL locally i.e. localhost.
I am using RESTLET POST call.
For example: http://localhost:8085/Test/requests
But doesn't works if I replace the URL to be https with remote host.
For example: https://www.myweb.com/Test/requests
The following is by just mentioning the remote URL:
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1439)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:209)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:878)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:814)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
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 sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at org.restlet.engine.connector.HttpUrlConnectionCall.sendRequest(HttpUrlConnectionCall.java:356)
at org.restlet.engine.adapter.ClientAdapter.commit(ClientAdapter.java:105)
at org.restlet.engine.adapter.HttpClientHelper.handle(HttpClientHelper.java:119)
at org.restlet.Client.handle(Client.java:153)
at org.restlet.routing.Filter.doHandle(Filter.java:150)
at org.restlet.routing.Filter.handle(Filter.java:197)
at org.restlet.resource.ClientResource.handle(ClientResource.java:1092)
at org.restlet.resource.ClientResource.handleOutbound(ClientResource.java:1176)
at org.restlet.resource.ClientResource.handle(ClientResource.java:1047)
... 6 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1421)
... 25 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
Code:
Client side:
String json = gson.toJson(obj);
ClientResource clientResource =
new ClientResource("https://www.myweb.com/Test/requests");
StringRepresentation rep = new StringRepresentation(json);
clientResource.post(rep.getText());
Server side:
Main.java -
Component component = new Component();
component.getServers().add(Protocol.HTTPS, port);
component.getDefaultHost().attach("/www.myweb.com"),new UserApplication());
component.start();
UserApplication.java -
#Override
public Restlet createInboundRoot() {
String routerName = "/Test";
String aPIName = "/requests";
Router rootRouter2 = new Router(getContext());
Router getAdapterRouter = new Router(getContext());
getEnerNocAdapterRouter.attach(aPIName, PersistentData.class);
rootRouter2.attach(routerName, getAdapterRouter);
return rootRouter2;
}
PersistentData.java-
#Post
public void receiveData(Representation rep) throws ResourceException{
LOGGER.info("Server received Data");
try {
LOGGER.info("Server Data: "+rep.getText().toString());
} catch (IOException e) {
LOGGER.error("Error in receiving data", e);
}
}
If the certificate is a self-signed one (it seems to be the case), you should have a look at this page within the Restlet documentation: http://restlet.com/technical-resources/restlet-framework/guide/2.3/core/security/https
Hope it will help you,
Thierry

Ignoring bad certificate on HTTPS connection when using Apache Async HttpClient 4.0.x

I'm using the Async Apache HttpClient (CloseableHttpAsyncClient) to connect to a server but I run into the following exception:
javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at org.apache.http.concurrent.BasicFuture.failed(BasicFuture.java:130)
at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.failed(DefaultClientExchangeHandlerImpl.java:258)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.exception(HttpAsyncRequestExecutor.java:123)
at org.apache.http.impl.nio.client.InternalIODispatch.onException(InternalIODispatch.java:68)
at org.apache.http.impl.nio.client.InternalIODispatch.onException(InternalIODispatch.java:37)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:124)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:159)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:338)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:316)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:277)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:105)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:584)
at java.lang.Thread.run(Thread.java:695)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Handshaker.java:1015)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:485)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(SSLEngineImpl.java:1108)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(SSLEngineImpl.java:1080)
at javax.net.ssl.SSLEngine.wrap(SSLEngine.java:452)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doWrap(SSLIOSession.java:220)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:254)
at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:391)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:119)
... 7 more
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1508)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:243)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1209)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:135)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Handshaker.java:533)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Handshaker.java:952)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doRunTask(SSLIOSession.java:238)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:276)
... 9 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
at sun.security.validator.Validator.validate(Validator.java:218)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1188)
... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)
... 22 more
Since this is a test server I just want CloseableHttpAsyncClient to ignore all SSL errors. I know how to do this using the non-async version of HttpClient (this has been answered here for example) but I cannot get this to work using the async version.
I've tried the following:
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
public boolean isTrusted(X509Certificate[] certificate, String authType) {
return true;
}
};
SSLContext sslContext = null;
try {
sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
} catch (Exception e) {
// Handle error
}
CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSSLContext(sslContext).build();
but it doesn't work. Does anyone know how to solve this?
Actually the code that I provided in my question worked. The problem was that I was using Unirest (which uses Apache HttpClient under the hood) and had configured it like this:
Unirest.setAsyncHttpClient(createHttpAsyncClient(CONNECTION_TIMEOUT, SOCKET_TIMEOUT));
Unirest.setTimeouts(CONNECTION_TIMEOUT, SOCKET_TIMEOUT);
The problem was that "setTimeouts" overrode the configuration I made in createHttpAsyncClient without any indication. Changing to
Unirest.setTimeouts(CONNECTION_TIMEOUT, SOCKET_TIMEOUT);
Unirest.setAsyncHttpClient(createHttpAsyncClient(CONNECTION_TIMEOUT, SOCKET_TIMEOUT));
made everything work.
So if someone else has the same problem with plain Async Apache HTTPClient then the code to make it trust all certificates is the following:
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
public boolean isTrusted(X509Certificate[] certificate, String authType) {
return true;
}
};
SSLContext sslContext = null;
try {
sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
} catch (Exception e) {
// Handle error
}
CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSSLContext(sslContext).build();
I suspect this problem has nothing to do with hostname verification. SSL handshake likely fails much earlier, before an SSL session could be negotiated. There can be various reasons for such failure, SSL protocol version mismatch being most likely. You should run your application with SSL debug log activated (using -Djavax.net.debug=all system property) and analyze the log output

How do you programatically authenticate to a web server using NTLM Authentication with apache's commons httpclient?

I'm using this code, and I get the stack trace that is listed below.
I've got this working with just https and with basic authentication, but not ntlm.
HttpClient client = null;
HttpMethod get = null;
try
{
Protocol myhttps = new Protocol("https", ((ProtocolSocketFactory) new EasySSLProtocolSocketFactory()), 443);
Protocol.registerProtocol("https", myhttps);
client = new HttpClient();
get = new GetMethod("https://tt.dummycorp.com/tmtrack/");
Credentials creds = new NTCredentials("dummy", "dummy123", "host", "DUMMYDOMAIN");
client.getState().setCredentials(AuthScope.ANY, creds);
get.setDoAuthentication(true);
int resultCode = client.executeMethod(get);
System.out.println(get.getResponseBodyAsString());
}
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1591)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:975)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:123)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:516)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:454)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:828)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2116)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at com.dummycorp.teamtrack.TeamTrackHack.main(TeamTrackHack.java:38)
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:251)
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:234)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:158)
at sun.security.validator.Validator.validate(Validator.java:218)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
at org.apache.commons.httpclient.contrib.ssl.EasyX509TrustManager.checkServerTrusted(EasyX509TrustManager.java:104)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:967)
... 17 more
Caused by: java.security.cert.CertPathValidatorException: signature check failed
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:139)
at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:316)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:178)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:250)
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:246)
... 24 more
Caused by: java.security.SignatureException: Signature does not match.
at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:446)
at sun.security.provider.certpath.BasicChecker.verifySignature(BasicChecker.java:133)
at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:112)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:117)
... 28 more
HttpClient does not fully support NTLM. Please have a look at Known limitations and problems. The HttpClient documentation regarding NTLM is a bit confusing, but the bottom line is that they do not support NTLMv2 which makes it hardly usable in this regard.
NTLM is supported by standard java HttpURLConnection (link), but HttpClient has some advantages over jdk's HttpURLConnection.
Have a look at the utility posted here.
It solves different problem, namely the absence of the certificate, whereas you have invalid certificate installed, but probably its verbose output about installed certificates could be helpful.

Categories