Can't restrict accepted CA roots via X509TrustManager.getAcceptedIssuers

39 Views Asked by At

I am trying to write a custom X509TrustManager that will use the default system trust store, but allowing only a restricted set of trusted CA roots.

I am trying to do this by returning a modified list of accepted CA roots from the getAcceptedIssuers method, but this does not seem to work -- server certificates are accepted as valid even when the root certificate is not part of the list returned by getAcceptedIssuers.

Here is a simple implementation that delegates to the system's default trust manager, but overrides getAcceptedIssuers to return an empty array:

import java.security.KeyStore;
import java.security.cert.*;
import javax.net.ssl.*;

public class DefaultTrustManagerWrapper implements X509TrustManager {
    private final X509TrustManager defaultTrustManager;

    public DefaultTrustManagerWrapper() throws Exception {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init((KeyStore) null); // Init with default keystore

        // Find the X509TrustManager instance from the array of trust managers
        X509TrustManager foundTrustManager = null;
        for (TrustManager tm : tmf.getTrustManagers()) {
            if (tm instanceof X509TrustManager) {
                defaultTrustManager = (X509TrustManager) tm;
            }
        }

        if (defaultTrustManager == null) {
            throw new IllegalStateException("No X509TrustManager found");
        }
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        defaultTrustManager.checkClientTrusted(chain, authType);
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        defaultTrustManager.checkServerTrusted(chain, authType);
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // Return no accepted issuers
        return new X509Certificate[0];
    }
}

But when using this, server certificates still validate OK.

Why is this happening? Isn't getAcceptedIssuers called by default when validating a server certificate?

1

There are 1 best solutions below

0
Grodriguez On

According to the accepted answer to a related question, getAcceptedIssuers is not used to decide whether to trust a certificate. So that would explain the behaviour I am seeing.

The linked answer also includes some additional detail on when is getAcceptedIssuers actually used.