Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

host name wrong exception

Tags:

java

https

I got host name wrong exception.I have used this code(got it from some link) in my program.My program is working fine.My question is it secure enough?? (as it is not validating certificate chains)

public class Host {

    public String subscribe() throws Exception {   
        String resp = "";
        String urlString="https://xxx.xxx.xx.xx:8443/WebApplication3/NewServlet";
        URL url;
        URLConnection urlConn;
        DataOutputStream printout;
        DataInputStream input;
        String str = "";
        int flag=1;

        try {
            HostnameVerifier hv = new HostnameVerifier() {
                public boolean verify(String urlHostName, SSLSession session) {
                    System.out.println("Warning: URL Host: " + urlHostName + " vs. "
                      + session.getPeerHost());
                    return true;
                }
            };

            trustAllHttpsCertificates();
            HttpsURLConnection.setDefaultHostnameVerifier(hv);

            url = new URL(urlString);
            urlConn = url.openConnection();
            urlConn.setDoInput(true);
            Object object;
            urlConn.setUseCaches(false);

            urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            input = new DataInputStream(urlConn.getInputStream());

            while (null != ((str = input.readLine()))) {
                if (str.length() >0) {
                    str = str.trim();
                    if(!str.equals("")) {
                        //System.out.println(str);
                        resp += str;
                    }
                }
            }
            input.close();
        } catch ( MalformedURLException mue) { 
            mue.printStackTrace();
        } catch(IOException ioe) {
            ioe.printStackTrace();
        }
        return resp;
    }

    public static class miTM implements javax.net.ssl.TrustManager,
        javax.net.ssl.X509TrustManager {

        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
            return;
        }

        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
            return;
        }
    }

    private static void trustAllHttpsCertificates() throws Exception {

        //  Create a trust manager that does not validate certificate chains:
        javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];

        javax.net.ssl.TrustManager tm = new miTM();

        trustAllCerts[0] = tm;

        javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");

        sc.init(null, trustAllCerts, null);

        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    }

}
like image 637
user10101 Avatar asked Apr 10 '12 08:04

user10101


2 Answers

The code in miTM actually disables any SSL security checks, so the security level is pretty low (you will only get errors if the SSL certificate is broken but you don't get errors when the certificate doesn't match the domain).

Basically, you try to make a connection without any security at all. If that's what you want, the solution might be "secure enough" but most likely, the answer is "no."

The correct solution for this kind of problem is to create a matching certificate for this domain.

Unfortunately, this isn't possible when your HTTP server is using "virtual hosting" (= many domain names map to the same IP address). The correct solution for this problem is to get your own IP address.

If you still want to try a Java-only solution, have a look at this answer: https://stackoverflow.com/a/3293720/34088

like image 200
Aaron Digulla Avatar answered Oct 06 '22 02:10

Aaron Digulla


Here is a way to clean up your code and to remain secure. I suppose the code connects to a known service (trusted). To make Java SSL stack accept connection even with hostname mismatch, the best way is to add the server certificate to the JVM trust store.

First you can export the server certificate from your browser and save it on disk. From Linux, you can use openssl s_client -connect xxx.xxx.xx.xx:8443 and copy/paster the server certificate in ascii-armored format to a text file.

Then import the server certificate into jre/lib/security/cacerts JKS file with keytool

keytool -import -alias myservice -file servercertificate.cer

Another option I prefer, to avoid regression when Java is updated, is to copy cacerts in your own place and declares it thanks to the javax.net.ssl.trustStore system property.

As the server certificate is in the trust store... it is trusted, until it expires. This is often used for self-signed server certificates.

like image 36
Yves Martin Avatar answered Oct 06 '22 00:10

Yves Martin