only check the autotls hostnames once when serving

not twice: for root process and for child process
This commit is contained in:
Mechiel Lukkien 2023-03-05 23:56:02 +01:00
parent 1bee32679a
commit b2e6c29849
No known key found for this signature in database
18 changed files with 34 additions and 30 deletions

View file

@ -188,7 +188,7 @@ func Load(name, acmeDir, contactEmail, directoryURL string, shutdown <-chan stru
// are fully served by publicIPs (only if non-empty and there is no unspecified // are fully served by publicIPs (only if non-empty and there is no unspecified
// address in the list). If no, log an error with a warning that ACME validation // address in the list). If no, log an error with a warning that ACME validation
// may fail. // may fail.
func (m *Manager) SetAllowedHostnames(resolver dns.Resolver, hostnames map[dns.Domain]struct{}, publicIPs []string) { func (m *Manager) SetAllowedHostnames(resolver dns.Resolver, hostnames map[dns.Domain]struct{}, publicIPs []string, checkHosts bool) {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
@ -210,7 +210,7 @@ func (m *Manager) SetAllowedHostnames(resolver dns.Resolver, hostnames map[dns.D
} }
m.hosts = hostnames m.hosts = hostnames
if len(added) > 0 && len(publicIPs) > 0 { if checkHosts && len(added) > 0 && len(publicIPs) > 0 {
for _, ip := range publicIPs { for _, ip := range publicIPs {
if net.ParseIP(ip).IsUnspecified() { if net.ParseIP(ip).IsUnspecified() {
return return
@ -225,6 +225,7 @@ func (m *Manager) SetAllowedHostnames(resolver dns.Resolver, hostnames map[dns.D
publicIPstrs[ip] = struct{}{} publicIPstrs[ip] = struct{}{}
} }
xlog.Debug("checking ips of hosts configured for acme tls cert validation")
for _, h := range added { for _, h := range added {
ips, err := resolver.LookupIP(ctx, "ip", h.ASCII+".") ips, err := resolver.LookupIP(ctx, "ip", h.ASCII+".")
if err != nil { if err != nil {

View file

@ -28,7 +28,7 @@ func TestAutotls(t *testing.T) {
if err := m.HostPolicy(context.Background(), "mox.example"); err == nil || !errors.Is(err, errHostNotAllowed) { if err := m.HostPolicy(context.Background(), "mox.example"); err == nil || !errors.Is(err, errHostNotAllowed) {
t.Fatalf("hostpolicy, got err %v, expected errHostNotAllowed", err) t.Fatalf("hostpolicy, got err %v, expected errHostNotAllowed", err)
} }
m.SetAllowedHostnames(dns.StrictResolver{}, map[dns.Domain]struct{}{{ASCII: "mox.example"}: {}}, nil) m.SetAllowedHostnames(dns.StrictResolver{}, map[dns.Domain]struct{}{{ASCII: "mox.example"}: {}}, nil, false)
l = m.Hostnames() l = m.Hostnames()
if !reflect.DeepEqual(l, []dns.Domain{{ASCII: "mox.example"}}) { if !reflect.DeepEqual(l, []dns.Domain{{ASCII: "mox.example"}}) {
t.Fatalf("hostnames, got %v, expected single mox.example", l) t.Fatalf("hostnames, got %v, expected single mox.example", l)
@ -79,7 +79,7 @@ func TestAutotls(t *testing.T) {
t.Fatalf("private key changed after reload") t.Fatalf("private key changed after reload")
} }
m.shutdown = make(chan struct{}) m.shutdown = make(chan struct{})
m.SetAllowedHostnames(dns.StrictResolver{}, map[dns.Domain]struct{}{{ASCII: "mox.example"}: {}}, nil) m.SetAllowedHostnames(dns.StrictResolver{}, map[dns.Domain]struct{}{{ASCII: "mox.example"}: {}}, nil, false)
if err := m.HostPolicy(context.Background(), "mox.example"); err != nil { if err := m.HostPolicy(context.Background(), "mox.example"); err != nil {
t.Fatalf("hostpolicy, got err %v, expected no error", err) t.Fatalf("hostpolicy, got err %v, expected no error", err)
} }

View file

@ -130,7 +130,7 @@ func TestDSN(t *testing.T) {
// Test for valid DKIM signature. // Test for valid DKIM signature.
mox.Context = context.Background() mox.Context = context.Background()
mox.ConfigStaticPath = "../testdata/dsn/mox.conf" mox.ConfigStaticPath = "../testdata/dsn/mox.conf"
mox.MustLoadConfig() mox.MustLoadConfig(false)
msgbuf, err = m.Compose(log, false) msgbuf, err = m.Compose(log, false)
if err != nil { if err != nil {
t.Fatalf("composing utf-8 dsn with utf-8 support: %v", err) t.Fatalf("composing utf-8 dsn with utf-8 support: %v", err)

View file

@ -33,7 +33,7 @@ func TestAccount(t *testing.T) {
os.RemoveAll("../testdata/httpaccount/data") os.RemoveAll("../testdata/httpaccount/data")
mox.ConfigStaticPath = "../testdata/httpaccount/mox.conf" mox.ConfigStaticPath = "../testdata/httpaccount/mox.conf"
mox.ConfigDynamicPath = filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf") mox.ConfigDynamicPath = filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf")
mox.MustLoadConfig() mox.MustLoadConfig(false)
acc, err := store.OpenAccount("mjl") acc, err := store.OpenAccount("mjl")
tcheck(t, err, "open account") tcheck(t, err, "open account")
defer acc.Close() defer acc.Close()

View file

@ -17,7 +17,7 @@ func TestServeHTTP(t *testing.T) {
os.RemoveAll("../testdata/web/data") os.RemoveAll("../testdata/web/data")
mox.ConfigStaticPath = "../testdata/web/mox.conf" mox.ConfigStaticPath = "../testdata/web/mox.conf"
mox.ConfigDynamicPath = filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf") mox.ConfigDynamicPath = filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf")
mox.MustLoadConfig() mox.MustLoadConfig(false)
srv := &serve{ srv := &serve{
PathHandlers: []pathHandler{ PathHandlers: []pathHandler{

View file

@ -17,7 +17,7 @@ func TestWebserver(t *testing.T) {
os.RemoveAll("../testdata/webserver/data") os.RemoveAll("../testdata/webserver/data")
mox.ConfigStaticPath = "../testdata/webserver/mox.conf" mox.ConfigStaticPath = "../testdata/webserver/mox.conf"
mox.ConfigDynamicPath = filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf") mox.ConfigDynamicPath = filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf")
mox.MustLoadConfig() mox.MustLoadConfig(false)
srv := &serve{Webserver: true} srv := &serve{Webserver: true}

View file

@ -59,7 +59,7 @@ func FuzzServer(f *testing.F) {
mox.Context = context.Background() mox.Context = context.Background()
mox.ConfigStaticPath = "../testdata/imap/mox.conf" mox.ConfigStaticPath = "../testdata/imap/mox.conf"
mox.MustLoadConfig() mox.MustLoadConfig(false)
dataDir := mox.ConfigDirPath(mox.Conf.Static.DataDir) dataDir := mox.ConfigDirPath(mox.Conf.Static.DataDir)
os.RemoveAll(dataDir) os.RemoveAll(dataDir)
acc, err := store.OpenAccount("mjl") acc, err := store.OpenAccount("mjl")

View file

@ -310,7 +310,7 @@ func startArgs(t *testing.T, first, isTLS, allowLoginWithoutTLS bool) *testconn
} }
mox.Context = context.Background() mox.Context = context.Background()
mox.ConfigStaticPath = "../testdata/imap/mox.conf" mox.ConfigStaticPath = "../testdata/imap/mox.conf"
mox.MustLoadConfig() mox.MustLoadConfig(false)
acc, err := store.OpenAccount("mjl") acc, err := store.OpenAccount("mjl")
tcheck(t, err, "open account") tcheck(t, err, "open account")
if first { if first {

View file

@ -53,7 +53,7 @@ func TestDeliver(t *testing.T) {
// Load mox config. // Load mox config.
mox.ConfigStaticPath = "testdata/integration/config/mox.conf" mox.ConfigStaticPath = "testdata/integration/config/mox.conf"
filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf") filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf")
if errs := mox.LoadConfig(mox.Context); len(errs) > 0 { if errs := mox.LoadConfig(mox.Context, false); len(errs) > 0 {
t.Fatalf("loading mox config: %v", errs) t.Fatalf("loading mox config: %v", errs)
} }

View file

@ -355,7 +355,7 @@ var loglevel string
// restores any loglevel specified on the command-line, instead of using the // restores any loglevel specified on the command-line, instead of using the
// loglevels from the config file. // loglevels from the config file.
func mustLoadConfig() { func mustLoadConfig() {
mox.MustLoadConfig() mox.MustLoadConfig(false)
if level, ok := mlog.Levels[loglevel]; ok && loglevel != "" { if level, ok := mlog.Levels[loglevel]; ok && loglevel != "" {
mox.Conf.Log[""] = level mox.Conf.Log[""] = level
mlog.SetConfig(mox.Conf.Log) mlog.SetConfig(mox.Conf.Log)
@ -478,7 +478,7 @@ are printed.
c.Usage() c.Usage()
} }
_, errs := mox.ParseConfig(context.Background(), mox.ConfigStaticPath, true, false) _, errs := mox.ParseConfig(context.Background(), mox.ConfigStaticPath, true, false, false)
if len(errs) > 1 { if len(errs) > 1 {
log.Printf("multiple errors:") log.Printf("multiple errors:")
for _, err := range errs { for _, err := range errs {

View file

@ -139,7 +139,7 @@ func (c *Config) loadDynamic() []error {
c.Dynamic = d c.Dynamic = d
c.dynamicMtime = mtime c.dynamicMtime = mtime
c.accountDestinations = accDests c.accountDestinations = accDests
c.allowACMEHosts() c.allowACMEHosts(true)
return nil return nil
} }
@ -206,7 +206,7 @@ func (c *Config) WebServer() (r map[dns.Domain]dns.Domain, l []config.WebHandler
return r, l return r, l
} }
func (c *Config) allowACMEHosts() { func (c *Config) allowACMEHosts(checkACMEHosts bool) {
for _, l := range c.Static.Listeners { for _, l := range c.Static.Listeners {
if l.TLS == nil || l.TLS.ACME == "" { if l.TLS == nil || l.TLS.ACME == "" {
continue continue
@ -248,7 +248,7 @@ func (c *Config) allowACMEHosts() {
} }
} }
m.SetAllowedHostnames(dns.StrictResolver{Pkg: "autotls"}, hostnames, c.Static.Listeners["public"].IPs) m.SetAllowedHostnames(dns.StrictResolver{Pkg: "autotls"}, hostnames, c.Static.Listeners["public"].IPs, checkACMEHosts)
} }
} }
@ -305,17 +305,17 @@ func writeDynamic(ctx context.Context, log *mlog.Log, c config.Dynamic) error {
Conf.Dynamic = c Conf.Dynamic = c
Conf.accountDestinations = accDests Conf.accountDestinations = accDests
Conf.allowACMEHosts() Conf.allowACMEHosts(true)
return nil return nil
} }
// MustLoadConfig loads the config, quitting on errors. // MustLoadConfig loads the config, quitting on errors.
func MustLoadConfig() { func MustLoadConfig(checkACMEHosts bool) {
Shutdown, ShutdownCancel = context.WithCancel(context.Background()) Shutdown, ShutdownCancel = context.WithCancel(context.Background())
Context, ContextCancel = context.WithCancel(context.Background()) Context, ContextCancel = context.WithCancel(context.Background())
errs := LoadConfig(context.Background()) errs := LoadConfig(context.Background(), checkACMEHosts)
if len(errs) > 1 { if len(errs) > 1 {
xlog.Error("loading config file: multiple errors") xlog.Error("loading config file: multiple errors")
for _, err := range errs { for _, err := range errs {
@ -329,8 +329,8 @@ func MustLoadConfig() {
// LoadConfig attempts to parse and load a config, returning any errors // LoadConfig attempts to parse and load a config, returning any errors
// encountered. // encountered.
func LoadConfig(ctx context.Context) []error { func LoadConfig(ctx context.Context, checkACMEHosts bool) []error {
c, errs := ParseConfig(ctx, ConfigStaticPath, false, false) c, errs := ParseConfig(ctx, ConfigStaticPath, false, false, checkACMEHosts)
if len(errs) > 0 { if len(errs) > 0 {
return errs return errs
} }
@ -350,7 +350,9 @@ func SetConfig(c *Config) {
// are made, such as registering ACME identities. If skipCheckTLSKeyCerts is true, // are made, such as registering ACME identities. If skipCheckTLSKeyCerts is true,
// the TLS KeyCerts configuration is not checked. This is used during the // the TLS KeyCerts configuration is not checked. This is used during the
// quickstart in the case the user is going to provide their own certificates. // quickstart in the case the user is going to provide their own certificates.
func ParseConfig(ctx context.Context, p string, checkOnly, skipCheckTLSKeyCerts bool) (c *Config, errs []error) { // If checkACMEHosts is true, the hosts allowed for acme are compared with the
// explicitly configured ips we are listening on.
func ParseConfig(ctx context.Context, p string, checkOnly, skipCheckTLSKeyCerts, checkACMEHosts bool) (c *Config, errs []error) {
c = &Config{ c = &Config{
Static: config.Static{ Static: config.Static{
DataDir: ".", DataDir: ".",
@ -377,7 +379,7 @@ func ParseConfig(ctx context.Context, p string, checkOnly, skipCheckTLSKeyCerts
c.Dynamic, c.dynamicMtime, c.accountDestinations, errs = ParseDynamicConfig(ctx, pp, c.Static) c.Dynamic, c.dynamicMtime, c.accountDestinations, errs = ParseDynamicConfig(ctx, pp, c.Static)
if !checkOnly { if !checkOnly {
c.allowACMEHosts() c.allowACMEHosts(checkACMEHosts)
} }
return c, errs return c, errs

View file

@ -33,7 +33,7 @@ func setup(t *testing.T) (*store.Account, func()) {
os.RemoveAll("../testdata/queue/data") os.RemoveAll("../testdata/queue/data")
mox.Context = context.Background() mox.Context = context.Background()
mox.ConfigStaticPath = "../testdata/queue/mox.conf" mox.ConfigStaticPath = "../testdata/queue/mox.conf"
mox.MustLoadConfig() mox.MustLoadConfig(false)
acc, err := store.OpenAccount("mjl") acc, err := store.OpenAccount("mjl")
tcheck(t, err, "open account") tcheck(t, err, "open account")
err = acc.SetPassword("testtest") err = acc.SetPassword("testtest")

View file

@ -616,7 +616,7 @@ listed in more DNS block lists, visit:
// Verify config. // Verify config.
skipCheckTLSKeyCerts := existingWebserver skipCheckTLSKeyCerts := existingWebserver
mc, errs := mox.ParseConfig(context.Background(), "config/mox.conf", true, skipCheckTLSKeyCerts) mc, errs := mox.ParseConfig(context.Background(), "config/mox.conf", true, skipCheckTLSKeyCerts, false)
if len(errs) > 0 { if len(errs) > 0 {
if len(errs) > 1 { if len(errs) > 1 {
log.Printf("checking generated config, multiple errors:") log.Printf("checking generated config, multiple errors:")

View file

@ -145,7 +145,8 @@ requested, other TLS certificates are requested on demand.
mox.Conf.Log[""] = mlog.LevelDebug mox.Conf.Log[""] = mlog.LevelDebug
mlog.SetConfig(mox.Conf.Log) mlog.SetConfig(mox.Conf.Log)
mox.MustLoadConfig() checkACMEHosts := os.Getuid() != 0
mox.MustLoadConfig(checkACMEHosts)
log := mlog.New("serve") log := mlog.New("serve")

View file

@ -32,7 +32,7 @@ func FuzzServer(f *testing.F) {
mox.Context = context.Background() mox.Context = context.Background()
mox.ConfigStaticPath = "../testdata/smtp/mox.conf" mox.ConfigStaticPath = "../testdata/smtp/mox.conf"
mox.MustLoadConfig() mox.MustLoadConfig(false)
dataDir := mox.ConfigDirPath(mox.Conf.Static.DataDir) dataDir := mox.ConfigDirPath(mox.Conf.Static.DataDir)
os.RemoveAll(dataDir) os.RemoveAll(dataDir)
acc, err := store.OpenAccount("mjl") acc, err := store.OpenAccount("mjl")

View file

@ -87,7 +87,7 @@ func newTestServer(t *testing.T, configPath string, resolver dns.Resolver) *test
mox.Context = context.Background() mox.Context = context.Background()
mox.ConfigStaticPath = configPath mox.ConfigStaticPath = configPath
mox.MustLoadConfig() mox.MustLoadConfig(false)
dataDir := mox.ConfigDirPath(mox.Conf.Static.DataDir) dataDir := mox.ConfigDirPath(mox.Conf.Static.DataDir)
os.RemoveAll(dataDir) os.RemoveAll(dataDir)
var err error var err error

View file

@ -26,7 +26,7 @@ func tcheck(t *testing.T, err error, msg string) {
func TestMailbox(t *testing.T) { func TestMailbox(t *testing.T) {
os.RemoveAll("../testdata/store/data") os.RemoveAll("../testdata/store/data")
mox.ConfigStaticPath = "../testdata/store/mox.conf" mox.ConfigStaticPath = "../testdata/store/mox.conf"
mox.MustLoadConfig() mox.MustLoadConfig(false)
acc, err := OpenAccount("mjl") acc, err := OpenAccount("mjl")
tcheck(t, err, "open account") tcheck(t, err, "open account")
defer acc.Close() defer acc.Close()

View file

@ -21,7 +21,7 @@ func TestExport(t *testing.T) {
os.RemoveAll("../testdata/store/data") os.RemoveAll("../testdata/store/data")
mox.ConfigStaticPath = "../testdata/store/mox.conf" mox.ConfigStaticPath = "../testdata/store/mox.conf"
mox.MustLoadConfig() mox.MustLoadConfig(false)
acc, err := OpenAccount("mjl") acc, err := OpenAccount("mjl")
tcheck(t, err, "open account") tcheck(t, err, "open account")
defer acc.Close() defer acc.Close()