diff options
author | Matt Holt <mholt@users.noreply.github.com> | 2019-10-10 11:27:45 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-10 11:27:45 -0600 |
commit | b38365ff3b6ab8b2c474603fa0603831e7eff2a7 (patch) | |
tree | 7a35ea901e4ce8d3fbe028e8fc81bd1f69c6be68 /modules/caddytls/certselection.go | |
parent | 53dd600b4de0c2b169f1eb4450a0f02950912524 (diff) | |
parent | 26cc8837084f9cea6057e9908f0b5bde0eb15d3e (diff) |
Merge pull request #2799 from caddyserver/v2-enterprise-merge
v2: Merge enterprise code into open source v2 branch
Diffstat (limited to 'modules/caddytls/certselection.go')
-rw-r--r-- | modules/caddytls/certselection.go | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/modules/caddytls/certselection.go b/modules/caddytls/certselection.go new file mode 100644 index 0000000..b56185a --- /dev/null +++ b/modules/caddytls/certselection.go @@ -0,0 +1,71 @@ +package caddytls + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "math/big" + + "github.com/caddyserver/caddy/v2" + "github.com/mholt/certmagic" +) + +func init() { + caddy.RegisterModule(Policy{}) +} + +// Policy represents a policy for selecting the certificate used to +// complete a handshake when there may be multiple options. All fields +// specified must match the candidate certificate for it to be chosen. +// This was needed to solve https://github.com/caddyserver/caddy/issues/2588. +type Policy struct { + SerialNumber *big.Int `json:"serial_number,omitempty"` + SubjectOrganization string `json:"subject_organization,omitempty"` + PublicKeyAlgorithm PublicKeyAlgorithm `json:"public_key_algorithm,omitempty"` + Tag string `json:"tag,omitempty"` +} + +// CaddyModule returns the Caddy module information. +func (Policy) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + Name: "tls.certificate_selection.custom", + New: func() caddy.Module { return new(Policy) }, + } +} + +// SelectCertificate implements certmagic.CertificateSelector. +func (p Policy) SelectCertificate(_ *tls.ClientHelloInfo, choices []certmagic.Certificate) (certmagic.Certificate, error) { + for _, cert := range choices { + if p.SerialNumber != nil && cert.SerialNumber.Cmp(p.SerialNumber) != 0 { + continue + } + + if p.PublicKeyAlgorithm != PublicKeyAlgorithm(x509.UnknownPublicKeyAlgorithm) && + PublicKeyAlgorithm(cert.PublicKeyAlgorithm) != p.PublicKeyAlgorithm { + continue + } + + if p.SubjectOrganization != "" { + var matchOrg bool + for _, org := range cert.Subject.Organization { + if p.SubjectOrganization == org { + matchOrg = true + break + } + } + if !matchOrg { + continue + } + } + + if p.Tag != "" && !cert.HasTag(p.Tag) { + continue + } + + return cert, nil + } + return certmagic.Certificate{}, fmt.Errorf("no certificates matched custom selection policy") +} + +// Interface guard +var _ certmagic.CertificateSelector = (*Policy)(nil) |