4

I am trying to call a webservice hosted on the local network using https secure connection, first it gave the exception that HostNameUnresolved, so I used the ip address instead of the name, now I am getting the following error:

Error in geting tags.=javax.net.ssl.SSLException: hostname in certificate didn't match: <10.100.248.99> !=

I have already added the intermediate and root certificates to the android trusted list.

Could anyone give me a solution to access a securely hosted webservice on local network using host name not ip address?

Jav_Rock
  • 22,059
  • 20
  • 123
  • 164
Vikram
  • 8,235
  • 33
  • 47
  • 1
    Check this...http://stackoverflow.com/questions/7256955/java-sslexception-hostname-in-certificate-didnt-match. – Suave Nti Feb 09 '12 at 14:26
  • @Dark Rider i am trying to call the webservice hosted at local network and not at my system. also i am not able to view it from emulator browser. – Vikram Feb 21 '12 at 11:15
  • Have a look at this link to see why DNS lookup is failing: http://stackoverflow.com/questions/3184463/host-is-unresolved-in-lan – Dheeraj Vepakomma Mar 16 '12 at 15:56
  • SSL handshake will NEVER work unless the Common Name of the cert matches the domain name of your service... the reason why it works in web browsers is that you are able to override the security setting, however, in code there's just no way to say, "Please accept this name mismatch" Your can either create a DNS (hostname) entry on your local machine that matches the common name of your cert... or create a cert with a common name that is your IP Address – El Guapo Mar 19 '12 at 17:07
  • @EL Guapo i not able to connect to webservice on lan with http also... – Vikram Mar 19 '12 at 18:57
  • Use a local DNS that matches your hostname to this internal IP. (a hosts file may be enough) – njzk2 Mar 19 '12 at 17:00
  • how to do that is the question... – Vikram Mar 19 '12 at 18:59
  • if you are running on a unix based os (linux or macosx, most likely), you probably can edit your /etc/hosts file to add the binding. Under windows, I think there is a hosts file too, but I wouldn't know where it is. – njzk2 Mar 20 '12 at 09:19
  • i am able to connect and resolve dns from desktop browser, the problem is with the same URL not working on android emulator – Vikram Mar 20 '12 at 10:26
  • the hostname is most likely resolved using netbios, which i don't think android supports. you have to put the host resolution in the hosts file. – njzk2 Mar 20 '12 at 11:21

3 Answers3

2

As mentioned by others, you need a couple of things to be able to connect your web-service:
- the emulator to know what is the IP address of the server you need to connect to
- the server name URL you connect through HTTPS must resolve to the domain of the SSL certificate

To do that, you need to:

  • mount your emulator partitions writeable

From your desktop shell (example for linux but would be similar on windows, and assume the Android sdk is intalled on /android-sdk):

cd /android-sdk/tools/
./emulator -avd NexusS -partition-size 128

where NexusS is the AVD name of your device. You MUST start the emulator from command line or you will get an error in later steps.

Now open another shell terminal and get your emulator /system/etc/hosts file:

cd /android-sdk/platform-tools
./adb remount
./adb pull /system/etc/hosts /tmp/

The remount is to set the partitions writeable. The pull command above copies the hosts file to /tmp/hosts of your desktop.
From the desktop edit the /tmp/hosts file to match your need, i.e. if the Web Service is https://www.example.com/foo and IP is 192.168.1.10:

127.0.0.1      locahost
192.168.1.10   www.example.com

Then push it back to the emulator:

cd /android-sdk/platform-tools
./adb push /tmp/hosts /system/etc/

You should be able to connect to the web-service now.

Note that you could still have error in case of a self-signed certificate.

The image below is before editing the hosts file:
IP doesn't match the certificate

After editing:
Server name match

JScoobyCed
  • 10,203
  • 6
  • 34
  • 58
1

I once saw a similar error in one of the projects my colleague was doing and the reason we found out was that if you try to make network calls from the main ui thread the android system blocks it though this feature was introduced into the API later on as previously it used to work fine.This was done so as to reduce the stress on the main ui thread so we created a separate service and then within it we provided an asynctask to make the network calls. I don't remember the exact API level in which it was introduced but you can always check it in goggle and also by the way which API level you are using ?

Nav
  • 10,304
  • 20
  • 56
  • 83
  • @Vikram ok.. my friend was using API level 2.3 when we received that problem .I am not sure about the which API level it was included in so you can try and see if it works for you that way ..do let me know if it solved your problem... – Nav Mar 22 '12 at 12:18
1

You should use the HostnameVerifier to trust android with given host.

HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 30000);
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

DefaultHttpClient httpClient = new DefaultHttpClient();

SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(httpClient.getParams(), registry);
DefaultHttpClient client = new DefaultHttpClient(mgr, httpClient.getParams());

// Set verifier      
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

Now execute the request you want on client object.

Neeraj Nama
  • 1,562
  • 1
  • 18
  • 24