]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
submission: Add workarounds for well-known MAIL and RCPT command syntax deviations.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 8 Apr 2018 13:53:37 +0000 (15:53 +0200)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Fri, 27 Apr 2018 10:40:00 +0000 (13:40 +0300)
This adds a new `submission_client_workarounds' setting that works analogous to
the `imap_client_workarounds' setting.

Workarounds:

- whitespace-before-path: Allow one or more spaces or tabs between `MAIL FROM:'
                          and path and between `RCPT TO:' and path.
- mailbox-for-path:       Allow using bare Mailbox syntax (i.e., without <...>)
                          instead of full path syntax.

doc/example-config/conf.d/20-submission.conf
src/submission/submission-client.c
src/submission/submission-settings.c
src/submission/submission-settings.h

index d27009a3822e16aa16752cac6ad1bbe25d5f8b8a..078faf128b02e4f57732f8c2830d4ff25367ce8c 100644 (file)
 # Maximum number of recipients accepted per connection (default: unlimited)
 #submission_max_recipients =
 
+# Workarounds for various client bugs:
+#   whitespace-before-path:
+#     Allow one or more spaces or tabs between `MAIL FROM:' and path and between
+#     `RCPT TO:' and path.
+#   mailbox-for-path:
+#     Allow using bare Mailbox syntax (i.e., without <...>) instead of full path
+#     syntax.
+#
+# The list is space-separated.
+#submission_client_workarounds =
+
 # Relay server configuration:
 #
 # The Dovecot SMTP submission service directly proxies the mail transaction
index c4f8cf3812c42cc0b7e5059085cbb13e1f2c5153..f98a16f436501580731f1adc9976f7f39815e91c 100644 (file)
@@ -185,6 +185,8 @@ struct client *client_create(int fd_in, int fd_out,
                             const char *helo,
                             const unsigned char *pdata, unsigned int pdata_len)
 {
+       enum submission_client_workarounds workarounds =
+               set->parsed_workarounds;
        const struct mail_storage_settings *mail_set;
        struct smtp_server_settings smtp_set;
        const char *ident;
@@ -207,6 +209,15 @@ struct client *client_create(int fd_in, int fd_out,
        smtp_set.max_client_idle_time_msecs = CLIENT_IDLE_TIMEOUT_MSECS;
        smtp_set.debug = user->mail_debug;
 
+       if ((workarounds & WORKAROUND_WHITESPACE_BEFORE_PATH) != 0) {
+               smtp_set.workarounds |=
+                       SMTP_SERVER_WORKAROUND_WHITESPACE_BEFORE_PATH;
+       }
+       if ((workarounds & WORKAROUND_MAILBOX_FOR_PATH) != 0) {
+               smtp_set.workarounds |=
+                       SMTP_SERVER_WORKAROUND_MAILBOX_FOR_PATH;
+       }
+
        client->conn = smtp_server_connection_create(smtp_server,
                fd_in, fd_out, user->conn.remote_ip, user->conn.remote_port,
                FALSE, &smtp_set, &smtp_callbacks, client);
index 160ec087779c3409124a2fd79bf4063bbcb4be9a..29bce42ddc268d473794724aa3a55a60efb8249b 100644 (file)
@@ -11,7 +11,8 @@
 #include <stddef.h>
 #include <unistd.h>
 
-static bool submission_settings_check(void *_set, pool_t pool, const char **error_r);
+static bool submission_settings_verify(void *_set, pool_t pool,
+                                      const char **error_r);
 
 /* <settings checks> */
 static struct file_listener_settings submission_unix_listeners_array[] = {
@@ -65,6 +66,7 @@ static const struct setting_define submission_setting_defines[] = {
 
        DEF(SET_SIZE, submission_max_mail_size),
        DEF(SET_UINT, submission_max_recipients),
+       DEF(SET_STR, submission_client_workarounds),
        DEF(SET_STR, submission_logout_format),
 
        DEF(SET_STR, submission_relay_host),
@@ -100,6 +102,7 @@ static const struct submission_settings submission_default_settings = {
 
        .submission_max_mail_size = 0,
        .submission_max_recipients = 0,
+       .submission_client_workarounds = "",
        .submission_logout_format = "in=%i out=%o",
 
        .submission_relay_host = "",
@@ -138,22 +141,67 @@ const struct setting_parser_info submission_setting_parser_info = {
 
        .parent_offset = (size_t)-1,
 
-#ifndef CONFIG_BINARY
-       .check_func = submission_settings_check,
-#endif
+       .check_func = submission_settings_verify,
        .dependencies = submission_setting_dependencies
 };
 
-static bool submission_settings_check(void *_set, pool_t pool,
-                                const char **error_r ATTR_UNUSED)
+/* <settings checks> */
+struct submission_client_workaround_list {
+       const char *name;
+       enum submission_client_workarounds num;
+};
+
+static const struct submission_client_workaround_list
+submission_client_workaround_list[] = {
+       { "whitespace-before-path", WORKAROUND_WHITESPACE_BEFORE_PATH },
+       { "mailbox-for-path", WORKAROUND_MAILBOX_FOR_PATH },
+       { NULL, 0 }
+};
+
+static int
+submission_settings_parse_workarounds(struct submission_settings *set,
+                               const char **error_r)
+{
+       enum submission_client_workarounds client_workarounds = 0;
+        const struct submission_client_workaround_list *list;
+       const char *const *str;
+
+        str = t_strsplit_spaces(set->submission_client_workarounds, " ,");
+       for (; *str != NULL; str++) {
+               list = submission_client_workaround_list;
+               for (; list->name != NULL; list++) {
+                       if (strcasecmp(*str, list->name) == 0) {
+                               client_workarounds |= list->num;
+                               break;
+                       }
+               }
+               if (list->name == NULL) {
+                       *error_r = t_strdup_printf(
+                               "submission_client_workarounds: "
+                               "Unknown workaround: %s", *str);
+                       return -1;
+               }
+       }
+       set->parsed_workarounds = client_workarounds;
+       return 0;
+}
+
+static bool
+submission_settings_verify(void *_set, pool_t pool ATTR_UNUSED, const char **error_r)
 {
        struct submission_settings *set = _set;
 
+       if (submission_settings_parse_workarounds(set, error_r) < 0)
+               return FALSE;
+
+#ifndef CONFIG_BINARY
        if (set->submission_relay_max_idle_time == 0) {
                *error_r = "submission_relay_max_idle_time must not be 0";
                return FALSE;
        }
        if (*set->hostname == '\0')
                set->hostname = p_strdup(pool, my_hostdomain());
+#endif
        return TRUE;
 }
+/* </settings checks> */
index 6c260d0def3045020dac3572106777f2a112965b..dee42607e6f098ed70f1d3bdc1b57db92042e4d1 100644 (file)
@@ -1,6 +1,15 @@
 #ifndef SUBMISSION_SETTINGS_H
 #define SUBMISSION_SETTINGS_H
 
+#include "smtp-server.h"
+
+/* <settings checks> */
+enum submission_client_workarounds {
+       WORKAROUND_WHITESPACE_BEFORE_PATH       = BIT(0),
+       WORKAROUND_MAILBOX_FOR_PATH             = BIT(1),
+};
+/* </settings checks> */
+
 struct submission_settings {
        bool verbose_proctitle;
 
@@ -12,6 +21,7 @@ struct submission_settings {
        /* submission: */
        size_t submission_max_mail_size;
        unsigned int submission_max_recipients;
+       const char *submission_client_workarounds;
        const char *submission_logout_format;
 
        /* submission relay: */
@@ -35,6 +45,8 @@ struct submission_settings {
        /* imap urlauth: */
        const char *imap_urlauth_host;
        in_port_t imap_urlauth_port;
+
+       enum submission_client_workarounds parsed_workarounds;
 };
 
 extern const struct setting_parser_info submission_setting_parser_info;