Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
package caddytls
|
2016-02-11 02:06:05 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
2016-02-11 15:48:52 -05:00
|
|
|
"strings"
|
2016-02-11 02:06:05 -05:00
|
|
|
"sync"
|
2016-02-11 15:48:52 -05:00
|
|
|
"sync/atomic"
|
2016-02-11 02:06:05 -05:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// configGroup is a type that keys configs by their hostname
|
|
|
|
// (hostnames can have wildcard characters; use the getConfig
|
2017-02-21 11:49:22 -05:00
|
|
|
// method to get a config by matching its hostname).
|
|
|
|
type configGroup map[string]*Config
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
|
|
|
|
// getConfig gets the config by the first key match for name.
|
|
|
|
// In other words, "sub.foo.bar" will get the config for "*.foo.bar"
|
2017-02-21 11:49:22 -05:00
|
|
|
// if that is the closest match. If no match is found, the first
|
|
|
|
// (random) config will be loaded, which will defer any TLS alerts
|
|
|
|
// to the certificate validation (this may or may not be ideal;
|
|
|
|
// let's talk about it if this becomes problematic).
|
2016-02-11 02:06:05 -05:00
|
|
|
//
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// This function follows nearly the same logic to lookup
|
|
|
|
// a hostname as the getCertificate function uses.
|
2017-02-21 11:49:22 -05:00
|
|
|
func (cg configGroup) getConfig(name string) *Config {
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
name = strings.ToLower(name)
|
|
|
|
|
|
|
|
// exact match? great, let's use it
|
|
|
|
if config, ok := cg[name]; ok {
|
|
|
|
return config
|
|
|
|
}
|
|
|
|
|
|
|
|
// try replacing labels in the name with wildcards until we get a match
|
|
|
|
labels := strings.Split(name, ".")
|
|
|
|
for i := range labels {
|
|
|
|
labels[i] = "*"
|
|
|
|
candidate := strings.Join(labels, ".")
|
|
|
|
if config, ok := cg[candidate]; ok {
|
|
|
|
return config
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-21 11:49:22 -05:00
|
|
|
// as a fallback, try a config that serves all names
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
if config, ok := cg[""]; ok {
|
|
|
|
return config
|
|
|
|
}
|
|
|
|
|
2017-02-21 11:49:22 -05:00
|
|
|
// as a last resort, use a random config
|
|
|
|
// (even if the config isn't for that hostname,
|
|
|
|
// it should help us serve clients without SNI
|
|
|
|
// or at least defer TLS alerts to the cert)
|
|
|
|
for _, config := range cg {
|
|
|
|
return config
|
|
|
|
}
|
|
|
|
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
return nil
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
2017-02-21 11:49:22 -05:00
|
|
|
// GetConfigForClient gets a TLS configuration satisfying clientHello.
|
|
|
|
// In getting the configuration, it abides the rules and settings
|
|
|
|
// defined in the Config that matches clientHello.ServerName. If no
|
|
|
|
// tls.Config is set on the matching Config, a nil value is returned.
|
|
|
|
//
|
|
|
|
// This method is safe for use as a tls.Config.GetConfigForClient callback.
|
|
|
|
func (cg configGroup) GetConfigForClient(clientHello *tls.ClientHelloInfo) (*tls.Config, error) {
|
|
|
|
config := cg.getConfig(clientHello.ServerName)
|
|
|
|
if config != nil {
|
|
|
|
return config.tlsConfig, nil
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// GetCertificate gets a certificate to satisfy clientHello. In getting
|
|
|
|
// the certificate, it abides the rules and settings defined in the
|
|
|
|
// Config that matches clientHello.ServerName. It first checks the in-
|
2016-06-20 19:25:31 -05:00
|
|
|
// memory cache, then, if the config enables "OnDemand", it accesses
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// disk, then accesses the network if it must obtain a new certificate
|
|
|
|
// via ACME.
|
2016-02-11 02:06:05 -05:00
|
|
|
//
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// This method is safe for use as a tls.Config.GetCertificate callback.
|
2017-02-21 11:49:22 -05:00
|
|
|
func (cfg *Config) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
|
|
|
cert, err := cfg.getCertDuringHandshake(strings.ToLower(clientHello.ServerName), true, true)
|
2016-02-16 01:39:04 -05:00
|
|
|
return &cert.Certificate, err
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// getCertDuringHandshake will get a certificate for name. It first tries
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// the in-memory cache. If no certificate for name is in the cache, the
|
|
|
|
// config most closely corresponding to name will be loaded. If that config
|
|
|
|
// allows it (OnDemand==true) and if loadIfNecessary == true, it goes to disk
|
|
|
|
// to load it into the cache and serve it. If it's not on disk and if
|
|
|
|
// obtainIfNecessary == true, the certificate will be obtained from the CA,
|
|
|
|
// cached, and served. If obtainIfNecessary is true, then loadIfNecessary
|
|
|
|
// must also be set to true. An error will be returned if and only if no
|
|
|
|
// certificate is available.
|
2016-02-11 02:06:05 -05:00
|
|
|
//
|
|
|
|
// This function is safe for concurrent use.
|
2017-02-21 11:49:22 -05:00
|
|
|
func (cfg *Config) getCertDuringHandshake(name string, loadIfNecessary, obtainIfNecessary bool) (Certificate, error) {
|
2016-02-11 02:06:05 -05:00
|
|
|
// First check our in-memory cache to see if we've already loaded it
|
2016-02-18 22:33:15 -05:00
|
|
|
cert, matched, defaulted := getCertificate(name)
|
|
|
|
if matched {
|
2016-02-11 02:06:05 -05:00
|
|
|
return cert, nil
|
|
|
|
}
|
|
|
|
|
2017-02-21 11:49:22 -05:00
|
|
|
// If OnDemand is enabled, then we might be able to load or
|
|
|
|
// obtain a needed certificate
|
|
|
|
if cfg.OnDemand && loadIfNecessary {
|
2016-02-11 02:06:05 -05:00
|
|
|
// Then check to see if we have one on disk
|
2017-02-21 11:49:22 -05:00
|
|
|
loadedCert, err := cfg.CacheManagedCertificate(name)
|
2016-02-11 15:48:52 -05:00
|
|
|
if err == nil {
|
2017-02-21 11:49:22 -05:00
|
|
|
loadedCert, err = cfg.handshakeMaintenance(name, loadedCert)
|
2016-02-11 02:06:05 -05:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("[ERROR] Maintaining newly-loaded certificate for %s: %v", name, err)
|
|
|
|
}
|
2016-02-18 22:33:15 -05:00
|
|
|
return loadedCert, nil
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
2016-02-11 15:48:52 -05:00
|
|
|
if obtainIfNecessary {
|
2016-02-11 16:27:57 -05:00
|
|
|
// By this point, we need to ask the CA for a certificate
|
|
|
|
|
2016-02-11 15:48:52 -05:00
|
|
|
name = strings.ToLower(name)
|
|
|
|
|
|
|
|
// Make sure aren't over any applicable limits
|
2017-02-21 11:49:22 -05:00
|
|
|
err := cfg.checkLimitsForObtainingNewCerts(name)
|
2016-02-11 16:27:57 -05:00
|
|
|
if err != nil {
|
|
|
|
return Certificate{}, err
|
2016-02-11 15:48:52 -05:00
|
|
|
}
|
|
|
|
|
2016-02-11 16:27:57 -05:00
|
|
|
// Name has to qualify for a certificate
|
2016-02-11 15:48:52 -05:00
|
|
|
if !HostQualifies(name) {
|
|
|
|
return cert, errors.New("hostname '" + name + "' does not qualify for certificate")
|
|
|
|
}
|
2016-02-11 02:06:05 -05:00
|
|
|
|
2016-02-11 16:27:57 -05:00
|
|
|
// Obtain certificate from the CA
|
2017-02-21 11:49:22 -05:00
|
|
|
return cfg.obtainOnDemandCertificate(name)
|
2016-02-11 15:48:52 -05:00
|
|
|
}
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// Fall back to the default certificate if there is one
|
2016-02-18 22:33:15 -05:00
|
|
|
if defaulted {
|
|
|
|
return cert, nil
|
|
|
|
}
|
|
|
|
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
return Certificate{}, fmt.Errorf("no certificate available for %s", name)
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
2016-02-11 16:27:57 -05:00
|
|
|
// checkLimitsForObtainingNewCerts checks to see if name can be issued right
|
|
|
|
// now according to mitigating factors we keep track of and preferences the
|
|
|
|
// user has set. If a non-nil error is returned, do not issue a new certificate
|
|
|
|
// for name.
|
2017-02-21 11:49:22 -05:00
|
|
|
func (cfg *Config) checkLimitsForObtainingNewCerts(name string) error {
|
2016-02-11 16:27:57 -05:00
|
|
|
// User can set hard limit for number of certs for the process to issue
|
2016-07-28 12:08:18 -05:00
|
|
|
if cfg.OnDemandState.MaxObtain > 0 &&
|
|
|
|
atomic.LoadInt32(&cfg.OnDemandState.ObtainedCount) >= cfg.OnDemandState.MaxObtain {
|
|
|
|
return fmt.Errorf("%s: maximum certificates issued (%d)", name, cfg.OnDemandState.MaxObtain)
|
2016-02-11 16:27:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure name hasn't failed a challenge recently
|
|
|
|
failedIssuanceMu.RLock()
|
|
|
|
when, ok := failedIssuance[name]
|
|
|
|
failedIssuanceMu.RUnlock()
|
|
|
|
if ok {
|
|
|
|
return fmt.Errorf("%s: throttled; refusing to issue cert since last attempt on %s failed", name, when.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure, if we've issued a few certificates already, that we haven't
|
|
|
|
// issued any recently
|
|
|
|
lastIssueTimeMu.Lock()
|
|
|
|
since := time.Since(lastIssueTime)
|
|
|
|
lastIssueTimeMu.Unlock()
|
2016-07-28 12:08:18 -05:00
|
|
|
if atomic.LoadInt32(&cfg.OnDemandState.ObtainedCount) >= 10 && since < 10*time.Minute {
|
2016-02-11 16:27:57 -05:00
|
|
|
return fmt.Errorf("%s: throttled; last certificate was obtained %v ago", name, since)
|
|
|
|
}
|
|
|
|
|
2017-02-21 11:49:22 -05:00
|
|
|
// Good to go 👍
|
2016-02-11 16:27:57 -05:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-02-11 02:06:05 -05:00
|
|
|
// obtainOnDemandCertificate obtains a certificate for name for the given
|
2016-02-16 01:39:04 -05:00
|
|
|
// name. If another goroutine has already started obtaining a cert for
|
|
|
|
// name, it will wait and use what the other goroutine obtained.
|
2016-02-11 02:06:05 -05:00
|
|
|
//
|
|
|
|
// This function is safe for use by multiple concurrent goroutines.
|
2017-02-21 11:49:22 -05:00
|
|
|
func (cfg *Config) obtainOnDemandCertificate(name string) (Certificate, error) {
|
2016-02-11 02:06:05 -05:00
|
|
|
// We must protect this process from happening concurrently, so synchronize.
|
|
|
|
obtainCertWaitChansMu.Lock()
|
|
|
|
wait, ok := obtainCertWaitChans[name]
|
|
|
|
if ok {
|
|
|
|
// lucky us -- another goroutine is already obtaining the certificate.
|
|
|
|
// wait for it to finish obtaining the cert and then we'll use it.
|
|
|
|
obtainCertWaitChansMu.Unlock()
|
|
|
|
<-wait
|
2017-02-21 11:49:22 -05:00
|
|
|
return cfg.getCertDuringHandshake(name, true, false)
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
2016-09-14 23:30:49 -05:00
|
|
|
// looks like it's up to us to do all the work and obtain the cert.
|
|
|
|
// make a chan others can wait on if needed
|
2016-02-11 02:06:05 -05:00
|
|
|
wait = make(chan struct{})
|
|
|
|
obtainCertWaitChans[name] = wait
|
|
|
|
obtainCertWaitChansMu.Unlock()
|
|
|
|
|
2016-09-14 23:30:49 -05:00
|
|
|
// do the obtain
|
2016-02-11 02:06:05 -05:00
|
|
|
log.Printf("[INFO] Obtaining new certificate for %s", name)
|
2016-09-14 23:30:49 -05:00
|
|
|
err := cfg.ObtainCert(name, false)
|
|
|
|
|
|
|
|
// immediately unblock anyone waiting for it; doing this in
|
|
|
|
// a defer would risk deadlock because of the recursive call
|
|
|
|
// to getCertDuringHandshake below when we return!
|
|
|
|
obtainCertWaitChansMu.Lock()
|
|
|
|
close(wait)
|
|
|
|
delete(obtainCertWaitChans, name)
|
|
|
|
obtainCertWaitChansMu.Unlock()
|
2016-02-11 02:06:05 -05:00
|
|
|
|
2016-09-14 23:30:49 -05:00
|
|
|
if err != nil {
|
2016-02-11 15:48:52 -05:00
|
|
|
// Failed to solve challenge, so don't allow another on-demand
|
|
|
|
// issue for this name to be attempted for a little while.
|
|
|
|
failedIssuanceMu.Lock()
|
|
|
|
failedIssuance[name] = time.Now()
|
|
|
|
go func(name string) {
|
|
|
|
time.Sleep(5 * time.Minute)
|
|
|
|
failedIssuanceMu.Lock()
|
|
|
|
delete(failedIssuance, name)
|
|
|
|
failedIssuanceMu.Unlock()
|
|
|
|
}(name)
|
|
|
|
failedIssuanceMu.Unlock()
|
2016-02-11 02:06:05 -05:00
|
|
|
return Certificate{}, err
|
|
|
|
}
|
|
|
|
|
2016-02-11 16:27:57 -05:00
|
|
|
// Success - update counters and stuff
|
2016-07-28 12:08:18 -05:00
|
|
|
atomic.AddInt32(&cfg.OnDemandState.ObtainedCount, 1)
|
2016-02-11 16:27:57 -05:00
|
|
|
lastIssueTimeMu.Lock()
|
|
|
|
lastIssueTime = time.Now()
|
|
|
|
lastIssueTimeMu.Unlock()
|
2016-02-11 15:48:52 -05:00
|
|
|
|
2016-09-14 23:30:49 -05:00
|
|
|
// certificate is already on disk; now just start over to load it and serve it
|
2017-02-21 11:49:22 -05:00
|
|
|
return cfg.getCertDuringHandshake(name, true, false)
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// handshakeMaintenance performs a check on cert for expiration and OCSP
|
|
|
|
// validity.
|
|
|
|
//
|
|
|
|
// This function is safe for use by multiple concurrent goroutines.
|
2017-02-21 11:49:22 -05:00
|
|
|
func (cfg *Config) handshakeMaintenance(name string, cert Certificate) (Certificate, error) {
|
2016-02-11 02:06:05 -05:00
|
|
|
// Check cert expiration
|
|
|
|
timeLeft := cert.NotAfter.Sub(time.Now().UTC())
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
if timeLeft < RenewDurationBefore {
|
2016-02-11 02:06:05 -05:00
|
|
|
log.Printf("[INFO] Certificate for %v expires in %v; attempting renewal", cert.Names, timeLeft)
|
2017-02-21 11:49:22 -05:00
|
|
|
return cfg.renewDynamicCertificate(name)
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check OCSP staple validity
|
|
|
|
if cert.OCSP != nil {
|
|
|
|
refreshTime := cert.OCSP.ThisUpdate.Add(cert.OCSP.NextUpdate.Sub(cert.OCSP.ThisUpdate) / 2)
|
|
|
|
if time.Now().After(refreshTime) {
|
|
|
|
err := stapleOCSP(&cert, nil)
|
|
|
|
if err != nil {
|
|
|
|
// An error with OCSP stapling is not the end of the world, and in fact, is
|
|
|
|
// quite common considering not all certs have issuer URLs that support it.
|
|
|
|
log.Printf("[ERROR] Getting OCSP for %s: %v", name, err)
|
|
|
|
}
|
|
|
|
certCacheMu.Lock()
|
|
|
|
certCache[name] = cert
|
|
|
|
certCacheMu.Unlock()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cert, nil
|
|
|
|
}
|
|
|
|
|
Rewrote Caddy from the ground up; initial commit of 0.9 branch
These changes span work from the last ~4 months in an effort to make
Caddy more extensible, reduce the coupling between its components, and
lay a more robust foundation of code going forward into 1.0. A bunch of
new features have been added, too, with even higher future potential.
The most significant design change is an overall inversion of
dependencies. Instead of the caddy package knowing about the server
and the notion of middleware and config, the caddy package exposes an
interface that other components plug into. This does introduce more
indirection when reading the code, but every piece is very modular and
pluggable. Even the HTTP server is pluggable.
The caddy package has been moved to the top level, and main has been
pushed into a subfolder called caddy. The actual logic of the main
file has been pushed even further into caddy/caddymain/run.go so that
custom builds of Caddy can be 'go get'able.
The HTTPS logic was surgically separated into two parts to divide the
TLS-specific code and the HTTPS-specific code. The caddytls package can
now be used by any type of server that needs TLS, not just HTTP. I also
added the ability to customize nearly every aspect of TLS at the site
level rather than all sites sharing the same TLS configuration. Not all
of this flexibility is exposed in the Caddyfile yet, but it may be in
the future. Caddy can also generate self-signed certificates in memory
for the convenience of a developer working on localhost who wants HTTPS.
And Caddy now supports the DNS challenge, assuming at least one DNS
provider is plugged in.
Dozens, if not hundreds, of other minor changes swept through the code
base as I literally started from an empty main function, copying over
functions or files as needed, then adjusting them to fit in the new
design. Most tests have been restored and adapted to the new API,
but more work is needed there.
A lot of what was "impossible" before is now possible, or can be made
possible with minimal disruption of the code. For example, it's fairly
easy to make plugins hook into another part of the code via callbacks.
Plugins can do more than just be directives; we now have plugins that
customize how the Caddyfile is loaded (useful when you need to get your
configuration from a remote store).
Site addresses no longer need be just a host and port. They can have a
path, allowing you to scope a configuration to a specific path. There is
no inheretance, however; each site configuration is distinct.
Thanks to amazing work by Lucas Clemente, this commit adds experimental
QUIC support. Turn it on using the -quic flag; your browser may have
to be configured to enable it.
Almost everything is here, but you will notice that most of the middle-
ware are missing. After those are transferred over, we'll be ready for
beta tests.
I'm very excited to get this out. Thanks for everyone's help and
patience these last few months. I hope you like it!!
2016-06-04 18:00:29 -05:00
|
|
|
// renewDynamicCertificate renews the certificate for name using cfg. It returns the
|
2016-02-11 02:06:05 -05:00
|
|
|
// certificate to use and an error, if any. currentCert may be returned even if an
|
|
|
|
// error occurs, since we perform renewals before they expire and it may still be
|
|
|
|
// usable. name should already be lower-cased before calling this function.
|
|
|
|
//
|
|
|
|
// This function is safe for use by multiple concurrent goroutines.
|
2017-02-21 11:49:22 -05:00
|
|
|
func (cfg *Config) renewDynamicCertificate(name string) (Certificate, error) {
|
2016-02-11 02:06:05 -05:00
|
|
|
obtainCertWaitChansMu.Lock()
|
|
|
|
wait, ok := obtainCertWaitChans[name]
|
|
|
|
if ok {
|
|
|
|
// lucky us -- another goroutine is already renewing the certificate.
|
|
|
|
// wait for it to finish, then we'll use the new one.
|
|
|
|
obtainCertWaitChansMu.Unlock()
|
|
|
|
<-wait
|
2017-02-21 11:49:22 -05:00
|
|
|
return cfg.getCertDuringHandshake(name, true, false)
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// looks like it's up to us to do all the work and renew the cert
|
|
|
|
wait = make(chan struct{})
|
|
|
|
obtainCertWaitChans[name] = wait
|
|
|
|
obtainCertWaitChansMu.Unlock()
|
|
|
|
|
2016-09-14 23:30:49 -05:00
|
|
|
// do the renew
|
2016-02-11 02:06:05 -05:00
|
|
|
log.Printf("[INFO] Renewing certificate for %s", name)
|
2016-09-14 23:30:49 -05:00
|
|
|
err := cfg.RenewCert(name, false)
|
|
|
|
|
|
|
|
// immediately unblock anyone waiting for it; doing this in
|
|
|
|
// a defer would risk deadlock because of the recursive call
|
|
|
|
// to getCertDuringHandshake below when we return!
|
|
|
|
obtainCertWaitChansMu.Lock()
|
|
|
|
close(wait)
|
|
|
|
delete(obtainCertWaitChans, name)
|
|
|
|
obtainCertWaitChansMu.Unlock()
|
2016-02-11 02:06:05 -05:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return Certificate{}, err
|
|
|
|
}
|
|
|
|
|
2017-02-21 11:49:22 -05:00
|
|
|
return cfg.getCertDuringHandshake(name, true, false)
|
2016-02-11 02:06:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// obtainCertWaitChans is used to coordinate obtaining certs for each hostname.
|
|
|
|
var obtainCertWaitChans = make(map[string]chan struct{})
|
|
|
|
var obtainCertWaitChansMu sync.Mutex
|
2016-02-11 15:48:52 -05:00
|
|
|
|
|
|
|
// failedIssuance is a set of names that we recently failed to get a
|
|
|
|
// certificate for from the ACME CA. They are removed after some time.
|
2016-02-11 16:27:57 -05:00
|
|
|
// When a name is in this map, do not issue a certificate for it on-demand.
|
2016-02-11 15:48:52 -05:00
|
|
|
var failedIssuance = make(map[string]time.Time)
|
|
|
|
var failedIssuanceMu sync.RWMutex
|
2016-02-11 16:27:57 -05:00
|
|
|
|
|
|
|
// lastIssueTime records when we last obtained a certificate successfully.
|
|
|
|
// If this value is recent, do not make any on-demand certificate requests.
|
|
|
|
var lastIssueTime time.Time
|
|
|
|
var lastIssueTimeMu sync.Mutex
|