Is it possible to get Java to ignore the "trust store" and just accept whatever SSL certificate it gets?
Asked Answered
P

5

34

I am trying to write an SSL client that sends mail using the javax.mail API. The problem I am having is that the server request that I use SSL, but the server is also configured with a non-standard SSL certificate. The web pages I have found say that I need to install the certificate into the trust store. I don't want to do that (I don't have the necessary permissions.)

  1. Is there a way to get Java to just ignore the certificate error and accept it?
  2. Failing that, is there a way to have the trust store be local for my program, and not installed for the whole JVM?
Predacious answered 2/8, 2009 at 16:26 Comment(4)
Just to clarify, can you change the server code, or just the client?Arrester
Ignoring the certificate verification step is a bad idea. There's hardly any point talking secretly to someone if you haven't made sure who it is in the first place. Option 2 (a local trust store) is easy enough to use.Bunt
Ignoring verification step is fine in some circumstances---for example, if you are on an isolated network and SSL is the only enabled service not because of policy, but because your admin doesn't know how to enable the non-SSL service.Predacious
I don't think it is good idea to by-pass cert truststore validation. Especially if the remote server is outside your control. For your case maybe self-sign cert issue. If you validated the issuer, then you can just adds to truststore using keytool. This is better than using custom TrustManager that blindly accept certificates.Spheno
M
19

You need to create a fake TrustManager that accepts all certificates, and register it as a manager. Something like this:

public class MyManager implements com.sun.net.ssl.X509TrustManager {
  public boolean isClientTrusted(X509Certificate[] chain) { return true; }
  public boolean isHostTrusted(X509Certificate[] chain) { return true; }
  ...
}


com.sun.net.ssl.TrustManager[] managers =
  new com.sun.net.ssl.TrustManager[] {new MyManager()};

com.sun.net.ssl.SSLContext.getInstance("SSL").
       .init(null, managers, new SecureRandom());
Morphia answered 2/8, 2009 at 16:41 Comment(1)
All of this should really be done using the JSSE public API rather than tweaking the hidden com.sun.* classes. (See so_mv answer.)Bunt
H
41

Working code ( in jdk1.6.0_23) for #1.

Imports

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

The actual trust all TrustManager code.

TrustManager trm = new X509TrustManager() {
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }

    public void checkClientTrusted(X509Certificate[] certs, String authType) {

    }

    public void checkServerTrusted(X509Certificate[] certs, String authType) {
    }
};

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { trm }, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
Haematoblast answered 15/4, 2011 at 0:0 Comment(5)
Thanks, this worked great for me. The only problem with this is that it globally sets the settings to trust any certs.... A safer approach might be to cast the URLConnection back to a HttpsURLConnection and the call setSSLSocketFactory on that. Nevertheless this is a GREAT answer, several other ones said it was impossible to bypass the trust check and it was necessary to add a cert or tweak some JVM optionsDunsany
This may be needed too, in case the hostname doesn't match the certificate: HostnameVerifier nullVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(nullVerifier);Burgenland
This should be accepted answer since it does not use sun specific packages.Surge
In my case what helped was to force the client to use TLSv1 instead of TLS1.2. See this post: https://mcmap.net/q/35885/-javafx-webview-jdk-8-can-not-load-self-signed-certificateKynan
You might want getAcceptedIssuers() to return new X509Certificate[0] instead of null, if you're using newer versions of OkHttp. Otherwise it will run into a NullPointerException.Cottager
M
19

You need to create a fake TrustManager that accepts all certificates, and register it as a manager. Something like this:

public class MyManager implements com.sun.net.ssl.X509TrustManager {
  public boolean isClientTrusted(X509Certificate[] chain) { return true; }
  public boolean isHostTrusted(X509Certificate[] chain) { return true; }
  ...
}


com.sun.net.ssl.TrustManager[] managers =
  new com.sun.net.ssl.TrustManager[] {new MyManager()};

com.sun.net.ssl.SSLContext.getInstance("SSL").
       .init(null, managers, new SecureRandom());
Morphia answered 2/8, 2009 at 16:41 Comment(1)
All of this should really be done using the JSSE public API rather than tweaking the hidden com.sun.* classes. (See so_mv answer.)Bunt
R
8

Try this (answer to question 2):

System.setProperty("javax.net.ssl.trustStore", "/path/to/truststore");

You can also specify this as an additional command line parameter:

java -Djavax.net.ssl.trustStore=/path/to/truststore <remaining arguments>

On Fedora this could be the system wide java trust store in /etc/pki/java/cacerts

Renny answered 2/8, 2009 at 16:35 Comment(3)
is there a way to specify "trust all" as 2nd argument in this like using * etc ?Sunderland
@UmerHayat No. You have to code like in the other two answers.Renny
This setting is actually what I was looking for, rather than #1. Perhaps to be a more complete answer, it should mention that you have to add the cert for the server you want to access to this trust store.Dituri
K
4

Just add -Dtrust_all_cert=true to VM arguments. This argument tells java to ignore all certificate checks.

Kasper answered 21/11, 2016 at 7:33 Comment(4)
That's pretty frightening, but it seems like a good answer! I would like to do it within Java, though, and perhaps have a bit more control moving forward.Predacious
That is not a VM argument and will not work in general.Nickname
I tried. This works on JDK8. This is really helpful when you trusts all the URLs JVM is hitting. e.g. OWASP's dependency-check toolAnuska
@Anuska - The string "trust_all_cert" is not in the OpenJDK 8 source codebase ... anywhere. (Or any other OpenJDK version, starting from Java 6!) So if this "worked for you" then the propoerty is being recognized by the application that you are running, not by the JVM itself.Monomer
F
-12

In Command Line you can add argument -noCertificationCheck to java to ignore the certificate checks.

Fuze answered 31/7, 2017 at 5:23 Comment(2)
What cli? where? and where does that argument belong?Surge
In what version of Java? Because not on Java 8. That argument is not recognized and it will prevent Java from booting.Notepaper

© 2022 - 2024 — McMap. All rights reserved.