Android HttpClient - hostname in certificate didn't match <example.com> != <*.example.com>
Asked Answered
C

4

18

I'm using HttpClient on Android to connect to https://someUrl.com/somePath. The problem is that the site's certificate is for *.someUrl.com, not someUrl.com, so I get an SSLException. Lame on the part of the site, yes, but unless I can get it fixed, I'm stuck. Is there a way I can get HttpClient to relax and accept the certificate?

Cambrel answered 28/6, 2010 at 19:52 Comment(0)
C
33

This is my (edited) solution:

class MyVerifier extends AbstractVerifier {

    private final X509HostnameVerifier delegate;

    public MyVerifier(final X509HostnameVerifier delegate) {
        this.delegate = delegate;
    }

    @Override
    public void verify(String host, String[] cns, String[] subjectAlts)
                throws SSLException {
        boolean ok = false;
        try {
            delegate.verify(host, cns, subjectAlts);
        } catch (SSLException e) {
            for (String cn : cns) {
                if (cn.startsWith("*.")) {
                    try {
                          delegate.verify(host, new String[] { 
                                cn.substring(2) }, subjectAlts);
                          ok = true;
                    } catch (Exception e1) { }
                }
            }
            if(!ok) throw e;
        }
    }
}


public DefaultHttpClient getTolerantClient() {
    DefaultHttpClient client = new DefaultHttpClient();
    SSLSocketFactory sslSocketFactory = (SSLSocketFactory) client
            .getConnectionManager().getSchemeRegistry().getScheme("https")
            .getSocketFactory();
    final X509HostnameVerifier delegate = sslSocketFactory.getHostnameVerifier();
    if(!(delegate instanceof MyVerifier)) {
        sslSocketFactory.setHostnameVerifier(new MyVerifier(delegate));
    }
    return client;
}

It has the advantage of not changing the default behavior unless there is a wildcard domain, and in that case it revalidates as though the 2 part domain (e.g., someUrl.com) were part of the certificate, otherwise the original exception is rethrown. That means truly invalid certs will still fail.

Cambrel answered 28/6, 2010 at 19:53 Comment(3)
I tried using the above, but sometimes get stack overflow exceptions - the verify() method never stops recursing. Out of a few hundred thousand installs, it happens about 80 times a week. Have you seen any issues with this?Emboss
@Emboss I've edited the code to try and work around your problem. I would guess the problem is that you end up setting the verifier on the same factory again, so it ends up delegating to itself somehow... Feel free to edit my answer if you find a better way.Cambrel
In any case, I am facing the server cannot service the request because the media type is unsupported' error. Not getting any clue about the reason for this.Believe
A
3

The BouncyCastle on Android is too old and it doesn't recognize wildcard certificate.

You can write your own X509TrustManager to check for wildcard.

or you can disable certificate check altogether if you can accept the risk. See this question,

Self-signed SSL acceptance on Android

Actinotherapy answered 28/6, 2010 at 21:34 Comment(1)
Actually ZZ, if the OP is correct about the name of the site and the structure of the certificate, then the error message is correct: *.someUrl.com is supposed to match www.someUrl.com and anything.someUrl.com, but not someUrl.com or this.that.someUrl.com.Meghan
K
1

If it wants *.someUrl.com, then it seems like you could just give it www.someUrl.com/somePath instead of someUrl.com/somePath.

Kokaras answered 28/6, 2010 at 19:59 Comment(3)
Nope. www.someUrl.com redirects to someUrl.comCambrel
I suppose that's useless, then. Do you really need https? I would guess so, but that would make life a lot easier.Kokaras
This is a great temporary solution when the site does NOT do a redirect!Vaginismus
F
1

if you use a WebView just call

webview.clearSslPreferences();

to ignore SSL errors

Fontana answered 7/10, 2011 at 15:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.