[Commits] [SCM] claws branch, master, updated. 4.3.1-34-gcda3dae3e
wwp at claws-mail.org
wwp at claws-mail.org
Fri Mar 7 13:12:34 UTC 2025
The branch, master has been updated
via cda3dae3ec9771b9f9581d14481e5c3cf67110b3 (commit)
from e483717e6c13c883c410c6382c98ecd912f68956 (commit)
Summary of changes:
src/plugins/spamassassin/libspamc.c | 196 +++++++++++++++++++++++++++++++-----
src/plugins/spamassassin/libspamc.h | 10 ++
2 files changed, 180 insertions(+), 26 deletions(-)
- Log -----------------------------------------------------------------
commit cda3dae3ec9771b9f9581d14481e5c3cf67110b3
Author: wwp <subscript at free.fr>
Date: Fri Mar 7 14:12:04 2025 +0100
Update SpamAssassin (client) third-party code to 4.0.1.
diff --git a/src/plugins/spamassassin/libspamc.c b/src/plugins/spamassassin/libspamc.c
index 47b8c0c2c..8f2cd79fd 100644
--- a/src/plugins/spamassassin/libspamc.c
+++ b/src/plugins/spamassassin/libspamc.c
@@ -39,6 +39,7 @@
#define sleep Sleep
#include <io.h>
#else
+#include <strings.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/types.h>
@@ -489,7 +490,6 @@ static int _try_to_connect_tcp(const struct transport *tp, int *sockptr)
#ifdef SPAMC_HAS_ADDRINFO
res = tp->hosts[hostix];
while(res) {
-#ifdef DO_CONNECT_DEBUG_SYSLOGS
char *family = NULL;
switch(res->ai_family) {
case AF_INET:
@@ -502,7 +502,6 @@ static int _try_to_connect_tcp(const struct transport *tp, int *sockptr)
family = "Unknown";
break;
}
-#endif
if ((ret = _opensocket(tp->flags, res, &mysock)) != EX_OK) {
res = res->ai_next;
@@ -610,6 +609,120 @@ static int _try_to_connect_tcp(const struct transport *tp, int *sockptr)
return _translate_connect_errno(origerr);
}
+#ifdef SPAMC_SSL
+static char * _ssl_err_as_string (void) {
+ BIO *bio = BIO_new(BIO_s_mem());
+ ERR_print_errors(bio);
+ char *buf = NULL;
+ size_t len = BIO_get_mem_data(bio, &buf);
+ char *ret = (char *)calloc(1, 1 + len);
+ if (!ret) {
+ BIO_free(bio);
+ char *err = "(could not get SSL error)";
+ return err;
+ }
+ memcpy(ret, buf, len);
+ BIO_free(bio);
+ /* Only return up to first newline */
+ char *lf = strchr(ret, '\n');
+ if (lf)
+ *lf = '\0';
+ return ret;
+}
+
+static SSL_CTX * _try_ssl_ctx_init(int flags)
+{
+ const SSL_METHOD *meth;
+ SSL_CTX *ctx;
+
+ SSLeay_add_ssl_algorithms();
+ SSL_load_error_strings();
+ /* this method allows negotiation of version */
+ meth = SSLv23_client_method();
+ ctx = SSL_CTX_new(meth);
+ if (ctx == NULL) {
+ libspamc_log(flags, LOG_ERR, "cannot create SSL CTX context: %s",
+ _ssl_err_as_string());
+ return NULL;
+ }
+ if (flags & SPAMC_TLSV1) {
+ /* allow TLSv1.0 or better */
+ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
+ } else {
+ /* allow SSLv3 or better */
+ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
+ }
+ SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+ return ctx;
+}
+
+static int _try_ssl_connect(SSL_CTX *ctx, struct transport *tp,
+ SSL **pssl, int flags, int sock)
+{
+ SSL *ssl;
+ int ssl_rtn;
+ if (tp->ssl_ca_file || tp->ssl_ca_path) {
+ if (!SSL_CTX_load_verify_locations(ctx, tp->ssl_ca_file,
+ tp->ssl_ca_path)) {
+ libspamc_log(flags, LOG_ERR,
+ "error loading CA file %s or path %s: %s",
+ tp->ssl_ca_file ? tp->ssl_ca_file : "(void)",
+ tp->ssl_ca_path ? tp->ssl_ca_path : "(void)",
+ _ssl_err_as_string());
+ return EX_OSERR;
+ }
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+ } else {
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+ }
+ if (flags & SPAMC_CLIENT_SSL_CERT) {
+ /* libspamc_log(flags, LOG_ERR, "loading client cert %s key %s",
+ tp->ssl_cert_file, tp->ssl_key_file); */
+ if (!SSL_CTX_use_certificate_file(ctx, tp->ssl_cert_file,
+ SSL_FILETYPE_PEM)) {
+ libspamc_log(flags, LOG_ERR,
+ "unable to load certificate file %s: %s",
+ tp->ssl_cert_file, _ssl_err_as_string());
+ return EX_OSERR;
+ }
+ if (!SSL_CTX_use_PrivateKey_file(ctx, tp->ssl_key_file,
+ SSL_FILETYPE_PEM)) {
+ libspamc_log(flags, LOG_ERR,
+ "unable to load key file %s: %s",
+ tp->ssl_key_file, _ssl_err_as_string());
+ return EX_OSERR;
+ }
+ if (!SSL_CTX_check_private_key(ctx)) {
+ libspamc_log(flags, LOG_ERR,
+ "key file %s and cert file %s do not match: %s",
+ tp->ssl_key_file, tp->ssl_cert_file,
+ _ssl_err_as_string());
+ return EX_OSERR;
+ }
+ }
+ ssl = SSL_new(ctx);
+ if (ssl == NULL) {
+ libspamc_log(flags, LOG_ERR,
+ "SSL_new failed: %s", _ssl_err_as_string());
+ return EX_OSERR;
+ }
+ *pssl = ssl;
+ if (!SSL_set_fd(ssl, sock)) {
+ libspamc_log(flags, LOG_ERR,
+ "SSL_set_fd failed: %s", _ssl_err_as_string());
+ return EX_OSERR;
+ }
+ ssl_rtn = SSL_connect(ssl);
+ if (ssl_rtn != 1) {
+ int ssl_err = SSL_get_error(ssl, ssl_rtn);
+ libspamc_log(flags, LOG_ERR,
+ "SSL_connect error: %s", _ssl_err_as_string());
+ return EX_UNAVAILABLE;
+ }
+ return EX_OK;
+}
+#endif
+
/* Aug 14, 2002 bj: Reworked things. Now we have message_read, message_write,
* message_dump, lookup_host, message_filter, and message_process, and a bunch
* of helper functions.
@@ -919,7 +1032,7 @@ _spamc_read_full_line(struct message *m, int flags, SSL * ssl, int sock,
}
}
- libspamc_log(flags, LOG_ERR, "spamd responded with line of %lu bytes, dying", len);
+ libspamc_log(flags, LOG_ERR, "spamd responded with line of %d bytes, dying", len);
failureval = EX_TOOBIG;
failure:
@@ -1216,13 +1329,13 @@ int message_filter(struct transport *tp, const char *username,
if (flags & SPAMC_USE_SSL) {
#ifdef SPAMC_SSL
- SSLeay_add_ssl_algorithms();
- meth = SSLv23_client_method();
- SSL_load_error_strings();
- ctx = SSL_CTX_new(meth);
+ ctx = _try_ssl_ctx_init(flags);
+ if (ctx == NULL) {
+ failureval = EX_OSERR;
+ goto failure;
+ }
#else
UNUSED_VARIABLE(ssl);
- UNUSED_VARIABLE(meth);
UNUSED_VARIABLE(ctx);
libspamc_log(flags, LOG_ERR, "spamc not built with SSL support");
return EX_SOFTWARE;
@@ -1375,17 +1488,33 @@ int message_filter(struct transport *tp, const char *username,
if (flags & SPAMC_USE_SSL) {
#ifdef SPAMC_SSL
- ssl = SSL_new(ctx);
- SSL_set_fd(ssl, sock);
- SSL_connect(ssl);
+ rc = _try_ssl_connect(ctx, tp, &ssl, flags, sock);
+ if (rc != EX_OK) {
+ failureval = rc;
+ goto failure;
+ }
#endif
}
/* Send to spamd */
if (flags & SPAMC_USE_SSL) {
#ifdef SPAMC_SSL
- SSL_write(ssl, buf, len);
- SSL_write(ssl, towrite_buf, towrite_len);
+ rc = SSL_write(ssl, buf, len);
+ if (rc <= 0) {
+ libspamc_log(flags, LOG_ERR, "SSL write failed (%d)",
+ SSL_get_error(ssl, rc));
+ failureval = EX_IOERR;
+ goto failure;
+ }
+ rc = SSL_write(ssl, towrite_buf, towrite_len);
+ if (rc <= 0) {
+ libspamc_log(flags, LOG_ERR, "SSL write failed (%d)",
+ SSL_get_error(ssl, rc));
+ failureval = EX_IOERR;
+ goto failure;
+ }
+ SSL_shutdown(ssl);
+ shutdown(sock, SHUT_WR);
#endif
}
else {
@@ -1596,20 +1725,19 @@ int message_tell(struct transport *tp, const char *username, int flags,
int failureval;
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
- const SSL_METHOD *meth;
assert(tp != NULL);
assert(m != NULL);
if (flags & SPAMC_USE_SSL) {
#ifdef SPAMC_SSL
- SSLeay_add_ssl_algorithms();
- meth = SSLv23_client_method();
- SSL_load_error_strings();
- ctx = SSL_CTX_new(meth);
+ ctx = _try_ssl_ctx_init(flags);
+ if (ctx == NULL) {
+ failureval = EX_OSERR;
+ goto failure;
+ }
#else
UNUSED_VARIABLE(ssl);
- UNUSED_VARIABLE(meth);
UNUSED_VARIABLE(ctx);
libspamc_log(flags, LOG_ERR, "spamc not built with SSL support");
return EX_SOFTWARE;
@@ -1723,17 +1851,33 @@ int message_tell(struct transport *tp, const char *username, int flags,
if (flags & SPAMC_USE_SSL) {
#ifdef SPAMC_SSL
- ssl = SSL_new(ctx);
- SSL_set_fd(ssl, sock);
- SSL_connect(ssl);
+ rc = _try_ssl_connect(ctx, tp, &ssl, flags, sock);
+ if (rc != EX_OK) {
+ failureval = rc;
+ goto failure;
+ }
#endif
}
/* Send to spamd */
if (flags & SPAMC_USE_SSL) {
#ifdef SPAMC_SSL
- SSL_write(ssl, buf, len);
- SSL_write(ssl, m->msg, m->msg_len);
+ rc = SSL_write(ssl, buf, len);
+ if (rc <= 0) {
+ libspamc_log(flags, LOG_ERR, "SSL write failed (%d)",
+ SSL_get_error(ssl, rc));
+ failureval = EX_IOERR;
+ goto failure;
+ }
+ rc = SSL_write(ssl, m->msg, m->msg_len);
+ if (rc <= 0) {
+ libspamc_log(flags, LOG_ERR, "SSL write failed (%d)",
+ SSL_get_error(ssl, rc));
+ failureval = EX_IOERR;
+ goto failure;
+ }
+ SSL_shutdown(ssl);
+ shutdown(sock, SHUT_WR);
#endif
}
else {
@@ -1911,7 +2055,7 @@ static void _randomize_hosts(struct transport *tp)
int transport_setup(struct transport *tp, int flags)
{
#ifdef SPAMC_HAS_ADDRINFO
- struct addrinfo hints, *res; /* , *addrp; */
+ struct addrinfo hints, *res, *addrp;
char port[6];
int origerr;
#else
@@ -2248,7 +2392,7 @@ libspamc_log (int flags, int level, char *msg, ...)
syslog (level, "%s", buf);
#else
(void) level; /* not used. suppress compiler warning */
- f_printerr ("%s\n", buf);
+ fprintf (stderr, "%s\n", buf);
#endif
}
diff --git a/src/plugins/spamassassin/libspamc.h b/src/plugins/spamassassin/libspamc.h
index 7a6fc1209..269e57464 100644
--- a/src/plugins/spamassassin/libspamc.h
+++ b/src/plugins/spamassassin/libspamc.h
@@ -139,6 +139,9 @@
* */
#define SPAMC_UNAVAIL_TEMPFAIL (1<<13)
+/* April 2022, add SSL client certificate support, bug 7267 */
+#define SPAMC_CLIENT_SSL_CERT (1<<12)
+
#define SPAMC_MESSAGE_CLASS_SPAM 1
#define SPAMC_MESSAGE_CLASS_HAM 2
@@ -249,6 +252,13 @@ struct transport
/* Added for filterloop */
int filter_retries;
int filter_retry_sleep;
+
+#ifdef SPAMC_SSL
+ const char *ssl_cert_file;
+ const char *ssl_key_file;
+ const char *ssl_ca_file;
+ const char *ssl_ca_path;
+#endif
};
/* Initialise and setup transport-specific context for the connection
-----------------------------------------------------------------------
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list