MMMail: Add optional support to match client host with HELO host for the master
authorMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 21 May 2020 13:08:47 +0000 (13:08 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 21 May 2020 13:08:47 +0000 (13:08 +0000)
last two domain parts, MATCH_HELO_HOST.  Still subject to nores DB exceptions.

mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.c
mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.h

index b5e8a4f..5b9014d 100644 (file)
@@ -308,6 +308,7 @@ main(int argc, char **argv)
        {CAT_BOOL, CAF_NONE, 0, 0, "RESOLVE_HELO", &CONF.RESOLVE_HELO},
        {CAT_BOOL, CAF_NONE, 0, 0, "RESOLVE_MX_MAIL", &CONF.RESOLVE_MX_MAIL},
        {CAT_BOOL, CAF_NONE, 0, 0, "RESOLVE_MX_RCPT", &CONF.RESOLVE_MX_RCPT},
+       {CAT_BOOL, CAF_NONE, 0, 0, "MATCH_HELO_HOST", &CONF.MATCH_HELO_HOST},
        {CAT_BOOL, CAF_NONE, 0, 0, "REQUIRE_HELO", &CONF.REQUIRE_HELO},
        {CAT_BOOL, CAF_NONE, 0, 0, "REQUIRE_HOP", &CONF.REQUIRE_HOP},
        {CAT_BOOL, CAF_NONE, 0, 0, "FLOOD_PROTECTION", &CONF.FLOOD_PROTECTION},
@@ -386,6 +387,7 @@ main(int argc, char **argv)
     CONF.RESOLVE_HELO = false;
     CONF.RESOLVE_MX_MAIL = false;
     CONF.RESOLVE_MX_RCPT = false;
+    CONF.MATCH_HELO_HOST = false;
     CONF.REQUIRE_HELO = false;
     CONF.REQUIRE_HOP = false;
     CONF.FLOOD_PROTECTION = true;
@@ -1632,12 +1634,29 @@ valid_host(clientenv *clenv, char *host, int res, bool addr, bool sanity)
                return true;
 
        if (res == HOST_RES_MX) {
-           /* Check for an MX DNS IP address entry for it */
+           /* Check for an MX DNS IP address entry for it,
+            * Used for MAIL FROM and RCPT TO if relaying
+            */
            if ((a_res_query(clenv, host, C_IN, T_MX, answer,
                            sizeof(answer) - 1)) == -1)
                return false;
        } else if (res == HOST_RES) {
-           /* Check if hostname resolves to normal A/AAAA record */
+           /* Ensure that client and HELO hostname last parts match */
+           if (CONF.MATCH_HELO_HOST && clenv->c_hostname != NULL) {
+               register char *ptr1, *ptr2;
+               register int i = 0;
+
+               for (ptr1 = clenv->c_hostname; *ptr1 != '\0'; ptr1++) ;
+               for (ptr2 = host; *ptr2 != '\0'; ptr2++) ;
+               for (i = 0; i < 2 && ptr1 >= clenv->c_hostname && ptr2 >= host;
+                   ptr1--, ptr2--) {
+                   if (tolower((int)*ptr1 != tolower((int)*ptr2)))
+                       return false;
+                   if (*ptr1 == '.')
+                           i++;
+               }
+           }
+           /* Check if hostname resolves to normal A/AAAA record, for HELO */
            if (a_res_query(clenv, host, C_IN, T_A, answer,
                        sizeof(answer) - 1) == -1 &&
                    a_res_query(clenv, host, C_IN, T_AAAA, answer,
index 0d7a264..317210f 100644 (file)
@@ -145,10 +145,10 @@ typedef struct config {
        MAX_DATA_LINES, MAX_DATA_SIZE, MAX_HOPS, FLOOD_MESSAGES,
        FLOOD_EXPIRES, FLOOD_CACHE, ASYNC_PROCESSES;
     bool RESOLVE_HOSTS, RESOLVE_HELO, RESOLVE_MX_MAIL, RESOLVE_MX_RCPT,
-       REQUIRE_HELO, REQUIRE_HOP, FLOOD_PROTECTION, STATFAIL_HELO,
-       STATFAIL_NOHELO, STATFAIL_NOFROM, STATFAIL_ADDRESS, STATFAIL_RELAY,
-       STATFAIL_FLOOD, STATFAIL_FULL, STATFAIL_TIMEOUT, STATFAIL_EOF,
-       STATFAIL_FILTER, DELAY_ON_ERROR, RELAYING, DB_VACUUM;
+       MATCH_HELO_HOST, REQUIRE_HELO, REQUIRE_HOP, FLOOD_PROTECTION,
+       STATFAIL_HELO, STATFAIL_NOHELO, STATFAIL_NOFROM, STATFAIL_ADDRESS,
+       STATFAIL_RELAY, STATFAIL_FLOOD, STATFAIL_FULL, STATFAIL_TIMEOUT,
+       STATFAIL_EOF, STATFAIL_FILTER, DELAY_ON_ERROR, RELAYING, DB_VACUUM;
 } CONFIG;