Glassfish Web Service Application Encounters Certification Path Error

The requested target had no valid certification path, leading to errors in the PKIX validation process, as seen in the code of PKIXValidator and Validator. This caused issues during the invocation of all tests in JUnitPlatformProvider, which was invoked by the ForkedBooter class.

Question:

My Java application effectively generates user accounts on a Windows DC through ldaps by importing the self-signed certificate from the Windows server to my local keystore.

I have developed a web service that operates on Glassfish 4.0 and employs identical code to generate user accounts.

The issue at hand is that the web service is currently presenting an error that was previously encountered and resolved through the importation of the certificate to the local keystore (cacerts).

Severe:   javax.naming.CommunicationException: simple bind failed: 196.220.119.21:636 [Root 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.jndi.ldap.LdapClient.authenticate(LdapClient.java:219)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2788)
at com.sun.jndi.ldap.LdapCtx.(LdapCtx.java:319)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.ldap.InitialLdapContext.(InitialLdapContext.java:154)
at engine.CreateStudent.(CreateStudent.java:89)
at service.Create.createAccount(Create.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.glassfish.webservices.InstanceResolverImpl$1.invoke(InstanceResolverImpl.java:143)
at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:149)
at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:88)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:1136)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:1050)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:1019)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:877)
at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:136)
at org.glassfish.webservices.MonitoringPipe.process(MonitoringPipe.java:142)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:1136)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:1050)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:1019)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:877)
at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:136)
at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.processRequest(CommonServerSecurityPipe.java:210)
at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.process(CommonServerSecurityPipe.java:142)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:1136)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:1050)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:1019)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:877)
at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:420)
at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:687)
at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:266)
at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:169)
at org.glassfish.webservices.JAXWSServlet.doPost(JAXWSServlet.java:169)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:745)

An SSLHandshakeException was caused by a ValidatorException, specifically, a PKIX path building failure. This occurred because a valid certification path could not be found for the requested target. As a result, Alerts.getSSLException() threw an exception, and the SSLSocketImpl and Handshaker classes also encountered fatal errors. The ClientHandshaker class was unable to process the server’s certificate message, and the SSLSocketImpl was unable to read the record. In addition, there were issues with the AppOutputStream, BufferedOutputStream, and Connection classes.

The error occurred at line 359 in LdapClient.java where ldapBind() method is invoked, followed by authentication at line 214 in the same class. The exception was caused by ValidatorException from the sun.security package, indicating that PKIX path building failed due to SunCertPathBuilderException. The exception occurred at line 387 in PKIXValidator.java where doBuild() method is called, followed by engineValidate() at line 292. The Validator interface’s validate() method was called at line 260, and the X509TrustManagerImpl’s validate() method was called at line 324. The checkTrusted() method was called at line 229, and the checkServerTrusted() method was called at line 124. The ClientHandshaker class’s serverCertificate() method was called at line 1351. The cause of the exception was SunCertPathBuilderException, which occurred at line 145 in SunCertPathBuilder.java, followed by engineBuild() at line 131. The CertPathBuilder’s build() method was called at line 280 in CertPathBuilder.java.

Despite importing the certificate to both cacerts.jks and keystore.jks located in the C:Program Filesglassfish-4.0glassfishdomainsdomain1config folder, it did not work.

In an attempt to resolve the issue, I experimented with defining the keystore location in my code utilizing the “System.setProperty” method. Specifically, I set the value for ”
javax.net.ssl.truststore
” to “C:Program FilesJavajdk1.8.0_05jrelibsecuritycacerts” and also specified the trust store password as “changeit” using the “javax.net.ssl.trustStorePassword” property.

Still no joy

Is there anything significant that I’ve overlooked? Additionally, I have installed both the 32-bit and 64-bit versions of JDK on my Windows 8 computer.


Solution 1:

The cause of my application’s inability to detect my certificates was due to the necessary configuration in GlassFish that I had overlooked.

To enable secure communication through the SMTPS transport protocol, the keystore and truststore of the GlassFish Server domain can be accessed by configuring it with the master password of the server.

  1. Access the GlassFish Server Administration Console by typing in the URL
    localhost:4848
    in a web browser.
  2. Firstly, expand the Configurations tab, followed by the server-config tab. Finally, select
    JVM Settings
    .
  3. To set the keystore master password in the JVM Options tab, simply add the option -Djavax.net.ssl.keyStorePassword=master-password. Replace
    master-password
    with the desired password, keeping in mind that the default master password is changeit. This applies to the async Example Application and the use of synchronous method invocation in Session Beans 36-5.
  4. To add a JVM option, input ‘-Djavax.net.ssl.trustStorePassword=master-password’ and substitute ‘master-password’ with the truststore master password. By default, the master password is ‘changeit’.
  5. Save your changes and select the
    restart glassfish
    Server option.


Solution 2:


It appears that the
glassfish container
relies on a specific version and has replaced your default JDK Keystore file with its own path. If the other Java applications on your machine are functioning properly, it seems that the issue is specific to Glassfish. You may want to try the following solution.

System.clearProperty("javax.net.ssl.trustStore"); //add in servlet init()

Upon servlet startup, it is recommended to execute a one-time operation that replaces the Keystore of glassfish with the system default Keystore to ensure optimal functionality.

If the startup servlet class lacks an init, include this in it.

@Override 
public void init() throws ServletException
{
    super.init();
    System.clearProperty("javax.net.ssl.trustStore");
}

To set this property for your JDK, a different approach is required. This is because the code should be executed in two different environments: one without containers (compile and run), and the other within a servlet in your web application (printing the result on a sample webpage instead of using system println).

System.out.println(System.getProperty("javax.net.ssl.trustStore"));

The presence or absence of glassfish significantly affects the outcome. Specifically, when glassfish is present, the result is as follows:

/Users/jianqing/GlassFish_Server/glassfish/domains/domain1/config/cacerts.jks

Result without glassfish:

null

Nullifying it resolves all the issues.

Frequently Asked Questions