How to make Restlet client ignore SSL Certificate problems
Asked Answered
A

2

6

I am currently working in a test environment where the server has a default Self signed SSL certificate. I am using Restlet 2.1-RC2 and instantiating client resource like this:

Client client = new Client(new Context(), Protocol.HTTP);
cr = new ClientResource(String.format(itql_endpoint,riQuery));
cr.setNext(client);

and reusing client for each call I make. How can I set up client so that it ignores problematic certificates.

Abri answered 25/1, 2012 at 10:44 Comment(2)
No - I am particularly asking about how to do this with the Restlet framework (restlet.org) .I have done this on other occasions with other types of connections, I would just like to know the right way of doing it with RestletAbri
Apologies, somehow I did not get that...Hollandia
H
9

The right way is to import this self-signed certificate into the client's trust store, using keytool for example:

keytool -import -file server-cert.pem -alias myserver -keystore mytruststore.jks

You can either do it directly in the JRE's trust store (lib/security/cacerts), which may lack some flexibility, or do it in your own copy of this file, which you then set as the trust store (the default password is changeit or changeme on OSX). You configure this truststore globally for your application using the usual javax.net.ssl.trustStore* system properties (e.g. -Djavax.net.ssl.trustStore=mytruststore system property (and -Djavax.net.ssl.trustStorePassword) or you can configure it for a specific connector in Restlet using the server context parameters, for example:

Series<Parameter> parameters = client.getContext().getParameters();
parameters.add("truststorePath", "/path/to/your/truststore.jks");
// parameters.add("truststorePassword", "password");
// parameters.add("trustPassword", "password");
// parameters.add("truststoreType", "JKS");

The wrong way is to use a TrustManager that's going to disable any verification and pass it via an SslContextFactory (in the SSL extension). Something along these lines.

TrustManager tm = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] chain,
                    String authType)
                    throws CertificateException {
    }

    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }

    public void checkServerTrusted(X509Certificate[] chain,
                    String authType)
                    throws CertificateException {
        // This will never throw an exception.
        // This doesn't check anything at all: it's insecure.
    }
};

final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {tm}, null);
Context context = client.getContext();
context.getAttributes().put("sslContextFactory", new SslContextFactory() {
    public void init(Series<Parameter> parameters) { }
    public SSLContext createSslContext() { return sslContext; }
});

While the first method may seem a bit more tedious than the second (since you need to obtain the server certificate first and copy files around), the second will simply make the error messages go away by not verifying anything about the server certificate, thereby making it vulnerable to active MITM attacks. This will apply to any connection where this SSLContext is configured. (This "wrong way isn't wrong because it uses a custom SSLContext, it's wrong because of this particular configuration of the SSLContext.)

Hydrokinetics answered 25/1, 2012 at 13:37 Comment(4)
Thanks a lot. A very complete answer! Unfortunately now stuck with javax.net.ssl.SSLException: hostname in certificate didn't match. And there seems no way around that: restlet.tigris.org/issues/show_bug.cgi?id=1078Abri
I must admit I can't remember off the top of my head how to tweak the host name verification. The best way is to use a self-signed certificate with the correct name. Often, setting just the CN in the Subject DN should do, but you can also set the Subject Alt Name (you'll need it if using an IP address anyway), see https://mcmap.net/q/18556/-how-are-ssl-certificate-server-names-resolved-can-i-add-alternative-names-using-keytoolHydrokinetics
I used a self signed certificate in Android, this solution in combination with developer.android.com/training/articles/… fixed my problem. Thank you so much!Dipody
Hi @Bruno, maybe you can share some idea with this Restlet issue: #66794541Debonair
M
1
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
      public boolean verify(String hostname, SSLSession session) {
        return true;
      }
    };
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
Manakin answered 1/7, 2013 at 12:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.