I'm facing a SSL certificate on Android when trying to get the HTTP communications between my server and my app working. We are developping a web/iOS/Android application, that communicates with a server.
Until today, i didn't need to use https, but as our product evolves, it has become mandatory.
I used a certificate provided with our hosting solution, that is a real and trusted one (*.netopenservices.fr), provided by RapidSSL, which is trusted by Geotrust (if i read well what Chrome tells me). So everything is supposed to work fine. And it does with Chrome on Mac, chrome on Win8, Firefox on Mac, and Safari on iOS (and in our app in iOS too).
But the heck is Android : it seems to miss an intermediate certificate that most (every ?) other browser/OS have built-in. We tested with a nexus 7 under 4.2.2, and an htc Explorer under 2.3.5, in our app AND in the built-in browser, and the result is the same. We get an error while debugging our app, and a basic "SSL Connection error" in the browsers. Here is the stack trace, if it can help :
07-26 17:24:19.988: W/System.err(13833): org.springframework.web.client.ResourceAccessException: I/O error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.; nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
07-26 17:24:20.008: W/System.err(13833): at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:491)
07-26 17:24:20.008: W/System.err(13833): at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
07-26 17:24:20.018: W/System.err(13833): at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237)
(some of our own stack)
07-26 17:24:20.018: W/System.err(13833): Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
07-26 17:24:20.018: W/System.err(13833): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:381)
07-26 17:24:20.018: W/System.err(13833): at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
07-26 17:24:20.018: W/System.err(13833): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
07-26 17:24:20.018: W/System.err(13833): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
07-26 17:24:20.018: W/System.err(13833): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
07-26 17:24:20.018: W/System.err(13833): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
07-26 17:24:20.018: W/System.err(13833): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)
07-26 17:24:20.018: W/System.err(13833): at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:165)
07-26 17:24:20.018: W/System.err(13833): at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:72)
07-26 17:24:20.018: W/System.err(13833): at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:46)
07-26 17:24:20.018: W/System.err(13833): at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:63)
07-26 17:24:20.018: W/System.err(13833): at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:476)
07-26 17:24:20.018: W/System.err(13833): ... 8 more
07-26 17:24:20.018: W/System.err(13833): Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
07-26 17:24:20.018: W/System.err(13833): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:276)
07-26 17:24:20.018: W/System.err(13833): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:197)
07-26 17:24:20.018: W/System.err(13833): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:584)
07-26 17:24:20.018: W/System.err(13833): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
07-26 17:24:20.018: W/System.err(13833): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:378)
07-26 17:24:20.018: W/System.err(13833): ... 19 more
07-26 17:24:20.018: W/System.err(13833): Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
07-26 17:24:20.028: W/System.err(13833): ... 24 more
We obviously CANNOT trust every certificate in our app, as it will be in stores, hold sensitive data, and so on...
We also CANNOT ask the user to do anything except using the app (most of user would quit...)
Is there a way to make Android trust/know this legit missing (intermediate ?) certificate safely and simply ?
Thanks for any help !
EDIT : the 3 certificates (netopenservices.fr.2048.key, .fr.CA.crt and .fr.crt) are stored in the keystore of our server (Tomcat6.0.37)