mailbox-list.c revision 25d9db0c00e8041165540e0829d7eab7548cbaa5
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2006-2007 Timo Sirainen */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen then start renaming them to larger names from end to beginning, which
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen eventually would start causing the failures when trying to use too
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen long mailbox names. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen/* Message to show to users when critical error occurs */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen "Internal error occurred. Refer to server log for more information."
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenvoid (*hook_mailbox_list_created)(struct mailbox_list *list);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen unsigned int i, count;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen drivers = array_get(&mailbox_list_drivers, &count);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen for (i = 0; i < count; i++) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (strcasecmp(drivers[i]->name, name) == 0) {
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen unsigned int idx;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen array_append(&mailbox_list_drivers, &list, 1);
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen unsigned int idx;
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
c1d4780bc0c9017e8e5d366b81e4fad31174c0adTimo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mailbox_list **list_r, const char **error_r)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int idx;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* copy settings */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen list->set.index_dir = set->index_dir == NULL ||
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen list->set.control_dir = set->control_dir == NULL ||
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen if (mkdir_parents(list->set.index_dir, 0700) < 0 &&
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_error("mkdir(%s) failed: %m", list->set.index_dir);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (mkdir_parents(list->set.control_dir, 0700) < 0 &&
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_error("mkdir(%s) failed: %m", list->set.control_dir);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen p_strdup(list->pool, set->subscription_fname);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen list->set.maildir_name = p_strdup(list->pool, set->maildir_name);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen list->set.mail_storage_flags = set->mail_storage_flags;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen list->set.index_dir == NULL ? "" : list->set.index_dir,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenvoid mailbox_list_deinit(struct mailbox_list *list)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenconst char *mailbox_list_get_driver_name(struct mailbox_list *list)
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainenchar mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenbool mailbox_list_is_valid_mask(struct mailbox_list *list, const char *mask)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen return list->v.is_valid_existing_name(list, name);
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen return list->v.is_valid_create_name(list, name);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
5297aa3ceddf3a4ecc09f49c832bc424eff8f906Timo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenconst char *mailbox_list_join_refmask(struct mailbox_list *list,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* the default implementation: */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* merge reference and mask */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenint mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return list->v.get_mailbox_name_status(list, name, status);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenmailbox_list_iter_init(struct mailbox_list *list, const char *mask,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenmailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainenint mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen struct mailbox_list_iterate_context *ctx = *_ctx;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_set_subscribed(struct mailbox_list *list,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return list->v.set_subscribed(list, name, set);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_rename_mailbox(struct mailbox_list *list,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, oldname) ||
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen !mailbox_list_is_valid_create_name(list, newname)) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return list->v.rename_mailbox(list, oldname, newname);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenint mailbox_list_delete_index_control(struct mailbox_list *list,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mailbox_list_set_error(list, "INBOX can't be deleted.");
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name)) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mailbox_list_set_error(list, "Invalid mailbox name");
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen /* delete the index directory first, so that if we crash we don't
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen leave indexes for deleted mailboxes lying around */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (*index_dir != '\0' && strcmp(index_dir, path) != 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (unlink_directory(index_dir, TRUE) < 0 && errno != ENOENT) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen "unlink_directory(%s) failed: %m", index_dir);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* control directory next */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen dir = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen if (unlink_directory(dir, TRUE) < 0 && errno != ENOENT) {
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainenbool mailbox_list_name_is_too_large(const char *name, char sep)
9ec30d84a736a2d0726b600213dcf630ff28bdebTimo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainenenum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen switch (d->d_type) {
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainenconst char *mailbox_list_get_last_error(struct mailbox_list *list,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenvoid mailbox_list_clear_error(struct mailbox_list *list)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenvoid mailbox_list_set_error(struct mailbox_list *list, const char *error)
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainenvoid mailbox_list_set_internal_error(struct mailbox_list *list)
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainenvoid mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen /* critical errors may contain sensitive data, so let user
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen see only "Internal error" with a timestamp to make it
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen easier to look from log files the actual error message. */