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"