mirror of
https://github.com/mjl-/mox.git
synced 2024-12-27 08:53:48 +03:00
only check the autotls hostnames once when serving
not twice: for root process and for child process
This commit is contained in:
parent
1bee32679a
commit
b2e6c29849
18 changed files with 34 additions and 30 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
main.go
4
main.go
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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:")
|
||||||
|
|
3
serve.go
3
serve.go
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue