Add SMTP TLS and Authentication using libcurl#2195
Add SMTP TLS and Authentication using libcurl#2195atomicturtle wants to merge 4 commits intoossec:mainfrom
Conversation
Starting on rocky. Based on PR ossec#2158 by @cmac9203. Refactoring for make Signed-off-by: Scott R. Shinn <scott@atomicorp.com>
Enable authenticated and TLS SMTP for ossec-maild when built with USE_CURL=yes (off by default). Uses libcurl for SMTP AUTH (PLAIN/LOGIN) and TLS/STARTTLS; credentials and TLS are validated and sanitized. Security hardening: header/envelope CR/LF sanitization, hostname validation for smtp_server, timeouts, mandatory TLS when AUTH is on, post-parse credential validation, and secure clearing of password in config and at exit. CA bundle and chroot ossec-maild runs inside a chroot (e.g. /var/ossec). libcurl uses CURLOPT_SSL_VERIFYPEER=1 and by default looks for the system CA bundle (e.g. /etc/ssl/certs/ca-certificates.crt). After chroot, that path is not visible, so TLS verification fails (CURLE_PEER_FAILED_VERIFICATION) and mail is dropped unless the CA bundle is available inside the chroot. Installation (or the admin) must copy or symlink the system CA bundle into the chroot (e.g. <chroot>/etc/ssl/certs/ca-certificates.crt) and either set CURLOPT_CAINFO to that path in code or ensure the default path resolves inside the chroot. Do not disable VERIFYPEER. Original idea and initial implementation from alexbartlow via Allow TLS Email sends as a compile-time option ossec#1360 Credit: alexbartlow (PR ossec#1360) Signed-off-by: Scott R. Shinn <scott@atomicorp.com>
There was a problem hiding this comment.
Pull request overview
Adds an optional libcurl-based SMTP delivery path to ossec-maild (enabled only when building with USE_CURL=yes) to support SMTP AUTH and TLS/STARTTLS while running inside the project’s chrooted environment.
Changes:
- Introduces
USE_CURLbuild flag (USE_SMTP_CURL) and a new libcurl-based SMTP sender implementation. - Extends mail/global config parsing with
auth_smtp,secure_smtp,smtp_user,smtp_password, andsmtp_port, plus pre-resolution support for chroot. - Adds a new GitHub Actions multi-platform Make build workflow (Rocky + Windows cross-compile).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/os_maild/sendmail.c | Compiles out legacy SMTP/local sendmail implementation when USE_SMTP_CURL is set. |
| src/os_maild/maild.c | Adds SMTP secret clearing and pre-chroot hostname resolution for curl mode. |
| src/os_maild/curlmail.c | New libcurl-based SMTP sender (TLS + AUTH) behind USE_SMTP_CURL. |
| src/os_maild/config.c | Initializes new mail config fields and adds curl-gated validation for AUTH. |
| src/monitord/main.c | Adjusts how monitord reads/validates smtp_server when USE_SMTP_CURL is defined. |
| src/config/mail-config.h | Adds SMTP TLS/AUTH-related fields to MailConfig. |
| src/config/global-config.h | Adds authsmtp/securesmtp flags to global config struct. |
| src/config/global-config.c | Parses new SMTP TLS/AUTH-related XML elements and pre-resolves SMTP host in curl mode. |
| src/Makefile | Adds USE_CURL toggle to enable USE_SMTP_CURL and link with -lcurl. |
| .github/workflows/make-multi-platform.yml | New CI workflow for Rocky Linux container builds + Windows cross-compile. |
| .github/workflows/README.md | Documents the workflows. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Signed-off-by: Scott R. Shinn <scott@atomicorp.com>
There was a problem hiding this comment.
Pull request overview
Adds an optional (compile-time) libcurl-based SMTP delivery path for ossec-maild, enabling SMTP AUTH and TLS/STARTTLS when built with USE_CURL=yes, along with related config parsing and build/CI wiring.
Changes:
- Add new libcurl SMTP sender (
OS_Sendmail) supporting AUTH + TLS/STARTTLS and hostname/IP pre-resolution for chrooted operation. - Extend global/mail config parsing with
auth_smtp,secure_smtp,smtp_user,smtp_password, andsmtp_port. - Add
USE_CURLbuild switch (definesUSE_SMTP_CURL, links-lcurl) and introduce a multi-platform GitHub Actions build workflow.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/os_maild/sendmail.c | Excludes the legacy sendmail/plain SMTP implementation when USE_SMTP_CURL is enabled. |
| src/os_maild/maild.c | Initializes/cleans up libcurl and pre-resolves SMTP hostnames before chroot; clears credentials in child. |
| src/os_maild/curlmail.c | New libcurl-based SMTP implementation (TLS/AUTH, CRLF sanitization, timeouts, CURLOPT_RESOLVE). |
| src/os_maild/config.c | Initializes new MailConfig fields and enforces option validity depending on USE_SMTP_CURL. |
| src/monitord/main.c | Adjusts SMTP server validation/storage to preserve hostname for libcurl builds. |
| src/config/mail-config.h | Extends MailConfig with curl/TLS/auth fields and pre-resolved SMTP IP. |
| src/config/global-config.h | Extends global _Config with auth/TLS flags. |
| src/config/global-config.c | Parses new SMTP auth/TLS options; pre-resolves SMTP host for chroot when curl is enabled. |
| src/Makefile | Adds USE_CURL switch to enable USE_SMTP_CURL and link -lcurl. |
| .github/workflows/make-multi-platform.yml | New CI workflow to build on Rocky Linux container + cross-compile Windows agent. |
| .github/workflows/README.md | Documents the workflows. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| if (Mail->authsmtp && (!Mail->smtp_user || !Mail->smtp_pass)) { | ||
| merror("%s: auth_smtp=yes requires both smtp_user and smtp_password to be set.", ARGV0); | ||
| return (OS_INVALID); |
| if (!is_valid_smtp_host(mail->smtpserver)) { | ||
| merror("%s: Invalid smtp_server (hostname only, no path or invalid chars).", ARGV0); | ||
| return -1; | ||
| } | ||
|
|
||
| if (mail->authsmtp && (!mail->smtp_user || !mail->smtp_pass)) { | ||
| merror("%s: auth_smtp=yes requires smtp_user and smtp_password to be set.", ARGV0); | ||
| return -1; | ||
| } | ||
|
|
||
| /* Build URL: optional smtp_port overrides defaults (465/587/25 per mode) */ | ||
| { | ||
| int port = mail->smtp_port; | ||
| int n; | ||
| if (port <= 0 || port > 65535) { | ||
| if (mail->securesmtp) { | ||
| port = 465; | ||
| } else if (mail->authsmtp) { | ||
| port = 587; | ||
| } else { | ||
| port = 25; | ||
| } | ||
| } | ||
| if (mail->securesmtp) { | ||
| n = snprintf(url, sizeof(url), "smtps://%s:%d", mail->smtpserver, port); | ||
| } else { | ||
| n = snprintf(url, sizeof(url), "smtp://%s:%d", mail->smtpserver, port); | ||
| } |
| hostname[0] = '\0'; | ||
| if (gethostname(hostname, sizeof(hostname)) != 0) { | ||
| strncpy(hostname, "localhost", sizeof(hostname) - 1); | ||
| hostname[sizeof(hostname) - 1] = '\0'; | ||
| } else { | ||
| hostname[sizeof(hostname) - 1] = '\0'; | ||
| } | ||
| strftime(message_id, sizeof(message_id), "%Y%m%d%H%M%S.%z", p); | ||
| strftime(date_buf, sizeof(date_buf), "%a, %d %b %Y %T %z", p); | ||
|
|
||
| sanitize_header_value(msg->subject ? msg->subject : "", sanitized_subject, sizeof(sanitized_subject)); | ||
| sanitize_header_value(mail->from, sanitized_from, sizeof(sanitized_from)); | ||
| sanitize_header_value(mail->to[0], sanitized_to, sizeof(sanitized_to)); | ||
|
|
||
| body_len = msg->body ? strlen(msg->body) : 0; | ||
| { | ||
| int n = snprintf(header_buf, sizeof(header_buf), | ||
| "Date: %s\r\n" | ||
| "To: %s\r\n" | ||
| "From: %s\r\n" | ||
| "Message-ID: <%s@%s>\r\n" | ||
| "Subject: %s\r\n" | ||
| "\r\n", | ||
| date_buf, | ||
| sanitized_to, | ||
| sanitized_from, | ||
| message_id, | ||
| hostname, | ||
| sanitized_subject); |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Enable authenticated and TLS SMTP for ossec-maild when built with
USE_CURL=yes (off by default). Uses libcurl for SMTP AUTH (PLAIN/LOGIN)
and TLS/STARTTLS; credentials and TLS are validated and sanitized.
Security hardening: header/envelope CR/LF sanitization, hostname
validation for smtp_server, timeouts, mandatory TLS when AUTH is on,
post-parse credential validation, and secure clearing of password
in config and at exit.
CA bundle and chroot
ossec-maild runs inside a chroot (e.g. /var/ossec). libcurl uses
CURLOPT_SSL_VERIFYPEER=1 and by default looks for the system CA bundle
(e.g. /etc/ssl/certs/ca-certificates.crt). After chroot, that path
is not visible, so TLS verification fails (CURLE_PEER_FAILED_VERIFICATION)
and mail is dropped unless the CA bundle is available inside the chroot.
Installation (or the admin) must copy or symlink the system CA bundle
into the chroot (e.g. /etc/ssl/certs/ca-certificates.crt) and
either set CURLOPT_CAINFO to that path in code or ensure the default
path resolves inside the chroot. Do not disable VERIFYPEER.
Original idea and initial implementation from alexbartlow via
Allow TLS Email sends as a compile-time option
#1360
Credit: alexbartlow (PR #1360)