From dbe4a73174ab34bea683d8b60cad2d5ae6b32bb0 Mon Sep 17 00:00:00 2001 From: Aine Date: Mon, 13 Feb 2023 11:58:31 +0200 Subject: [PATCH] make TLS reload thread-safe on TCP listener --- smtp/listener.go | 13 ++++++++++++- smtp/manager.go | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/smtp/listener.go b/smtp/listener.go index 6057956..ba870aa 100644 --- a/smtp/listener.go +++ b/smtp/listener.go @@ -3,6 +3,7 @@ package smtp import ( "crypto/tls" "net" + "sync" "gitlab.com/etke.cc/go/logger" ) @@ -12,6 +13,7 @@ type Listener struct { log *logger.Logger done chan struct{} tls *tls.Config + tlsMu sync.Mutex listener net.Listener isBanned func(net.Addr) bool } @@ -32,7 +34,9 @@ func NewListener(port string, tlsConfig *tls.Config, isBanned func(net.Addr) boo } func (l *Listener) SetTLSConfig(cfg *tls.Config) { + l.tlsMu.Lock() l.tls = cfg + l.tlsMu.Unlock() } // Accept waits for and returns the next connection to the listener. @@ -57,12 +61,19 @@ func (l *Listener) Accept() (net.Conn, error) { l.log.Info("accepted connection from %q", conn.RemoteAddr()) if l.tls != nil { - return tls.Server(conn, l.tls), nil + return l.acceptTLS(conn) } return conn, nil } } +func (l *Listener) acceptTLS(conn net.Conn) (net.Conn, error) { + l.tlsMu.Lock() + defer l.tlsMu.Unlock() + + return tls.Server(conn, l.tls), nil +} + // Close closes the listener. // Any blocked Accept operations will be unblocked and return errors. func (l *Listener) Close() error { diff --git a/smtp/manager.go b/smtp/manager.go index 0b63dc2..faed614 100644 --- a/smtp/manager.go +++ b/smtp/manager.go @@ -174,7 +174,7 @@ func (m *Manager) listen(port string, tlsConfig *tls.Config) { // loadTLSConfig returns true if certs were loaded and false if not func (m *Manager) loadTLSConfig() bool { - m.log.Debug("loading SSL certs...") + m.log.Info("(re)loading TLS config") if len(m.tls.Certs) == 0 || len(m.tls.Keys) == 0 { m.log.Warn("SSL certificates are not provided") return false