From d90e3b30a9b8b8bd1f7a5226a2c0756032377476 Mon Sep 17 00:00:00 2001 From: "Michael T. Babcock" Date: Wed, 3 Feb 2021 14:36:01 -0500 Subject: [PATCH 1/5] Added basic systemd watchdog support --- configure.ac | 27 +++++++++++++++++++++++++++ src/Makefile.am | 2 +- src/send.cc | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index aec9978..9b7fbf3 100644 --- a/configure.ac +++ b/configure.ac @@ -86,5 +86,32 @@ if $tls; then [AC_DEFINE(HAVE_GNUTLS_PRIORITY_SET_DIRECT, 1, [libgnutls has gnutls_priority_set_direct])]) fi +AC_ARG_ENABLE(systemd, + AS_HELP_STRING( + [--enable-systemd], + [build with systemd watchdog support]), + enable_systemd=$enableval,enable_systemd=auto) + +dnl systemd detection +if test x$enable_systemd = xno ; then + have_systemd=no; +else + PKG_CHECK_MODULES([SYSTEMD], + [libsystemd >= 209], + [have_systemd=yes], + [PKG_CHECK_MODULES([SYSTEMD], + [libsystemd-daemon >= 32], + [have_systemd=yes], + [have_systemd=no])]) +fi + +if test x$have_systemd = xyes; then + AC_DEFINE(HAVE_SYSTEMD,1,[Have systemd]) +fi + +if test x$enable_systemd = xyes -a x$have_systemd != xyes ; then + AC_MSG_ERROR([Explicitly requested systemd support, but systemd not found]) +fi + AC_CONFIG_FILES([Makefile doc/Makefile lib/Makefile lib/cli++/Makefile lib/fdbuf/Makefile lib/mystring/Makefile protocols/Makefile src/Makefile test/Makefile]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 4a742c2..a70078c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,7 +25,7 @@ nullmailer_queue_SOURCES = queue.cc nullmailer_queue_LDADD = ../lib/libnullmailer.a ../lib/cli++/libcli++.a nullmailer_send_SOURCES = send.cc -nullmailer_send_LDADD = ../lib/libnullmailer.a ../lib/cli++/libcli++.a +nullmailer_send_LDADD = ../lib/libnullmailer.a ../lib/cli++/libcli++.a $(SYSTEMD_LIBS) nullmailer_smtpd_SOURCES = smtpd.cc nullmailer_smtpd_LDADD = ../lib/libnullmailer.a diff --git a/src/send.cc b/src/send.cc index 95f8400..e56663e 100644 --- a/src/send.cc +++ b/src/send.cc @@ -44,6 +44,11 @@ #include "list.h" #include "selfpipe.h" #include "setenv.h" +#ifdef HAVE_SYSTEMD +#include +#endif + +#define MICROSECOND 1000000 const char* cli_program = "nullmailer-send"; @@ -71,6 +76,12 @@ typedef list msglist; static mystring trigger_path; static mystring msg_dir; +#ifdef HAVE_SYSTEMD +#define MAXPAUSE_DEFAULT 9*60 +#else +#define MAXPAUSE_DEFAULT 24*60*60 +#endif + struct remote { static const mystring default_proto; @@ -115,8 +126,8 @@ typedef list rlist; static rlist remotes; static int minpause = 60; static int pausetime = minpause; -static int maxpause = 24*60*60; -static int sendtimeout = 60*60; +static int maxpause = MAXPAUSE_DEFAULT; +static int sendtimeout = 5*60; // reduced from 60*60 static int queuelifetime = 7*24*60*60; bool load_remotes() @@ -149,7 +160,7 @@ bool load_config() if(!config_readint("pausetime", minpause)) minpause = 60; if(!config_readint("maxpause", maxpause)) - maxpause = 24*60*60; + maxpause = MAXPAUSE_DEFAULT; if(!config_readint("sendtimeout", sendtimeout)) sendtimeout = 60*60; if(!config_readint("queuelifetime", queuelifetime)) @@ -375,6 +386,18 @@ bool bounce_msg(const message& msg, const remote& remote, const mystring& output return true; } +#ifdef HAVE_SYSTEMD +void systemd_notify_ready() +{ + sd_notify(0, "READY=1"); +} + +void systemd_notify_heartbeat() +{ + sd_notify(0, "WATCHDOG=1"); +} +#endif + void send_all() { if(!load_config()) { @@ -468,6 +491,10 @@ bool do_select() if (pausetime > maxpause) pausetime = maxpause; +#ifdef HAVE_SYSTEMD + systemd_notify_heartbeat(); +#endif + int s = select(trigger+1, &readfds, 0, 0, &timeout); if(s == 1) { fout << "Trigger pulled." << endl; @@ -508,6 +535,9 @@ int main(int, char*[]) signal(SIGHUP, SIG_IGN); load_config(); load_messages(); +#ifdef HAVE_SYSTEMD + systemd_notify_ready(); +#endif for(;;) { send_all(); if (minpause == 0) break; From 7f572927a280bda554c7fca6f0335f777e778a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 3 Mar 2022 18:46:34 +0100 Subject: [PATCH 2/5] Add "AUTH EXTERNAL" option for certificate authentication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork --- doc/nullmailer-send.8 | 3 +++ protocols/protocol.cc | 2 ++ protocols/protocol.h | 1 + protocols/smtp.cc | 9 ++++++++- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/nullmailer-send.8 b/doc/nullmailer-send.8 index 34e5f96..85b705c 100644 --- a/doc/nullmailer-send.8 +++ b/doc/nullmailer-send.8 @@ -137,6 +137,9 @@ Set the source address for connections to the remote host. .B auth-login Force SMTP "AUTH LOGIN" mode instead of auto-detecting. .TP +.B auth-external +Use SMTP "AUTH EXTERNAL" for TLS client certificate authentication. +.TP .B tls Connect using TLS. This will automatically switch the default port to diff --git a/protocols/protocol.cc b/protocols/protocol.cc index 6c43d55..edf9cfc 100644 --- a/protocols/protocol.cc +++ b/protocols/protocol.cc @@ -55,6 +55,8 @@ cli_option cli_options[] = { { 0, "source", cli_option::string, 0, &source, "Source address for connections", 0 }, #ifdef HAVE_TLS + { 0, "auth-external", cli_option::flag, AUTH_EXTERNAL, &auth_method, + "Use AUTH EXTERNAL for certificate based authentication", 0 }, { 0, "tls", cli_option::flag, 1, &use_tls, "Connect using TLS (on an alternate port by default)", 0 }, { 0, "ssl", cli_option::flag, 1, &use_tls, diff --git a/protocols/protocol.h b/protocols/protocol.h index 2b1c9f6..1a13e0a 100644 --- a/protocols/protocol.h +++ b/protocols/protocol.h @@ -13,6 +13,7 @@ extern void protocol_succ(const char* msg); #define AUTH_DETECT 0 #define AUTH_LOGIN 1 #define AUTH_PLAIN 2 +#define AUTH_EXTERNAL 3 extern const char* user; extern const char* pass; extern int auth_method; diff --git a/protocols/smtp.cc b/protocols/smtp.cc index de6be32..00f076e 100644 --- a/protocols/smtp.cc +++ b/protocols/smtp.cc @@ -231,7 +231,14 @@ void protocol_send(fdibuf& in, fdibuf& netin, fdobuf& netout) if (!did_starttls) conn.docmd("", 200); - if (user != 0 && pass != 0) { + if (auth_method == AUTH_EXTERNAL) { + conn.dohelo(true); + if (conn.hascap("AUTH", "EXTERNAL")) + conn.docmd("AUTH EXTERNAL =", 200, ERR_AUTH_FAILED); + else + protocol_fail(ERR_MSG_TEMPFAIL, "Server does not advertise certificate authentication"); + } + else if (user != 0 && pass != 0) { conn.dohelo(true); if (auth_method == AUTH_LOGIN) conn.auth_login(); From 13586e65c11c6b406a70e1987bc56a543bd5282e Mon Sep 17 00:00:00 2001 From: "Michael T. Babcock" Date: Fri, 22 Jul 2022 12:38:45 -0400 Subject: [PATCH 3/5] Minor systemd related fixes --- src/send.cc | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/send.cc b/src/send.cc index e56663e..450458e 100644 --- a/src/send.cc +++ b/src/send.cc @@ -50,6 +50,12 @@ #define MICROSECOND 1000000 +#ifdef HAVE_SYSTEMD +#define MAXPAUSE_DEFAULT 9*60 +#else +#define MAXPAUSE_DEFAULT 24*60*60 +#endif + const char* cli_program = "nullmailer-send"; selfpipe selfpipe; @@ -77,9 +83,8 @@ static mystring trigger_path; static mystring msg_dir; #ifdef HAVE_SYSTEMD -#define MAXPAUSE_DEFAULT 9*60 -#else -#define MAXPAUSE_DEFAULT 24*60*60 +static int watchdog_enabled = 0; +static uint64_t watchdog_timeout = 0; #endif struct remote @@ -387,16 +392,36 @@ bool bounce_msg(const message& msg, const remote& remote, const mystring& output } #ifdef HAVE_SYSTEMD +/* update maxpause so select will return before we need to send our next notification + maxpause is in seconds, watchdog_timeout is microseconds */ +int get_maxpause() +{ + int new_maxpause = (watchdog_timeout/(2*MICROSECOND)); + if (new_maxpause < 1) { + fout << "systemd watchdog timeout is too short, disabling" << endl; + watchdog_enabled = false; + return maxpause; + } + return new_maxpause; +} + void systemd_notify_ready() { - sd_notify(0, "READY=1"); + watchdog_enabled = sd_watchdog_enabled(0, &watchdog_timeout); + if (watchdog_enabled) { + fout << "systemd watchdog enabled every " << (int)(watchdog_timeout/MICROSECOND) << " seconds" << endl; + sd_notify(0, "READY=1"); + maxpause = get_maxpause(); + } } void systemd_notify_heartbeat() { - sd_notify(0, "WATCHDOG=1"); + if (watchdog_enabled) { + sd_notify(0, "WATCHDOG=1"); + } } -#endif +#endif // HAVE_SYSTEMD void send_all() { @@ -418,6 +443,7 @@ void send_all() while(msg) { switch (send_one((*msg).filename, *remote, output)) { case tempfail: + systemd_notify_heartbeat(); if (time(0) - (*msg).timestamp > queuelifetime) { if (bounce_msg(*msg, *remote, output)) { messages.remove(msg); From b5f57d5407a88eacee26121ae5ecd63bddfa8a5d Mon Sep 17 00:00:00 2001 From: "Michael T. Babcock" Date: Fri, 22 Jul 2022 13:02:32 -0400 Subject: [PATCH 4/5] Simplify #ifdef --- src/send.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/send.cc b/src/send.cc index 450458e..0946396 100644 --- a/src/send.cc +++ b/src/send.cc @@ -44,18 +44,17 @@ #include "list.h" #include "selfpipe.h" #include "setenv.h" + #ifdef HAVE_SYSTEMD #include -#endif - -#define MICROSECOND 1000000 -#ifdef HAVE_SYSTEMD #define MAXPAUSE_DEFAULT 9*60 #else #define MAXPAUSE_DEFAULT 24*60*60 #endif +#define MICROSECOND 1000000 + const char* cli_program = "nullmailer-send"; selfpipe selfpipe; From 3da38f95a7df820a1259eb814d0db324309170f6 Mon Sep 17 00:00:00 2001 From: "Michael T. Babcock" Date: Mon, 25 Jul 2022 12:25:48 -0400 Subject: [PATCH 5/5] Revert "Add "AUTH EXTERNAL" option for certificate authentication" This reverts commit 7f572927a280bda554c7fca6f0335f777e778a91. --- doc/nullmailer-send.8 | 3 --- protocols/protocol.cc | 2 -- protocols/protocol.h | 1 - protocols/smtp.cc | 9 +-------- 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/doc/nullmailer-send.8 b/doc/nullmailer-send.8 index 85b705c..34e5f96 100644 --- a/doc/nullmailer-send.8 +++ b/doc/nullmailer-send.8 @@ -137,9 +137,6 @@ Set the source address for connections to the remote host. .B auth-login Force SMTP "AUTH LOGIN" mode instead of auto-detecting. .TP -.B auth-external -Use SMTP "AUTH EXTERNAL" for TLS client certificate authentication. -.TP .B tls Connect using TLS. This will automatically switch the default port to diff --git a/protocols/protocol.cc b/protocols/protocol.cc index edf9cfc..6c43d55 100644 --- a/protocols/protocol.cc +++ b/protocols/protocol.cc @@ -55,8 +55,6 @@ cli_option cli_options[] = { { 0, "source", cli_option::string, 0, &source, "Source address for connections", 0 }, #ifdef HAVE_TLS - { 0, "auth-external", cli_option::flag, AUTH_EXTERNAL, &auth_method, - "Use AUTH EXTERNAL for certificate based authentication", 0 }, { 0, "tls", cli_option::flag, 1, &use_tls, "Connect using TLS (on an alternate port by default)", 0 }, { 0, "ssl", cli_option::flag, 1, &use_tls, diff --git a/protocols/protocol.h b/protocols/protocol.h index 1a13e0a..2b1c9f6 100644 --- a/protocols/protocol.h +++ b/protocols/protocol.h @@ -13,7 +13,6 @@ extern void protocol_succ(const char* msg); #define AUTH_DETECT 0 #define AUTH_LOGIN 1 #define AUTH_PLAIN 2 -#define AUTH_EXTERNAL 3 extern const char* user; extern const char* pass; extern int auth_method; diff --git a/protocols/smtp.cc b/protocols/smtp.cc index 00f076e..de6be32 100644 --- a/protocols/smtp.cc +++ b/protocols/smtp.cc @@ -231,14 +231,7 @@ void protocol_send(fdibuf& in, fdibuf& netin, fdobuf& netout) if (!did_starttls) conn.docmd("", 200); - if (auth_method == AUTH_EXTERNAL) { - conn.dohelo(true); - if (conn.hascap("AUTH", "EXTERNAL")) - conn.docmd("AUTH EXTERNAL =", 200, ERR_AUTH_FAILED); - else - protocol_fail(ERR_MSG_TEMPFAIL, "Server does not advertise certificate authentication"); - } - else if (user != 0 && pass != 0) { + if (user != 0 && pass != 0) { conn.dohelo(true); if (auth_method == AUTH_LOGIN) conn.auth_login();