changeset 1023:dc660f588218 HEAD

Disconnect client if given non-sync literal size is too large. Better than eating the input.
author Timo Sirainen <tss@iki.fi>
date Thu, 23 Jan 2003 05:28:46 +0200
parents 09bac2875ed8
children 2b7eaf2d31a1
files src/imap/client.c src/imap/client.h src/imap/cmd-append.c src/imap/commands-util.c src/lib-imap/imap-parser.c src/lib-imap/imap-parser.h
diffstat 6 files changed, 40 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/client.c	Thu Jan 23 05:17:09 2003 +0200
+++ b/src/imap/client.c	Thu Jan 23 05:28:46 2003 +0200
@@ -45,9 +45,8 @@
 {
 	struct client *client = context;
 
-	client_send_line(my_client, "* BYE Disconnected for inactivity "
-			 "while waiting for command data.");
-	o_stream_close(client->output);
+	client_disconnect_with_error(client,
+		"Disconnected for inactivity while waiting for command data.");
 }
 
 struct client *client_create(int hin, int hout, struct mail_storage *storage)
@@ -112,6 +111,12 @@
 	o_stream_close(client->output);
 }
 
+void client_disconnect_with_error(struct client *client, const char *msg)
+{
+	client_send_line(client, t_strconcat("* BYE ", msg, NULL));
+	client_disconnect(client);
+}
+
 void client_send_line(struct client *client, const char *data)
 {
 	if (client->output->closed)
@@ -140,18 +145,23 @@
 void client_send_command_error(struct client *client, const char *msg)
 {
 	const char *error;
+	int fatal;
 
-	if (msg == NULL)
-                msg = imap_parser_get_error(client->parser);
+	if (msg == NULL) {
+		msg = imap_parser_get_error(client->parser, &fatal);
+		if (fatal) {
+			client_disconnect_with_error(client, msg);
+			return;
+		}
+	}
 	error = t_strconcat("BAD Error in IMAP command: ", msg, NULL);
 
 	client->cmd_error = TRUE;
 	client_send_tagline(client, error);
 
 	if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
-		client_send_line(client,
-				 "* BYE Too many invalid IMAP commands.");
-		client_disconnect(client);
+		client_disconnect_with_error(client,
+			"Too many invalid IMAP commands.");
 	}
 }
 
--- a/src/imap/client.h	Thu Jan 23 05:17:09 2003 +0200
+++ b/src/imap/client.h	Thu Jan 23 05:28:46 2003 +0200
@@ -41,6 +41,7 @@
 
 /* Disconnect client connection */
 void client_disconnect(struct client *client);
+void client_disconnect_with_error(struct client *client, const char *msg);
 
 /* Send a line of data to client */
 void client_send_line(struct client *client, const char *data);
--- a/src/imap/cmd-append.c	Thu Jan 23 05:17:09 2003 +0200
+++ b/src/imap/cmd-append.c	Thu Jan 23 05:28:46 2003 +0200
@@ -51,10 +51,10 @@
 	struct imap_arg_list *flags_list;
 	struct mail_full_flags flags;
 	time_t internal_date;
-	const char *mailbox, *internal_date_str;
+	const char *mailbox, *internal_date_str, *error;
 	uoff_t msg_size;
 	unsigned int count;
-	int ret, failed, timezone_offset, nonsync;
+	int ret, failed, timezone_offset, nonsync, fatal_error;
 
 	/* <mailbox> */
 	if (!client_read_string_args(client, 1, &mailbox))
@@ -94,8 +94,15 @@
 			if (ret >= 0)
 				break;
 			if (ret == -1) {
-				client_send_command_error(client,
-					imap_parser_get_error(save_parser));
+				error = imap_parser_get_error(save_parser,
+							      &fatal_error);
+				if (fatal_error) {
+					client_disconnect_with_error(client,
+								     error);
+				} else {
+					client_send_command_error(client,
+								  error);
+				}
 				break;
 			}
 
--- a/src/imap/commands-util.c	Thu Jan 23 05:17:09 2003 +0200
+++ b/src/imap/commands-util.c	Thu Jan 23 05:28:46 2003 +0200
@@ -110,9 +110,8 @@
 	if (client->mailbox != NULL &&
 	    client->mailbox->is_inconsistency_error(client->mailbox)) {
 		/* we can't do forced CLOSE, so have to disconnect */
-		client_send_line(client, "* BYE Mailbox is in inconsistent "
-				 "state, please relogin.");
-		client_disconnect(client);
+		client_disconnect_with_error(client,
+			"Mailbox is in inconsistent state, please relogin.");
 		return;
 	}
 
--- a/src/lib-imap/imap-parser.c	Thu Jan 23 05:17:09 2003 +0200
+++ b/src/lib-imap/imap-parser.c	Thu Jan 23 05:28:46 2003 +0200
@@ -45,6 +45,7 @@
 	unsigned int literal_nonsync:1;
 	unsigned int inside_bracket:1;
 	unsigned int eol:1;
+	unsigned int fatal_error:1;
 };
 
 /* @UNSAFE */
@@ -113,8 +114,9 @@
 	imap_args_realloc(parser, LIST_ALLOC_SIZE);
 }
 
-const char *imap_parser_get_error(struct imap_parser *parser)
+const char *imap_parser_get_error(struct imap_parser *parser, int *fatal)
 {
+        *fatal = parser->fatal_error;
 	return parser->error;
 }
 
@@ -334,6 +336,7 @@
 		if (parser->literal_size > parser->max_literal_size) {
 			/* too long string, abort. */
 			parser->error = "Literal size too large";
+			parser->fatal_error = TRUE;
 			return FALSE;
 		}
 
--- a/src/lib-imap/imap-parser.h	Thu Jan 23 05:17:09 2003 +0200
+++ b/src/lib-imap/imap-parser.h	Thu Jan 23 05:28:46 2003 +0200
@@ -68,8 +68,10 @@
 /* Reset the parser to initial state. */
 void imap_parser_reset(struct imap_parser *parser);
 
-/* Return the last error in parser. */
-const char *imap_parser_get_error(struct imap_parser *parser);
+/* Return the last error in parser. fatal is set to TRUE if there's no way to
+   continue parsing, currently only if too large non-sync literal size was
+   given. */
+const char *imap_parser_get_error(struct imap_parser *parser, int *fatal);
 
 /* Read a number of arguments. This function doesn't call i_stream_read(), you
    need to do that. Returns number of arguments read (may be less than count