@marcel91200 / caddy Mirror · read-only / commits / 9cd6f35e
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

Separate out certificate selection

Matthew Holt committed May 27, 2019 at 11:31 UTC 9cd6f35e9d4873946060e79cb50643bae8ba8e2c
2 files changed +28 -55
modules/caddytls/connpolicy.go
+24 -51
@@ -5,7 +5,6 @@ import (
5 "crypto/x509"
6 "encoding/json"
7 "fmt"
8 - "math/big"
8 "strings"
9
10 "bitbucket.org/lightcodelabs/caddy2"
@@ -22,16 +21,27 @@ type ConnectionPolicies []*ConnectionPolicy
21 // TLS configuration which selects the first matching policy based on
22 // the ClientHello.
23 func (cp ConnectionPolicies) TLSConfig(ctx caddy2.Context) (*tls.Config, error) {
25 - // connection policy matchers
24 + // set up each of the connection policies
25 for i, pol := range cp {
27 - for modName, rawMsg := range pol.MatchersRaw {
26 + // matchers
27 + for modName, rawMsg := range pol.Matchers {
28 val, err := ctx.LoadModule("tls.handshake_match."+modName, rawMsg)
29 if err != nil {
30 return nil, fmt.Errorf("loading handshake matcher module '%s': %s", modName, err)
31 }
32 cp[i].matchers = append(cp[i].matchers, val.(ConnectionMatcher))
33 }
34 - cp[i].MatchersRaw = nil // allow GC to deallocate - TODO: Does this help?
34 + cp[i].Matchers = nil // allow GC to deallocate - TODO: Does this help?
35 +
36 + // certificate selector
37 + if pol.CertSelection != nil {
38 + val, err := ctx.LoadModuleInline("policy", "tls.certificate_selection", pol.CertSelection)
39 + if err != nil {
40 + return nil, fmt.Errorf("loading certificate selection module: %s", err)
41 + }
42 + cp[i].certSelector = val.(certmagic.CertificateSelector)
43 + cp[i].CertSelection = nil // allow GC to deallocate - TODO: Does this help?
44 + }
45 }
46
47 // pre-build standard TLS configs so we don't have to at handshake-time
@@ -83,7 +93,8 @@ func (cp ConnectionPolicies) TLSConfig(ctx caddy2.Context) (*tls.Config, error)
93
94 // ConnectionPolicy specifies the logic for handling a TLS handshake.
95 type ConnectionPolicy struct {
86 - MatchersRaw map[string]json.RawMessage `json:"match,omitempty"`
96 + Matchers map[string]json.RawMessage `json:"match,omitempty"`
97 + CertSelection json.RawMessage `json:"certificate_selection,omitempty"`
98
99 CipherSuites []string `json:"cipher_suites,omitempty"`
100 Curves []string `json:"curves,omitempty"`
@@ -91,14 +102,14 @@ type ConnectionPolicy struct {
102 ProtocolMin string `json:"protocol_min,omitempty"`
103 ProtocolMax string `json:"protocol_max,omitempty"`
104
94 - CertSelection *CertSelectionPolicy `json:"certificate_selection,omitempty"`
95 -
105 // TODO: Client auth
106
107 // TODO: see if starlark could be useful here - enterprise only
108 StarlarkHandshake string `json:"starlark_handshake,omitempty"`
109
110 matchers []ConnectionMatcher
111 + certSelector certmagic.CertificateSelector
112 +
113 stdTLSConfig *tls.Config
114 }
115
@@ -118,8 +129,8 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy2.Context) error {
129 return nil, fmt.Errorf("getting config for name %s: %v", hello.ServerName, err)
130 }
131 newCfg := certmagic.New(tlsApp.certCache, cfgTpl)
121 - if p.CertSelection != nil {
122 - newCfg.CertSelector = makeCertSelector(p)
132 + if p.certSelector != nil {
133 + newCfg.CertSelection = p.certSelector
134 }
135 return newCfg.GetCertificate(hello)
136 },
@@ -178,56 +189,18 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy2.Context) error {
189 return nil
190 }
191
181 -// CertSelectionPolicy represents a policy for selecting the certificate
182 -// used to complete a handshake when there may be multiple options. All
183 -// fields specified must match the candidate certificate for it to be chosen.
184 -// This was needed to solve https://github.com/mholt/caddy/issues/2588.
185 -type CertSelectionPolicy struct {
186 - SerialNumber *big.Int `json:"serial_number,omitempty"`
187 - SubjectOrganization string `json:"subject.organization,omitempty"`
188 - PublicKeyAlgorithm pkAlgorithm `json:"public_key_algorithm,omitempty"`
189 -}
190 -
191 -func makeCertSelector(p *ConnectionPolicy) func(*tls.ClientHelloInfo, []certmagic.Certificate) (certmagic.Certificate, error) {
192 - return func(hello *tls.ClientHelloInfo, choices []certmagic.Certificate) (certmagic.Certificate, error) {
193 - for _, cert := range choices {
194 - var matchOrg bool
195 - if p.CertSelection.SubjectOrganization != "" {
196 - for _, org := range cert.Subject.Organization {
197 - if p.CertSelection.SubjectOrganization == org {
198 - matchOrg = true
199 - break
200 - }
201 - }
202 - }
203 - if !matchOrg {
204 - continue
205 - }
206 - if p.CertSelection.PublicKeyAlgorithm != pkAlgorithm(x509.UnknownPublicKeyAlgorithm) &&
207 - pkAlgorithm(cert.PublicKeyAlgorithm) != p.CertSelection.PublicKeyAlgorithm {
208 - continue
209 - }
210 - if p.CertSelection.SerialNumber != nil &&
211 - cert.SerialNumber.Cmp(p.CertSelection.SerialNumber) != 0 {
212 - continue
213 - }
214 - return cert, nil
215 - }
216 - return certmagic.Certificate{}, fmt.Errorf("no certificates matched custom selection policy")
217 - }
218 -}
219 -
220 -type pkAlgorithm x509.PublicKeyAlgorithm
192 +// PublicKeyAlgorithm is a JSON-unmarshalable wrapper type.
193 +type PublicKeyAlgorithm x509.PublicKeyAlgorithm
194
195 // UnmarshalJSON satisfies json.Unmarshaler.
223 -func (a *pkAlgorithm) UnmarshalJSON(b []byte) error {
196 +func (a *PublicKeyAlgorithm) UnmarshalJSON(b []byte) error {
197 algoStr := strings.ToLower(strings.Trim(string(b), `"`))
198 algo, ok := publicKeyAlgorithms[algoStr]
199 if !ok {
200 return fmt.Errorf("unrecognized public key algorithm: %s (expected one of %v)",
201 algoStr, publicKeyAlgorithms)
202 }
230 - a = &algo
203 + *a = PublicKeyAlgorithm(algo)
204 return nil
205 }
206
modules/caddytls/tls.go
+4 -4
@@ -318,10 +318,10 @@ var supportedProtocols = map[string]uint16{
318 }
319
320 // publicKeyAlgorithms is the map of supported public key algorithms.
321 -var publicKeyAlgorithms = map[string]pkAlgorithm{
322 - "rsa": pkAlgorithm(x509.RSA),
323 - "dsa": pkAlgorithm(x509.DSA),
324 - "ecdsa": pkAlgorithm(x509.ECDSA),
321 +var publicKeyAlgorithms = map[string]x509.PublicKeyAlgorithm{
322 + "rsa": x509.RSA,
323 + "dsa": x509.DSA,
324 + "ecdsa": x509.ECDSA,
325 }
326
327 const automateKey = "automate"