Repository: netty/netty
File: handler/src/main/java/io/netty/handler/ssl/EnhancingX509ExtendedTrustManager.java (Java)

Code before:
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.x500.X500Principal;

/**
 * Wraps an existing {@link X509ExtendedTrustManager} and enhances the {@link CertificateException} that is thrown
 * because of hostname validation.
 */
final class EnhancingX509ExtendedTrustManager extends X509ExtendedTrustManager {

    // Constants for subject alt names of type DNS and IP. See X509Certificate#getSubjectAlternativeNames() javadocs.
    static final int ALTNAME_DNS = 2;
    static final int ALTNAME_IP = 7;
    private static final String SEPARATOR = ", ";

    private final X509ExtendedTrustManager wrapped;

    EnhancingX509ExtendedTrustManager(X509TrustManager wrapped) {
        this.wrapped = (X509ExtendedTrustManager) wrapped;
    }

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

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket)
            throws CertificateException {
        try {
            wrapped.checkServerTrusted(chain, authType, socket);
        } catch (CertificateException e) {
            throwEnhancedCertificateException(chain, e);
        }
    }

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

    @Override

Review comment (bug):
Consider adding URI names to the mix (code `6`). These are common in some environments with gRPC services that use SPIFFEs. Though the hostname matcher won't be looking at them, having them there can help debugging cases where hostname verification was enabled when it shouldn't be.

Code after:
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.net.ssl.ExtendedSSLSession;
import javax.net.ssl.SNIHostName;
import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.x500.X500Principal;

/**
 * Wraps an existing {@link X509ExtendedTrustManager} and enhances the {@link CertificateException} that is thrown
 * because of hostname validation.
 */
final class EnhancingX509ExtendedTrustManager extends X509ExtendedTrustManager {

    // Constants for subject alt names of type DNS and IP. See X509Certificate#getSubjectAlternativeNames() javadocs.
    static final int ALTNAME_DNS = 2;
    static final int ALTNAME_URI = 6;
    static final int ALTNAME_IP = 7;
    private static final String SEPARATOR = ", ";

    private final X509ExtendedTrustManager wrapped;

    EnhancingX509ExtendedTrustManager(X509TrustManager wrapped) {
        this.wrapped = (X509ExtendedTrustManager) wrapped;
    }

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

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket)
            throws CertificateException {
        try {
            wrapped.checkServerTrusted(chain, authType, socket);
        } catch (CertificateException e) {
            throwEnhancedCertificateException(e, chain,
                    socket instanceof SSLSocket ? ((SSLSocket) socket).getHandshakeSession() : null);
        }
    }