func decodeBase64DERCert(certStr string) (*x509.Certificate, error) {
	derBytes, err := base64.StdEncoding.DecodeString(certStr)
	if err != nil {
		return nil, err
	}
	return x509.ParseCertificate(derBytes)
}
decodeBase64DERCert base64-decodes, then DER-decodes, certStr.
package caddytls
import (
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"fmt"
	"os"
	"strings"
	"github.com/caddyserver/caddy/v2"
	"github.com/mholt/acmez"
)
type ConnectionPolicies []*ConnectionPolicy
func (cp ConnectionPolicies) Provision(ctx caddy.Context) error {
	for i, pol := range cp {
		mods, err := ctx.LoadModule(pol, "MatchersRaw")
		if err != nil {
			return fmt.Errorf("loading handshake matchers: %v", err)
		}
		for _, modIface := range mods.(map[string]interface{}) {
			cp[i].matchers = append(cp[i].matchers, modIface.(ConnectionMatcher))
		}
		if len(pol.ALPN) == 0 {
			pol.ALPN = append(pol.ALPN, defaultALPN...)
		}
		err = pol.buildStandardTLSConfig(ctx)
		if err != nil {
			return fmt.Errorf("connection policy %d: building standard TLS config: %s", i, err)
		}
	}
	return nil
}
func (cp ConnectionPolicies) TLSConfig(ctx caddy.Context) *tls.Config {
	indexedBySNI := make(map[string]ConnectionPolicies)
	if len(cp) > 30 {
		for _, p := range cp {
			for _, m := range p.matchers {
				if sni, ok := m.(MatchServerName); ok {
					for _, sniName := range sni {
						indexedBySNI[sniName] = append(indexedBySNI[sniName], p)
					}
				}
			}
		}
	}
	return &tls.Config{
		MinVersion: tls.VersionTLS12,
		GetConfigForClient: func(hello *tls.ClientHelloInfo) (*tls.Config, error) {
			possiblePolicies := cp
			if indexedPolicies, ok := indexedBySNI[hello.ServerName]; ok {
				possiblePolicies = indexedPolicies
			}
		policyLoop:
			for _, pol := range possiblePolicies {
				for _, matcher := range pol.matchers {
					if !matcher.Match(hello) {
						continue policyLoop
					}
				}
				return pol.stdTLSConfig, nil
			}
			return nil, fmt.Errorf("no server TLS configuration available for ClientHello: %+v", hello)
		},
	}
}
type ConnectionPolicy struct {
	MatchersRaw caddy.ModuleMap `json:"match,omitempty" caddy:"namespace=tls.handshake_match"`
	CertSelection *CustomCertSelectionPolicy `json:"certificate_selection,omitempty"`
	CipherSuites []string `json:"cipher_suites,omitempty"`
	Curves []string `json:"curves,omitempty"`
	ALPN []string `json:"alpn,omitempty"`
	ProtocolMin string `json:"protocol_min,omitempty"`
	ProtocolMax string `json:"protocol_max,omitempty"`
	ClientAuthentication *ClientAuthentication `json:"client_authentication,omitempty"`
	DefaultSNI string `json:"default_sni,omitempty"`
	matchers     []ConnectionMatcher
	stdTLSConfig *tls.Config
}
func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
	tlsAppIface, err := ctx.App("tls")
	if err != nil {
		return fmt.Errorf("getting tls app: %v", err)
	}
	tlsApp := tlsAppIface.(*TLS)
	cfg := &tls.Config{
		NextProtos:               p.ALPN,
		PreferServerCipherSuites: true,
		GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
			cfg := *tlsApp.getConfigForName(hello.ServerName)
			if p.CertSelection != nil {
				cfg.CertSelection = p.CertSelection
			}
			cfg.DefaultServerName = p.DefaultSNI
			return cfg.GetCertificate(hello)
		},
		MinVersion: tls.VersionTLS12,
		MaxVersion: tls.VersionTLS13,
	}
	if tlsApp.SessionTickets != nil {
		cfg.SessionTicketsDisabled = tlsApp.SessionTickets.Disabled
		tlsApp.SessionTickets.register(cfg)
		ctx.OnCancel(func() {
			tlsApp.SessionTickets.unregister(cfg)
		})
	}
	cipherSuitesAdded := make(map[uint16]struct{})
	for _, csName := range p.CipherSuites {
		csID := CipherSuiteID(csName)
		if csID == 0 {
			return fmt.Errorf("unsupported cipher suite: %s", csName)
		}
		if _, ok := cipherSuitesAdded[csID]; !ok {
			cipherSuitesAdded[csID] = struct{}{}
			cfg.CipherSuites = append(cfg.CipherSuites, csID)
		}
	}
	curvesAdded := make(map[tls.CurveID]struct{})
	for _, curveName := range p.Curves {
		curveID := SupportedCurves[curveName]
		if _, ok := curvesAdded[curveID]; !ok {
			curvesAdded[curveID] = struct{}{}
			cfg.CurvePreferences = append(cfg.CurvePreferences, curveID)
		}
	}
	var alpnFound bool
	for _, a := range p.ALPN {
		if a == acmez.ACMETLS1Protocol {
			alpnFound = true
			break
		}
	}
	if !alpnFound {
		cfg.NextProtos = append(cfg.NextProtos, acmez.ACMETLS1Protocol)
	}
	if (p.ProtocolMin != "" && p.ProtocolMax != "") && p.ProtocolMin > p.ProtocolMax {
		return fmt.Errorf("protocol min (%x) cannot be greater than protocol max (%x)", p.ProtocolMin, p.ProtocolMax)
	}
	if p.ProtocolMin != "" {
		cfg.MinVersion = SupportedProtocols[p.ProtocolMin]
	}
	if p.ProtocolMax != "" {
		cfg.MaxVersion = SupportedProtocols[p.ProtocolMax]
	}
	if p.ClientAuthentication != nil {
		err := p.ClientAuthentication.ConfigureTLSConfig(cfg)
		if err != nil {
			return fmt.Errorf("configuring TLS client authentication: %v", err)
		}
	}
	setDefaultTLSParams(cfg)
	p.stdTLSConfig = cfg
	return nil
}
func (p ConnectionPolicy) SettingsEmpty() bool {
	return p.CertSelection == nil &&
		p.CipherSuites == nil &&
		p.Curves == nil &&
		p.ALPN == nil &&
		p.ProtocolMin == "" &&
		p.ProtocolMax == "" &&
		p.ClientAuthentication == nil &&
		p.DefaultSNI == ""
}
type ClientAuthentication struct {
	TrustedCACerts []string `json:"trusted_ca_certs,omitempty"`
	TrustedCACertPEMFiles []string `json:"trusted_ca_certs_pem_files,omitempty"`
	TrustedLeafCerts []string `json:"trusted_leaf_certs,omitempty"`
	Mode string `json:"mode,omitempty"`
	trustedLeafCerts       []*x509.Certificate
	existingVerifyPeerCert func([][]byte, [][]*x509.Certificate) error
}
func (clientauth ClientAuthentication) Active() bool {
	return len(clientauth.TrustedCACerts) > 0 ||
		len(clientauth.TrustedCACertPEMFiles) > 0 ||
		len(clientauth.TrustedLeafCerts) > 0 ||
		len(clientauth.Mode) > 0
}
func (clientauth *ClientAuthentication) ConfigureTLSConfig(cfg *tls.Config) error {
	if !clientauth.Active() {
		cfg.ClientAuth = tls.NoClientCert
		return nil
	}
	if len(clientauth.Mode) > 0 {
		switch clientauth.Mode {
		case "request":
			cfg.ClientAuth = tls.RequestClientCert
		case "require":
			cfg.ClientAuth = tls.RequireAnyClientCert
		case "verify_if_given":
			cfg.ClientAuth = tls.VerifyClientCertIfGiven
		case "require_and_verify":
			cfg.ClientAuth = tls.RequireAndVerifyClientCert
		default:
			return fmt.Errorf("client auth mode not recognized: %s", clientauth.Mode)
		}
	} else {
		if len(clientauth.TrustedCACerts) > 0 ||
			len(clientauth.TrustedCACertPEMFiles) > 0 ||
			len(clientauth.TrustedLeafCerts) > 0 {
			cfg.ClientAuth = tls.RequireAndVerifyClientCert
		} else {
			cfg.ClientAuth = tls.RequireAnyClientCert
		}
	}
	if len(clientauth.TrustedCACerts) > 0 || len(clientauth.TrustedCACertPEMFiles) > 0 {
		caPool := x509.NewCertPool()
		for _, clientCAString := range clientauth.TrustedCACerts {
			clientCA, err := decodeBase64DERCert(clientCAString)
			if err != nil {
				return fmt.Errorf("parsing certificate: %v", err)
			}
			caPool.AddCert(clientCA)
		}
		for _, pemFile := range clientauth.TrustedCACertPEMFiles {
			pemContents, err := os.ReadFile(pemFile)
			if err != nil {
				return fmt.Errorf("reading %s: %v", pemFile, err)
			}
			caPool.AppendCertsFromPEM(pemContents)
		}
		cfg.ClientCAs = caPool
	}
	if len(clientauth.TrustedLeafCerts) > 0 {
		clientauth.trustedLeafCerts = []*x509.Certificate{}
		for _, clientCertString := range clientauth.TrustedLeafCerts {
			clientCert, err := decodeBase64DERCert(clientCertString)
			if err != nil {
				return fmt.Errorf("parsing certificate: %v", err)
			}
			clientauth.trustedLeafCerts = append(clientauth.trustedLeafCerts, clientCert)
		}
		clientauth.existingVerifyPeerCert = cfg.VerifyPeerCertificate
		cfg.VerifyPeerCertificate = clientauth.verifyPeerCertificate
	}
	return nil
}
func (clientauth ClientAuthentication) verifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
	if clientauth.existingVerifyPeerCert != nil {
		err := clientauth.existingVerifyPeerCert(rawCerts, verifiedChains)
		if err != nil {
			return err
		}
	}
	if len(rawCerts) == 0 {
		return fmt.Errorf("no client certificate provided")
	}
	remoteLeafCert, err := x509.ParseCertificate(rawCerts[0])
	if err != nil {
		return fmt.Errorf("can't parse the given certificate: %s", err.Error())
	}
	for _, trustedLeafCert := range clientauth.trustedLeafCerts {
		if remoteLeafCert.Equal(trustedLeafCert) {
			return nil
		}
	}
	return fmt.Errorf("client leaf certificate failed validation")
}