hivemq/hivemq-mqtt-client

How to ignore server certificate validation by setting Custom TrustManager?

nishankhadka09 opened this issue · 4 comments

Checklist

❓ Question

How can I do something similar to setting custom SSL context in PAHO and using Custom SSLSockketFactory to trust all certificates? There is key manager and trust manager to allow connection using self-signed certificates. But what if I want to ignore the trust store and accept all certificates? Is there any way to achieve this?

tkeksa commented

See my code snippet:

        String scheme = mqttBroker.getScheme();
        MqttClientTransportConfigBuilder trBld = MqttClientTransportConfig.builder()
                .serverHost(mqttBroker.getHost())
                .serverPort(mqttBroker.getPort())
                .socketConnectTimeout(SOCKET_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
                .mqttConnectTimeout(MQTT_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        if (scheme.equals("ws") || scheme.equals("wss")) {
            MqttWebSocketConfigBuilder wsBld = MqttWebSocketConfig.builder().serverPath("mqtt");
            trBld = trBld.webSocketConfig(wsBld.build());
        }
        if (scheme.equals("mqtts") || scheme.equals("wss")) {
            MqttClientSslConfigBuilder sslBld = MqttClientSslConfig.builder();
            if (disableCertVerification) {
                sslBld = sslBld.trustManagerFactory(UtilSec.trustAllCertsFactory());  // <=============
            }
            trBld = trBld.sslConfig(sslBld.build());
        }

@tkeksa I believe UtilSec.trustAllCertsFactory() returns custom trustManagerFactory. Could you share the snippet of your UtilSec.trustAllCertsFactory().

tkeksa commented

Yes, it returns TrustManagerFactory creating simple TrustManager accepting all certificates. I will try to copy all necessary code here:

    public static TrustManagerFactory trustAllCertsFactory() {
        return new TrustAllCertsFactory();
    }

    private static final class TrustAllCertsFactory extends TrustManagerFactory {
        private TrustAllCertsFactory() {
            super(new TrustAllCertsFactorySpi(), TMF_DEF.getProvider(), TMF_DEF.getAlgorithm());
        }
    }

    private static class TrustAllCertsFactorySpi extends TrustManagerFactorySpi {

        TrustAllCertsFactorySpi() {
        }

        @Override
        protected void engineInit(KeyStore ks) {
        }

        @Override
        protected void engineInit(ManagerFactoryParameters spec) {
        }

        @Override
        protected TrustManager[] engineGetTrustManagers() {
            return new TrustManager[]{new TrustManagerAllCerts()};
        }
    }

    private static class TrustManagerAllCerts extends X509ExtendedTrustManager {

        TrustManagerAllCerts() {
        }

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) {
        }

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) {
        }

    private final static TrustManagerFactory TMF_DEF = createTmfDefault();

    private static TrustManagerFactory createTmfDefault() {
        try {
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init((KeyStore) null);  // initialises the TMF with the default trust store
            return tmf;
        } catch (NoSuchAlgorithmException | KeyStoreException e) {
            throw  new IllegalStateException(e);
        }
    }

I didn't know that there was this approach to set Custom Trust manager through TrustManagerFactorySpi(). Thanks a lot! @tkeksa that worked as I wanted it to. Much appreciated.