7 Replies Latest reply on Jul 7, 2006 1:20 PM by Jens Elkner

    Calling web service from another jboss application using SSL

    Hardeep Kwatra Newbie

      Hi,

      I am trying to deploy an application as service, which reads the contents of a jms Queue and tries to send it to the other webservices i.e. within the same container and to another jboss application server using certificate authentication (SSL) on port 443.

      I am getting invalidate certificate exception. If i run this application as a standalone, it works fine.

      anybody please help me.

        • 1. Re: Calling web service from another jboss application using
          Sohil Shah Master

           

          "hardeep.kwatra" wrote:

          I am getting invalidate certificate exception. If i run this application as a standalone, it works fine.


          When you say running as standalone you mean the client application to the SSL webservice running in JBoss?

          Also, can you post the client Java code that is calling the web service via SSL in JBoss?

          A stack trace will also help from when you get the invalid certificate exception in JBoss.

          btw- my initial guess is that in your Java client code that calls the SSL webservice, you need to "Trust all certs" when you setup the connection programmatically

          • 2. Re: Calling web service from another jboss application using
            Jens Elkner Apprentice

             

            "sohil.shah@jboss.com" wrote:
            ... you need to "Trust all certs" when you setup the connection programmatically


            Well, why do you need SSL, if you trust all certs? Definitely a "no master" hint ...

            • 3. Re: Calling web service from another jboss application using
              Sohil Shah Master

               

              "elkner" wrote:

              Well, why do you need SSL, if you trust all certs? Definitely a "no master" hint


              Well, this is because if you are using a self-signed cert you will get an invalid certificate exception unless a proper TrustManager is setup in the SSL Context on the client.

              For a self signed cert you need to setup a proper TrustManager in your SSL client context which maybe accepts just a cert signed by you or something like that. I just said Trust All Certs to just get it to work for now

              If the cert is properly signed by verisign or someone this won't be an issue.



              • 4. Re: Calling web service from another jboss application using
                Jens Elkner Apprentice

                Yes, setting up a suitable X509TrustManager (+ see SSLContext) is a much better hint ;-)

                • 5. Re: Calling web service from another jboss application using
                  Hardeep Kwatra Newbie

                  Hi!

                  Stand alone pplication means running the application from the command prompt i.e. java -jar <jar file name>, not in the jboss. if i try to deploy it as a service it starts giving the exception, where it works fine in the previous case.

                  I am using JAXRPC in my application. here is the code snippet which does the handshake with the application server on port 443(I am using kestore at the server side and certificate at the client)

                  public Object getService(String serverURL) throws Exception {
                   StatusListener statusListener = null;
                   String JBOSS_HOME = System.getenv("JBOSS_HOME");
                  
                   mLogger.info("certfcate name in servcie locator>>" + certificate);
                   String pathToCert = "c:\\certificate\\svsos.cer";
                   mLogger.info("Path of certificate in service Utility =======" + pathToCert);
                  
                   SSLContext ctx = null;
                   TrustManagerFactory tmf = null;
                   KeyStore ksSvr = KeyStore.getInstance("JKS");
                   ksSvr.load(null, null);
                   FileInputStream fis = new FileInputStream(pathToCert);
                   CertificateFactory cfe = CertificateFactory.getInstance("X.509");
                   Collection c = cfe.generateCertificates(fis);
                   Iterator i = c.iterator();
                   Certificate cert = null;
                   while (i.hasNext()) {
                   cert = (Certificate) i.next();
                   }
                   ksSvr.setCertificateEntry("sos", cert);
                   tmf = TrustManagerFactory.getInstance("SunX509");
                   tmf.init(ksSvr);
                   // initialize context with server certificate.....
                   ctx = SSLContext.getInstance("TLSv1");
                   ctx.init(null, tmf.getTrustManagers(), null);
                   // get socket factory class....
                   SSLSocketFactory factory = ctx.getSocketFactory();
                  
                   HttpsURLConnection.setDefaultSSLSocketFactory(factory);
                   Service service = null;
                   String urlstr = "https://" + serverURL + ReplicationConfigParser.getInstance().getWebserviceContext();
                   mLogger.info("Contacting webservice at " + urlstr);
                   URL url = new URL(urlstr);
                  
                   HostnameVerifier hv = new HostnameVerifier() {
                   public boolean verify(String urlHostName, SSLSession session) {
                   return true;
                   }
                   };
                   HttpsURLConnection.setDefaultHostnameVerifier(hv);
                   QName qname = new QName(ReplicationConfigParser.getInstance().getNamespaceURI(), ReplicationConfigParser.getInstance().getLocalPart());
                   ServiceFactory factory1 = ServiceFactory.newInstance();
                   service = factory1.createService(url, qname);
                   statusListener = (StatusListener) service.getPort(StatusListener.class);
                   return statusListener;
                   }


                  if u get any idea where the problem is, please let me know.

                  Thanks

                  Hardeep

                  • 6. Re: Calling web service from another jboss application using
                    Sohil Shah Master

                    Hardeep-

                    Looks like this might be a configuration issue.

                    Some things to look at:

                    1) if the server side keystore has a self-signed cert, the SunX509 TrustManager you are using in your client code accepts them

                    2) Looks like you are setting up the TrustManager on the client side to trust svsos.cer. Is this the cert that is also setup in the keystore on the jboss server side as well?


                    I guess to play elimination, you can implement your own TrustManager that "Trusts All Certs" instead of the SunX509 and see if that works.

                    If it works, chances are you might need to use a properly signed cert to use SunX509 as the TrustManager

                    • 7. Re: Calling web service from another jboss application using
                      Jens Elkner Apprentice

                      OK, to help you out here an copy-and-paste complete example:


                      package foo.bar;
                      
                      import java.io.BufferedInputStream;
                      import java.io.IOException;
                      import java.io.InputStream;
                      import java.security.cert.Certificate;
                      import java.security.cert.CertificateException;
                      import java.security.cert.CertificateFactory;
                      import java.security.cert.X509Certificate;
                      import java.util.ArrayList;
                      import javax.net.ssl.X509TrustManager;
                      import org.slf4j.Logger;
                      import org.slf4j.LoggerFactory;
                      import sun.security.validator.Validator;
                      import com.ehsbe.commons.common.Misc;
                      
                      /**
                       * @author Jens Elkner
                       * @version $Revision$
                       */
                      public class CaHandler
                       implements X509TrustManager
                      {
                       private static final Logger log = LoggerFactory
                       .getLogger(CaHandler.class);
                       private static X509TrustManager manager;
                       private ArrayList<X509Certificate> issuers;
                       private Validator valServer;
                       private Validator valClient;
                      
                       private CaHandler() {
                       try {
                       init();
                       } catch (CertificateException e) {
                       log.warn(e.getLocalizedMessage());
                       if (log.isDebugEnabled()) {
                       log.debug("init()", e);
                       }
                       } catch (IOException e) {
                       log.warn(e.getLocalizedMessage());
                       if (log.isDebugEnabled()) {
                       log.debug("init()", e);
                       }
                       }
                       }
                      
                       private void init() throws CertificateException, IOException {
                       ClassLoader cl = Thread.currentThread().getContextClassLoader();
                       InputStream in =
                       cl.getResourceAsStream(Misc.getResourcePath(this) + "ca-bundle.crt");
                       if (in == null) {
                       throw new IOException("Certificate bundle not found");
                       }
                       BufferedInputStream bis = null;
                       try {
                       bis = new BufferedInputStream(in);
                       CertificateFactory cf = CertificateFactory.getInstance("X.509");
                       issuers = new ArrayList<X509Certificate>();
                       while (bis.available() > 0) {
                       Certificate cert = cf.generateCertificate(bis);
                       if (cert instanceof X509Certificate) {
                       issuers.add((X509Certificate) cert);
                       }
                       }
                       } finally {
                       try { bis.close(); } catch (Exception e) { /* */ }
                       }
                       }
                      
                       /**
                       * Get the singleton, which handles local certs.
                       * @return always the same instance.
                       */
                       public static X509TrustManager getInstance() {
                       if (manager == null) {
                       manager = new CaHandler();
                       }
                       return manager;
                       }
                      
                       /**
                       * {@inheritDoc}
                       */
                       public void checkClientTrusted(X509Certificate[] chain, String authType)
                       throws CertificateException
                       {
                       if (valClient == null) {
                       valClient = Validator.getInstance(Validator.TYPE_PKIX,
                       Validator.VAR_TLS_CLIENT, issuers);
                       }
                       valClient.validate(chain, null, authType);
                       }
                      
                       /**
                       * {@inheritDoc}
                       */
                       public void checkServerTrusted(X509Certificate[] chain, String authType)
                       throws CertificateException
                       {
                       if (valServer == null) {
                       valServer = Validator.getInstance(Validator.TYPE_PKIX,
                       Validator.VAR_TLS_SERVER, issuers);
                       }
                       valServer.validate(chain, null, authType);
                       }
                      
                      
                      
                       /**
                       * {@inheritDoc}
                       */
                       public X509Certificate[] getAcceptedIssuers() {
                       return issuers.toArray(new X509Certificate[issuers.size()]);
                       }
                      }


                      and somewhere else something like that should work:

                      private static SSLContext ctx;
                      ...
                       ctx = SSLContext.getInstance("TLS");
                       ctx.init(null, CaHandler.getInstance(), null);
                      ...


                      If you wanna trust the default certs (i.e. coming with the JDK) as well, you might wrap the default into CaHandler. To get the default stuff, one may use:
                      ...
                       TrustManagerFactory factory =
                       TrustManagerFactory.getInstance("PKIX", "SunJSSE");
                       KeyStore ks = null;
                       factory.init(ks);
                       TrustManager[] managers = factory.getTrustManagers();
                       for (int k=0; k < managers.length; k++) {
                       if (managers[k] instanceof X509TrustManager) {
                       origTrustManager = (X509TrustManager) managers[k];
                       break;
                       }
                       }
                       if (origTrustManager == null) {
                       throw new UnsupportedOperationException(
                       "no TrustManager PKIX/SunJSSE found");
                       }
                      ...


                      With small adaption you should be able to use it, where you want ...