]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: smtp-command-parser - Accept valid UTF-8 characters for command parameters.
authorStephan Bosch <stephan.bosch@open-xchange.com>
Fri, 4 Oct 2019 18:47:35 +0000 (20:47 +0200)
committerStephan Bosch <stephan.bosch@open-xchange.com>
Fri, 4 Oct 2019 18:48:23 +0000 (20:48 +0200)
src/lib-smtp/smtp-command-parser.c
src/lib-smtp/test-smtp-command-parser.c

index c8b09c8d4e1c5f8d957fcc4a831a1476fdfd64c1..4fd6bd59e97c0559168c9b6e8425fbf46d3ab2ec 100644 (file)
@@ -1,6 +1,7 @@
 /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "unichar.h"
 #include "istream.h"
 #include "istream-failure-at.h"
 #include "istream-sized.h"
@@ -169,12 +170,31 @@ static int smtp_command_parse_parameters(struct smtp_command_parser *parser)
                parser->limits.max_auth_size :
                parser->limits.max_parameters_size);
 
-       /* We assume parameters to match textstr
-          => HT, SP, Printable US-ASCII
+       /* We assume parameters to match textstr (HT, SP, Printable US-ASCII).
+          For command parameters, we also accept valid UTF-8 characters.
         */
        p = parser->cur + parser->state.poff;
-       while (p < parser->end && smtp_char_is_textstr(*p))
-               p++;
+       while (p < parser->end) {
+               unichar_t ch;
+               int nch = 1;
+
+               if (parser->auth_response)
+                       ch = *p;
+               else {
+                       nch = uni_utf8_get_char_n(p, (size_t)(p - parser->end),
+                                                 &ch);
+               }
+               if (nch < 0) {
+                       smtp_command_parser_error(parser,
+                               SMTP_COMMAND_PARSE_ERROR_BAD_COMMAND,
+                               "Invalid UTF-8 character in command parameters");
+                       return -1;
+               }
+               if ((parser->auth_response || (ch & 0x80) == 0x00) &&
+                   !smtp_char_is_textstr((unsigned char)ch))
+                       break;
+               p += nch;
+       }
        if (max_size > 0 && (uoff_t)(p - parser->cur) > max_size) {
                smtp_command_parser_error(parser,
                        SMTP_COMMAND_PARSE_ERROR_LINE_TOO_LONG,
index 71ef1a23157537553f820cc428fb9d783cbeb9c6..304409cff3ed71c9472375297c6e85ec66c0e8e1 100644 (file)
@@ -56,6 +56,10 @@ valid_command_parse_tests[] = {
                .limits = { .max_parameters_size = 39 },
                .cmd_name = "RCPT",
                .cmd_params = "TO:<recipient@example.com> NOTIFY=NEVER"
+       }, {
+               .command = "MAIL FROM:<f\xc3\xb6\xc3\xa4@\xc3\xb6\xc3\xa4>\r\n",
+               .cmd_name = "MAIL",
+               .cmd_params = "FROM:<f\xc3\xb6\xc3\xa4@\xc3\xb6\xc3\xa4>"
        }
 };
 
@@ -271,6 +275,9 @@ static const struct smtp_auth_response_parse_invalid_test
                        "B2ZXJ5IHZlcnkgdmVyeSBsb25nIEJhc2U2NCB0ZXN0\r\n",
                .limits = { .max_auth_size = 83 },
                .error_code = SMTP_COMMAND_PARSE_ERROR_LINE_TOO_LONG
+       }, {
+               .auth_response = "\xc3\xb6\xc3\xa4\xc3\xb6\xc3\xa4\r\n",
+               .error_code = SMTP_COMMAND_PARSE_ERROR_BAD_COMMAND,
        }
 };