Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting SSLHandShakeException

While I am accessing the wsdl url I am getting the exception in android

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

i have used ksoap2 library for executing the WSDL file.

I had also implemented certification classes, but i am getting the same issue

please tell if there is any solution for this.

I am using these two classes for certification:

AndroidInsecureHttpsServiceConnectionSE class:

    package com.example.androidwsdltest;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.ksoap2.HeaderProperty;
import org.ksoap2.transport.ServiceConnection;

import android.util.Log;

public class AndroidInsecureHttpsServiceConnectionSE implements
        ServiceConnection {
    private HttpsURLConnection connection;

    public AndroidInsecureHttpsServiceConnectionSE(String host, int port,
            String file, int timeout) throws IOException {
        // allowAllSSL();
        connection = (HttpsURLConnection) new URL("https", host, port, file)
                .openConnection();
        updateConnectionParameters(timeout);
    }

    private static TrustManager[] trustManagers;

    public static class EasyX509TrustManager implements X509TrustManager {

        private X509TrustManager standardTrustManager = null;

        /**
         * Constructor for EasyX509TrustManager.
         */
        public EasyX509TrustManager(KeyStore keystore)
                throws NoSuchAlgorithmException, KeyStoreException {
            super();
            TrustManagerFactory factory = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            factory.init(keystore);
            TrustManager[] trustmanagers = factory.getTrustManagers();
            if (trustmanagers.length == 0) {
                throw new NoSuchAlgorithmException("no trust manager found");
            }
            this.standardTrustManager = (X509TrustManager) trustmanagers[0];
        }

        /**
         * @see 
         *      javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate
         *      [],String authType)
         */
        public void checkClientTrusted(X509Certificate[] certificates,
                String authType) throws CertificateException {
            standardTrustManager.checkClientTrusted(certificates, authType);
        }

        /**
         * @see 
         *      javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate
         *      [],String authType)
         */
        public void checkServerTrusted(X509Certificate[] certificates,
                String authType) throws CertificateException {
            if ((certificates != null) && (certificates.length == 1)) {
                certificates[0].checkValidity();
            } else {
                standardTrustManager.checkServerTrusted(certificates, authType);
            }
        }

        /**
         * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
         */
        public X509Certificate[] getAcceptedIssuers() {
            return this.standardTrustManager.getAcceptedIssuers();
        }

    }

    public static class FakeX509TrustManager implements X509TrustManager {
        private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};

        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        public boolean isClientTrusted(X509Certificate[] chain) {
            return true;
        }

        public boolean isServerTrusted(X509Certificate[] chain) {
            return true;
        }

        public X509Certificate[] getAcceptedIssuers() {
            return (_AcceptedIssuers);
        }
    }

    /**
     * Allow all SSL certificates by setting up a host name verifier that passes
     * everything and as well setting up a SocketFactory with the
     * #FakeX509TrustManager.
     */
    public static void allowAllSSL() {

        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

            @Override
            public boolean verify(String hostname, SSLSession session) {
                // TODO Auto-generated method stub
                return true;
            }

        });

        SSLContext context = null;

        if (trustManagers == null) {
            try {
                trustManagers = new TrustManager[] { new EasyX509TrustManager(
                        null) };
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (KeyStoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try {
            context = SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            Log.e("allowAllSSL", e.toString());
        } catch (KeyManagementException e) {
            Log.e("allowAllSSL", e.toString());
        }
        // HttpsURLConnection.setDefaultAllowUserInteraction(true);
        HttpsURLConnection.setDefaultSSLSocketFactory(context
                .getSocketFactory());
    }

    /**
     * update the connection with the timeout parameter as well as allowing SSL
     * if the Android version is 7 or lower (since these versions have a broken
     * certificate manager, which throws a SSL exception saying "Not trusted
     * security certificate"
     * 
     * @param timeout
     */
    private void updateConnectionParameters(int timeout) {
        connection.setConnectTimeout(timeout); // 20 seconds
        connection.setReadTimeout(timeout); // even if we connect fine we want
                                            // to time out if we cant read
                                            // anything..
        connection.setUseCaches(false);
        connection.setDoOutput(true);
        connection.setDoInput(true);

        allowAllSSL();

        /*
         * int buildVersion = Build.VERSION.SDK_INT; if (buildVersion <= 7) {
         * Log.d("Detected old operating system version " + buildVersion +
         * " with SSL certificate problems. Allowing " + "all certificates.",
         * String.valueOf(buildVersion)); allowAllSSL(); } else {
         * Log.d("Full SSL active on new operating system version ",
         * String.valueOf(buildVersion)); }
         */
    }

    public void connect() throws IOException {
        connection.connect();
    }

    public void disconnect() {
        connection.disconnect();
    }

    public List getResponseProperties() {
        Map properties = connection.getHeaderFields();
        Set keys = properties.keySet();
        List retList = new LinkedList();

        for (Iterator i = keys.iterator(); i.hasNext();) {
            String key = (String) i.next();
            List values = (List) properties.get(key);

            for (int j = 0; j < values.size(); j++) {
                retList.add(new HeaderProperty(key, (String) values.get(j)));
            }
        }

        return retList;
    }

    public void setRequestProperty(String key, String value) {
        // We want to ignore any setting of "Connection: close" because
        // it is buggy with Android SSL.
        if ("Connection".equalsIgnoreCase(key)
                && "close".equalsIgnoreCase(value)) {
            // do nothing
        } else {
            connection.setRequestProperty(key, value);
        }
    }

    public void setRequestMethod(String requestMethod) throws IOException {
        connection.setRequestMethod(requestMethod);
    }

    public OutputStream openOutputStream() throws IOException {
        return connection.getOutputStream();
    }

    public InputStream openInputStream() throws IOException {
        return connection.getInputStream();
    }

    public InputStream getErrorStream() {
        return connection.getErrorStream();
    }

    public String getHost() {
        return connection.getURL().getHost();
    }

    public int getPort() {
        return connection.getURL().getPort();
    }

    public String getPath() {
        return connection.getURL().getPath();
    }

}

AndroidInsecureKeepAliveHttpsTransportSE class:

 package com.example.androidwsdltest;

import java.io.IOException;

import org.ksoap2.transport.HttpsTransportSE;
import org.ksoap2.transport.ServiceConnection;

public class AndroidInsecureKeepAliveHttpsTransportSE extends HttpsTransportSE {

    private AndroidInsecureHttpsServiceConnectionSE conn = null;
    private final String host;
    private final int port;
    private final String file;
    private final int timeout;

    public AndroidInsecureKeepAliveHttpsTransportSE(String host, int port,
            String file, int timeout) {
        super(host, port, file, timeout);
        this.host = host;
        this.port = port;
        this.file = file;
        this.timeout = timeout;
    }

    @Override
    protected ServiceConnection getServiceConnection() throws IOException {
        super.getServiceConnection();
        conn = new AndroidInsecureHttpsServiceConnectionSE(host, port, file,
                timeout);
        conn.setRequestProperty("Connection", "keep-alive");

        return conn;
    }
}

After using these certification classes I am getting the same exception

Please help me..

Thanks in advance......:)

like image 940
Hareesh Avatar asked Apr 02 '13 10:04

Hareesh


People also ask

How do I resolve SSLHandshakeException?

This issue can happen because the JDK does not use the operating systems's truststore, into which your IT would have added the self-signed certificate. The solution would be to import the proxy's self-signed certificate into your JDK's truststore (i.e. the cacerts file).

How do I fix error 525?

If you're using Chrome, go to settings > advanced > system > open your computer's proxy settings. Once you've opened your proxy settings, click Advanced. In the security section, make sure TLS 1.2 is checked and make sure the boxes for SSL 2.0 and SSL 3.0 are unchecked.


2 Answers

You shall have an authorized SSL certificate - That may solve the problem, and that is the best way solving the problem.

If not, you have to work a little bit:

The concept is that when using SSL, Android is little tougher than usual, and you shall have the certificate rights on your android, so for that, you shall have a basic keystore on your Android (like google store, but for free, and on your own Android), and make your own one trusted, by some basic manipulations.

  1. Find your certificate on server, and export with private key (you shall have admin privileges). This can be done by running from start->run + certmgr.msc. Look for 'Trusted Root Certificate Authorities'. Found your certificate and do export (the keytool can load existing pfx certificate. on *.cer kind of certificate, there may be little problems.
  2. You shall have a keytool. You can find explanation on http://keytool.sourceforge.net/ You can install, but I prefer the following recommandation: This is done through Help - Software Updates - Find and install - Search for new feature.... Click New Remote Site and add http://keytool.sourceforge.net/update in name and URL, and make sure its checked. Hit Finish.
  3. Add a new keystore, and load your certificate (use pcs12 protocol, choose password you can remember).
  4. The code need to be add is like : http://developer.android.com/training/articles/security-ssl.html#UnknownCa
  5. You shall relate your connection. You use HttpTransportSE::ServiceConnection::setSSLSocketFactory like the sample. https://code.google.com/p/androidzon/source/browse/Androidzon/src/it/marco/ksoap2/HttpTransportSE.java?r=77 (Just create new function of your own, and connect it to the web service. If not working, remove ?wsdl)

Good luck!!!

like image 168
Eitan Avatar answered Oct 20 '22 15:10

Eitan


The error is due to an issue in building trust with the server. Mostly your truststore does not have the certificates the server is submitting. Answers of following 2 questions may help you.

[1] - How Can I Access an SSL Connection Through Android?

[2] - Certificate is trusted by PC but not by Android

like image 43
Pushpalanka Avatar answered Oct 20 '22 14:10

Pushpalanka