#include <ctype.h>
#define MAILBOX_DELETE_RETRY_SECS 30
+#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 255
extern struct mail_search_register *mail_search_register_imap;
extern struct mail_search_register *mail_search_register_human;
int mailbox_verify_create_name(struct mailbox *box)
{
- char sep = mail_namespace_get_sep(box->list->ns);
-
/* mailbox_alloc() already checks that vname is valid UTF8,
so we don't need to verify that.
"Control characters not allowed in new mailbox names");
return -1;
}
- if (mailbox_list_name_is_too_large(box->vname, sep)) {
+ if (strlen(box->vname) > MAILBOX_LIST_NAME_MAX_LENGTH) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
+ "Mailbox name too long");
+ return -1;
+ }
+ /* check individual component names, too */
+ const char *old_name = box->name;
+ const char *name;
+ const char sep = mailbox_list_get_hierarchy_sep(box->list);
+ while((name = strchr(old_name, sep)) != NULL) {
+ if (name - old_name > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
+ "Mailbox name too long");
+ return -1;
+ }
+ name++;
+ old_name = name;
+ }
+ if (old_name != NULL && strlen(old_name) > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
"Mailbox name too long");
return -1;
return TRUE;
}
+static
+int mailbox_rename_check_children(struct mailbox *src, struct mailbox *dest)
+{
+ int ret = 0;
+ size_t src_prefix_len = strlen(src->vname)+1; /* include separator */
+ size_t dest_prefix_len = strlen(dest->vname)+1;
+ /* this can return folders with * in their name, that are not
+ actually our children */
+ const char *pattern = t_strdup_printf("%s%c*", src->vname,
+ mail_namespace_get_sep(src->list->ns));
+
+ struct mailbox_list_iterate_context *iter = mailbox_list_iter_init(src->list, pattern,
+ MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
+
+ const struct mailbox_info *child;
+ while((child = mailbox_list_iter_next(iter)) != NULL) {
+ if (strncmp(child->vname, src->vname, src_prefix_len) != 0)
+ continue; /* not our child */
+ /* if total length of new name exceeds the limit, fail */
+ if (strlen(child->vname + src_prefix_len)+dest_prefix_len > MAILBOX_LIST_NAME_MAX_LENGTH) {
+ mail_storage_set_error(dest->storage, MAIL_ERROR_PARAMS,
+ "Mailbox or child name too long");
+ ret = -1;
+ break;
+ }
+ }
+
+ /* something went bad */
+ if (mailbox_list_iter_deinit(&iter) < 0) {
+ mail_storage_copy_list_error(dest->storage, src->list);
+ ret = -1;
+ }
+ return ret;
+}
+
int mailbox_rename(struct mailbox *src, struct mailbox *dest)
{
const char *error = NULL;
mail_storage_copy_error(dest->storage, src->storage);
return -1;
}
+ if (mailbox_rename_check_children(src, dest) != 0) {
+ return -1;
+ }
+
if (!mail_storages_rename_compatible(src->storage,
dest->storage, &error) ||
!mailbox_lists_rename_compatible(src->list,
#include <dirent.h>
#include <sys/stat.h>
-/* 16 * (255+1) = 4096 which is the standard PATH_MAX. Having these settings
- prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
- then start renaming them to larger names from end to beginning, which
- eventually would start causing the failures when trying to use too
- long mailbox names. 255 is the standard single directory name length, so
- allow up to that high. */
-#define MAILBOX_MAX_HIERARCHY_LEVELS 16
-#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 255
-
#define MAILBOX_LIST_FS_CONTEXT(obj) \
MODULE_CONTEXT(obj, mailbox_list_fs_module)
list->changelog_timestamp = stamp;
}
-bool mailbox_list_name_is_too_large(const char *name, char sep)
-{
- unsigned int levels = 1, level_len = 0;
-
- for (; *name != '\0'; name++) {
- if (*name == sep) {
- if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
- return TRUE;
- levels++;
- level_len = 0;
- } else {
- level_len++;
- }
- }
-
- if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
- return TRUE;
- if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
- return TRUE;
- return FALSE;
-}
-
enum mailbox_list_file_type
mailbox_list_get_file_type(const struct dirent *d ATTR_UNUSED)
{