Compare commits

..

2 Commits

Author SHA1 Message Date
Matthew Holt 6cef20d257 caddytls: Enable ECH on the "gotten" tls.Config instead of the "getter"
No idea if this fixes #7555
2026-03-12 15:42:47 -06:00
Matthew Holt 1fbb28720b Fix lint errors
Tests / test (s390x on IBM Z) (push) Has been skipped
Tests / goreleaser-check (push) Has been skipped
Cross-Build / build (~1.26.0, 1.26, aix) (push) Successful in 2m15s
Tests / test (./cmd/caddy/caddy, ~1.26.0, ubuntu-latest, 0, 1.26, linux) (push) Failing after 2m36s
Cross-Build / build (~1.26.0, 1.26, darwin) (push) Successful in 1m14s
Cross-Build / build (~1.26.0, 1.26, dragonfly) (push) Successful in 1m27s
Cross-Build / build (~1.26.0, 1.26, freebsd) (push) Successful in 1m14s
Cross-Build / build (~1.26.0, 1.26, illumos) (push) Successful in 1m27s
Cross-Build / build (~1.26.0, 1.26, linux) (push) Successful in 1m14s
Cross-Build / build (~1.26.0, 1.26, netbsd) (push) Successful in 1m24s
Cross-Build / build (~1.26.0, 1.26, openbsd) (push) Successful in 1m14s
Cross-Build / build (~1.26.0, 1.26, solaris) (push) Successful in 1m26s
Cross-Build / build (~1.26.0, 1.26, windows) (push) Successful in 1m13s
Lint / lint (ubuntu-latest, linux) (push) Failing after 1m13s
Lint / govulncheck (push) Successful in 1m31s
Lint / dependency-review (push) Failing after 59s
OpenSSF Scorecard supply-chain security / Scorecard analysis (push) Failing after 29s
Tests / test (./cmd/caddy/caddy, ~1.26.0, macos-14, 0, 1.26, mac) (push) Has been cancelled
Tests / test (./cmd/caddy/caddy.exe, ~1.26.0, windows-latest, True, 1.26, windows) (push) Has been cancelled
Lint / lint (macos-14, mac) (push) Has been cancelled
Lint / lint (windows-latest, windows) (push) Has been cancelled
Use VerifyConnection instead of VerifyPeerCertificate; the other 2 fixes are "meh" not really a big deal or an issue at all.
2026-03-11 13:33:59 -06:00
3 changed files with 44 additions and 22 deletions
+1 -1
View File
@@ -697,7 +697,7 @@ func cmdFmt(fl Flags) (int, error) {
output := caddyfile.Format(input)
if fl.Bool("overwrite") {
if err := os.WriteFile(configFile, output, 0o600); err != nil {
if err := os.WriteFile(configFile, output, 0o600); err != nil { //nolint:gosec // path traversal is not really a thing here, this is either "Caddyfile" or admin-controlled
return caddy.ExitCodeFailedStartup, fmt.Errorf("overwriting formatted file: %v", err)
}
return caddy.ExitCodeSuccess, nil
+27 -15
View File
@@ -167,12 +167,6 @@ func (cp ConnectionPolicies) TLSConfig(ctx caddy.Context) *tls.Config {
}
tlsApp.RegisterServerNames(echNames)
}
tlsCfg.GetEncryptedClientHelloKeys = func(chi *tls.ClientHelloInfo) ([]tls.EncryptedClientHelloKey, error) {
tlsApp.EncryptedClientHello.configsMu.RLock()
defer tlsApp.EncryptedClientHello.configsMu.RUnlock()
return tlsApp.EncryptedClientHello.stdlibReady, nil
}
}
}
@@ -376,6 +370,19 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
cfg.MaxVersion = SupportedProtocols[p.ProtocolMax]
}
// enable ECH (Encrypted ClientHello) if configured
if tlsApp.EncryptedClientHello != nil {
cfg.GetEncryptedClientHelloKeys = func(_ *tls.ClientHelloInfo) ([]tls.EncryptedClientHelloKey, error) {
tlsApp.EncryptedClientHello.configsMu.RLock()
defer tlsApp.EncryptedClientHello.configsMu.RUnlock()
return tlsApp.EncryptedClientHello.stdlibReady, nil
}
// TLS 1.3 is the first version that supports ECH
if cfg.MinVersion < tls.VersionTLS13 {
cfg.MaxVersion = tls.VersionTLS13
}
}
// client authentication
if p.ClientAuthentication != nil {
if err := p.ClientAuthentication.provision(ctx); err != nil {
@@ -885,24 +892,29 @@ func (clientauth *ClientAuthentication) ConfigureTLSConfig(cfg *tls.Config) erro
// if a custom verification function already exists, wrap it
clientauth.existingVerifyPeerCert = cfg.VerifyPeerCertificate
cfg.VerifyPeerCertificate = clientauth.verifyPeerCertificate
cfg.VerifyConnection = clientauth.verifyConnection
return nil
}
// verifyPeerCertificate is for use as a tls.Config.VerifyPeerCertificate
// callback to do custom client certificate verification. It is intended
// for installation only by clientauth.ConfigureTLSConfig().
func (clientauth *ClientAuthentication) verifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
// verifyConnection is for use as a tls.Config.VerifyConnection callback
// to do custom client certificate verification. It is intended for
// installation only by clientauth.ConfigureTLSConfig().
//
// Unlike VerifyPeerCertificate, VerifyConnection is called on every
// connection including resumed sessions, preventing session-resumption bypass.
func (clientauth *ClientAuthentication) verifyConnection(cs tls.ConnectionState) error {
// first use any pre-existing custom verification function
if clientauth.existingVerifyPeerCert != nil {
err := clientauth.existingVerifyPeerCert(rawCerts, verifiedChains)
if err != nil {
rawCerts := make([][]byte, len(cs.PeerCertificates))
for i, cert := range cs.PeerCertificates {
rawCerts[i] = cert.Raw
}
if err := clientauth.existingVerifyPeerCert(rawCerts, cs.VerifiedChains); err != nil {
return err
}
}
for _, verifier := range clientauth.verifiers {
err := verifier.VerifyClientCertificate(rawCerts, verifiedChains)
if err != nil {
if err := verifier.VerifyClientCertificate(nil, cs.VerifiedChains); err != nil {
return err
}
}
+16 -6
View File
@@ -19,6 +19,7 @@ import (
"crypto/tls"
"encoding/pem"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
@@ -62,18 +63,27 @@ func (fl FolderLoader) Provision(ctx caddy.Context) error {
func (fl FolderLoader) LoadCertificates() ([]Certificate, error) {
var certs []Certificate
for _, dir := range fl {
err := filepath.Walk(dir, func(fpath string, info os.FileInfo, err error) error {
root, err := os.OpenRoot(dir)
if err != nil {
return nil, fmt.Errorf("unable to open root directory %s: %w", dir, err)
}
err = filepath.WalkDir(dir, func(fpath string, d fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("unable to traverse into path: %s", fpath)
}
if info.IsDir() {
if d.IsDir() {
return nil
}
if !strings.HasSuffix(strings.ToLower(info.Name()), ".pem") {
if !strings.HasSuffix(strings.ToLower(d.Name()), ".pem") {
return nil
}
bundle, err := os.ReadFile(fpath)
rel, err := filepath.Rel(dir, fpath)
if err != nil {
return fmt.Errorf("unable to get relative path for %s: %w", fpath, err)
}
bundle, err := root.ReadFile(rel)
if err != nil {
return err
}
@@ -83,11 +93,11 @@ func (fl FolderLoader) LoadCertificates() ([]Certificate, error) {
}
certs = append(certs, Certificate{Certificate: cert})
return nil
})
_ = root.Close()
if err != nil {
return nil, err
return nil, fmt.Errorf("walking certificates directory %s: %w", dir, err)
}
}
return certs, nil