mirror of
https://github.com/caddyserver/caddy.git
synced 2026-11-11 19:37:55 +00:00
caddytls: preserve regexp quantifiers during placeholder expansion
Expand only known placeholders in TLS regexp patterns, matching HTTP regexp behavior. Test numeric quantifiers and selection of the client-certificate-verifying fallback policy. Addresses scan report b6c9c0a1-79a7-4254-b057-b1d8fc96b412. Code written by GitHub Copilot (GPT-6.1 Sol, Claude Opus 5.5); reviewed by mholt. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
b0731f7d2a
commit
9461da6583
2 files changed
+61
-2
No files matched your search
@@ -175,10 +175,11 @@ type MatchRegexp struct {
|
||||
compiled *regexp.Regexp
|
||||
}
|
||||
|
||||
// Provision compiles the regular expression which may include placeholders.
|
||||
// Provision compiles the regular expression which may include known placeholders.
|
||||
// Unknown placeholders are preserved so regexp quantifiers remain intact.
|
||||
func (mre *MatchRegexp) Provision(caddy.Context) error {
|
||||
repl := caddy.NewReplacer()
|
||||
re, err := regexp.Compile(repl.ReplaceAll(mre.Pattern, ""))
|
||||
re, err := regexp.Compile(repl.ReplaceKnown(mre.Pattern, ""))
|
||||
if err != nil {
|
||||
return fmt.Errorf("compiling matcher regexp %s: %v", mre.Pattern, err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package caddytls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"testing"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
)
|
||||
|
||||
func TestServerNameRegexpQuantifiers(t *testing.T) {
|
||||
t.Setenv("CADDY_TEST_SNI_SUFFIX", "example")
|
||||
ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
|
||||
defer cancel()
|
||||
for _, tc := range []struct {
|
||||
pattern, input string
|
||||
match bool
|
||||
}{
|
||||
{`^a{2}\.example$`, "aa.example", true},
|
||||
{`^a{2}\.example$`, "a.example", false},
|
||||
{`^a{2,}\.example$`, "aaa.example", true},
|
||||
{`^a{2,}\.example$`, "a.example", false},
|
||||
{`^a{2,3}\.example$`, "aaa.example", true},
|
||||
{`^a{2,3}\.example$`, "a.example", false},
|
||||
{`^a{2,3}\.example$`, "aaaa.example", false},
|
||||
{`^a{2}\.{env.CADDY_TEST_SNI_SUFFIX}$`, "aa.example", true},
|
||||
{`^a{unknown}\.example$`, "a.example", false},
|
||||
} {
|
||||
t.Run(tc.pattern+"/"+tc.input, func(t *testing.T) {
|
||||
matcher := &MatchServerNameRE{MatchRegexp: MatchRegexp{Pattern: tc.pattern}}
|
||||
if err := matcher.Provision(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
public := &tls.Config{MinVersion: tls.VersionTLS12}
|
||||
protected := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
ClientCAs: x509.NewCertPool(),
|
||||
}
|
||||
policies := ConnectionPolicies{
|
||||
{matchers: []ConnectionMatcher{matcher}, TLSConfig: public},
|
||||
{TLSConfig: protected},
|
||||
}
|
||||
selected, err := policies.TLSConfig(ctx).GetConfigForClient(&tls.ClientHelloInfo{ServerName: tc.input})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := protected
|
||||
if tc.match {
|
||||
want = public
|
||||
}
|
||||
if selected != want {
|
||||
t.Fatalf("selected client authentication %v, want %v", selected.ClientAuth, want.ClientAuth)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user