dovecot-1.2: pop3: Prevent clients from looping forever trying t...

dovecot at dovecot.org dovecot at dovecot.org
Wed Jan 14 18:13:19 EET 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/16f4752882b9
changeset: 8624:16f4752882b9
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jan 14 11:13:15 2009 -0500
description:
pop3: Prevent clients from looping forever trying to fetch an expunged message.

diffstat:

2 files changed, 22 insertions(+), 8 deletions(-)
src/pop3/client.h   |    1 +
src/pop3/commands.c |   29 +++++++++++++++++++++--------

diffs (89 lines):

diff -r e6a58515d86d -r 16f4752882b9 src/pop3/client.h
--- a/src/pop3/client.h	Wed Jan 14 10:47:47 2009 -0500
+++ b/src/pop3/client.h	Wed Jan 14 11:13:15 2009 -0500
@@ -23,6 +23,7 @@ struct client {
 
 	time_t last_input, last_output;
 	unsigned int bad_counter;
+	unsigned int highest_expunged_fetch_msgnum;
 
 	unsigned int uid_validity;
 	unsigned int messages_count;
diff -r e6a58515d86d -r 16f4752882b9 src/pop3/commands.c
--- a/src/pop3/commands.c	Wed Jan 14 10:47:47 2009 -0500
+++ b/src/pop3/commands.c	Wed Jan 14 11:13:15 2009 -0500
@@ -373,10 +373,24 @@ static void fetch_callback(struct client
 	client->cmd = NULL;
 }
 
-static void fetch(struct client *client, unsigned int msgnum, uoff_t body_lines)
+static int client_reply_msg_expunged(struct client *client, unsigned int msgnum)
+{
+	client_send_line(client, "-ERR Message %u expunged.", msgnum + 1);
+	if (msgnum <= client->highest_expunged_fetch_msgnum) {
+		/* client tried to fetch an expunged message again.
+		   treat this as error so we'll eventually disconnect the
+		   client instead of letting it loop forever. */
+		return -1;
+	}
+	client->highest_expunged_fetch_msgnum = msgnum;
+	return 1;
+}
+
+static int fetch(struct client *client, unsigned int msgnum, uoff_t body_lines)
 {
         struct fetch_context *ctx;
 	struct mail_search_args *search_args;
+	int ret;
 
 	search_args = pop3_search_build(client, msgnum+1);
 
@@ -389,9 +403,9 @@ static void fetch(struct client *client,
 
 	if (mailbox_search_next(ctx->search_ctx, ctx->mail) <= 0 ||
 	    mail_get_stream(ctx->mail, NULL, NULL, &ctx->stream) < 0) {
-		client_send_line(client, "-ERR Message not found.");
+		ret = client_reply_msg_expunged(client, msgnum);
 		fetch_deinit(ctx);
-		return;
+		return ret;
 	}
 
 	if (body_lines == (uoff_t)-1 && !no_flag_updates) {
@@ -414,6 +428,7 @@ static void fetch(struct client *client,
 	client->cmd = fetch_callback;
 	client->cmd_context = ctx;
 	fetch_callback(client);
+	return 1;
 }
 
 static int cmd_retr(struct client *client, const char *args)
@@ -430,8 +445,7 @@ static int cmd_retr(struct client *clien
 	client->byte_counter = &client->retr_bytes;
 	client->byte_counter_offset = client->output->offset;
 
-	fetch(client, msgnum, (uoff_t)-1);
-	return 1;
+	return fetch(client, msgnum, (uoff_t)-1);
 }
 
 static int cmd_rset(struct client *client, const char *args ATTR_UNUSED)
@@ -495,8 +509,7 @@ static int cmd_top(struct client *client
 	client->byte_counter = &client->top_bytes;
 	client->byte_counter_offset = client->output->offset;
 
-	fetch(client, msgnum, max_lines);
-	return 1;
+	return fetch(client, msgnum, max_lines);
 }
 
 struct cmd_uidl_context {
@@ -653,7 +666,7 @@ static int cmd_uidl(struct client *clien
 
 		ctx = cmd_uidl_init(client, msgnum+1);
 		if (!list_uids_iter(client, ctx))
-			client_send_line(client, "-ERR Message not found.");
+			return client_reply_msg_expunged(client, msgnum);
 	}
 
 	return 1;


More information about the dovecot-cvs mailing list