Reputation: 89
I want to connect to a SSL-certificated server with certificate.
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.params.BasicHttpParams;
[...]
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory sslSocketFactory = new SSLSocketFactory( keyStore, profile.getIdentityPassPhrase(), trustStore );
sslSocketFactory.setHostnameVerifier( new AllowAllHostnameVerifier() );
registry.register( new Scheme( "http", PlainSocketFactory.getSocketFactory(), 80) );
registry.register( new Scheme( "https", sslSocketFactory, 443 ) );
// Create a new HttpClient and Post Header
HttpParams httpParams = new BasicHttpParams();
httpParams.setBooleanParameter( "http.protocol.expect-continue", true );
HttpProtocolParams.setVersion( httpParams, HTTP_VERSION );
HttpProtocolParams.setContentCharset( httpParams, CONTENT_CHARSET );
HttpConnectionParams.setConnectionTimeout( httpParams, TIMEOUT_MILLISEC );
HttpConnectionParams.setSoTimeout( httpParams, TIMEOUT_MILLISEC );
httpClient = new DefaultHttpClient( new ThreadSafeClientConnManager( httpParams, registry ), httpParams );
In Android 4.2.2 (and lower) it works fine. But on Android 4.3 it throws error message
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
Where is the error? Why it works with API 17 and lower, but not with API 18?
EDIT The exception is thrown in HttpClient-class (org.apache.http.client) while executing //execute//-function. What changed in 4.3 in these function but in 4.2.2 not? Android GIT says there is no important changing: https://android.googlesource.com/platform/external/apache-http/
Upvotes: 2
Views: 1399
Reputation: 4306
I've found a solution to my problem. I used openssl s_client -connect my_server.com:443 -CApath /etc/ssl/certs/
to check my ssl certificate. It returned the wrong certificate! It turned out that i had two different vHosts set up with different ssl certificates on the same ip. This requires the client to handle this: http://en.wikipedia.org/wiki/Server_Name_Indication .
As it turns out Android seems not to handle this, at least when using this code:
String responseString = "";
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
try {
response = httpclient.execute(new HttpGet(uri[0]));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK || statusLine.getStatusCode() == 428){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
} else{
//Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (ClientProtocolException e) {
Log.e("err",e.getMessage());
} catch (IOException e) {
Log.e("err",e.getMessage());
}
return responseString;
I removed the second vHost so that in every situation only one certificate is returned from the server. Now the javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
exception disappeared.
Upvotes: 1