From 493fae62b9dcfa025cc7c61d1974e2cb7ed4b292 Mon Sep 17 00:00:00 2001 From: Bas van der Vlies Date: Mon, 30 Mar 2026 15:13:31 +0200 Subject: [PATCH 1/5] CFE-4648: cf-execd SMTP port configurable CFE-4648: cf-execd SMTP port configurable --- cf-execd/cf-execd-runner.c | 9 +-------- cf-execd/exec-config.c | 6 ++++++ cf-execd/exec-config.h | 1 + libpromises/cf3.defs.h | 1 + libpromises/mod_common.c | 1 + tests/unit/exec-config-test.c | 2 ++ 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cf-execd/cf-execd-runner.c b/cf-execd/cf-execd-runner.c index 75b7ebcc5d..fc36d421d0 100644 --- a/cf-execd/cf-execd-runner.c +++ b/cf-execd/cf-execd-runner.c @@ -572,17 +572,10 @@ int ConnectToSmtpSocket(const ExecConfig *config) return -1; } - struct servent *server = getservbyname("smtp", "tcp"); - if (!server) - { - Log(LOG_LEVEL_ERR, "Mail report: unable to lookup smtp service. (getservbyname: %s)", GetErrorStr()); - return -1; - } - struct sockaddr_in raddr; memset(&raddr, 0, sizeof(raddr)); - raddr.sin_port = (unsigned int) server->s_port; + raddr.sin_port = config->mail_port; raddr.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr; raddr.sin_family = AF_INET; diff --git a/cf-execd/exec-config.c b/cf-execd/exec-config.c index 433b48a08e..8a2b93e6d5 100644 --- a/cf-execd/exec-config.c +++ b/cf-execd/exec-config.c @@ -138,6 +138,7 @@ ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Poli exec_config->agent_expireafter = 2 * 60; /* two hours */ exec_config->mail_server = xstrdup(""); + exec_config->mail_port = 25; exec_config->mail_from_address = xstrdup(""); exec_config->mail_to_address = xstrdup(""); exec_config->mail_subject = xstrdup(""); @@ -199,6 +200,11 @@ ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Poli exec_config->mail_server = xstrdup(value); Log(LOG_LEVEL_DEBUG, "smtpserver '%s'", exec_config->mail_server); } + else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SMTPPORT].lval) == 0) + { + exec_config->mail_port = IntFromString(value); + Log(LOG_LEVEL_DEBUG, "smtpport '%d'", exec_config->mail_port); + } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_EXECCOMMAND].lval) == 0) { free(exec_config->exec_command); diff --git a/cf-execd/exec-config.h b/cf-execd/exec-config.h index 5d7f3769fd..74c118a9d3 100644 --- a/cf-execd/exec-config.h +++ b/cf-execd/exec-config.h @@ -40,6 +40,7 @@ typedef struct char *mail_to_address; char *mail_subject; int mail_max_lines; + unsigned int mail_port; // These two contain regular expression strings. Seq *mailfilter_include; Seq *mailfilter_exclude; diff --git a/libpromises/cf3.defs.h b/libpromises/cf3.defs.h index fe02dba7c3..71ca9f7f3b 100644 --- a/libpromises/cf3.defs.h +++ b/libpromises/cf3.defs.h @@ -515,6 +515,7 @@ typedef enum EXEC_CONTROL_EXECCOMMAND, EXEC_CONTROL_AGENT_EXPIREAFTER, EXEC_CONTROL_RUNAGENT_ALLOW_USERS, + EXEC_CONTROL_SMTPPORT, EXEC_CONTROL_NONE } ExecControl; diff --git a/libpromises/mod_common.c b/libpromises/mod_common.c index 17e0485b5e..3d41cd4270 100644 --- a/libpromises/mod_common.c +++ b/libpromises/mod_common.c @@ -394,6 +394,7 @@ const ConstraintSyntax CFEX_CONTROLBODY[] = /* enum cfexcontrol */ ConstraintSyntaxNewString("exec_command", CF_ABSPATHRANGE,"The full path and command to the executable run by default (overriding builtin)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("agent_expireafter", "0,10080", "Maximum agent runtime (in minutes). Default value: 120", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("runagent_socket_allow_users", "", "Users allowed to work with the runagent.socket to trigger agent runs", SYNTAX_STATUS_NORMAL), + ConstraintSyntaxNewInt("smtpport", "0,10080", "Port used for sending mail", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; diff --git a/tests/unit/exec-config-test.c b/tests/unit/exec-config-test.c index 8e4de9662c..0bb662ef49 100644 --- a/tests/unit/exec-config-test.c +++ b/tests/unit/exec-config-test.c @@ -101,6 +101,7 @@ static void exec_config_empty_cb(const EvalContext *ctx, const Policy *policy) /* FIXME: exec-config should provide default subject */ assert_string_equal("", config->mail_subject); assert_int_equal(30, config->mail_max_lines); + assert_int_equal(25, config->mail_port); assert_string_equal("localhost.localdomain", config->fq_name); assert_string_equal("127.0.0.100", config->ip_address); assert_string_equal("127.0.0.100 127.0.0.101", config->ip_addresses); @@ -123,6 +124,7 @@ static void CheckFullExecConfig(const ExecConfig *config) assert_string_equal("cfengine_mail@example.org", config->mail_to_address); assert_string_equal("Test [localhost/127.0.0.1]", config->mail_subject); assert_int_equal(50, config->mail_max_lines); + assert_int_equal(25, config->mail_port); assert_string_equal("localhost.localdomain", config->fq_name); assert_string_equal("127.0.0.100", config->ip_address); assert_string_equal("127.0.0.100 127.0.0.101", config->ip_addresses); From 613df5dec842b7f544e1627defb9b9ae395e1c3d Mon Sep 17 00:00:00 2001 From: Bas van der Vlies Date: Mon, 30 Mar 2026 17:38:35 +0200 Subject: [PATCH 2/5] forgot one statement --- cf-execd/exec-config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cf-execd/exec-config.c b/cf-execd/exec-config.c index 8a2b93e6d5..995602b42f 100644 --- a/cf-execd/exec-config.c +++ b/cf-execd/exec-config.c @@ -249,6 +249,7 @@ ExecConfig *ExecConfigCopy(const ExecConfig *config) copy->exec_command = xstrdup(config->exec_command); copy->agent_expireafter = config->agent_expireafter; copy->mail_server = xstrdup(config->mail_server); + copy->mail_port = config->mail_port; copy->mail_from_address = xstrdup(config->mail_from_address); copy->mail_to_address = xstrdup(config->mail_to_address); copy->mail_subject = xstrdup(config->mail_subject); From cffe3dff8821caed9c5c2b47f0faf182b455a34f Mon Sep 17 00:00:00 2001 From: Bas van der Vlies Date: Tue, 31 Mar 2026 13:57:02 +0200 Subject: [PATCH 3/5] silence warning --- cf-execd/cf-execd-runner.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cf-execd/cf-execd-runner.c b/cf-execd/cf-execd-runner.c index fc36d421d0..bf14a1cbe4 100644 --- a/cf-execd/cf-execd-runner.c +++ b/cf-execd/cf-execd-runner.c @@ -564,6 +564,7 @@ static bool CompareResultEqualOrFiltered(const ExecConfig *config, #ifndef TEST_CF_EXECD int ConnectToSmtpSocket(const ExecConfig *config) { + assert(config != NULL); struct hostent *hp = gethostbyname(config->mail_server); if (!hp) { From 26e0eef30ce032d8df74d800d82de341510ed94c Mon Sep 17 00:00:00 2001 From: Bas van der Vlies Date: Tue, 31 Mar 2026 14:31:40 +0200 Subject: [PATCH 4/5] silence warningi 2 --- cf-execd/exec-config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cf-execd/exec-config.c b/cf-execd/exec-config.c index 995602b42f..dd9529cc9f 100644 --- a/cf-execd/exec-config.c +++ b/cf-execd/exec-config.c @@ -243,6 +243,7 @@ ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Poli ExecConfig *ExecConfigCopy(const ExecConfig *config) { + assert(config != NULL); ExecConfig *copy = xcalloc(1, sizeof(ExecConfig)); copy->scheduled_run = config->scheduled_run; From 3096540b77563e916c5c6f777c67216fbe462c53 Mon Sep 17 00:00:00 2001 From: Bas van der Vlies Date: Tue, 31 Mar 2026 22:55:54 +0200 Subject: [PATCH 5/5] getservbyname is the default value, fallback to 25 --- cf-execd/exec-config.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cf-execd/exec-config.c b/cf-execd/exec-config.c index dd9529cc9f..31d7381d8f 100644 --- a/cf-execd/exec-config.c +++ b/cf-execd/exec-config.c @@ -138,7 +138,6 @@ ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Poli exec_config->agent_expireafter = 2 * 60; /* two hours */ exec_config->mail_server = xstrdup(""); - exec_config->mail_port = 25; exec_config->mail_from_address = xstrdup(""); exec_config->mail_to_address = xstrdup(""); exec_config->mail_subject = xstrdup(""); @@ -152,6 +151,17 @@ ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Poli exec_config->ip_address = xstrdup(VIPADDRESS); exec_config->ip_addresses = GetIpAddresses(ctx); + struct servent *server = getservbyname("smtp", "tcp"); + if (!server) + { + exec_config->mail_port = 25; + } + else + { + exec_config->mail_port = (unsigned int) server->s_port; + } + + Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_EXECUTOR); if (constraints) {