0
Fork 0
mirror of https://github.com/caddyserver/caddy.git synced 2024-12-23 22:27:38 -05:00

Fix HTTPS config for empty/no Caddyfile

This fixes a regression introduced in recent commits that enabled TLS on the default ":2015" config. This fix is possible because On-Demand TLS is no longer implicit; it must be explicitly enabled by the user by setting a maximum number of certificates to issue.
This commit is contained in:
Matthew Holt 2016-02-12 13:04:24 -07:00
parent 04c7c442c5
commit a11e14aca8
5 changed files with 31 additions and 30 deletions

View file

@ -95,7 +95,7 @@ func Deactivate() (err error) {
} }
// MarkQualified scans each config and, if it qualifies for managed // MarkQualified scans each config and, if it qualifies for managed
// TLS, it sets the Marked field of the TLSConfig to true. // TLS, it sets the Managed field of the TLSConfig to true.
func MarkQualified(configs []server.Config) { func MarkQualified(configs []server.Config) {
for i := 0; i < len(configs); i++ { for i := 0; i < len(configs); i++ {
if ConfigQualifies(configs[i]) { if ConfigQualifies(configs[i]) {
@ -152,9 +152,10 @@ func ObtainCerts(configs []server.Config, allowPrompts, proxyACME bool) error {
return nil return nil
} }
// groupConfigsByEmail groups configs by the email address to be used by its // groupConfigsByEmail groups configs by the email address to be used by an
// ACME client. It only includes configs that are marked as fully managed. // ACME client. It only groups configs that have TLS enabled and that are
// If userPresent is true, the operator MAY be prompted for an email address. // marked as Managed. If userPresent is true, the operator MAY be prompted
// for an email address.
func groupConfigsByEmail(configs []server.Config, userPresent bool) map[string][]server.Config { func groupConfigsByEmail(configs []server.Config, userPresent bool) map[string][]server.Config {
initMap := make(map[string][]server.Config) initMap := make(map[string][]server.Config)
for _, cfg := range configs { for _, cfg := range configs {
@ -214,7 +215,7 @@ func hostHasOtherPort(allConfigs []server.Config, thisConfigIdx int, otherPort s
// all configs. // all configs.
func MakePlaintextRedirects(allConfigs []server.Config) []server.Config { func MakePlaintextRedirects(allConfigs []server.Config) []server.Config {
for i, cfg := range allConfigs { for i, cfg := range allConfigs {
if cfg.TLS.Managed && if (cfg.TLS.Managed || cfg.TLS.OnDemand) &&
!hostHasOtherPort(allConfigs, i, "80") && !hostHasOtherPort(allConfigs, i, "80") &&
(cfg.Port == "443" || !hostHasOtherPort(allConfigs, i, "443")) { (cfg.Port == "443" || !hostHasOtherPort(allConfigs, i, "443")) {
allConfigs = append(allConfigs, redirPlaintextHost(cfg)) allConfigs = append(allConfigs, redirPlaintextHost(cfg))
@ -224,10 +225,11 @@ func MakePlaintextRedirects(allConfigs []server.Config) []server.Config {
} }
// ConfigQualifies returns true if cfg qualifies for // ConfigQualifies returns true if cfg qualifies for
// fully managed TLS. It does NOT check to see if a // fully managed TLS (but not on-demand TLS, which is
// not considered here). It does NOT check to see if a
// cert and key already exist for the config. If the // cert and key already exist for the config. If the
// config does qualify, you should set cfg.TLS.Managed // config does qualify, you should set cfg.TLS.Managed
// to true and use that instead, because the process of // to true and check that instead, because the process of
// setting up the config may make it look like it // setting up the config may make it look like it
// doesn't qualify even though it originally did. // doesn't qualify even though it originally did.
func ConfigQualifies(cfg server.Config) bool { func ConfigQualifies(cfg server.Config) bool {
@ -238,10 +240,8 @@ func ConfigQualifies(cfg server.Config) bool {
cfg.Port != "80" && cfg.Port != "80" &&
cfg.TLS.LetsEncryptEmail != "off" && cfg.TLS.LetsEncryptEmail != "off" &&
// we get can't certs for some kinds of hostnames, // we get can't certs for some kinds of hostnames
// but we CAN get certs at request-time even if HostQualifies(cfg.Host)
// the hostname in the config is empty right now.
(cfg.Host == "" || HostQualifies(cfg.Host))
} }
// HostQualifies returns true if the hostname alone // HostQualifies returns true if the hostname alone

View file

@ -46,7 +46,7 @@ func TestConfigQualifies(t *testing.T) {
cfg server.Config cfg server.Config
expect bool expect bool
}{ }{
{server.Config{Host: ""}, true}, {server.Config{Host: ""}, false},
{server.Config{Host: "localhost"}, false}, {server.Config{Host: "localhost"}, false},
{server.Config{Host: "123.44.3.21"}, false}, {server.Config{Host: "123.44.3.21"}, false},
{server.Config{Host: "example.com"}, true}, {server.Config{Host: "example.com"}, true},
@ -302,6 +302,7 @@ func TestGroupConfigsByEmail(t *testing.T) {
func TestMarkQualified(t *testing.T) { func TestMarkQualified(t *testing.T) {
// TODO: TestConfigQualifies and this test share the same config list... // TODO: TestConfigQualifies and this test share the same config list...
configs := []server.Config{ configs := []server.Config{
{Host: ""},
{Host: "localhost"}, {Host: "localhost"},
{Host: "123.44.3.21"}, {Host: "123.44.3.21"},
{Host: "example.com"}, {Host: "example.com"},
@ -313,9 +314,8 @@ func TestMarkQualified(t *testing.T) {
{Host: "example.com", Port: "1234"}, {Host: "example.com", Port: "1234"},
{Host: "example.com", Scheme: "https"}, {Host: "example.com", Scheme: "https"},
{Host: "example.com", Port: "80", Scheme: "https"}, {Host: "example.com", Port: "80", Scheme: "https"},
{Host: ""},
} }
expectedManagedCount := 5 expectedManagedCount := 4
MarkQualified(configs) MarkQualified(configs)

View file

@ -83,6 +83,7 @@ func Setup(c *setup.Controller) (middleware.Middleware, error) {
c.TLS.Manual = true c.TLS.Manual = true
case "max_certs": case "max_certs":
c.Args(&maxCerts) c.Args(&maxCerts)
c.TLS.OnDemand = true
default: default:
return nil, c.Errf("Unknown keyword '%s'", c.Val()) return nil, c.Errf("Unknown keyword '%s'", c.Val())
} }
@ -93,21 +94,18 @@ func Setup(c *setup.Controller) (middleware.Middleware, error) {
return nil, c.ArgErr() return nil, c.ArgErr()
} }
if c.TLS.Manual && maxCerts != "" { // set certificate limit if on-demand TLS is enabled
return nil, c.Err("Cannot limit certificate count (max_certs) for manual TLS configurations")
}
if maxCerts != "" { if maxCerts != "" {
maxCertsNum, err := strconv.Atoi(maxCerts) maxCertsNum, err := strconv.Atoi(maxCerts)
if err != nil || maxCertsNum < 0 { if err != nil || maxCertsNum < 1 {
return nil, c.Err("max_certs must be a positive integer") return nil, c.Err("max_certs must be a positive integer")
} }
if onDemandMaxIssue == 0 || int32(maxCertsNum) < onDemandMaxIssue { // keep the minimum; TODO: This is global; should be per-server or per-vhost... if onDemandMaxIssue == 0 || int32(maxCertsNum) < onDemandMaxIssue { // keep the minimum; TODO: We have to do this because it is global; should be per-server or per-vhost...
onDemandMaxIssue = int32(maxCertsNum) onDemandMaxIssue = int32(maxCertsNum)
} }
} }
// don't load certificates unless we're supposed to // don't try to load certificates unless we're supposed to
if !c.TLS.Enabled || !c.TLS.Manual { if !c.TLS.Enabled || !c.TLS.Manual {
continue continue
} }

View file

@ -65,10 +65,11 @@ func (c Config) Address() string {
// TLSConfig describes how TLS should be configured and used. // TLSConfig describes how TLS should be configured and used.
type TLSConfig struct { type TLSConfig struct {
Enabled bool Enabled bool // will be set to true if TLS is enabled
LetsEncryptEmail string LetsEncryptEmail string
Managed bool // will be set to true if config qualifies for automatic, managed TLS Manual bool // will be set to true if user provides own certs and keys
Manual bool // will be set to true if user provides the cert and key files Managed bool // will be set to true if config qualifies for automatic/managed HTTPS
OnDemand bool // will be set to true if user enables on-demand TLS (obtain certs during handshakes)
Ciphers []uint16 Ciphers []uint16
ProtocolMinVersion uint16 ProtocolMinVersion uint16
ProtocolMaxVersion uint16 ProtocolMaxVersion uint16

View file

@ -63,14 +63,16 @@ func New(addr string, configs []Config, gracefulTimeout time.Duration) (*Server,
var useTLS, useOnDemandTLS bool var useTLS, useOnDemandTLS bool
if len(configs) > 0 { if len(configs) > 0 {
useTLS = configs[0].TLS.Enabled useTLS = configs[0].TLS.Enabled
if useTLS {
host, _, err := net.SplitHostPort(addr) host, _, err := net.SplitHostPort(addr)
if err != nil { if err != nil {
host = addr host = addr
} }
if useTLS && host == "" && !configs[0].TLS.Manual { if host == "" && configs[0].TLS.OnDemand {
useOnDemandTLS = true useOnDemandTLS = true
} }
} }
}
s := &Server{ s := &Server{
Server: &http.Server{ Server: &http.Server{