caddytls: validate curve and protocol names, compare protocol IDs (#8266)

* caddytls: validate curve and protocol names, compare protocol IDs
* caddytls: Add final newline to tests and drop duplicate protocol comment

(cherry picked from commit 71c5812cfe)
pull/8349/head
Akinyemi Toluwalase 2026-10-26 21:14:59 +01:00 committed by Francis Lavoie
parent f13be23fce
commit 8818870dcd
No known key found for this signature in database
4 changed files with 79 additions and 7 deletions

View File

@ -896,7 +896,10 @@ func (t *TLSConfig) MakeTLSClientConfig(ctx caddy.Context) (*tls.Config, error)
curvesAdded := make(map[tls.CurveID]struct{})
for _, curveName := range t.Curves {
curveID := caddytls.SupportedCurves[curveName]
curveID, ok := caddytls.SupportedCurves[curveName]
if !ok {
return nil, fmt.Errorf("unsupported curve: %s", curveName)
}
if _, ok := curvesAdded[curveID]; !ok {
curvesAdded[curveID] = struct{}{}
cfg.CurvePreferences = append(cfg.CurvePreferences, curveID)

View File

@ -406,3 +406,13 @@ func TestHTTPTransportH3UsesConfiguredTrustPool(t *testing.T) {
t.Fatal("HTTP/3 transport: TLS client config must be a clone, not the same pointer as the HTTP/1.1+2 transport's")
}
}
func TestTLSConfigRejectsUnknownCurve(t *testing.T) {
ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
defer cancel()
tc := &TLSConfig{Curves: []string{"X25519"}}
if _, err := tc.MakeTLSClientConfig(ctx); err == nil {
t.Fatal("expected an error for an unknown curve, got nil")
}
}

View File

@ -363,7 +363,10 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
// add all the curve preferences in order, without duplicates
curvesAdded := make(map[tls.CurveID]struct{})
for _, curveName := range p.Curves {
curveID := SupportedCurves[curveName]
curveID, ok := SupportedCurves[curveName]
if !ok {
return fmt.Errorf("unsupported curve: %s", curveName)
}
if _, ok := curvesAdded[curveID]; !ok {
curvesAdded[curveID] = struct{}{}
cfg.CurvePreferences = append(cfg.CurvePreferences, curveID)
@ -377,14 +380,23 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
}
// min and max protocol versions
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]
minVersion, ok := SupportedProtocols[p.ProtocolMin]
if !ok {
return fmt.Errorf("unsupported protocol_min: %s", p.ProtocolMin)
}
cfg.MinVersion = minVersion
}
if p.ProtocolMax != "" {
cfg.MaxVersion = SupportedProtocols[p.ProtocolMax]
maxVersion, ok := SupportedProtocols[p.ProtocolMax]
if !ok {
return fmt.Errorf("unsupported protocol_max: %s", p.ProtocolMax)
}
cfg.MaxVersion = maxVersion
}
if cfg.MinVersion > cfg.MaxVersion {
return fmt.Errorf("protocol min (%s) cannot be greater than protocol max (%s)",
ProtocolName(cfg.MinVersion), ProtocolName(cfg.MaxVersion))
}
// client authentication

View File

@ -418,3 +418,50 @@ func TestParseCaddyfileNestedMatcherSet(t *testing.T) {
}
}
}
func TestConnectionPolicyRejectsUnknownNames(t *testing.T) {
for _, tc := range []struct {
name string
policy ConnectionPolicy
}{
{"unknown curve", ConnectionPolicy{Curves: []string{"X25519"}}},
{"unknown protocol_min", ConnectionPolicy{ProtocolMin: "TLS1.3"}},
{"unknown protocol_max", ConnectionPolicy{ProtocolMax: "tls13"}},
{"protocol_min greater than protocol_max", ConnectionPolicy{ProtocolMin: "tls1.3", ProtocolMax: "tls1.2"}},
} {
t.Run(tc.name, func(t *testing.T) {
ctx, err := caddy.ProvisionContext(&caddy.Config{})
if err != nil {
t.Fatal(err)
}
if err := (ConnectionPolicies{&tc.policy}).Provision(ctx); err == nil {
t.Fatal("expected an error, got nil")
}
})
}
}
func TestConnectionPolicyProtocolDefaults(t *testing.T) {
for _, tc := range []struct {
name string
policy ConnectionPolicy
min, max uint16
}{
{"both empty", ConnectionPolicy{}, tls.VersionTLS12, tls.VersionTLS13},
{"min only", ConnectionPolicy{ProtocolMin: "tls1.3"}, tls.VersionTLS13, tls.VersionTLS13},
{"max only", ConnectionPolicy{ProtocolMax: "tls1.2"}, tls.VersionTLS12, tls.VersionTLS12},
} {
t.Run(tc.name, func(t *testing.T) {
ctx, err := caddy.ProvisionContext(&caddy.Config{})
if err != nil {
t.Fatal(err)
}
if err := (ConnectionPolicies{&tc.policy}).Provision(ctx); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got := tc.policy.TLSConfig; got.MinVersion != tc.min || got.MaxVersion != tc.max {
t.Fatalf("got min=%x max=%x, want min=%x max=%x", got.MinVersion, got.MaxVersion, tc.min, tc.max)
}
})
}
}