package me.proxylink.plugin.tunnel;

import me.proxylink.plugin.tls.CertificateFingerprints;

import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

final class PinnedCertificateTrustManager implements X509TrustManager {
    private final String expectedFingerprint;
    private final boolean trustOnFirstUse;
    private volatile String learnedFingerprint;

    PinnedCertificateTrustManager(String expectedFingerprint, boolean trustOnFirstUse) {
        this.expectedFingerprint = CertificateFingerprints.normalize(expectedFingerprint);
        this.trustOnFirstUse = trustOnFirstUse;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        throw new CertificateException("Client certificate authentication is not enabled");
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        if (chain == null || chain.length == 0) {
            throw new CertificateException("Server did not provide a TLS certificate");
        }

        chain[0].checkValidity();
        String actualPretty = CertificateFingerprints.sha256(chain[0]);
        String actual = CertificateFingerprints.normalize(actualPretty);

        if (!expectedFingerprint.isBlank()) {
            if (!expectedFingerprint.equals(actual)) {
                throw new CertificateException("Frontend TLS certificate fingerprint mismatch. Expected "
                        + expectedFingerprint + " but got " + actualPretty);
            }
            return;
        }

        if (!trustOnFirstUse) {
            throw new CertificateException("No pinned frontend TLS certificate fingerprint is configured");
        }

        learnedFingerprint = actualPretty;
    }

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

    String learnedFingerprint() {
        return learnedFingerprint;
    }
}
