diff --git a/include/ilib/curl_imapsmtp.h b/include/ilib/curl_imapsmtp.h
new file mode 100644
index 0000000..d3af1b0
--- /dev/null
+++ b/include/ilib/curl_imapsmtp.h
@@ -0,0 +1,56 @@
+/*
+ * this is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * this is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .";
+ *
+ * (c) Alexander Vdolainen 2007, 2026
+ * subrelay: a minimalistic maillist server based on external IMAPs/SMTPs
+ *
+ * curl_imapsmtp.h: IMAPS SMTPs functions using libcurl
+ *
+ */
+#ifndef __MAIL_ENGINE_H__
+#define __MAIL_ENGINE_H__
+
+#include
+
+#include
+
+#define MAX_IMAP_RESPONSE (25u * 1024u * 1024u)
+
+typedef struct mail_message {
+ char *raw_data; /* Full raw RFC 822 byte payload */
+ size_t size; /* Size of raw payload */
+ unsigned long uid; /* IMAP Unique Identifier */
+} mail_message_t;
+
+typedef struct mail_list_results {
+ unsigned long *uids;
+ size_t count;
+} mail_list_results_t;
+
+/* Initialize and cleanup global libcurl environment */
+int mail_engine_global_init(void);
+void mail_engine_global_cleanup(void);
+
+/* IMAP Client API */
+int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *results);
+int imap_fetch_message(const subrelay_config_t *cfg, unsigned long uid, mail_message_t *msg);
+int imap_expunge_message(const subrelay_config_t *cfg, unsigned long uid);
+void mail_message_free(mail_message_t *msg);
+void mail_list_results_free(mail_list_results_t *res);
+
+/* SMTP Client API */
+int smtp_send_message(const subrelay_config_t *cfg, const char **recipients,
+ size_t recipient_count, const char *raw_msg, size_t msg_len);
+
+#endif /* __MAIL_ENGINE_H__ */
diff --git a/include/ilib/mail_engine.h b/include/ilib/mail_engine.h
deleted file mode 100644
index b78baaf..0000000
--- a/include/ilib/mail_engine.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* mail_engine.h - IMAP fetching & SMTP fan-out engine using libcurl */
-#ifndef __MAIL_ENGINE_H__
-#define __MAIL_ENGINE_H__
-
-#include
-
-#include
-
-typedef struct mail_message {
- char *raw_data; /* Full raw RFC 822 byte payload */
- size_t size; /* Size of raw payload */
- unsigned long uid; /* IMAP Unique Identifier */
-} mail_message_t;
-
-typedef struct mail_list_results {
- unsigned long *uids;
- size_t count;
-} mail_list_results_t;
-
-/* Initialize and cleanup global libcurl environment */
-int mail_engine_global_init(void);
-void mail_engine_global_cleanup(void);
-
-/* IMAP Client API */
-int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *results);
-int imap_fetch_message(const subrelay_config_t *cfg, unsigned long uid, mail_message_t *msg);
-int imap_expunge_message(const subrelay_config_t *cfg, unsigned long uid);
-void mail_message_free(mail_message_t *msg);
-void mail_list_results_free(mail_list_results_t *res);
-
-/* SMTP Client API */
-int smtp_send_message(const subrelay_config_t *cfg,
- const char **recipients,
- size_t recipient_count,
- const char *raw_msg,
- size_t msg_len);
-
-#endif /* __MAIL_ENGINE_H__ */
diff --git a/include/ilib/mail_processor.h b/include/ilib/mail_processor.h
index fbbbcbd..4d2781b 100644
--- a/include/ilib/mail_processor.h
+++ b/include/ilib/mail_processor.h
@@ -24,7 +24,7 @@
#include
#include
#include
-#include
+#include
typedef struct mail_processor {
subrelay_config_t *cfg;
diff --git a/src/Makefile.am b/src/Makefile.am
index 64234d6..dec4334 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,7 @@ bin_PROGRAMS = subrelayd sbrlctrl
noinst_HEADERS = \
$(top_srcdir)/include/ilib/configuration.h \
$(top_srcdir)/include/ilib/local.h \
- $(top_srcdir)/include/ilib/mail_engine.h \
+ $(top_srcdir)/include/ilib/curl_imapsmtp.h \
$(top_srcdir)/include/ilib/mail_processor.h \
$(top_srcdir)/include/ilib/pending.h \
$(top_srcdir)/include/ilib/splay.h \
@@ -20,7 +20,7 @@ subrelayd_SOURCES = \
pending.c \
configuration.c \
template.c \
- mail_engine.c \
+ curl_imapsmtp.c \
mail_processor.c \
local.c
diff --git a/src/mail_engine.c b/src/curl_imapsmtp.c
similarity index 76%
rename from src/mail_engine.c
rename to src/curl_imapsmtp.c
index 407c239..fd2476d 100644
--- a/src/mail_engine.c
+++ b/src/curl_imapsmtp.c
@@ -1,11 +1,33 @@
-/* mail_engine.c - libcurl IMAP and SMTP implementation */
+/*
+ * this is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * this is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .";
+ *
+ * (c) Alexander Vdolainen 2007, 2026
+ * subrelay: a minimalistic maillist server based on external IMAPs/SMTPs
+ *
+ * curl_imapsmtp.c: IMAPS SMTPs functions using libcurl
+ *
+ */
+
+
#include
#include
+#include
#include
#include
#include
-#include
+#include
typedef struct memory_buffer {
char *data;
@@ -20,24 +42,28 @@ typedef struct upload_buffer {
/* Callback for libcurl to append fetched HTTP/IMAP bytes into memory */
static size_t write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp)
{
- size_t real_size = size * nmemb;
- memory_buffer_t *mem = (memory_buffer_t *)userp;
+ memory_buffer_t *mem = userp;
- char *ptr = realloc(mem->data, mem->size + real_size + 1);
- if (!ptr) return 0; /* Out of memory */
+ if (size != 0 && nmemb > SIZE_MAX / size) return 0;
+ size_t n = size * nmemb;
+ if (n > MAX_IMAP_RESPONSE - mem->size) return 0;
+
+ char *ptr = realloc(mem->data, mem->size + n + 1);
+ if (!ptr) return 0;
mem->data = ptr;
- memcpy(&(mem->data[mem->size]), contents, real_size);
- mem->size += real_size;
- mem->data[mem->size] = 0;
+ memcpy(mem->data + mem->size, contents, n);
+ mem->size += n;
+ mem->data[mem->size] = '\0';
- return real_size;
+ return n;
}
/* Callback for libcurl to read bytes when sending outbound mail via SMTP */
static size_t read_payload_callback(char *buffer, size_t size, size_t nitems, void *userp)
{
upload_buffer_t *upload = (upload_buffer_t *)userp;
+ if (size != 0 && nitems > SIZE_MAX / size) return CURL_READFUNC_ABORT;
size_t max_bytes = size * nitems;
if (upload->bytes_remaining == 0) return 0; /* EOF */
@@ -61,9 +87,7 @@ void mail_engine_global_cleanup(void)
curl_global_cleanup();
}
-/* -------------------------------------------------------------------------- */
-/* IMAP Operations */
-/* -------------------------------------------------------------------------- */
+/* IMAPs */
int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *results)
{
@@ -77,6 +101,7 @@ int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *re
snprintf(url, sizeof(url), "imaps://%s:%d/INBOX", cfg->imap_host, cfg->imap_port);
memory_buffer_t buf = { calloc(1, 1), 0 };
+ if(!buf.data) return -ENOMEM;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_USERNAME, cfg->maillist_addr);
@@ -97,12 +122,18 @@ int imap_fetch_unseen_uids(const subrelay_config_t *cfg, mail_list_results_t *re
/* Parse IMAP response string (e.g., "* SEARCH 101 102 103\r\n") */
char *search_str = strstr(buf.data, "* SEARCH");
if (search_str) {
- search_str += 8; /* Skip "* SEARCH" */
+ search_str += 8; /* skip "* SEARCH" */
char *token = strtok(search_str, " \r\n");
while (token) {
unsigned long uid = strtoul(token, NULL, 10);
if (uid > 0) {
- results->uids = realloc(results->uids, sizeof(unsigned long) * (results->count + 1));
+ unsigned long *tmp = realloc(results->uids, sizeof(unsigned long) * (results->count + 1));
+ if(!tmp) {
+ free(buf.data);
+ mail_list_results_free(results);
+ return -ENOMEM;
+ }
+ results->uids = tmp;
results->uids[results->count++] = uid;
}
token = strtok(NULL, " \r\n");
@@ -125,6 +156,7 @@ int imap_fetch_message(const subrelay_config_t *cfg, unsigned long uid, mail_mes
snprintf(url, sizeof(url), "imaps://%s:%d/INBOX;UID=%lu", cfg->imap_host, cfg->imap_port, uid);
memory_buffer_t buf = { calloc(1, 1), 0 };
+ if(!buf.data) return -ENOMEM;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_USERNAME, cfg->maillist_addr);
@@ -179,15 +211,10 @@ int imap_expunge_message(const subrelay_config_t *cfg, unsigned long uid)
return (res == CURLE_OK) ? 0 : -EIO;
}
-/* -------------------------------------------------------------------------- */
-/* SMTP Operations */
-/* -------------------------------------------------------------------------- */
+/* SMTPS */
-int smtp_send_message(const subrelay_config_t *cfg,
- const char **recipients,
- size_t recipient_count,
- const char *raw_msg,
- size_t msg_len)
+int smtp_send_message(const subrelay_config_t *cfg, const char **recipients, size_t recipient_count,
+ const char *raw_msg, size_t msg_len)
{
if (!cfg || !recipients || recipient_count == 0 || !raw_msg) return -EINVAL;
diff --git a/src/subrelayd.c b/src/subrelayd.c
index ad31881..691e371 100644
--- a/src/subrelayd.c
+++ b/src/subrelayd.c
@@ -33,7 +33,7 @@
#include
#include
#include
-#include
+#include
#include
#include