func NewCertVerifierAll(verifiers ...CertVerifier) CertVerifierAll {
	return CertVerifierAll{verifiers: verifiers}
}
NewCertVerifierAll creates new CertVerifierAll, verifier that tries all internally contained verifiers
package network
import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"flag"
	"fmt"
	log "github.com/sirupsen/logrus"
	"strings"
)
var (
	ErrCertWasRevoked = errors.New("certificate was revoked")
	ErrEmptyCertChain = errors.New("empty verified certificates chain")
)
var (
	tlsOcspURL                      string
	tlsOcspClientURL                string
	tlsOcspDbURL                    string
	tlsOcspRequired                 string
	tlsOcspFromCert                 string
	tlsOcspCheckOnlyLeafCertificate bool
	tlsCrlURL                       string
	tlsCrlClientURL                 string
	tlsCrlDbURL                     string
	tlsCrlFromCert                  string
	tlsCrlCheckOnlyLeafCertificate  bool
	tlsCrlCacheSize                 uint
	tlsCrlCacheTime                 uint
)
func registerCertVerifierArgs(separateClientDBUrls bool) {
	flag.StringVar(&tlsOcspURL, "tls_ocsp_url", "", "OCSP service URL")
	if separateClientDBUrls {
		flag.StringVar(&tlsOcspClientURL, "tls_ocsp_client_url", "", "OCSP service URL, for client/connector certificates only")
		flag.StringVar(&tlsOcspDbURL, "tls_ocsp_database_url", "", "OCSP service URL, for database certificates only")
	}
	flag.StringVar(&tlsOcspRequired, "tls_ocsp_required", OcspRequiredDenyUnknownStr,
		fmt.Sprintf("How to treat certificates unknown to OCSP: <%s>", strings.Join(OcspRequiredValuesList, "|")))
	flag.StringVar(&tlsOcspFromCert, "tls_ocsp_from_cert", OcspFromCertPreferStr,
		fmt.Sprintf("How to treat OCSP server described in certificate itself: <%s>", strings.Join(OcspFromCertValuesList, "|")))
	flag.BoolVar(&tlsOcspCheckOnlyLeafCertificate, "tls_ocsp_check_only_leaf_certificate", false,
		"Put 'true' to check only final/last certificate, or 'false' to check the whole certificate chain using OCSP")
	flag.StringVar(&tlsCrlURL, "tls_crl_url", "", "URL of the Certificate Revocation List (CRL) to use")
	if separateClientDBUrls {
		flag.StringVar(&tlsCrlClientURL, "tls_crl_client_url", "", "URL of the Certificate Revocation List (CRL) to use, for client/connector certificates only")
		flag.StringVar(&tlsCrlDbURL, "tls_crl_database_url", "", "URL of the Certificate Revocation List (CRL) to use, for database certificates only")
	}
	flag.StringVar(&tlsCrlFromCert, "tls_crl_from_cert", CrlFromCertPreferStr,
		fmt.Sprintf("How to treat CRL URL described in certificate itself: <%s>", strings.Join(CrlFromCertValuesList, "|")))
	flag.BoolVar(&tlsCrlCheckOnlyLeafCertificate, "tls_crl_check_only_leaf_certificate", false,
		"Put 'true' to check only final/last certificate, or 'false' to check the whole certificate chain using CRL")
	flag.UintVar(&tlsCrlCacheSize, "tls_crl_cache_size", CrlDefaultCacheSize, "How many CRLs to cache in memory (use 0 to disable caching)")
	flag.UintVar(&tlsCrlCacheTime, "tls_crl_cache_time", CrlDisableCacheTime,
		fmt.Sprintf("How long to keep CRLs cached, in seconds (use 0 to disable caching, maximum: %d s)", CrlCacheTimeMax))
}
func RegisterCertVerifierArgs() {
	registerCertVerifierArgs(false)
}
func RegisterCertVerifierArgsWithSeparateClientAndDatabase() {
	registerCertVerifierArgs(true)
}
type CertVerifier interface {
	Verify(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
}
func NewCertVerifier() (CertVerifier, error) {
	ocspConfig, err := NewOCSPConfig(tlsOcspURL, tlsOcspRequired, tlsOcspFromCert, tlsOcspCheckOnlyLeafCertificate)
	if err != nil {
		return nil, err
	}
	crlConfig, err := NewCRLConfig(tlsCrlURL, tlsCrlFromCert, tlsCrlCheckOnlyLeafCertificate, tlsCrlCacheSize, tlsCrlCacheTime)
	if err != nil {
		return nil, err
	}
	return NewCertVerifierFromConfigs(ocspConfig, crlConfig)
}
func NewClientCertVerifier(clientAuthType int) (CertVerifier, error) {
	var ocspURL, crlURL string
	if tlsOcspClientURL != "" {
		ocspURL = tlsOcspClientURL
	} else {
		ocspURL = tlsOcspURL
	}
	if tlsCrlClientURL != "" {
		crlURL = tlsCrlClientURL
	} else {
		crlURL = tlsCrlURL
	}
	ocspConfig, err := NewOCSPConfig(ocspURL, tlsOcspRequired, tlsOcspFromCert, tlsOcspCheckOnlyLeafCertificate)
	if err != nil {
		return nil, err
	}
	ocspConfig.ClientAuthType = tls.ClientAuthType(clientAuthType)
	crlConfig, err := NewCRLConfig(crlURL, tlsCrlFromCert, tlsCrlCheckOnlyLeafCertificate, tlsCrlCacheSize, tlsCrlCacheTime)
	if err != nil {
		return nil, err
	}
	crlConfig.ClientAuthType = tls.ClientAuthType(clientAuthType)
	return NewCertVerifierFromConfigs(ocspConfig, crlConfig)
}
func NewDatabaseCertVerifier() (CertVerifier, error) {
	var ocspURL, crlURL string
	if tlsOcspDbURL != "" {
		ocspURL = tlsOcspDbURL
	} else {
		ocspURL = tlsOcspURL
	}
	if tlsCrlDbURL != "" {
		crlURL = tlsCrlDbURL
	} else {
		crlURL = tlsCrlURL
	}
	ocspConfig, err := NewOCSPConfig(ocspURL, tlsOcspRequired, tlsOcspFromCert, tlsOcspCheckOnlyLeafCertificate)
	if err != nil {
		return nil, err
	}
	crlConfig, err := NewCRLConfig(crlURL, tlsCrlFromCert, tlsCrlCheckOnlyLeafCertificate, tlsCrlCacheSize, tlsCrlCacheTime)
	if err != nil {
		return nil, err
	}
	return NewCertVerifierFromConfigs(ocspConfig, crlConfig)
}
func NewCertVerifierFromConfigs(ocspConfig *OCSPConfig, crlConfig *CRLConfig) (CertVerifier, error) {
	certVerifier := NewCertVerifierAll()
	if ocspConfig.UseOCSP() {
		log.Debugln("NewCertVerifierFromConfigs(): adding OCSP verifier")
		ocspVerifier := DefaultOCSPVerifier{
			Config: *ocspConfig,
			Client: NewDefaultOCSPClient(),
		}
		certVerifier.Push(ocspVerifier)
	}
	if crlConfig.UseCRL() {
		log.Debugln("NewCertVerifierFromConfigs(): adding CRL verifier")
		crlVerifier := DefaultCRLVerifier{
			Config: *crlConfig,
			Client: NewDefaultCRLClient(),
			Cache:  NewLRUCRLCache(crlConfig.cacheSize),
		}
		certVerifier.Push(crlVerifier)
	}
	return certVerifier, nil
}
type CertVerifierAll struct {
	verifiers []CertVerifier
}