From: Timo Sirainen Date: Fri, 8 Aug 2008 21:16:07 +0000 (-0400) Subject: virtual mailboxes: Detect loops in virtual mailbox definitions. X-Git-Tag: 1.2.alpha1~80 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c93ff0433cc3d348116f75a64f9988fedb86fd18;p=thirdparty%2Fdovecot%2Fcore.git virtual mailboxes: Detect loops in virtual mailbox definitions. --HG-- branch : HEAD --- diff --git a/src/plugins/virtual/virtual-storage.c b/src/plugins/virtual/virtual-storage.c index 9cfca23f0b..d172033cc1 100644 --- a/src/plugins/virtual/virtual-storage.c +++ b/src/plugins/virtual/virtual-storage.c @@ -72,6 +72,7 @@ static struct mail_storage *virtual_alloc(void) storage = p_new(pool, struct virtual_storage, 1); storage->storage = virtual_storage; storage->storage.pool = pool; + p_array_init(&storage->open_stack, pool, 8); return &storage->storage; } @@ -151,6 +152,20 @@ virtual_backend_box_lookup(struct virtual_mailbox *mbox, uint32_t mailbox_id) return NULL; } +static bool virtual_mailbox_is_in_open_stack(struct virtual_storage *storage, + const char *name) +{ + const char *const *names; + unsigned int i, count; + + names = array_get(&storage->open_stack, &count); + for (i = 0; i < count; i++) { + if (strcmp(names[i], name) == 0) + return TRUE; + } + return FALSE; +} + static int virtual_mailboxes_open(struct virtual_mailbox *mbox, enum mailbox_open_flags open_flags) { @@ -168,10 +183,15 @@ static int virtual_mailboxes_open(struct virtual_mailbox *mbox, ns = mail_namespace_find(virtual_all_namespaces, &mailbox); bboxes[i]->box = mailbox_open(ns->storage, mailbox, NULL, open_flags); + if (bboxes[i]->box == NULL) { - str = mail_storage_get_last_error(ns->storage, &error); - mail_storage_set_error(mbox->ibox.box.storage, - error, str); + if (ns->storage != mbox->ibox.box.storage) { + /* copy the error */ + str = mail_storage_get_last_error(ns->storage, + &error); + mail_storage_set_error(mbox->ibox.box.storage, + error, str); + } break; } i_array_init(&bboxes[i]->uids, 64); @@ -198,6 +218,13 @@ virtual_open(struct virtual_storage *storage, const char *name, struct mail_index *index; const char *path; pool_t pool; + bool failed; + + if (virtual_mailbox_is_in_open_stack(storage, name)) { + mail_storage_set_critical(_storage, + "Virtual mailbox loops: %s", name); + return NULL; + } path = mailbox_list_get_path(_storage->list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX); @@ -223,8 +250,12 @@ virtual_open(struct virtual_storage *storage, const char *name, sizeof(struct virtual_mail_index_record), sizeof(uint32_t)); - if (virtual_config_read(mbox) < 0 || - virtual_mailboxes_open(mbox, flags) < 0) { + array_append(&storage->open_stack, &name, 1); + failed = virtual_config_read(mbox) < 0 || + virtual_mailboxes_open(mbox, flags) < 0; + array_delete(&storage->open_stack, + array_count(&storage->open_stack)-1, 1); + if (failed) { virtual_config_free(mbox); pool_unref(&pool); return NULL; diff --git a/src/plugins/virtual/virtual-storage.h b/src/plugins/virtual/virtual-storage.h index 799bb466d2..59a3be21d6 100644 --- a/src/plugins/virtual/virtual-storage.h +++ b/src/plugins/virtual/virtual-storage.h @@ -43,6 +43,10 @@ struct virtual_mail_index_record { struct virtual_storage { struct mail_storage storage; union mailbox_list_module_context list_module_ctx; + + /* List of mailboxes while a virtual mailbox is being opened. + Used to track loops. */ + ARRAY_TYPE(const_string) open_stack; }; struct virtual_backend_uidmap {