diff --git a/caddytls/setup.go b/caddytls/setup.go index 785905f6..e8a62645 100644 --- a/caddytls/setup.go +++ b/caddytls/setup.go @@ -21,12 +21,13 @@ import ( "fmt" "io/ioutil" "log" + "net/http" "net/url" "os" "path/filepath" - "strconv" "strings" "sync/atomic" + "time" "github.com/mholt/caddy" "github.com/mholt/caddy/telemetry" @@ -289,11 +290,8 @@ func setupTLS(c *caddy.Controller) error { if onDemand { config.Manager.OnDemand = new(certmagic.OnDemandConfig) if maxCerts != "" { - maxCertsNum, err := strconv.Atoi(maxCerts) - if err != nil || maxCertsNum < 1 { - return c.Err("max_certs must be a positive integer") - } - config.Manager.OnDemand.MaxObtain = int32(maxCertsNum) + log.Println("[WARNING] The max_certs subdirective is now deprecated and offers no protection; please use ask instead.") + fmt.Printf("WARNING: The max_certs subdirective is now deprecated and offers no protection; please use ask instead.") } if askURL != "" { parsedURL, err := url.Parse(askURL) @@ -303,7 +301,29 @@ func setupTLS(c *caddy.Controller) error { if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { return c.Err("ask URL must use http or https") } - config.Manager.OnDemand.AskURL = parsedURL + config.Manager.OnDemand.DecisionFunc = func(name string) error { + askURLParsed, err := url.Parse(askURL) + if err != nil { + return fmt.Errorf("parsing ask URL: %v", err) + } + qs := askURLParsed.Query() + qs.Set("domain", name) + askURLParsed.RawQuery = qs.Encode() + + resp, err := onDemandAskClient.Get(askURLParsed.String()) + if err != nil { + return fmt.Errorf("error checking %v to deterine if certificate for hostname '%s' should be allowed: %v", + askURL, name, err) + } + resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode > 299 { + return fmt.Errorf("certificate for hostname '%s' not allowed; non-2xx status code %d returned from %v", + name, resp.StatusCode, askURL) + } + + return nil + } } } @@ -314,7 +334,7 @@ func setupTLS(c *caddy.Controller) error { // load a single certificate and key, if specified if certificateFile != "" && keyFile != "" { - err := config.Manager.CacheUnmanagedCertificatePEMFile(certificateFile, keyFile) + err := config.Manager.CacheUnmanagedCertificatePEMFile(certificateFile, keyFile, nil) if err != nil { return c.Errf("Unable to load certificate and key files for '%s': %v", c.Key, err) } @@ -341,7 +361,7 @@ func setupTLS(c *caddy.Controller) error { if err != nil { return fmt.Errorf("self-signed certificate generation: %v", err) } - err = config.Manager.CacheUnmanagedTLSCertificate(ssCert) + err = config.Manager.CacheUnmanagedTLSCertificate(ssCert, nil) if err != nil { return fmt.Errorf("self-signed: %v", err) } @@ -437,7 +457,7 @@ func loadCertsInDir(cfg *Config, c *caddy.Controller, dir string) error { return c.Errf("%s: no private key block found", path) } - err = cfg.Manager.CacheUnmanagedCertificatePEMBytes(certPEMBytes, keyPEMBytes) + err = cfg.Manager.CacheUnmanagedCertificatePEMBytes(certPEMBytes, keyPEMBytes, nil) if err != nil { return c.Errf("%s: failed to load cert and key for '%s': %v", path, c.Key, err) } @@ -475,4 +495,11 @@ func constructDefaultClusterPlugin() (certmagic.Storage, error) { return &certmagic.FileStorage{Path: caddy.AssetsPath()}, nil } +var onDemandAskClient = &http.Client{ + Timeout: 10 * time.Second, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return fmt.Errorf("following http redirects is not allowed") + }, +} + const configMapKey = "tls_custom_configs" diff --git a/go.mod b/go.mod index 8e125dcd..a5f4bdc4 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/klauspost/cpuid v1.2.0 github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 // indirect github.com/lucas-clemente/quic-go v0.10.2 - github.com/mholt/certmagic v0.6.1 + github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2 github.com/naoina/go-stringutil v0.1.0 // indirect github.com/naoina/toml v0.1.1 github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4 diff --git a/go.sum b/go.sum index 6ef55373..ffabb41d 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ github.com/lucas-clemente/quic-go v0.10.2/go.mod h1:hvaRS9IHjFLMq76puFJeWNfmn+H7 github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced h1:zqEC1GJZFbGZA0tRyNZqRjep92K5fujFtFsu5ZW7Aug= github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= -github.com/mholt/certmagic v0.6.1 h1:3u4+xP+ohbYOxlpEzfaxOceNpSUmERdB+71AT2fKyqo= -github.com/mholt/certmagic v0.6.1/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= +github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2 h1:xKE9kZ5C8gelJC3+BNM6LJs1x21rivK7yxfTZMAuY2s= +github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=