From a01d05ea35365933db365ad5443d44d24cd933f7 Mon Sep 17 00:00:00 2001 From: Daniel Richard G Date: Sun, 23 Apr 2023 06:23:20 -0400 Subject: [PATCH] Implement new DELIVERY config parameter. This allows dma to support three modes of delivery: local-only, remote-only, and local + remote (the default). It supersedes the NULLCLIENT directive, which is equivalent to the remote-only mode. Fixes: #121 --- conf.c | 27 +++++++++++++++++++++------ dma.8 | 22 +++++++++++++--------- dma.c | 11 ++++++----- dma.conf | 6 ++++-- dma.h | 3 ++- 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/conf.c b/conf.c index 0c88bb1..cd40f04 100644 --- a/conf.c +++ b/conf.c @@ -216,9 +216,23 @@ parse_conf(const char *config_path) user = NULL; config.masquerade_host = host; config.masquerade_user = user; + } else if (strcmp(word, "DELIVERY") == 0 && data != NULL) { + if (strcmp(data, "LOCALANDREMOTE") == 0) + config.features |= (DELIVERY_LOCAL | DELIVERY_REMOTE); + else if (strcmp(data, "LOCALONLY") == 0) { + config.features |= DELIVERY_LOCAL; + config.features &= ~DELIVERY_REMOTE; + } else if (strcmp(data, "REMOTEONLY") == 0) { + config.features &= ~DELIVERY_LOCAL; + config.features |= DELIVERY_REMOTE; + } else { + errlogx(EX_CONFIG, "invalid DELIVERY value in %s:%d", config_path, lineno); + /* NOTREACHED */ + } + free(data); } else if (strcmp(word, "STARTTLS") == 0 && data == NULL) config.features |= STARTTLS; - else if (strcmp(word, "FINGERPRINT") == 0) { + else if (strcmp(word, "FINGERPRINT") == 0 && data != NULL) { if (strlen(data) != SHA256_DIGEST_LENGTH * 2) { errlogx(EX_CONFIG, "invalid sha256 fingerprint length"); } @@ -244,16 +258,17 @@ parse_conf(const char *config_path) config.features |= INSECURE; else if (strcmp(word, "FULLBOUNCE") == 0 && data == NULL) config.features |= FULLBOUNCE; - else if (strcmp(word, "NULLCLIENT") == 0 && data == NULL) - config.features |= NULLCLIENT; - else { + else if (strcmp(word, "NULLCLIENT") == 0 && data == NULL) { + config.features &= ~DELIVERY_LOCAL; + config.features |= DELIVERY_REMOTE; + } else { errlogx(EX_CONFIG, "syntax error in %s:%d", config_path, lineno); /* NOTREACHED */ } } - if ((config.features & NULLCLIENT) && config.smarthost == NULL) { - errlogx(EX_CONFIG, "%s: NULLCLIENT requires SMARTHOST", config_path); + if (!(config.features & DELIVERY_LOCAL) && config.smarthost == NULL) { + errlogx(EX_CONFIG, "%s: remote-only delivery requires SMARTHOST", config_path); /* NOTREACHED */ } diff --git a/dma.8 b/dma.8 index cf8eb6a..2adf6cd 100644 --- a/dma.8 +++ b/dma.8 @@ -315,16 +315,20 @@ setting it to will send all mails as .Ql Sm off Va username @percolator . .Sm on -.It Ic NULLCLIENT Xo -(boolean, default=commented) +.It Ic DELIVERY Xo +(string, default=LOCALANDREMOTE) .Xc -Bypass aliases and local delivery, and instead forward all mails to -the defined -.Sq SMARTHOST . -.Sq NULLCLIENT -requires -.Sq SMARTHOST -to be set. +Type(s) of delivery that +.Nm +should perform. +Set this to +.Sq LOCALONLY +to allow only deliveries to local recipients. +Set it to +.Sq REMOTEONLY +to forward all messages to the defined +.Sq SMARTHOST , +bypassing local aliases. .El .Ss Environment variables The behavior of diff --git a/dma.c b/dma.c index 5206691..0040a42 100644 --- a/dma.c +++ b/dma.c @@ -81,7 +81,7 @@ struct config config = { .spooldir = "/var/spool/dma", .authpath = NULL, .certfile = NULL, - .features = 0, + .features = DELIVERY_LOCAL | DELIVERY_REMOTE, .mailname = NULL, .masquerade_host = NULL, .masquerade_user = NULL, @@ -233,10 +233,9 @@ add_recp(struct queue *queue, const char *str, int expand) LIST_INSERT_HEAD(&queue->queue, it, next); /** - * Do local delivery if there is no @. - * Do not do local delivery when NULLCLIENT is set. + * Do local delivery if there is no @ and DELIVERY_LOCAL is set. */ - if (strrchr(it->addr, '@') == NULL && (config.features & NULLCLIENT) == 0) { + if (strrchr(it->addr, '@') == NULL && (config.features & DELIVERY_LOCAL)) { it->remote = 0; if (expand) { aliased = do_alias(queue, it->addr); @@ -255,8 +254,10 @@ add_recp(struct queue *queue, const char *str, int expand) endpwent(); } } - } else { + } else if (config.features & DELIVERY_REMOTE) { it->remote = 1; + } else { + return (-1); } return (0); diff --git a/dma.conf b/dma.conf index fa95fc1..5a9690b 100644 --- a/dma.conf +++ b/dma.conf @@ -66,5 +66,7 @@ # MASQUERADE percolator will send mails as $username@percolator, e.g. fish@percolator # MASQUERADE herb@ert will send all mails as herb@ert -# Directly forward the mail to the SMARTHOST bypassing aliases and local delivery -#NULLCLIENT +# Uncomment and set to LOCALONLY or REMOTEONLY if you want local-only or +# remote-only delivery. Note that remote-only mode requires SMARTHOST to +# be specified, and ignores local aliases. +#DELIVERY LOCALANDREMOTE diff --git a/dma.h b/dma.h index 9e7f6cd..05df7a8 100644 --- a/dma.h +++ b/dma.h @@ -69,7 +69,8 @@ #define INSECURE 0x020 /* Allow plain login w/o encryption */ #define FULLBOUNCE 0x040 /* Bounce the full message */ #define TLS_OPP 0x080 /* Opportunistic STARTTLS */ -#define NULLCLIENT 0x100 /* Nullclient support */ +#define DELIVERY_LOCAL 0x100 /* Do local delivery */ +#define DELIVERY_REMOTE 0x200 /* Do remote delivery */ #ifndef CONF_PATH #error Please define CONF_PATH