Search code examples
javaandroidsslwebviewandroid-network-security-config

Best solution for the handshake failed SSL error in android web view without ignoring SSL errors


I creating a application which display a specific site to the user and I'm using web view to acoomplish that task. When I try to load that specific site web view shows nothing and log cat says,

E/chromium: [ERROR:ssl_client_socket_impl.cc(946)] handshake failed; returned -1, SSL error code 1, net_error -202

So after some searching I found this answer to ignore this SSL Certificate error and using following code I'm enable to load that site.

webView.setWebViewClient(new WebViewClient() {  
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {              
        handler.proceed();
        Log.d("ssl_error", error.toString());                
    }
});

As I send error.toString() to log cat, It says,

primary error: 3 certificate: Issued to: [some details of the company of that specific site] Issued by: CN=GeoTrust RSA CA 2018,OU=www.digicert.com,O=DigiCert Inc,C=US; on URL: [that spefic site url]

But I want to fix that error without ignoring that.

As in the previously mentioned stack overflow answer I'm unable to match the details of https://developer.android.com/training/articles/security-config to solve this problem without ignoring it. What should I do with network configuration to solve this problem ?

Note:- I want to work with only one specific site. No need to work with any site


Solution

  • The "Primary error: 3" is referring to the SSL_UNTRUSTED error code defined in the SslError class (documentation).

    It means that your client has connected to a server with an SSL certificate chain that is not acceptable. Specifically, your device does not accept the chain's root CA as trusted. It could be:

    • a self-signed certificate
    • a certificate chain with a root certificate that is not listed as a trusted root certificate in your keystore:
      • the root may have been dropped; e.g. for not being trustworthy!
      • the root may be a new one that your (out of date) device doesn't know about yet,
    • a broken certificate chain

    Note that these scenarios are potentially worse / more dangerous than an expired certificate.

    I would start by using https://www.ssllabs.com/ssltest/ to check the URL and see what it says. Depending on what it says, the correct fix is likely to be one of the following:

    • Contact the site owner and get them to update their site's SSL certificate.
    • Update your device (the client-side) to get the current set of trusted root certificates endorsed by your vendor.
    • Add the server's certificate (not the root or intermediate CA certs) as a trusted certificate, as per the instructions from your device vendor.

    Note that the last is effectively saying "I trust this server" ... and you should only do this if you can obtain the server's certificate securely.

    (It would be (IMO) a bad idea for an Android app to do this on the user's behalf. And from the user's standpoint, it would be a bad idea to trust any Android app that requests permission to do this. Why? Because an app that is able to install trusted root certs could install a bad certificate, opening the door for all sorts of nastiness.)


    UPDATE

    The SSLTest results indicate that the certificate chain is incomplete, which explains why you are getting an SSL_UNTRUSTED error

    You should report this to the site owner:

    • The certificate chain is incomplete and should be fixed.
    • The site is running old / out of date / deprecated SSL software.
    • The site has a number of other security vulnerabilities.

    If they are not responsive, the wise course of action is stop trying to use their site. It cannot be accessed securely.