From 6b16d3e04ef68a67390b31fbd18d714aaaa4528f Mon Sep 17 00:00:00 2001 From: Stephan Bosch Date: Sun, 8 Apr 2018 12:25:49 +0200 Subject: [PATCH] lib-smtp: server: Add workarounds for well-known MAIL and RCPT command syntax deviations. --- src/lib-smtp/smtp-server-cmd-mail.c | 24 +++++++++++++++++++++--- src/lib-smtp/smtp-server-cmd-rcpt.c | 23 ++++++++++++++++++++--- src/lib-smtp/smtp-server-connection.c | 2 ++ src/lib-smtp/smtp-server.c | 1 + src/lib-smtp/smtp-server.h | 6 ++++++ 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/lib-smtp/smtp-server-cmd-mail.c b/src/lib-smtp/smtp-server-cmd-mail.c index abb9cee778..a270f5b5df 100644 --- a/src/lib-smtp/smtp-server-cmd-mail.c +++ b/src/lib-smtp/smtp-server-cmd-mail.c @@ -73,6 +73,7 @@ void smtp_server_cmd_mail(struct smtp_server_cmd_ctx *cmd, const struct smtp_server_callbacks *callbacks = conn->callbacks; struct smtp_server_command *command = cmd->cmd; struct smtp_server_cmd_mail *mail_data; + enum smtp_address_parse_flags path_parse_flags; struct smtp_address *path; enum smtp_param_parse_error pperror; const char *error; @@ -91,9 +92,26 @@ void smtp_server_cmd_mail(struct smtp_server_cmd_ctx *cmd, smtp_server_reply(cmd, 501, "5.5.4", "Invalid parameters"); return; } - if (smtp_address_parse_path_full(pool_datastack_create(), params + 5, - SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY, - &path, &error, ¶ms) < 0) { + if (params[5] != ' ' && params[5] != '\t') { + params += 5; + } else if ((set->workarounds & + SMTP_SERVER_WORKAROUND_WHITESPACE_BEFORE_PATH) != 0) { + params += 5; + while (*params == ' ' || *params == '\t') + params++; + } else { + smtp_server_reply(cmd, 501, "5.5.4", + "Invalid FROM: " + "Unexpected whitespace before path"); + return; + } + path_parse_flags = SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY; + if (*params != '\0' && + (set->workarounds & SMTP_SERVER_WORKAROUND_MAILBOX_FOR_PATH) != 0) + path_parse_flags |= SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL; + if (smtp_address_parse_path_full(pool_datastack_create(), params, + path_parse_flags, &path, &error, + ¶ms) < 0) { smtp_server_reply(cmd, 501, "5.5.4", "Invalid FROM: %s", error); return; } diff --git a/src/lib-smtp/smtp-server-cmd-rcpt.c b/src/lib-smtp/smtp-server-cmd-rcpt.c index a3417b7b06..15bb5d6359 100644 --- a/src/lib-smtp/smtp-server-cmd-rcpt.c +++ b/src/lib-smtp/smtp-server-cmd-rcpt.c @@ -100,6 +100,7 @@ void smtp_server_cmd_rcpt(struct smtp_server_cmd_ctx *cmd, const struct smtp_server_callbacks *callbacks = conn->callbacks; struct smtp_server_command *command = cmd->cmd; struct smtp_server_cmd_rcpt *rcpt_data; + enum smtp_address_parse_flags path_parse_flags; struct smtp_address *path; enum smtp_param_parse_error pperror; const char *error; @@ -120,9 +121,25 @@ void smtp_server_cmd_rcpt(struct smtp_server_cmd_ctx *cmd, 501, "5.5.4", "Invalid parameters"); return; } - if (smtp_address_parse_path_full(pool_datastack_create(), params + 3, - SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART, - &path, &error, ¶ms) < 0) { + if (params[3] != ' ' && params[3] != '\t') { + params += 3; + } else if ((set->workarounds & + SMTP_SERVER_WORKAROUND_WHITESPACE_BEFORE_PATH) != 0) { + params += 3; + while (*params == ' ' || *params == '\t') + params++; + } else { + smtp_server_reply(cmd, 501, "5.5.4", + "Invalid TO: " + "Unexpected whitespace before path"); + return; + } + path_parse_flags = SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART; + if ((set->workarounds & SMTP_SERVER_WORKAROUND_MAILBOX_FOR_PATH) != 0) + path_parse_flags |= SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL; + if (smtp_address_parse_path_full(pool_datastack_create(), params, + path_parse_flags, &path, &error, + ¶ms) < 0) { smtp_server_reply(cmd, 501, "5.5.4", "Invalid TO: %s", error); return; diff --git a/src/lib-smtp/smtp-server-connection.c b/src/lib-smtp/smtp-server-connection.c index cca0e570a3..1c0fdb33d4 100644 --- a/src/lib-smtp/smtp-server-connection.c +++ b/src/lib-smtp/smtp-server-connection.c @@ -794,6 +794,8 @@ smtp_server_connection_alloc(struct smtp_server *server, } if (set->capabilities != 0) conn->set.capabilities = set->capabilities; + conn->set.workarounds |= set->workarounds; + if (set->max_client_idle_time_msecs > 0) { conn->set.max_client_idle_time_msecs = set->max_client_idle_time_msecs; diff --git a/src/lib-smtp/smtp-server.c b/src/lib-smtp/smtp-server.c index 003b6651fd..54ada3700f 100644 --- a/src/lib-smtp/smtp-server.c +++ b/src/lib-smtp/smtp-server.c @@ -43,6 +43,7 @@ struct smtp_server *smtp_server_init(const struct smtp_server_settings *set) } else { server->set.capabilities = set->capabilities; } + server->set.workarounds = set->workarounds; server->set.max_client_idle_time_msecs = set->max_client_idle_time_msecs; server->set.max_pipelined_commands = (set->max_pipelined_commands > 0 ? set->max_pipelined_commands : 1); diff --git a/src/lib-smtp/smtp-server.h b/src/lib-smtp/smtp-server.h index 98c5e420bb..bc749b06f2 100644 --- a/src/lib-smtp/smtp-server.h +++ b/src/lib-smtp/smtp-server.h @@ -226,9 +226,15 @@ struct smtp_server_callbacks { * Server */ +enum smtp_server_workarounds { + SMTP_SERVER_WORKAROUND_WHITESPACE_BEFORE_PATH = BIT(0), + SMTP_SERVER_WORKAROUND_MAILBOX_FOR_PATH = BIT(1) +}; + struct smtp_server_settings { enum smtp_protocol protocol; enum smtp_capability capabilities; + enum smtp_server_workarounds workarounds; const char *hostname; const char *login_greeting;