Temporary feature test with verbose logging
authorMatthew Mondor <mmondor@pulsar-zone.net>
Fri, 26 Dec 2008 08:45:11 +0000 (08:45 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Fri, 26 Dec 2008 08:45:11 +0000 (08:45 +0000)
mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.c
mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.h

index 46f9f80..902e23c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmsmtpd.c,v 1.97 2008/03/14 06:06:07 mmondor Exp $ */
+/* $Id: mmsmtpd.c,v 1.98 2008/12/26 08:45:11 mmondor Exp $ */
 
 /*
  * Copyright (C) 2001-2008, Matthew Mondor
@@ -86,7 +86,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2001-2007\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmsmtpd.c,v 1.97 2008/03/14 06:06:07 mmondor Exp $");
+MMRCSID("$Id: mmsmtpd.c,v 1.98 2008/12/26 08:45:11 mmondor Exp $");
 
 
 
@@ -177,8 +177,10 @@ static const struct reply_messages data_msg[DATA_MAX] = {
     {354, "Submit message ending with a single ."},
     {250, "Ok, mail delivered"},
     {552, "Too much mail data"},
+    {452, "Input timeout"},
     {552, "Too many hops"},
-    {452, "Internal error"}
+    {571, "Delivery not authorized, message refused"},
+    {452, "Internal error, contact administrator"}
 };
 
 /* Pth support for mmfd library (that library rocks my world :) */
@@ -1631,7 +1633,7 @@ validate_msg_line(char *line, ssize_t *len, int *res, void *udata)
     if (ud->header) {
 
        /* Still reading header and expecting ones */
-       char    *ptr;
+       char    header[64], *data, *ptr, *hptr, *ehptr = &header[63];
 
        /* Empty line means that body will follow */
        if (*len == 0)
@@ -1643,16 +1645,41 @@ validate_msg_line(char *line, ssize_t *len, int *res, void *udata)
         * ': '. Also allow continueing header lines which begin with
         * spaces/tabs.
         */
+       *header = '\0';
        if (*line != '\t' && *line != ' ') {
-           for (ptr = line; *ptr != '\0' && (isalnum((int)*ptr) ||
-                       *ptr == '-');
-                   ptr++) ;
-           if (*ptr != ':')
+           for (ptr = line, hptr = header;
+                   *ptr != '\0' && (isalnum((int)*ptr) || *ptr == '-') &&
+                   hptr < ehptr;
+                   *hptr++ = *ptr++) ;
+           if (*ptr++ != ':')
+               goto endheader;
+           if (*ptr++ != ' ')
                goto endheader;
+
+           *hptr = '\0';
+           while (*ptr != '\0' && isspace((int)*ptr))
+               ptr++;
+           data = ptr;
+           mm_strupper(header);
+           /* XXX
+            * Make sure <header> holds expected uppercase string without ':'
+            */
+           mmsyslog(0, LOGLEVEL, "Header: '%s'", header);
+       }
+
+       /* XXX
+        * Permit admin-supplied table to filter unwanted headers here.
+        */
+       if (mm_strcmp(header, "X-MAILER")) {
+           mm_strupper(data);
+           if (best_match(data, "*THE*BAT*") != -1) {
+               *res = CFDBRB_HEADER;
+               return FDBRB_STOP;
+           }
        }
 
        /* Count number of Received: headers (SMTP hops) */
-       if (mm_strncmp(line, "Received:", 9) == 0) {
+       if (mm_strcmp(header, "RECEIVED") == 0) {
            ud->hops++;
            if (ud->hops > CONF.MAX_HOPS) {
                /* Exceeded allowed number of hops, cancel reception */
@@ -1665,24 +1692,27 @@ validate_msg_line(char *line, ssize_t *len, int *res, void *udata)
        /* Now verify for existance of headers we consider mandatory.
         * We'll create them if necessary.
         */
-       if (mm_strncasecmp(line, "Message-Id: ", 12) == 0 && !ud->msgid) {
-           if ((ud->h_id = mmstrdup(&line[12])) != NULL)
+       if (mm_strcmp(header, "MESSAGE-ID") == 0 && !ud->msgid) {
+           if ((ud->h_id = mmstrdup(data)) != NULL)
                ud->msgid = true;
-       } else if (mm_strncasecmp(line, "Date:", 5) == 0)
+
+       } else if (mm_strcmp(header, "DATE") == 0 && !ud->date)
            ud->date = true;
-       else if (mm_strncasecmp(line, "From: ", 6) == 0 && !ud->from) {
-           if ((ud->h_from = mmstrdup(&line[6])) != NULL)
+
+       else if (mm_strcmp(header, "FROM") == 0 && !ud->from) {
+           if ((ud->h_from = mmstrdup(data)) != NULL)
                ud->from = true;
-       } else if (mm_strncasecmp(line, "To: ", 4) == 0 && !ud->to) {
-           if ((ud->h_to = mmstrdup(&line[4])) != NULL)
+
+       } else if (mm_strcmp(header, "TO") == 0 && !ud->to) {
+           if ((ud->h_to = mmstrdup(data)) != NULL)
                ud->to = true;
-       } else if (mm_strncasecmp(line, "Subject: ", 9) == 0 &&
-           !ud->subject) {
-           if ((ud->h_subject = mmstrdup(&line[9])) != NULL)
+
+       } else if (mm_strcmp(header, "SUBJECT") == 0 && !ud->subject) {
+           if ((ud->h_subject = mmstrdup(data)) != NULL)
                ud->subject = true;
-       } else if (mm_strncasecmp(line, "In-Reply-To: ", 13) == 0 &&
-               !ud->inreply) {
-           if ((ud->h_reply = mmstrdup(&line[13])) != NULL)
+
+       } else if (mm_strcmp(header, "IN-REPLY-TO") == 0 && !ud->inreply) {
+           if ((ud->h_reply = mmstrdup(data)) != NULL)
                ud->inreply = true;
        }
 
@@ -1823,6 +1853,7 @@ do_data(clientenv *clenv)
        if (CONF.STATFAIL_TIMEOUT)
            mmstat(&clenv->pstat, STAT_UPDATE, 1, "mmsmtpd|failed|timeout|%s",
                    clenv->c_ipaddr);
+       err = DATA_TIMEOUT;
        break;
     case FDBRB_EOF:
        mmsyslog(0, LOGLEVEL, "%08X * Unexpected EOF", clenv->id);
@@ -1832,6 +1863,11 @@ do_data(clientenv *clenv)
        err = DATA_HOPS;
        REGISTER_ERROR(clenv);
        break;
+    case CFDBRB_HEADER:
+       mmsyslog(0, LOGLEVEL, "%08X * Forbidden header match", clenv->id);
+       err = DATA_HEADER;
+       REGISTER_ERROR(clenv);
+       break;
     case FDBRB_OK:
        ok = TRUE;
        break;
index 956d68c..6d360b1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmsmtpd.h,v 1.46 2008/01/10 22:09:24 mmondor Exp $ */
+/* $Id: mmsmtpd.h,v 1.47 2008/12/26 08:45:11 mmondor Exp $ */
 
 /*
  * Copyright (C) 2001-2008, Matthew Mondor
@@ -97,7 +97,9 @@ enum data_reason {
     DATA_SUBMIT = 0,
     DATA_OK,
     DATA_OVERFLOW,
+    DATA_TIMEOUT,
     DATA_HOPS,
+    DATA_HEADER,
     DATA_INTERNAL,
     DATA_MAX
 };
@@ -109,6 +111,7 @@ enum data_reason {
 
 /* Custom fdbreadbuf() return result */
 #define CFDBRB_HOPS    -1
+#define CFDBRB_HEADER  -2
 
 /* Asynchroneous functions we attach */
 #define ASYNC_RESQUERY 1
@@ -214,8 +217,8 @@ typedef struct command {
 
 /* Information for a mailbox */
 struct box_info {
-    long       max_size, size, max_msgs, msgs;
-    bool       filter, filter_type;
+    long max_size, size, max_msgs, msgs;
+    bool filter, filter_type;
 };
 
 /* For fast command lookup */