7 Replies Latest reply on Jan 19, 2013 2:46 PM by aznan

    Using custom SSLSocketFactory

    aznan

      Hi!

      I have a web service that uses a custom SSLSocketFactory that accepts all certificates, as described here: http://stackoverflow.com/questions/1219208/is-it-possible-to-get-java-to-ignore-the-trust-store-and-just-accept-whatever

       

      When the web service was previously running on JBoss 4.2.3, the SocketFactory was packaged in a jar in the server's lib folder and the jar was added to java.class.path in the startup script.

       

      Now I'm migrating to JBoss 7.0.1 and I've made a global module out of the jar. I am able to access the class from within the web servce, but it will not load as a SSLSocketFactory.

       

      To illustrate the problem this is a mockup of my custom socket factory:

       

      package com.mycompany;
      
      import javax.net.ssl.*;
      import java.io.IOException;
      import java.net.*;
      
      public class MySocketFactory extends SSLSocketFactory {
      
        public void sayHello() {
          System.out.println("Hello from " + getClass().getName());
        }
      
        // Implement abstract methods.
        public String[] getDefaultCipherSuites() {
          return null;
        }
        public String[] getSupportedCipherSuites() {
          return null;
        }
        public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
          return null;
        }
        public Socket createSocket(String s, int i) throws IOException, UnknownHostException {
          return null;
        }
        public Socket createSocket(String s, int i, InetAddress inetAddress, int i2) throws IOException, UnknownHostException {
          return null;
        }
        public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
          return null;
        }
        public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress2, int i2) throws IOException {
          return null;
        }
      }
      

       

      And here is a class I've used to test it in the web service:

       

      package com.mycompany;
      
      import org.springframework.ldap.core.LdapTemplate;
      import org.springframework.ldap.core.support.LdapContextSource;
      
      import java.security.Security;
      
      public class MySocketFactoryTest {
      
        private LdapTemplate ldapTemplate;
      
        public MySocketFactoryTest() throws Exception {
          // Tell Java to use my socket factory.
          Security.setProperty("ssl.SocketFactory.provider", "com.mycompany.MySocketFactory");
      
          // Setup the ldap template.
          LdapContextSource contextSource = new LdapContextSource();
          contextSource.setUrl("ldaps://url");
          contextSource.setUserDn("usr");
          contextSource.setPassword("pwd");
      
          contextSource.afterPropertiesSet();
          ldapTemplate = new LdapTemplate(contextSource);
        }
      
        public void runTest() {
          new MySocketFactory().sayHello();
          ldapTemplate.lookup("testing");
        }
      
      }
      

       

      When I run runTest(), this line is first printed to the log:

       

      16:58:23,172 INFO  [stdout] Hello from com.mycompany.MySocketFactory
      

       

      So sayHello() went fine, but when I try to do the lookup I get this:

       

      java.lang.ClassNotFoundException: com.mycompany.MySocketFactory
      

       

      This is clearly a class loading issue. How do I make MySocketFactory visible to the JBoss? Just adding the jar to java.class.path doesn't seem to do the trick.

       

      Please help!

      /Matti

        • 1. Re: Using custom SSLSocketFactory
          nickarls

          You will probably have to reference your module in your test application according to https://docs.jboss.org/author/display/AS71/Class+Loading+in+AS7

          • 2. Re: Using custom SSLSocketFactory
            aznan

            Thank you for your reply, however the application can access the module just fine, as evidenced by the call to sayHello(). I'm guessing since the security property "ssl.SocketFactory.provider" is a system wide property, a different class loader is used when loading the default SSLSocketFactory during the lookup() call. That's just me guessing, though.

             

            Here is the full stack trace, if it helps any:

             

            08:40:19,183 INFO  [stdout] Hello from com.mycompany.MySocketFactory
            08:40:19,246 DEBUG [org.springframework.ws.soap.server.SoapMessageDispatcher] Endpoint invocation resulted in exception - responding with Fault: org.springframework.ldap.CommunicationException: url:636; nested exception is javax.naming.CommunicationException: url:636 [Root exception is java.net.SocketException: java.lang.ClassNotFoundException: com.mycompany.MySocketFactory]
                at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:100) [spring-ldap-core-1.3.1.RELEASE.jar:]
                at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:266) [spring-ldap-core-1.3.1.RELEASE.jar:]
                at org.springframework.ldap.core.support.AbstractContextSource.getContext(AbstractContextSource.java:106) [spring-ldap-core-1.3.1.RELEASE.jar:]
                at org.springframework.ldap.core.support.AbstractContextSource.getReadOnlyContext(AbstractContextSource.java:125) [spring-ldap-core-1.3.1.RELEASE.jar:]
                at org.springframework.ldap.core.LdapTemplate.executeReadOnly(LdapTemplate.java:792) [spring-ldap-core-1.3.1.RELEASE.jar:]
                at org.springframework.ldap.core.LdapTemplate.lookup(LdapTemplate.java:834) [spring-ldap-core-1.3.1.RELEASE.jar:]
                at com.mycompany.MySocketFactoryTest.runTest(MySocketFactoryTest.java:30) [classes:]
                at com.mycompany.MyEndpoint.invoke(MyEndpoint.java:34) [classes:]
                at org.springframework.ws.server.endpoint.adapter.MessageEndpointAdapter.invoke(MessageEndpointAdapter.java:41) [spring-ws-core-1.5.9.jar:]
                at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:228) [spring-ws-core-1.5.9.jar:]
                at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:170) [spring-ws-core-1.5.9.jar:]
                at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88) [spring-ws-core-1.5.9.jar:]
                at org.springframework.ws.transport.support.SimpleWebServiceMessageReceiverObjectSupport.handleConnection(SimpleWebServiceMessageReceiverObjectSupport.java:56) [spring-ws-support-1.5.9.jar:]
                at org.springframework.ws.transport.jms.JmsMessageReceiver.handleMessage(JmsMessageReceiver.java:82) [spring-ws-support-1.5.9.jar:]
                at org.springframework.ws.transport.jms.WebServiceMessageListener.onMessage(WebServiceMessageListener.java:45) [spring-ws-support-1.5.9.jar:]
                at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:535) [spring-jms-3.0.5.RELEASE.jar:]
                at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:495) [spring-jms-3.0.5.RELEASE.jar:]
                at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467) [spring-jms-3.0.5.RELEASE.jar:]
                at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325) [spring-jms-3.0.5.RELEASE.jar:]
                at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263) [spring-jms-3.0.5.RELEASE.jar:]
                at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058) [spring-jms-3.0.5.RELEASE.jar:]
                at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:952) [spring-jms-3.0.5.RELEASE.jar:]
                at java.lang.Thread.run(Thread.java:722) [:1.7.0_07]
            Caused by: javax.naming.CommunicationException: url:636 [Root exception is java.net.SocketException: java.lang.ClassNotFoundException: com.mycompany.MySocketFactory]
                at com.sun.jndi.ldap.Connection.<init>(Connection.java:214) [:1.7.0_07]
                at com.sun.jndi.ldap.LdapClient.<init>(LdapClient.java:136) [:1.7.0_07]
                at com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1600) [:1.7.0_07]
                at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2698) [:1.7.0_07]
                at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:316) [:1.7.0_07]
                at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:193) [:1.7.0_07]
                at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:211) [:1.7.0_07]
                at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:154) [:1.7.0_07]
                at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:84) [:1.7.0_07]
                at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684) [:1.7.0_07]
                at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307) [:1.7.0_07]
                at javax.naming.InitialContext.init(InitialContext.java:242) [:1.7.0_07]
                at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:153) [:1.7.0_07]
                at org.springframework.ldap.core.support.LdapContextSource.getDirContextInstance(LdapContextSource.java:43) [spring-ldap-core-1.3.1.RELEASE.jar:]
                at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:254) [spring-ldap-core-1.3.1.RELEASE.jar:]
                ... 20 more
            Caused by: java.net.SocketException: java.lang.ClassNotFoundException: com.mycompany.MySocketFactory
                at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:198) [:1.7.0_07]
                at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:211) [:1.7.0_07]
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.7.0_07]
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [:1.7.0_07]
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [:1.7.0_07]
                at java.lang.reflect.Method.invoke(Method.java:601) [:1.7.0_07]
                at com.sun.jndi.ldap.Connection.createSocket(Connection.java:331) [:1.7.0_07]
                at com.sun.jndi.ldap.Connection.<init>(Connection.java:201) [:1.7.0_07]
                ... 34 more
            Caused by: java.lang.ClassNotFoundException: com.mycompany.MySocketFactory
                at java.net.URLClassLoader$1.run(URLClassLoader.java:366) [:1.7.0_07]
                at java.net.URLClassLoader$1.run(URLClassLoader.java:355) [:1.7.0_07]
                at java.security.AccessController.doPrivileged(Native Method) [:1.7.0_07]
                at java.net.URLClassLoader.findClass(URLClassLoader.java:354) [:1.7.0_07]
                at java.lang.ClassLoader.loadClass(ClassLoader.java:423) [:1.7.0_07]
                at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) [:1.7.0_07]
                at java.lang.ClassLoader.loadClass(ClassLoader.java:356) [:1.7.0_07]
                at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:104) [:1.7.0_07]
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.7.0_07]
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [:1.7.0_07]
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [:1.7.0_07]
                at java.lang.reflect.Method.invoke(Method.java:601) [:1.7.0_07]
                at com.sun.jndi.ldap.Connection.createSocket(Connection.java:287) [:1.7.0_07]
                ... 35 more
            

             

            And this is how I've set up the module:

            I dropped the jar in modules/com/mycompany/ssl/main along with this module.xml:

             

            <?xml version="1.0" encoding="UTF-8"?>
            <module xmlns="urn:jboss:module:1.0" name="com.mycompany.ssl">
                <resources>
                    <resource-root path="myssl.jar"/>
                </resources>
                <dependencies>
                    <module name="javax.api"/>
                </dependencies>
            </module>
            

             

            And this is in my jboss-deployment-structure.xml:

             

            <jboss-deployment-structure>
              <deployment>
                <dependencies>
                  <module name="com.mycompany.ssl"/>
                </dependencies>
              </deployment>
            </jboss-deployment-structure>
            

             

            I've also tried making it a global module by putting this in the standalone.xml:

             

            <subsystem xmlns="urn:jboss:domain:ee:1.0">
              <global-modules>
                <module name="com.mycompany.ssl" slot="main"/>
              </global-modules>
            </subsystem>
            
            • 3. Re: Using custom SSLSocketFactory
              nickarls

              You might have to add the module to the sun.jdk module.xml

               

              (well, you probably want to search the forums for the way of adding it in jboss-structure, can't remember the syntax)

              • 4. Re: Using custom SSLSocketFactory
                aznan

                Thanks for helping out, Nicklas.

                 

                The module.xml of sun.jdk now looks like this:


                <?xml version="1.0" encoding="UTF-8"?> 
                <module xmlns="urn:jboss:module:1.0" name="sun.jdk">
                    <resources>
                        <!-- currently jboss modules has not way of importing services from
                        classes.jar so we duplicate them here -->
                        <resource-root path="service-loader-resources"/>
                    </resources>
                    <dependencies>
                        <module name="system" export="false" services="import">
                            <exports>
                                <include-set>
                                    <path name="com/sun/script/javascript"/>
                                    <path name="com/sun/jndi/dns"/>
                                    <path name="com/sun/jndi/ldap"/>
                                    <path name="com/sun/security/auth"/>
                                    <path name="com/sun/security/auth/module"/>
                                    <path name="sun/misc"/>
                                    <path name="sun/nio"/>
                                    <path name="sun/nio/ch"/>
                                    <path name="sun/util"/>
                                    <path name="sun/util/calendar"/>
                                    <path name="META-INF/services"/>
                                </include-set>
                            </exports>
                        </module>
                        <module name="com.mycompany.ssl" export="true"/>
                    </dependencies>
                </module>
                

                 

                 

                However, I get the same result as before.

                I tried removing the dependency to com.mycompany.ssl in jboss-deployment-structure.xml as well as the global-modules bit from standalone.xml but nothing changed.

                • 5. Re: Using custom SSLSocketFactory
                  aznan

                  I've now tried to add a dependency to com.mycompany.ssl to every single module (I have 214 of them) as well as a dependency to all 214 modules in my application's jboss-deployment-structure.xml. No change.

                  • 6. Re: Using custom SSLSocketFactory
                    nickarls

                    Did you at some point (around the 100th module) come to think that there was perhaps another way of doing it?

                     

                    Perhaps we'll wait and see if some dev drops by with the correct answer. But I'm a bit at loss trying to figure out which classloader tree could do that loading without seeing your class after the global module and all other inclusions...

                    • 7. Re: Using custom SSLSocketFactory
                      aznan

                      Hahaha, there's certainly a better way of doing it, but I have no clue where to even start, so this was a last-ditch act of desperation. Thankfully, I at least didn't have to do all the dependency declarations by hand.