I have problems loading SSL secured web pages with Androids WebView. I always get errors like:
onReceivedSslError: primary error: 3 certificate: Issued to: CN=intranet.<company>.de,C=DE,O=<company>,OU=<compay org unit>
I already installed all the certificates of the certificate chain of this server into Android's keychain via Settings->Security->Install from SD card. I can even see that one of the installed certificates matches perfectly the error output from LogCat.
It gets even more strange if I use the default Browser app: it loads the page without any problems even if I uninstall all of the certificats mentioned before.
I don't really have any clue on how I can fix this without trusting all certificats by calling handler.proceed()
in onReceivedSslError()
which is a potential security issue.
Any help is appreciated. Thanks!
Cheers Bjoern
EDIT: The root certificate is self-signed because it's only intended to be used for intranet servers. I thought that all certificates I that I add to the Android trusted credentials would be trusted.
Well onReceiveSslError()
and handler.proceed()
should be used when connection to services with self signed certificates, the webview doesn't get along with them.
The think I would look right now is the server side ssl implementation. If you have multiple services with the same cert check for SNI support and if it´s well configured. Then look if the service you're connecting return the right certificate. Also check the Subject Alternative Name from your server and configure it under your needs.
For that task you can use those commands.
openssl s_client -showcerts -connect yourhost.com:443
openssl s_client -connect yourhost.com:443
openssl s_client -servername yourhost.com -connect yourhost.com:443
openssl s_client -connect yourhost.com:443 | openssl x509 -text
Here you have some more info from the Android documentation
Common Problems with Hostname Verification As mentioned at the beginning of this article, there are two key parts to verifying an SSL connection. The first is to verify the certificate is from a trusted source, which was the focus of the previous section. The focus of this section is the second part: making sure the server you are talking to presents the right certificate. When it doesn't, you'll typically see an error like this:
java.io.IOException: Hostname 'example.com' was not verified at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:223) at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:446) at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290) at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240) at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282) at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177) at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271) One reason this can happen is due to a server configuration error. The server is configured with a certificate that does not have a subject or subject alternative name fields that match the server you are trying to reach. It is possible to have one certificate be used with many different servers. For example, looking at the google.com certificate with openssl s_client -connect google.com:443 | openssl x509 -text you can see that a subject that supports *.google.com but also subject alternative names for *.youtube.com, *.android.com, and others. The error occurs only when the server name you are connecting to isn't listed by the certificate as acceptable.
Unfortunately this can happen for another reason as well: virtual hosting. When sharing a server for more than one hostname with HTTP, the web server can tell from the HTTP/1.1 request which target hostname the client is looking for. Unfortunately this is complicated with HTTPS, because the server has to know which certificate to return before it sees the HTTP request. To address this problem, newer versions of SSL, specifically TLSv.1.0 and later, support Server Name Indication (SNI), which allows the SSL client to specify the intended hostname to the server so the proper certificate can be returned.
Fortunately, HttpsURLConnection supports SNI since Android 2.3. Unfortunately, Apache HTTP Client does not, which is one of the many reasons we discourage its use. One workaround if you need to support Android 2.2 (and older) or Apache HTTP Client is to set up an alternative virtual host on a unique port so that it's unambiguous which server certificate to return.
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With