]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap: If SELECT fails with "mailbox is inconsistent", disconnect client. (Plus relate...
authorTimo Sirainen <tss@iki.fi>
Tue, 3 Dec 2013 15:29:38 +0000 (17:29 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 3 Dec 2013 15:29:38 +0000 (17:29 +0200)
The inconsistency can also be used to indicate that something is badly wrong
and nothing useful can be done before client reconnects.

15 files changed:
src/imap/cmd-append.c
src/imap/cmd-create.c
src/imap/cmd-delete.c
src/imap/cmd-expunge.c
src/imap/cmd-getmetadata.c
src/imap/cmd-rename.c
src/imap/cmd-resetkey.c
src/imap/cmd-select.c
src/imap/cmd-setmetadata.c
src/imap/cmd-store.c
src/imap/cmd-subscribe.c
src/imap/cmd-thread.c
src/imap/imap-commands-util.c
src/imap/imap-commands-util.h
src/imap/imap-search.c

index b4099d7fe1aaa0dfd664e0e2b355bd2a3a3a6680..aaa3ebf6e74790fa46c5ffb4bde4746f2bca8be8 100644 (file)
@@ -26,7 +26,6 @@
 struct cmd_append_context {
        struct client *client;
         struct client_command_context *cmd;
-       struct mail_storage *storage;
        struct mailbox *box;
         struct mailbox_transaction_context *t;
        time_t started;
@@ -181,7 +180,7 @@ cmd_append_catenate_mpurl(struct client_command_context *cmd,
        /* catenate URL */
        ret = imap_msgpart_url_read_part(mpurl, &mpresult, &error);
        if (ret < 0) {
-               client_send_storage_error(cmd, ctx->storage);
+               client_send_box_error(cmd, ctx->box);
                return -1;
        }
        if (ret == 0) {
@@ -219,11 +218,11 @@ cmd_append_catenate_mpurl(struct client_command_context *cmd,
                        "read(%s) failed: %s (for CATENATE URL %s)",
                        i_stream_get_name(mpresult.input),
                        i_stream_get_error(mpresult.input), caturl);
-               client_send_storage_error(cmd, ctx->storage);
+               client_send_box_error(cmd, ctx->box);
                ret = -1;
        } else if (!mpresult.input->eof) {
                /* save failed */
-               client_send_storage_error(cmd, ctx->storage);
+               client_send_box_error(cmd, ctx->box);
                ret = -1;
        } else {
                /* all the input must be consumed, so istream-chain's read()
@@ -248,7 +247,7 @@ cmd_append_catenate_url(struct client_command_context *cmd, const char *caturl)
        ret = imap_msgpart_url_parse(cmd->client->user, cmd->client->mailbox,
                                     caturl, &mpurl, &error);
        if (ret < 0) {
-               client_send_storage_error(cmd, ctx->storage);
+               client_send_box_error(cmd, ctx->box);
                return -1;
        }
        if (ret == 0) {
@@ -356,7 +355,7 @@ static void cmd_append_finish_catenate(struct client_command_context *cmd)
                        mailbox_save_cancel(&ctx->save_ctx);
        } else {
                if (mailbox_save_finish(&ctx->save_ctx) < 0) {
-                       client_send_storage_error(cmd, ctx->storage);
+                       client_send_box_error(cmd, ctx->box);
                        ctx->failed = TRUE;
                }
        }
@@ -532,7 +531,7 @@ cmd_append_handle_args(struct client_command_context *cmd,
                else if (mailbox_keywords_create(ctx->box, keywords_list,
                                                 &keywords) < 0) {
                        /* invalid keywords - delay failure */
-                       client_send_storage_error(cmd, ctx->storage);
+                       client_send_box_error(cmd, ctx->box);
                        ctx->failed = TRUE;
                }
        }
@@ -594,7 +593,7 @@ cmd_append_handle_args(struct client_command_context *cmd,
                                               internal_date, timezone_offset);
                if (mailbox_save_begin(&ctx->save_ctx, ctx->input) < 0) {
                        /* save initialization failed */
-                       client_send_storage_error(cmd, ctx->storage);
+                       client_send_box_error(cmd, ctx->box);
                        ctx->failed = TRUE;
                }
        }
@@ -649,7 +648,7 @@ static bool cmd_append_finish_parsing(struct client_command_context *cmd)
 
        ret = mailbox_transaction_commit_get_changes(&ctx->t, &changes);
        if (ret < 0) {
-               client_send_storage_error(cmd, ctx->storage);
+               client_send_box_error(cmd, ctx->box);
                cmd_append_finish(ctx);
                return TRUE;
        }
@@ -845,7 +844,7 @@ static bool cmd_append_continue_message(struct client_command_context *cmd)
                                mailbox_save_cancel(&ctx->save_ctx);
                } else if (ctx->save_ctx == NULL) {
                        /* failed above */
-                       client_send_storage_error(cmd, ctx->storage);
+                       client_send_box_error(cmd, ctx->box);
                        ctx->failed = TRUE;
                } else if (lit_offset != ctx->literal_size) {
                        /* client disconnected before it finished sending the
@@ -857,7 +856,7 @@ static bool cmd_append_continue_message(struct client_command_context *cmd)
                } else if (ctx->catenate) {
                        /* CATENATE isn't finished yet */
                } else if (mailbox_save_finish(&ctx->save_ctx) < 0) {
-                       client_send_storage_error(cmd, ctx->storage);
+                       client_send_box_error(cmd, ctx->box);
                        ctx->failed = TRUE;
                }
 
@@ -909,8 +908,6 @@ bool cmd_append(struct client_command_context *cmd)
        if (client_open_save_dest_box(cmd, mailbox, &ctx->box) < 0)
                ctx->failed = TRUE;
        else {
-               ctx->storage = mailbox_get_storage(ctx->box);
-
                ctx->t = mailbox_transaction_begin(ctx->box,
                                        MAILBOX_TRANSACTION_FLAG_EXTERNAL |
                                        MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS);
index 15580e47454978c804acb8578818214f1d08f548..63394de905fc9721215b5d88c09cf69bf97748cc 100644 (file)
@@ -39,7 +39,7 @@ bool cmd_create(struct client_command_context *cmd)
 
        box = mailbox_alloc(ns->list, mailbox, 0);
        if (mailbox_create(box, NULL, directory) < 0)
-               client_send_storage_error(cmd, mailbox_get_storage(box));
+               client_send_box_error(cmd, box);
        else
                client_send_tagline(cmd, "OK Create completed.");
        mailbox_free(&box);
index 420755ba272528c7026e54158a50ad89624e0d0c..33ab1160ba91bd98c8b5d74183fe7df369cef453 100644 (file)
@@ -41,7 +41,7 @@ bool cmd_delete(struct client_command_context *cmd)
        else {
                errstr = mailbox_get_last_error(box, &error);
                if (error != MAIL_ERROR_EXISTS)
-                       client_send_storage_error(cmd, mailbox_get_storage(box));
+                       client_send_box_error(cmd, box);
                else {
                        /* mailbox has children */
                        client_send_tagline(cmd, t_strdup_printf("NO %s", errstr));
index 50889d7a3b060374ed5a2e07b1e2016a3a82dc33..1d25cd8bbb6d996620efd274e4ed548a368c3a8a 100644 (file)
@@ -35,8 +35,7 @@ cmd_expunge_finish(struct client_command_context *cmd,
        if (ret < 0) {
                errstr = mailbox_get_last_error(client->mailbox, &error);
                if (error != MAIL_ERROR_PERM) {
-                       client_send_storage_error(cmd,
-                               mailbox_get_storage(client->mailbox));
+                       client_send_box_error(cmd, client->mailbox);
                        return TRUE;
                } else {
                        return cmd_sync(cmd, 0, IMAP_SYNC_FLAG_SAFE,
index 534df73102f4d0a7af1adeb0a5eda2ac30c5f7cb..487e216ca64cfe97a4f483ad5cf35fb282ca9032 100644 (file)
@@ -374,7 +374,7 @@ bool cmd_getmetadata(struct client_command_context *cmd)
 
        ctx->box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY);
        if (mailbox_open(ctx->box) < 0) {
-               client_send_storage_error(cmd, mailbox_get_storage(ctx->box));
+               client_send_box_error(cmd, ctx->box);
                mailbox_free(&ctx->box);
                return TRUE;
        }
index b2c6744dc38bb09f230c6717e46e1df90a46e2c3..83e0e24a63305d9fb6a7ad41a6c22111525da43a 100644 (file)
@@ -38,7 +38,7 @@ bool cmd_rename(struct client_command_context *cmd)
        old_box = mailbox_alloc(old_ns->list, oldname, 0);
        new_box = mailbox_alloc(new_ns->list, newname, 0);
        if (mailbox_rename(old_box, new_box) < 0)
-               client_send_storage_error(cmd, mailbox_get_storage(old_box));
+               client_send_box_error(cmd, old_box);
        else
                client_send_tagline(cmd, "OK Rename completed.");
        mailbox_free(&old_box);
index 472fd45b790ab273fcaef75b5984031d83df315c..fdb440ab65db78944820d7faae59131f322a11bc 100644 (file)
@@ -50,7 +50,7 @@ cmd_resetkey_mailbox(struct client_command_context *cmd,
        /* open mailbox */
        box = mailbox_alloc(ns->list, mailbox, flags);
        if (mailbox_open(box) < 0) {
-               client_send_storage_error(cmd, mailbox_get_storage(box));
+               client_send_box_error(cmd, box);
                mailbox_free(&box);
                return TRUE;
        }
index 19ce02711692a15b14a00ef4e31a4704988a7dfe..f36dbf8b93feb9dc09addb9ab90f83e6d90c5031 100644 (file)
@@ -233,10 +233,8 @@ static bool cmd_select_continue(struct client_command_context *cmd)
        }
 
        ret = imap_fetch_end(ctx->fetch_ctx);
-       if (ret < 0) {
-               client_send_storage_error(ctx->cmd,
-                                         mailbox_get_storage(ctx->box));
-       }
+       if (ret < 0)
+               client_send_box_error(ctx->cmd, ctx->box);
        imap_fetch_free(&ctx->fetch_ctx);
        cmd_select_finish(ctx, ret);
        return TRUE;
@@ -302,8 +300,7 @@ select_open(struct imap_select_context *ctx, const char *mailbox, bool readonly)
                flags |= MAILBOX_FLAG_DROP_RECENT;
        ctx->box = mailbox_alloc(ctx->ns->list, mailbox, flags);
        if (mailbox_open(ctx->box) < 0) {
-               client_send_storage_error(ctx->cmd,
-                                         mailbox_get_storage(ctx->box));
+               client_send_box_error(ctx->cmd, ctx->box);
                mailbox_free(&ctx->box);
                return -1;
        }
@@ -312,8 +309,7 @@ select_open(struct imap_select_context *ctx, const char *mailbox, bool readonly)
                ret = mailbox_enable(ctx->box, client->enabled_features);
        if (ret < 0 ||
            mailbox_sync(ctx->box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
-               client_send_storage_error(ctx->cmd,
-                                         mailbox_get_storage(ctx->box));
+               client_send_box_error(ctx->cmd, ctx->box);
                return -1;
        }
        mailbox_get_open_status(ctx->box, STATUS_MESSAGES | STATUS_RECENT |
@@ -363,8 +359,7 @@ select_open(struct imap_select_context *ctx, const char *mailbox, bool readonly)
        if (ctx->qresync_uid_validity == status.uidvalidity &&
            status.uidvalidity != 0) {
                if ((ret = select_qresync(ctx)) < 0) {
-                       client_send_storage_error(ctx->cmd,
-                               mailbox_get_storage(ctx->box));
+                       client_send_box_error(ctx->cmd, ctx->box);
                        return -1;
                }
        } else {
index 94cfe3638ed8faaf676743e872c0bad86f0142e2..57880ddcca6583057802b1a0cf16ecb3aa9404a7 100644 (file)
@@ -244,9 +244,9 @@ static bool cmd_setmetadata_continue(struct client_command_context *cmd)
        if (ret < 0 || ctx->cmd_error_sent)
                /* already sent the error to client */ ;
        else if (ctx->storage_failure)
-               client_send_storage_error(cmd, mailbox_get_storage(ctx->box));
+               client_send_box_error(cmd, ctx->box);
        else if (mailbox_transaction_commit(&ctx->trans) < 0)
-               client_send_storage_error(cmd, mailbox_get_storage(ctx->box));
+               client_send_box_error(cmd, ctx->box);
        else
                client_send_tagline(cmd, "OK Setmetadata completed.");
        cmd_setmetadata_deinit(ctx);
@@ -301,8 +301,7 @@ bool cmd_setmetadata(struct client_command_context *cmd)
        else {
                ctx->box = mailbox_alloc(ns->list, mailbox, 0);
                if (mailbox_open(ctx->box) < 0) {
-                       client_send_storage_error(cmd,
-                               mailbox_get_storage(ctx->box));
+                       client_send_box_error(cmd, ctx->box);
                        mailbox_free(&ctx->box);
                        return TRUE;
                }
index 8f95cf6baf831dd74a76028a03ed934e020fbca0..7a187e475c2bb3edb29bb2b562534330d8eb3f83 100644 (file)
@@ -109,8 +109,7 @@ store_parse_args(struct imap_store_context *ctx, const struct imap_arg *args)
                if (mailbox_keywords_create(cmd->client->mailbox, keywords_list,
                                            &ctx->keywords) < 0) {
                        /* invalid keywords */
-                       client_send_storage_error(cmd,
-                               mailbox_get_storage(cmd->client->mailbox));
+                       client_send_box_error(cmd, cmd->client->mailbox);
                        return FALSE;
                }
        }
@@ -211,8 +210,7 @@ bool cmd_store(struct client_command_context *cmd)
                ret = mailbox_transaction_commit(&t);
        if (ret < 0) {
                array_free(&modified_set);
-               client_send_storage_error(cmd,
-                       mailbox_get_storage(client->mailbox));
+               client_send_box_error(cmd, client->mailbox);
                return TRUE;
        }
 
index a8c89c96fc14db4ba03c2af7bddc5e4342dfba94..7885f1ad7851d43755348cacd94981dd0d8a0fc8 100644 (file)
@@ -12,7 +12,7 @@ subscribe_is_valid_name(struct client_command_context *cmd, struct mailbox *box)
        int ret;
 
        if ((ret = mailbox_exists(box, TRUE, &existence)) < 0) {
-               client_send_storage_error(cmd, mailbox_get_storage(box));
+               client_send_box_error(cmd, box);
                return FALSE;
        }
        if (existence == MAILBOX_EXISTENCE_NONE) {
@@ -71,7 +71,7 @@ bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
 
        if (mailbox_set_subscribed(box, subscribe) < 0 &&
            !unsubscribed_mailbox2) {
-               client_send_storage_error(cmd, mailbox_get_storage(box));
+               client_send_box_error(cmd, box);
        } else {
                client_send_tagline(cmd, subscribe ?
                                    "OK Subscribe completed." :
index c48e6a590c5d8896f28f5d56418cc3aeac70e9f0..35b0fa3cd664245869083a8d64348138aa768bbd 100644 (file)
@@ -283,8 +283,7 @@ bool cmd_thread(struct client_command_context *cmd)
                ret = imap_thread_orderedsubject(cmd, sargs);
        mail_search_args_unref(&sargs);
        if (ret < 0) {
-               client_send_storage_error(cmd,
-                       mailbox_get_storage(client->mailbox));
+               client_send_box_error(cmd, client->mailbox);
                return TRUE;
        }
 
index ebe70680d9923dc6e59c7db4ce7d478b7b104762..fb2b3d01125d45a1cd4357d78577d9056ce4d75d 100644 (file)
@@ -98,14 +98,14 @@ int client_open_save_dest_box(struct client_command_context *cmd,
                        client_send_tagline(cmd,  t_strdup_printf(
                                "NO [TRYCREATE] %s", error_string));
                } else {
-                       client_send_storage_error(cmd, mailbox_get_storage(box));
+                       client_send_box_error(cmd, box);
                }
                mailbox_free(&box);
                return -1;
        }
        if (cmd->client->enabled_features != 0) {
                if (mailbox_enable(box, cmd->client->enabled_features) < 0) {
-                       client_send_storage_error(cmd, mailbox_get_storage(box));
+                       client_send_box_error(cmd, box);
                        mailbox_free(&box);
                        return -1;
                }
@@ -170,6 +170,18 @@ void client_send_list_error(struct client_command_context *cmd,
                                                       error));
 }
 
+void client_send_box_error(struct client_command_context *cmd,
+                          struct mailbox *box)
+{
+       if (mailbox_is_inconsistent(box)) {
+               /* we can't do forced CLOSE, so have to disconnect */
+               client_disconnect_with_error(cmd->client,
+                       "IMAP session state is inconsistent, please relogin.");
+               return;
+       }
+       client_send_storage_error(cmd, mailbox_get_storage(box));
+}
+
 void client_send_storage_error(struct client_command_context *cmd,
                               struct mail_storage *storage)
 {
index 304d0d35c25b0a423ae9b1fca6b9ef1d8da2e0be..2cf25fbaadb145a99126ead941422317ceca3e4f 100644 (file)
@@ -35,6 +35,9 @@ void client_send_list_error(struct client_command_context *cmd,
 /* Send last mail storage error message to client. */
 void client_send_storage_error(struct client_command_context *cmd,
                               struct mail_storage *storage);
+/* Send last mailbox's storage error message to client. */
+void client_send_box_error(struct client_command_context *cmd,
+                          struct mailbox *box);
 
 /* Send untagged error message to client. */
 void client_send_untagged_storage_error(struct client *client,
index bbeabab6bc9f50ebc8382f2401f192487b81d736..4c2a9f2e1a40d978b52fb1a667cd212c6090b132 100644 (file)
@@ -491,8 +491,7 @@ static bool cmd_search_more(struct client_command_context *cmd)
 
        lost_data = mailbox_search_seen_lost_data(ctx->search_ctx);
        if (imap_search_deinit(ctx) < 0) {
-               client_send_storage_error(cmd,
-                       mailbox_get_storage(cmd->client->mailbox));
+               client_send_box_error(cmd, cmd->client->mailbox);
                return TRUE;
        }