mailbox-list.c revision aaa340328f0c43b3ebdedd7bded70521d3f7a167
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen then start renaming them to larger names from end to beginning, which
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen eventually would start causing the failures when trying to use too
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen long mailbox names. */
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen/* Message to show to users when critical error occurs */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "Internal error occurred. Refer to server log for more information."
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenvoid (*hook_mailbox_list_created)(struct mailbox_list *list);
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen unsigned int i, count;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen drivers = array_get(&mailbox_list_drivers, &count);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen for (i = 0; i < count; i++) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (strcasecmp(drivers[i]->name, name) == 0) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen unsigned int idx;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen array_append(&mailbox_list_drivers, &list, 1);
e245fb1302121d2bc2580f61e040c2c8a558ee9eTimo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
e245fb1302121d2bc2580f61e040c2c8a558ee9eTimo Sirainen unsigned int idx;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenint mailbox_list_alloc(const char *driver, struct mailbox_list **list_r,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen const char **error_r)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen unsigned int idx;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen *error_r = t_strdup_printf("Unknown mailbox list driver: %s",
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
25ec868bd8b5375e1c1c4c3331d761667ddfe26cTimo Sirainenint mailbox_list_settings_parse(const char *data,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen const char **error_r)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* <root dir> */
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen else if (strcmp(key, "ALT") == 0 && alt_dir_r != NULL)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen *error_r = t_strdup_printf("Unknown setting: %s", key);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (set->index_dir != NULL && strcmp(set->index_dir, "MEMORY") == 0)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenvoid mailbox_list_init(struct mailbox_list *list, struct mail_namespace *ns,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen i_assert(set->root_dir == NULL || *set->root_dir != '\0');
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen /* copy settings */
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen list->set.index_dir = set->index_dir == NULL ||
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
c076ad69e28e7d41af83ada84e12019793ffcfa2Timo Sirainen list->set.control_dir = set->control_dir == NULL ||
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen p_strdup(list->pool, set->subscription_fname);
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen list->set.maildir_name = p_strdup(list->pool, set->maildir_name);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen list->set.mail_storage_flags = set->mail_storage_flags;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen list->set.index_dir == NULL ? "" : list->set.index_dir,
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainenvoid mailbox_list_deinit(struct mailbox_list *list)
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainenconst char *mailbox_list_get_driver_name(const struct mailbox_list *list)
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainenchar mailbox_list_get_hierarchy_sep(const struct mailbox_list *list)
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainenenum mailbox_list_flags mailbox_list_get_flags(const struct mailbox_list *list)
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenmailbox_list_get_namespace(const struct mailbox_list *list)
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenvoid mailbox_list_get_permissions(struct mailbox_list *list,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen path = mailbox_list_get_path(list, NULL, MAILBOX_LIST_PATH_TYPE_DIR);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m",
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen } else if ((list->flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen i_info("Namespace %s: Permission lookup failed from %s",
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen /* return safe defaults */
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen /* directory's GID is used automatically for new files */
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen /* group doesn't have any permissions, so don't bother
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen changing it */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* using our own gid, no need to change it */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if ((list->flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen i_info("Namespace %s: Using permissions from %s: "
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenvoid mailbox_list_get_dir_permissions(struct mailbox_list *list,
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen mailbox_list_get_permissions(list, &mode, gid_r);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen /* add the execute bit if either read or write bit is set */
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenbool mailbox_list_is_valid_pattern(struct mailbox_list *list,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return list->v.is_valid_pattern(list, pattern);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainen return list->v.is_valid_existing_name(list, name);
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen return list->v.is_valid_create_name(list, name);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
return pattern;
const char *name,
struct mailbox_list_iterate_context *
struct mailbox_list_iterate_context *
const char *const *patterns,
const struct mailbox_info *
const char *name)
const char *name)
if (created) {
if (create_flags != 0)
if (p == NULL)
const char *name)
T_BEGIN {
} T_END;
return TRUE;
levels++;
level_len = 0;
level_len++;
return TRUE;
return TRUE;
return FALSE;
#ifdef HAVE_DIRENT_D_TYPE
switch (d->d_type) {
case DT_UNKNOWN:
case DT_REG:
case DT_DIR:
case DT_LNK:
return type;
const char *error_string;
return FALSE;
return TRUE;