dovecot-2.2: imap: Allow very long MULTIAPPEND CATENATE lines th...

dovecot at dovecot.org dovecot at dovecot.org
Wed Aug 29 21:08:20 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/c73086239699
changeset: 14980:c73086239699
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Aug 29 21:08:08 2012 +0300
description:
imap: Allow very long MULTIAPPEND CATENATE lines that contain only URLs.

diffstat:

 src/imap/cmd-append.c |  40 ++++++++++++++++++++++++++++++++++------
 1 files changed, 34 insertions(+), 6 deletions(-)

diffs (70 lines):

diff -r e0a3812771fd -r c73086239699 src/imap/cmd-append.c
--- a/src/imap/cmd-append.c	Wed Aug 29 21:04:45 2012 +0300
+++ b/src/imap/cmd-append.c	Wed Aug 29 21:08:08 2012 +0300
@@ -339,7 +339,10 @@
 		return TRUE;
 	}
 
-	/* we're parsing inside CATENATE (..) list after handling a TEXT part */
+	/* we're parsing inside CATENATE (..) list after handling a TEXT part.
+	   it's fine that this would need to fully fit into input buffer
+	   (although clients attempting to DoS could simply insert an extra
+	   {1+} between the URLs) */
 	ret = imap_parser_read_args(ctx->save_parser, 0,
 				    IMAP_PARSE_FLAG_LITERAL_SIZE |
 				    IMAP_PARSE_FLAG_LITERAL8 |
@@ -603,12 +606,33 @@
 	return cmd_sync(cmd, sync_flags, imap_flags, str_c(msg));
 }
 
+static bool cmd_append_args_can_stop(const struct imap_arg *args)
+{
+	if (args->type == IMAP_ARG_EOL)
+		return TRUE;
+
+	/* [(flags)] ["internal date"] <message literal> | CATENATE (..) */
+	if (args->type == IMAP_ARG_LIST)
+		args++;
+	if (args->type == IMAP_ARG_STRING)
+		args++;
+
+	if (args->type == IMAP_ARG_LITERAL_SIZE ||
+	    args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC)
+		return TRUE;
+	if (imap_arg_atom_equals(args, "CATENATE") &&
+	    args[1].type == IMAP_ARG_LIST)
+		return TRUE;
+	return FALSE;
+}
+
 static bool cmd_append_parse_new_msg(struct client_command_context *cmd)
 {
 	struct client *client = cmd->client;
 	struct cmd_append_context *ctx = cmd->context;
 	const struct imap_arg *args;
 	const char *msg;
+	unsigned int arg_min_count;
 	bool fatal, nonsync;
 	int ret;
 
@@ -624,11 +648,15 @@
 	/* if error occurs, the CRLF is already read. */
 	client->input_skip_line = FALSE;
 
-	/* parse the entire line up to the first message literal
-	   FIXME: we could do with less with CATENATE.. */
-	ret = imap_parser_read_args(ctx->save_parser, 0,
-				    IMAP_PARSE_FLAG_LITERAL_SIZE |
-				    IMAP_PARSE_FLAG_LITERAL8, &args);
+	/* parse the entire line up to the first message literal, or in case
+	   the input buffer is full of MULTIAPPEND CATENATE URLs, parse at
+	   least until the beginning of the next message */
+	arg_min_count = 1;
+	do {
+		ret = imap_parser_read_args(ctx->save_parser, arg_min_count++,
+					    IMAP_PARSE_FLAG_LITERAL_SIZE |
+					    IMAP_PARSE_FLAG_LITERAL8, &args);
+	} while (ret > 0 && !cmd_append_args_can_stop(args));
 	if (ret == -1) {
 		if (!ctx->failed) {
 			msg = imap_parser_get_error(ctx->save_parser, &fatal);


More information about the dovecot-cvs mailing list