Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android : java.io.IOException: Hostname was not verified

Tags:

android

while running my app getting java.io.IOException: Hostname was not verified, how can i resolve it ?

java.io.IOException: Hostname '178.61.62.140' was not verified
01-03 16:34:37.613: W/System.err(17118):    at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:224)
01-03 16:34:37.615: W/System.err(17118):    at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:454)
01-03 16:34:37.615: W/System.err(17118):    at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
01-03 16:34:37.616: W/System.err(17118):    at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
01-03 16:34:37.617: W/System.err(17118):    at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
01-03 16:34:37.617: W/System.err(17118):    at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:194)
01-03 16:34:37.618: W/System.err(17118):    at libcore.net.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:280)
01-03 16:34:37.618: W/System.err(17118):    at com.axis.cbk.httpmodel.CustHttpClient.executeHttpPost(CustHttpClient.java:120)
01-03 16:34:37.619: W/System.err(17118):    at com.axis.cbk.MainActivity$ProcessIt.doInBackground(MainActivity.java:237)
01-03 16:34:37.619: W/System.err(17118):    at com.axis.cbk.MainActivity$ProcessIt.doInBackground(MainActivity.java:1)
01-03 16:34:37.621: W/System.err(17118):    at android.os.AsyncTask$2.call(AsyncTask.java:264)
01-03 16:34:37.626: W/System.err(17118):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-03 16:34:37.626: W/System.err(17118):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-03 16:34:37.627: W/System.err(17118):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
01-03 16:34:37.628: W/System.err(17118):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-03 16:34:37.630: W/System.err(17118):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-03 16:34:37.631: W/System.err(17118):    at java.lang.Thread.run(Thread.java:856)
01-03 16:34:37.632: I/System.out(17118): [CDS]close[48194]
01-03 16:34:37.633: I/System.out(17118): close [socket][/0.0.0.0:48194]
like image 905
devel Avatar asked Jan 07 '14 11:01

devel


3 Answers

You're making an HTTPS connection with an IP address. Now, SSL certificates are bound to DNS hostnames and since you're not using a DNS hostname to connect, the certificate cannot be verified.

Use an actual DNS name to connect, or in some rare cases, write your own hostname verifier that accepts your host (careful: it's very easy to introduce vulnerabilities there).

like image 198
laalto Avatar answered Nov 14 '22 23:11

laalto


@laalto's made some good points in his answer. There's also an alternative workaround that doesn't require any changes to your Android code which I've outlined below.

tl;dr - modify the /etc/hosts file on your Android device and add a new entry mapping your self signed cert common name to the IP address of your development server.

I've outlined the complete process below...

Create your certificate as usual with something like:

    sudo openssl genrsa -out key.pem 2048
    sudo openssl req -new -x509 -key key.pem -out cert.pem -days 1095
    sudo cat key.pem cert.pem >> stunnel.pem

In the second command, set the common name to whatever domain name you want, for this example I'll use testssl.com .

I'm using stunnel to proxy my ssl connection so the 3rd command might not be applicable. Anyway, once your test website is using the cert you just created, open up a browser on your desktop and navigate to your site. As you'd expect you should get a security warning if everything's going as expected. View the certificate and export it as an X.509 certificate with chain (PEM) . Lets say we save it as testssl.com.

Now run the following command to convert it from the PEM format into a certificate format that you can download onto your Android device.

    openssl x509 -inform PEM -outform DM -in testssl.com -out testssl.com.crt

Using adb you can now push your cert onto your device.

    adb push testssl.com.crt /sdcard/testssl.com.crt

On your Android device go to Settings->Security->Install from device storage. You should be presented with the name you gave your cert, for me that's testssl.com.crt.

To modify your /etc/hosts file you'll need to remount your /system partition as read write and unfortunately you will need su for this.

    adb shell
    su    
    mount -o rw,remount /system

We'll put the /system partition back to read only later on.

Now lets grab the hosts file, modify it, and then put it back on the device with the following commands.

    adb shell
    su
    dd if=/etc/hosts of=/sdcard/hosts
    exit
    exit
    adb pull /sdcard/hosts

You can now add an additional line to your hosts file so that it looks something like [development_server_ip_address] [domain_name]. So assuming I used the settings detailed above and that my dev server has an IP of 192.168.1.10, then I'd add the following line to my hosts file:

    192.168.1.10     testssl.com

You can now use your modified hosts file after running the following commands.

    adb push hosts /sdcard/hosts
    adb shell
    su
    dd if=/sdcard/hosts of=/etc/hosts

To make the /system partition read only run the following command from adb shell.

    mount -o ro,remount /system

Now your Android app, along with any others that use an HTTPSUrlConnection object to connect to the domain name you added in your hosts file, shouldn't receive any certificate errors. And best of all you didn't have to change a single line of code.

like image 21
skyjacks Avatar answered Nov 14 '22 22:11

skyjacks


Please note SSL Certificate work only by Domain not work by IP address.

if you use IP ,insert below code

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                if(hostname.equals("127.0.0.1 << your IP"))
                     return true;
            }
        });
like image 33
Ali Bagheri Avatar answered Nov 14 '22 22:11

Ali Bagheri