Commit 8e8e2f59 authored by Carter's avatar Carter Committed by GitHub

Merge branch 'master' into log-request-body

parents 532ab661 68be4a91
......@@ -50,6 +50,14 @@ var (
// was started as part of an upgrade, where a parent
// Caddy process started this one.
isUpgrade bool
// started will be set to true when the first
// instance is started; it never gets set to
// false after that.
started bool
// mu protects the variables 'isUpgrade' and 'started'.
mu sync.Mutex
)
// Instance contains the state of servers created as a result of
......@@ -497,6 +505,10 @@ func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]r
}
}
mu.Lock()
started = true
mu.Unlock()
return nil
}
......@@ -737,9 +749,20 @@ func Upgrade() error {
// where a parent caddy process spawned this one to ugprade
// the binary.
func IsUpgrade() bool {
mu.Lock()
defer mu.Unlock()
return isUpgrade
}
// Started returns true if at least one instance has been
// started by this package. It never gets reset to false
// once it is set to true.
func Started() bool {
mu.Lock()
defer mu.Unlock()
return started
}
// CaddyfileInput represents a Caddyfile as input
// and is simply a convenient way to implement
// the Input interface.
......
......@@ -10,7 +10,9 @@ import (
)
func activateHTTPS(cctx caddy.Context) error {
if !caddy.Quiet {
operatorPresent := !caddy.Started()
if !caddy.Quiet && operatorPresent {
fmt.Print("Activating privacy features...")
}
......@@ -21,7 +23,7 @@ func activateHTTPS(cctx caddy.Context) error {
// place certificates and keys on disk
for _, c := range ctx.siteConfigs {
err := c.TLS.ObtainCert(true)
err := c.TLS.ObtainCert(operatorPresent)
if err != nil {
return err
}
......@@ -44,9 +46,10 @@ func activateHTTPS(cctx caddy.Context) error {
return err
}
if !caddy.Quiet {
if !caddy.Quiet && operatorPresent {
fmt.Println(" done.")
}
return nil
}
......
......@@ -144,9 +144,11 @@ var newACMEClient = func(config *Config, allowPrompts bool) (*ACMEClient, error)
func (c *ACMEClient) Obtain(names []string) error {
Attempts:
for attempts := 0; attempts < 2; attempts++ {
namesObtaining.Add(names)
acmeMu.Lock()
certificate, failures := c.ObtainCertificate(names, true, nil)
acmeMu.Unlock()
namesObtaining.Remove(names)
if len(failures) > 0 {
// Error - try to fix it or report it to the user and abort
var errMsg string // we'll combine all the failures into a single error message
......@@ -234,9 +236,11 @@ func (c *ACMEClient) Renew(name string) error {
var newCertMeta acme.CertificateResource
var success bool
for attempts := 0; attempts < 2; attempts++ {
namesObtaining.Add([]string{name})
acmeMu.Lock()
newCertMeta, err = c.RenewCertificate(certMeta, true)
acmeMu.Unlock()
namesObtaining.Remove([]string{name})
if err == nil {
success = true
break
......@@ -294,3 +298,47 @@ func (c *ACMEClient) Revoke(name string) error {
return nil
}
// namesObtaining is a set of hostnames with thread-safe
// methods. A name should be in this set only while this
// package is in the process of obtaining a certificate
// for the name. ACME challenges that are received for
// names which are not in this set were not initiated by
// this package and probably should not be handled by
// this package.
var namesObtaining = nameCoordinator{names: make(map[string]struct{})}
type nameCoordinator struct {
names map[string]struct{}
mu sync.RWMutex
}
// Add adds names to c. It is safe for concurrent use.
func (c *nameCoordinator) Add(names []string) {
c.mu.Lock()
for _, name := range names {
c.names[strings.ToLower(name)] = struct{}{}
}
c.mu.Unlock()
}
// Remove removes names from c. It is safe for concurrent use.
func (c *nameCoordinator) Remove(names []string) {
c.mu.Lock()
for _, name := range names {
delete(c.names, strings.ToLower(name))
}
c.mu.Unlock()
}
// Has returns true if c has name. It is safe for concurrent use.
func (c *nameCoordinator) Has(name string) bool {
hostname, _, err := net.SplitHostPort(name)
if err != nil {
hostname = name
}
c.mu.RLock()
_, ok := c.names[strings.ToLower(hostname)]
c.mu.RUnlock()
return ok
}
......@@ -214,9 +214,11 @@ func (c *Config) renewCertName(name string, allowPrompts bool) error {
var newCertMeta acme.CertificateResource
var success bool
for attempts := 0; attempts < 2; attempts++ {
namesObtaining.Add([]string{name})
acmeMu.Lock()
newCertMeta, err = client.RenewCertificate(certMeta, true)
acmeMu.Unlock()
namesObtaining.Remove([]string{name})
if err == nil {
success = true
break
......
......@@ -19,6 +19,9 @@ func HTTPChallengeHandler(w http.ResponseWriter, r *http.Request, altPort string
if !strings.HasPrefix(r.URL.Path, challengeBasePath) {
return false
}
if !namesObtaining.Has(r.Host) {
return false
}
scheme := "http"
if r.TLS != nil {
......
......@@ -8,13 +8,17 @@ import (
)
func TestHTTPChallengeHandlerNoOp(t *testing.T) {
// try base paths that aren't handled by this handler
namesObtaining.Add([]string{"localhost"})
// try base paths and host names that aren't
// handled by this handler
for _, url := range []string{
"http://localhost/",
"http://localhost/foo.html",
"http://localhost/.git",
"http://localhost/.well-known/",
"http://localhost/.well-known/acme-challenging",
"http://other/.well-known/acme-challenge/foo",
} {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
......@@ -46,6 +50,9 @@ func TestHTTPChallengeHandlerSuccess(t *testing.T) {
}
ts.Listener = ln
// Tell this package that we are handling a challenge for 127.0.0.1
namesObtaining.Add([]string{"127.0.0.1"})
// Start our engines and run the test
ts.Start()
defer ts.Close()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment