tFinanlize errors, make debugging an option. - bmf-milter - bmf filter milter daemon
 (HTM) git clone git://r-36.net/bmf-milter
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 82206056ecfb4003651ef84ca27945fb33f818e8
 (DIR) parent b3b81916fc31048e89e418a5538d1f8812814479
 (HTM) Author: Christoph Lohmann <20h@r-36.net>
       Date:   Sun, 14 Jun 2020 13:00:42 +0200
       
       Finanlize errors, make debugging an option.
       
       Diffstat:
         bmf-milter.c                        |     169 ++++++++++++++++++++++---------
       
       1 file changed, 121 insertions(+), 48 deletions(-)
       ---
 (DIR) diff --git a/bmf-milter.c b/bmf-milter.c
       t@@ -6,6 +6,7 @@
        #include <sys/types.h>
        #include <sys/stat.h>
        #include <sys/wait.h>
       +#include <fcntl.h>
        #include <errno.h>
        #include <stdio.h>
        #include <stdlib.h>
       t@@ -20,8 +21,14 @@
        
        #include "arg.h"
        
       -struct Priv
       -{
       +/*
       + * In case any requires feature is not negotiable, simply do nothing,
       + * thus always return SMFI_CONTINUE. If we would return any FAIL, the
       + * message would be rejected.
       + */
       +int donothing = 0, dodebug = 0;
       +
       +struct Priv {
                /* read from execpipe[0], write to execpipe[1] */
                int        execpipe[2];
                int        execpid;
       t@@ -30,25 +37,41 @@ struct Priv
        #define MLFIPRIV ((struct Priv *) smfi_getpriv(ctx))
        
        sfsistat
       -mlfi_cleanup(SMFICTX *ctx)
       +mlfi_cleanup(SMFICTX *ctx, int iseom)
        {
                struct Priv *priv = MLFIPRIV;
                int retcode = -1;
        
       -        fprintf(stderr, "mlfi_cleanup\n");
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_cleanup\n");
        
                if (priv == NULL)
                        return SMFIS_CONTINUE;
       -
       +        if (dodebug)
       +                fprintf(stderr, "cleanup: closing execpipe[1]\n");
                close(priv->execpipe[1]);
       +        priv->execpipe[1] = -1;
       +        if (dodebug)
       +                fprintf(stderr, "cleanup: waitpid\n");
                waitpid(priv->execpid, &retcode, 0);
       -
       -        if (retcode == 0) {
       -                if (smfi_addheader(ctx, "X-Spam-Flag", "YES") == MI_FAILURE)
       -                        return SMFIS_TEMPFAIL;
       +        if (dodebug)
       +                fprintf(stderr, "cleanup: retcode = %d\n", retcode);
       +
       +        /*
       +         * smfi_addheader is only allowed in eom.
       +         */
       +        if (iseom) {
       +                if (retcode == 0) {
       +                        if (smfi_addheader(ctx, "X-Spam-Flag",
       +                                                " YES") == MI_FAILURE) {
       +                                if (dodebug)
       +                                        fprintf(stderr, "x-spam-flag failed\n");
       +                        }
       +                }
                        if (smfi_addheader(ctx, "X-BMF-Processed",
       -                                        "YES") == MI_FAILURE) {
       -                        return SMFIS_TEMPFAIL;
       +                                        " YES") == MI_FAILURE) {
       +                        if (dodebug)
       +                                fprintf(stderr, "x-bmf-processed failed\n");
                        }
                }
        
       t@@ -56,17 +79,32 @@ mlfi_cleanup(SMFICTX *ctx)
        }
        
        sfsistat
       +mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr)
       +{
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_connect(%s)\n", hostname);
       +
       +        return SMFIS_CONTINUE;
       +}
       +
       +sfsistat
        mlfi_helo(SMFICTX *ctx, char *helohost)
        {
                struct Priv *priv;
                char *ident;
       -        int pid;
       +        int pid, nullfd;
        
       -        fprintf(stderr, "mlfi_helo(%s)\n", helohost);
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_helo(%s)\n", helohost);
       +
       +        if (donothing) {
       +                smfi_setpriv(ctx, NULL);
       +                return SMFIS_CONTINUE;
       +        }
        
                priv = malloc(sizeof *priv);
                if (priv == NULL)
       -                return SMFIS_TEMPFAIL;
       +                return SMFIS_CONTINUE;
                memset(priv, '\0', sizeof *priv);
        
                smfi_setpriv(ctx, priv);
       t@@ -74,14 +112,25 @@ mlfi_helo(SMFICTX *ctx, char *helohost)
                if (pipe(priv->execpipe) < 0) {
                        free(priv);
                        smfi_setpriv(ctx, NULL);
       -                return SMFIS_TEMPFAIL;
       +                return SMFIS_CONTINUE;
                }
        
                switch((pid = fork())) {
                case 0:
                        while(dup2(priv->execpipe[0], 0) < 0 && errno == EINTR);
                        close(priv->execpipe[1]);
       -                if (execl("/usr/bin/bmf", "bmf", "-t", (char *)NULL) < 0) {
       +
       +                if (!dodebug) {
       +                        nullfd = open("/dev/null", O_WRONLY);
       +                        if (nullfd < 0) {
       +                                perror("open");
       +                                _exit(1);
       +                        }
       +                        while(dup2(priv->execpipe[0], 1) < 0 && errno == EINTR);
       +                        while(dup2(priv->execpipe[0], 2) < 0 && errno == EINTR);
       +                }
       +
       +                if (execl("/usr/bin/bmf", "bmf", "-t", "-v", "-v", (char *)NULL) < 0) {
                                perror("execl");
                                _exit(1);
                        }
       t@@ -89,7 +138,7 @@ mlfi_helo(SMFICTX *ctx, char *helohost)
                case -1:
                        free(priv);
                        smfi_setpriv(ctx, NULL);
       -                return SMFIS_TEMPFAIL;
       +                break;
                default:
                        priv->execpid = pid;
                        close(priv->execpipe[0]);
       t@@ -104,7 +153,8 @@ mlfi_envfrom(SMFICTX *ctx, char *argv[])
        {
                struct Priv *priv = MLFIPRIV;
        
       -        fprintf(stderr, "mlfi_envfrom(%s)\n", argv[0]);
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_envfrom(%s)\n", argv[0]);
        
                dprintf(priv->execpipe[1], "From: %s\n", argv[0]);
        
       t@@ -116,7 +166,8 @@ mlfi_envrcpt(SMFICTX *ctx, char *argv[])
        {
                struct Priv *priv = MLFIPRIV;
        
       -        fprintf(stderr, "mfli_envrcpt(%s)\n", argv[0]);
       +        if (dodebug)
       +                fprintf(stderr, "mfli_envrcpt(%s)\n", argv[0]);
        
                dprintf(priv->execpipe[1], "To: %s\n", argv[0]);
        
       t@@ -128,7 +179,8 @@ mlfi_header(SMFICTX *ctx, char *headerf, char *headerv)
        {
                struct Priv *priv = MLFIPRIV;
        
       -        fprintf(stderr, "mlfi_header(%s = '%s')\n", headerf, headerv);
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_header(%s = '%s')\n", headerf, headerv);
        
                dprintf(priv->execpipe[1], "%s: %s\n", headerf, headerv);
        
       t@@ -140,7 +192,8 @@ mlfi_eoh(SMFICTX *ctx)
        {
                struct Priv *priv = MLFIPRIV;
        
       -        fprintf(stderr, "mlfi_eoh\n");
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_eoh\n");
        
                dprintf(priv->execpipe[1], "\r\n");
        
       t@@ -153,9 +206,10 @@ mlfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t bodylen)
                struct Priv *priv = MLFIPRIV;
                int written;
        
       -        fprintf(stderr, "mlfi_body(%ld bytes)\n", bodylen);
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_body(%ld bytes)\n", bodylen);
        
       -        for (int written = 0, rw = 0; written <= bodylen; written += rw)
       +        for (int written = 0, rw = 0; written < bodylen; written += rw)
                        rw = write(priv->execpipe[1], bodyp+written, bodylen-written);
        
                return SMFIS_CONTINUE;
       t@@ -164,15 +218,19 @@ mlfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t bodylen)
        sfsistat
        mlfi_eom(SMFICTX *ctx)
        {
       -        fprintf(stderr, "mlfi_eom\n");
       -        return mlfi_cleanup(ctx);
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_eom\n");
       +
       +        return mlfi_cleanup(ctx, 1);
        }
        
        sfsistat
        mlfi_abort(SMFICTX *ctx)
        {
       -        fprintf(stderr, "mlfi_abort\n");
       -        return mlfi_cleanup(ctx);
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_abort\n");
       +
       +        return mlfi_cleanup(ctx, 0);
        }
        
        sfsistat
       t@@ -180,13 +238,22 @@ mlfi_close(SMFICTX *ctx)
        {
                struct Priv *priv = MLFIPRIV;
        
       -        fprintf(stderr, "mlfi_close\n");
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_close\n");
        
                if (priv != NULL) {
       -                if (priv->execpipe[1] != 0)
       +                if (priv->execpipe[1] > 0) {
       +                        if (dodebug)
       +                                fprintf(stderr, "Close execpipe[1]\n");
                                close(priv->execpipe[1]);
       -                if (priv->execpid != 0)
       +                }
       +                if (priv->execpid > 0) {
       +                        if (dodebug)
       +                                fprintf(stderr, "Kill pid %d.\n", priv->execpid);
                                kill(priv->execpid, SIGKILL);
       +                }
       +                if (dodebug)
       +                        fprintf(stderr, "Free priv\n");
                        free(priv);
                        smfi_setpriv(ctx, NULL);
                }
       t@@ -205,17 +272,24 @@ mlfi_negotiate(SMFICTX *ctx,
                        unsigned long *pf2,
                        unsigned long *pf3)
        {
       -        fprintf(stderr, "mlfi_negotiate\n");
       +        if (dodebug)
       +                fprintf(stderr, "mlfi_negotiate\n");
        
                /* milter actions */
                *pf0 = 0;
       -        if (f0 & SMFIF_ADDHDRS)
       -                f0 |= SMFIF_ADDHDRS;
       +        if (f0 & SMFIF_ADDHDRS) {
       +                *pf0 |= SMFIF_ADDHDRS;
       +        } else {
       +                donothing = 1;
       +        }
        
                /* milter protocol steps */
       -        *pf1 = f1 & (SMFIP_NOCONNECT|SMFIP_NOUNKNOWN|SMFIP_NODATA);
       -        if (f1 & SMFIP_HDR_LEADSPC)
       +        *pf1 = f1 & (SMFIP_NOUNKNOWN|SMFIP_NODATA);
       +        if (f1 & SMFIP_HDR_LEADSPC) {
                        *pf1 |= SMFIP_HDR_LEADSPC;
       +        } else {
       +                donothing = 1;
       +        }
        
                /* future */
                *pf2 = 0;
       t@@ -229,7 +303,7 @@ struct smfiDesc smfilter =
                "BMF",                /* filter name */
                SMFI_VERSION,        /* version code -- do not change */
                SMFIF_ADDHDRS,  /* flags */
       -        NULL,                /* connection info filter */
       +        mlfi_connect,        /* connection info filter */
                mlfi_helo,        /* SMTP HELO command filter */
                mlfi_envfrom,        /* envelope sender filter */
                mlfi_envrcpt,        /* envelope recipient filter */
       t@@ -259,11 +333,12 @@ main(int argc, char *argv[])
                int timeout;
        
                port = "inet:9957";
       -        timeout = 0;
       +        timeout = -1;
        
                ARGBEGIN(argv0) {
                case 'd':
                        smfi_setdbg(atoi(EARGF(argv0)));
       +                dodebug = 1;
                        break;
                case 'p':
                        port = EARGF(usage(argv0));
       t@@ -276,22 +351,20 @@ main(int argc, char *argv[])
                        return 1;
                } ARGEND;
        
       -        fprintf(stderr, "port = %s; timeout = %d;\n", port, timeout);
       -
                if (smfi_setconn(port) == MI_FAILURE) {
                        perror("smfi_setconn");
                        return 1;
                }
       +        if (dodebug)
       +                fprintf(stderr, "port set to '%s'\n", port);
        
       -        if (!strncasecmp(port, "unix:", 5)) {
       -                unlink(port + 5);
       -        } else if (!strncasecmp(port, "local:", 6)) {
       -                unlink(port + 6);
       -        }
       -
       -        if (smfi_settimeout(timeout) == MI_FAILURE) {
       -                perror("smfi_settimout");
       -                return 1;
       +        if (timeout > 0) {
       +                if (smfi_settimeout(timeout) == MI_FAILURE) {
       +                        perror("smfi_settimout");
       +                        return 1;
       +                }
       +                if (dodebug)
       +                        fprintf(stderr, "timeout set to %d\n", timeout);
                }
        
                if (smfi_register(smfilter) == MI_FAILURE) {