PKIX path building failed:unable to find valid certification path to reques
843811Apr 22 2009 — edited Apr 23 2009public class Client {
public static void main(String str[]) {
if (downloadcertificate(.....))
startConnection(.....);
else
System.out.println("Not able to download certificate");
}
private static boolean downloadcertificate(String host,int port)throws Exception {
String hostip=host;
char[] passphrase;
String p ="changeit";
passphrase = p.toCharArray();
String cacertsFile;
String fsep = System.getProperty("file.separator");
String ROOT = System.getProperty("ROOT");
if(ROOT==null || " ".equals(ROOT))
throw new RuntimeException("Certificate file not available or ROOT path is not found");
else
cacertsFile=ROOT + fsep + "data" + fsep + "conf" + fsep + "SSL" + fsep + "cacerts";
System.setProperty("javax.net.ssl.trustStore", cacertsFile);
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
KeyStore ks = KeyStore.getInstance("JKS");
InputStream in = null;
OutputStream out=null;
try{
in = new FileInputStream(cacertsFile);
ks.load(in, passphrase);
SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
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();
SSLSocket socket = (SSLSocket)factory.createSocket(hostip, port);
socket.setSoTimeout(10000);
try
{
socket.startHandshake();
socket.close();
} catch (SSLException e) {
e.printStackTrace(System.out);
}
X509Certificate[] chain = tm.chain;
if (chain == null) {
return false;
}
System.out.println("Server sent " + chain.length + " certificate(s):");
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
int k=0;
for (int i = 0; i < chain.length; i++)
{
X509Certificate cert = chain;
sha1.update(cert.getEncoded());
md5.update(cert.getEncoded());
k++;
String alias=host;
if(chain.length>;1){
alias = host + "-" + (k);
}
if(!ks.isCertificateEntry(alias))
{
ks.setCertificateEntry(alias, cert);
}
}
out = new FileOutputStream(cacertsFile);
ks.store(out, passphrase);
}
finally{
if(out!= null){
out.flush();
out.close();
}
if(in!=null){
in.close();
}
}
return true;
}
private static Object startConnection(String host,String userid,String password,String Release,int port )throws Exception{
String url= "https://"<em>host</em>":"<em>port</em>"/services/Application";
URL sourceurl = new URL(url);
ApplicationServiceLocator servicelocator=new ApplicationServiceLocator();
Application XML= servicelocator.getApplication(sourceurl);
((Stub) XML).setUsername(userid);
((Stub) XML).setPassword(password);
if(!Release.equals(XML.getVersion())) /* Getting PKIX path validation error, In XML.getVersion() step */
{ }
return XML;
}
private static class SavingTrustManager implements X509TrustManager {
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] chain, String authType) {
this.chain = chain;
}
public void checkServerTrusted(X509Certificate[] chain, String authType) {
this.chain = chain;
}
}
}
-------------------
I am using the above client program to get certificate from server. This client program is getting and storing trusted entries into my trustStore, but the client is failing at the time of sending a request to server. The exception it is throwing 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
case 1:
If I place original trustStore(cacerts, which java provides) and do the following:
1. I am trying to connect server1, It will connect properly.
2. If I try to connect server2, it will fail to connect.
3. If I stop & start JVM(my app), both servers got connected.
case2:
If I place original trustStore(cacerts, which java provides) and do the following:
1. I am trying to connect server2, It will connect properly.
2. If I try to connect server1, it will fail to connect.
3. If I stop & start JVM(my app), both servers got connected.
In both cases certificate entries are getting stored properly and if I restart my application, I am able to connect to both the servers.
Please provide your views why I am getting the exception when I am trying to connect to the second server in both the above cases. Why the JVM is not recognizing the second server's certificate ? Why the JVM is recognizing the certificate only if I do a restart the application ( My requirement is that I should not restart the application) ?
Thanks In Advance,
Vamsee.