Pages

Thursday, September 22, 2011

How to turn on the SSL Debugging in JBoss


How to turn on the SSL Debugging in JBoss

You need to add this to your JAVA_OPTIONS in your run.bat. Or if you have a batch file that does environment before running the run.bat batch file then you can add this config setting to your jboss startup batch file:

REM to turn ON the SSL debugging in JBoss
set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

this will turn on the ssl debugging on ssl handshake process and will be verbose in telling which keymanager and trustmanager will be used.

if you want all debugging information on start up then you can use following config setting:
 

set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.debug=all -Djava.security.debug=access:stack

The above commands will give you more information to be able to diagnose the error.


How to explicitly specify keystore and truststore in JAVA_OPTIONS in JBoss


You can explicitly specify the keystore and truststore with -D option in JBoss. Please see the configuration settings below:


REM to explicitly set the keystore and truststore
set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.ssl.trustStore=C:/Java/jboss-4.2.2.GA/server/{your_server_instance}/conf/server.truststore -Djavax.net.ssl.trustStorePassword=[your_password] -Djavax.net.ssl.keyStore=C:/Java/jboss-4.2.2.GA/server/{your_server_instance}/conf/server.keystore -Djavax.net.ssl.keyStorePassword=[your_password]

Saturday, September 17, 2011

How to fix "incompatible debugger version" error in eclipse PHP?

Bug:
when you are using PHP perspective in Eclipse IDE, you will often see a error popup alert. The popup alert will keep coming up for every 30 seconds or so. This is a known bug in Eclipse PDT and you can find more information on this link: "Incompatible debugger version" when not debugging 

Incompatible Debugger version error alert


Fix:
 As this bug gets fix sometime sooner in future, you would want that annoying popup to go away. Well there is a way to stop that alert from popping up. 
Change the debug ports in "Eclipse -> Preferences -> PHP -> Debug -> Installed Debuggers", with these values:
Zend Debugger (40000)
XDebug (29000)

This is how I fixed the annoying popup for Incompatible debugger Version


 

Friday, September 9, 2011

InstallCert.java

package com.aw.ad.util;
/*
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * http://blogs.sun.com/andreas/resource/InstallCert.java
 * Use:
 * java InstallCert hostname
 * Example:
 *% java InstallCert ecc.fedora.redhat.com
 */

import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Class used to add the server's certificate to the KeyStore
 * with your trusted certificates.
 */
public class InstallCert {

    public static void main(String[] args) throws Exception {
        String host;
        int port;
        char[] passphrase;
        if ((args.length == 1) || (args.length == 2)) {
            String[] c = args[0].split(":");
            host = c[0];
            port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
            String p = (args.length == 1) ? "changeit" : args[1];
            passphrase = p.toCharArray();
        } else {
            System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
            return;
        }

        File file = new File("jssecacerts");
        if (file.isFile() == false) {
            char SEP = File.separatorChar;
            File dir = new File(System.getProperty("java.home") + SEP
                    + "lib" + SEP + "security");
            file = new File(dir, "jssecacerts");
            if (file.isFile() == false) {
                file = new File(dir, "cacerts");
            }
        }
        System.out.println("Loading KeyStore " + file + "...");
        InputStream in = new FileInputStream(file);
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(in, passphrase);
        in.close();

        SSLContext context = SSLContext.getInstance("TLS");
        TrustManagerFactory tmf =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ks);
        X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
        SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
        context.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory factory = context.getSocketFactory();

        System.out.println("Opening connection to " + host + ":" + port + "...");
        SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
        socket.setSoTimeout(10000);
        try {
            System.out.println("Starting SSL handshake...");
            socket.startHandshake();
            socket.close();
            System.out.println();
            System.out.println("No errors, certificate is already trusted");
        } catch (SSLException e) {
            System.out.println();
            e.printStackTrace(System.out);
        }

        X509Certificate[] chain = tm.chain;
        if (chain == null) {
            System.out.println("Could not obtain server certificate chain");
            return;
        }

        BufferedReader reader =
                new BufferedReader(new InputStreamReader(System.in));

        System.out.println();
        System.out.println("Server sent " + chain.length + " certificate(s):");
        System.out.println();
        MessageDigest sha1 = MessageDigest.getInstance("SHA1");
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        for (int i = 0; i < chain.length; i++) {
            X509Certificate cert = chain[i];
            System.out.println
                    (" " + (i + 1) + " Subject " + cert.getSubjectDN());
            System.out.println("   Issuer  " + cert.getIssuerDN());
            sha1.update(cert.getEncoded());
            System.out.println("   sha1    " + toHexString(sha1.digest()));
            md5.update(cert.getEncoded());
            System.out.println("   md5     " + toHexString(md5.digest()));
            System.out.println();
        }

        System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
        String line = reader.readLine().trim();
        int k;
        try {
            k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
        } catch (NumberFormatException e) {
            System.out.println("KeyStore not changed");
            return;
        }

        X509Certificate cert = chain[k];
        String alias = host + "-" + (k + 1);
        ks.setCertificateEntry(alias, cert);

        OutputStream out = new FileOutputStream("jssecacerts");
        ks.store(out, passphrase);
        out.close();

        System.out.println();
        System.out.println(cert);
        System.out.println();
        System.out.println
                ("Added certificate to keystore 'jssecacerts' using alias '"
                        + alias + "'");
    }

    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

    private static String toHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 3);
        for (int b : bytes) {
            b &= 0xff;
            sb.append(HEXDIGITS[b >> 4]);
            sb.append(HEXDIGITS[b & 15]);
            sb.append(' ');
        }
        return sb.toString();
    }

    private static class SavingTrustManager implements X509TrustManager {

        private final X509TrustManager tm;
        private X509Certificate[] chain;

        SavingTrustManager(X509TrustManager tm) {
            this.tm = tm;
        }

        public X509Certificate[] getAcceptedIssuers() {
            throw new UnsupportedOperationException();
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            throw new UnsupportedOperationException();
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            this.chain = chain;
            tm.checkServerTrusted(chain, authType);
        }
    }

}

PKIX path building Faild for SSL in JBoss

Enabling SSL on JBoss. Using CA signed Certificate. PKIX path building Faild.

Exception at TCP connection sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Background Information:
  • I am using JBoss 4.2.2.GA server with SSL enabled. ( {jboss_server_path}\deploy\jboss-web.deployer\server.xml )
  <Connector port="28443" address="${jboss.bind.address}"   

   maxThreads="250" maxHttpHeaderSize="8192"

   emptySessionPath="true" protocol="HTTP/1.1"

   enableLookups="false" redirectPort="8443" acceptCount="100"

   connectionTimeout="20000" disableUploadTimeout="true"

   strategy="ms" scheme="https" secure="true"    

   clientAuth="false"

   SSLEnabled="true"

   keystoreFile="C:/Java/jboss-4.2.2.GA/server/{your_server_folder}/conf/server.keystore"

   keystorePass="your_password_here"        

   truststoreFile="C:/Java/jboss-4.2.2.GA/server/{your_server_folder}/conf/server.truststore"

   truststorePass="your_password_here"
   sslProtocol="TLS" />

  • I used the java keytool to generate the private keystore (server.keystore) and public truststore (server.truststore). 
  • I generated the CSR using java keytool and then supplied it to www.comodo.com to buy a SSL certificate (CA Signed Certificate)
  • On Comodo, I selected "Server Software" as "Tomcat". Because JBoss uses tomcat as the web container for SSL.
  • Received 5 files from Comodo (1 Domain crt, 3 intermediate certificates and 1 Root Certificate)
  • Imported them into my server.truststore successfully
  • Then I imported the CA certificates supplied by our host server that we are trying to connect to using our JBoss server.

Error Message:
When I started up my server, I got this error:

Exception at TCP connection sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I tried to find information on the Google. Did find a very good example as well which I will mention below. But this example was not directly relevant to my situation. SO, this is why I am writing this blog to help people who are stuck in same situation as mine. :)

Explanation Of why error happened and what it means?

What this error means is that the certificate received from host server (other server you are trying to connect to) during the SSL Handshake is not available or did not match to certificates in our Truststore (server.truststore). 

This error happens when we are doing the SSL handshake.
Simple, as JSSE does not have ability to handle popup messages and cannot interact automatically to accept the certificate, it throws this error by default. So, the certificate we received for doing the ssl handshake does not exist in our truststore or do not match to any one in our truststore.

How to fix this error?
Fixing this error is simple. Simply import the Certificate that is sent by the host server while connecting to it. Import this certificate to your truststore (server.truststore) file. Then restart the JBoss server again. This time it should pass the SSL Handshake.

You had already imported the certificates supplied by your host server (into your truststore) and still it threw the "PKIX path building failed" error?


Reason 1:

This means the certificate supplied by your host server to be imported in your trust store is different from what [certificate] they actually have in their truststore. Obviously, their actual certificate was not imported by us into our truststore. Therefore, failing on SSL handshake.


Reason 2:

Another reason for the failure could be that we are using CA signed certificates for our server identity. But (other party's) host server is using self signed certificate. 

Easiest way is that either both parties should have self-signed certificate for their ssl identification OR both parties should have CA signed certificates.


Important Tip:

Following communications can happen and setup is straight forward:

Client (With Self-signed certificate)  <-----------> Host Server (with Self-signed certificate)

Client (With Self-signed certificate)  <-----------> Host Server (with CA-signed certificate)

In this type of communication, you will use two files: server.keystore and server.truststore.



Special case:

Following communications CANNOT happen straightaway:

1) Client (With CA-signed certificate)  <-----------> Host Server (with CA-signed certificate)
Tomcat has a glitch in their code. So for this type of communication to happen, you need to use only one keystore file and you don't need truststore file as a separate file. Import all the CA certificates in  your server.keystore file. The order that you import is important as well.

To start with, your server.keystore will only have your private key. then import the other certificates in following order:
CA Root Certificate
CA Intermediate Certificate
Your Domain Certificate -- You should use same alias you had used for private certificate. This way a correct reply is stored in the certificate

Host Server's CA Root Certificate
Host Server's Intermediate Certificate
Host Server's Domain Certificate

2) Client (With CA-signed certificate)  <-----------> Host Server (with Self-signed certificate)

same as explained above. Only difference is that you will import only one self-signed certificate of Host server, into your server.keystore file.

  
Reason 3:


Check your Host Server's IP address again. If you are using INET then you may have your internal IP different than the Public IP. Same applies to the hosting server that you are trying to connect to. Make sure that the public certificate in your truststore belongs to the right server and you are connecting to the same server for which you have certificate in your truststore.

Reason 4:


May be you still have old ssl certificates of the host server in your system-wide keystore such as cacerts and/or jssecacerts. Usual location of these files : C:\Java\jdk6\jre-lib\security folder
So, please make sure that these cacerts and jssecacerts do NOT contain your host server's certificate. 
The host server's certificate should only be imported in your server.keystore or server.truststore files that you are using in your JBoss.


How to turn on the SSL debugging in JBoss?
You need to add this to your JAVA_OPTIONS in your JBoss run.bat. Or if you have a batch file that does environment before running the run.bat batch file then you can add this command to your this jboss startup batch file:

REM to turn ON the SSL debugging in JBoss
set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

this will turn on the ssl debugging on ssl handshake process and will be verbose in which keymanager and trustmanager will be used.


if you want all debugging information on start up then you can use following command:
set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.debug=all -Djava.security.debug=access:stack

The above commands will give you more information to fix the error.


The following is only for awareness.. if you use Jboss then you do NOT need to do any of the following:

Reference:
Very Useful blog by Leeland for this error: http://dreamingthings.blogspot.com/2006/12/no-more-unable-to-find-valid.html

In this blog, they are talking same error. But they are not using the JBoss server. They are using JSSE directly to connect to their host server. Therefore, they talk about importing the certificates in the JAVA_HOME\lib\security\cacerts using the InstallCert.java written by andreas.

However, their link to download the InstallCert.java is broken. You can easily find this java file somewhere else or download it from this blog of mine.

Steps to run the InstallCert.java
  1. Download the InstallCert.java from here
  2. Open a "command prompt" or "command console"
  3. In your command prompt, go to your "JAVA_HOME\lib\security\" folder
  4. Using Windows explorer, create this package in this folder mentioned in step 2: \com\aw\ad\util
  5. In your command prompt, go to this newly created package: "JAVA_HOME\lib\security\com\aw\ad\util"
  6. copy the downloaded file InstallCert.java here
  7. In your command prompt, compile this java file: javac InstallCert.java
  8. In your command prompt, now go up to the level: "JAVA_HOME\lib\security\"
  9.  run this command to execute the InstallCert program: java com.aw.ad.util.InstallCert {your_host_name}:{port} 
  10. you have to mention the full path [com.aw.ad.util] for running the InstallCert
  11. Then it will ask you if you wish to add the certificate to the cacaerts? type 1 at command prompt and press enter. 
  12. It will add the certificate to cacerts now, and will tell you how many certificates it imported.
Please correct me if I made any mistake in this blog. I hope this helps someone who is stuck with bloody painful ssl implementation in JBoss. :)