I am having an issue with a api that I communicate to via SSL. I am thinking the exception is coming due to the fact that the SSL cert has expired. The problem is that I do not administer the API box. Is it possible to ignore expired certificates?
Exception:
[ERROR,TaacWorkshop] Problem deleting user group from CADA:
org.apache.thrift.transport.TTransportException: javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
at org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:156)
at company.oss.thrift.cada.CADABackend$Client.send_DeleteUserGroup(CADABackend.java:580)
at company.oss.thrift.cada.CADABackend$Client.DeleteUserGroup(CADABackend.java:568)
at com.cable.company.nse.cada.CadaDao.deleteUserGroup(CadaDao.java:72)
at com.cable.company.nse.taac.business.TaacWorkshop.deleteTaac(TaacWorkshop.java:127)
at com.cable.company.nse.taac.controller.RemoteVendorAccessController.processRequest(RemoteVendorAccessController.java:130)
at com.cable.company.nse.taac.controller.RemoteVendorAccessController$$FastClassByCGLIB$$63639bdf.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:692)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:67)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
at com.cable.company.nse.taac.controller.RemoteVendorAccessController$$EnhancerByCGLIB$$bdd8aaad.processRequest(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:710)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:167)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:402)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:563)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:613)
Caused by: javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1232)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkWrite(SSLSocketImpl.java:1244)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:43)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:154)
... 66 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1584)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:877)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:618)
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.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:154)
at company.oss.thrift.cada.CADABackend$Client.send_CreateUserGroup(CADABackend.java:546)
at company.oss.thrift.cada.CADABackend$Client.CreateUserGroup(CADABackend.java:534)
at com.cable.company.nse.cada.CadaDao.createUserGroup(CadaDao.java:93)
at com.cable.company.nse.taac.business.TaacWorkshop.createTaac(TaacWorkshop.java:210)
at com.cable.company.nse.taac.controller.RemoteVendorAccessController.processRequest(RemoteVendorAccessController.java:111)
... 61 more
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:187)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:130)
at sun.security.validator.Validator.validate(Validator.java:203)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
... 76 more
Caused by: java.security.cert.CertPathValidatorException: timestamp 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:206)
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:182)
... 81 more
Caused by: java.security.cert.CertificateExpiredException: NotAfter: Sat Jul 17 13:44:42 MDT 2010
at sun.security.x509.CertificateValidity.valid(CertificateValidity.java:256)
at sun.security.x509.X509CertImpl.checkValidity(X509CertImpl.java:570)
at sun.security.provider.certpath.BasicChecker.verifyTimestamp(BasicChecker.java:157)
at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:109)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:117)
... 85 more
The current code has to be able to set a trust store, because there is a Client cert authentication. I have tried the below suggestions, but still run into some problem. Here is the current code I use:
KeyStore identityStore = KeyStore.getInstance(KeyStore.getDefaultType());
ClassPathResource keystore = new ClassPathResource(cadaBackendCertFile);
identityStore.load(keystore.getInputStream(), cadaBackendCertFilePassword.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(identityStore, cadaBackendCertFilePassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(identityStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
SSLSocketFactory fac = ctx.getSocketFactory();
Socket sslsock = fac.createSocket(cadaBackendEndpoint, cadaBackendPort);
TTransport transport = new TSocket(sslsock);
Changed that code to the following, and am getting server issues, but it fixed my problem with the security exception:
KeyStore identityStore = KeyStore.getInstance(KeyStore.getDefaultType());
ClassPathResource keystore = new ClassPathResource(cadaBackendCertFile);
identityStore.load(keystore.getInputStream(), cadaBackendCertFilePassword.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(identityStore, cadaBackendCertFilePassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(identityStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), new TrustManager[] {new X509TrustManager(){
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}}, new SecureRandom());
SSLSocketFactory fac = ctx.getSocketFactory();
Socket sslsock = fac.createSocket(cadaBackendEndpoint, cadaBackendPort);
TTransport transport = new TSocket(sslsock);
TProtocol proto = new TBinaryProtocol(transport);
cadaBackendClient = new Client(proto);
Actually - even that above code throws an exception:
ERROR[com.cable.nse.cada.CadaDaoTest][main] - Error:
org.apache.thrift.transport.TTransportException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:156)
at .oss.thrift.cada.CADABackend$Client.send_UserDetails(CADABackend.java:328)
at .oss.thrift.cada.CADABackend$Client.UserDetails(CADABackend.java:316)
at com.cable.nse.cada.CadaDao.getUserDetails(CadaDao.java:136)
at com.cable.nse.cada.CadaDaoTest.testCada(CadaDaoTest.java:73)
at com.cable.nse.cada.CadaDaoTest.test(CadaDaoTest.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:117)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1650)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:618)
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.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:154)
... 23 more
It is not safe to alter the default SSLContext since it affects the entire process. This lowers the security setting of every connection indiscriminately. It may also not be thread-safe although I am not sure.
I recommend delegating such operations to a separate process per-request.
String content = new HttpsNoVerify.fetch(URL.create(myURL));
Listing of com/example/HttpsNoVerify.java:
package com.example;
import org.apache.commons.io.IOUtils;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.URL;
public class HttpsNoVerify {
public static void main(String... args) throws Exception {
URL url = new URL(args[0]);
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {return null;}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType){}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType){}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
IOUtils.copy(url.openStream(), System.out);
}
public String fetch(URL url) throws Exception {
return new SubProcess(HttpsNoVerify.class).run(url.toString());
}
}
Listing of com/example/SubProcess.java:
package com.example;
import org.apache.commons.io.IOUtils;
import java.util.Arrays;
public class SubProcess {
private final Class<?> classToRun;
public SubProcess(Class<?> classToRun) {
this.classToRun = classToRun;
}
public String run(String... args) throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder("java",
"-Djava.library.path=" + System.getProperty("java.library.path"),
"-classpath", System.getProperty("java.class.path"),
classToRun.getCanonicalName());
for (String arg : args) processBuilder.command().add(arg);
processBuilder.redirectErrorStream();
Process process = processBuilder.start();
String output = IOUtils.toString(process.getInputStream());
process.waitFor();
if (process.exitValue() != 0)
throw new IllegalStateException(
String.format("Running %s with %s failed", classToRun, Arrays.toString(args)));
return output;
}
}
I'm not aware of a property that would let you ignore the time validity check on the remote certificate for the default X509TrustManager
s, but if you have access to the client code, you can probably configure a different SSLContext
with your own X509TrustManager
, within which you could catch this exception.
If you want to use something like jSSLutils and its SSLContextFactory
, you could write a wrapper along these lines:
PKIXSSLContextFactory sslContextFactory = new PKIXSSLContextFactory();
sslContextFactory.setTrustManagerWrapper(new X509TrustManagerWrapper() {
@Override
public X509TrustManager wrapTrustManager(final X509TrustManager origManager) {
return new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return origManager.getAcceptedIssuers();
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
try {
origManager.checkServerTrusted(chain, authType);
} catch (CertificateExpiredException e) {
// TODO log or do something else to rethrow
// the exception if chain[0] isn't the certificate
// for which you want to make this special case.
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
origManager.checkClientTrusted(chain, authType);
}
};
}
});
SSLContext sslContext = sslContextFactory.buildSSLContext();
Making use of this SSLContext
then really depends on what uses SSL in your application. In the worst case, you can configure it globally using SSLContext.setDefault(sslContext)
with Java 6 and above. Otherwise, some libraries will let you configure an SSLContext
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With