static int index_storage_get_dict(struct mailbox *box, enum mail_attribute_type type, struct dict **dict_r, const char **mailbox_prefix_r) { struct mail_storage *storage = box->storage; struct mail_namespace *ns; struct mailbox_metadata metadata; struct dict_settings set; const char *error; if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) return -1; *mailbox_prefix_r = guid_128_to_string(metadata.guid); ns = mailbox_get_namespace(box); if (type == MAIL_ATTRIBUTE_TYPE_PRIVATE) { /* private attributes are stored in user's own dict */ return index_storage_get_user_dict(storage, storage->user, dict_r); } else if (ns->user == ns->owner) { /* user owns the mailbox. shared attributes are stored in the same dict. */ return index_storage_get_user_dict(storage, storage->user, dict_r); } else if (ns->owner != NULL) { /* accessing shared attribute of a shared mailbox. use the owner's dict. */ return index_storage_get_user_dict(storage, ns->owner, dict_r); } /* accessing shared attributes of a public mailbox. no user owns it, so use the storage's dict. */ if (storage->_shared_attr_dict != NULL) { *dict_r = storage->_shared_attr_dict; return 0; } if (*storage->set->mail_attribute_dict == '\0') { mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE, "Mailbox attributes not enabled"); return -1; } if (storage->shared_attr_dict_failed) { mail_storage_set_internal_error(storage); return -1; } memset(&set, 0, sizeof(set)); set.username = storage->user->username; set.base_dir = storage->user->set->base_dir; if (mail_user_get_home(storage->user, &set.home_dir) <= 0) set.home_dir = NULL; if (dict_init_full(storage->set->mail_attribute_dict, &set, &storage->_shared_attr_dict, &error) < 0) { mail_storage_set_critical(storage, "mail_attribute_dict: dict_init(%s) failed: %s", storage->set->mail_attribute_dict, error); storage->shared_attr_dict_failed = TRUE; return -1; } *dict_r = storage->_shared_attr_dict; return 0; }
static void mail_user_expand_plugins_envs(struct mail_user *user) { const char **envs, *home; string_t *str; unsigned int i, count; if (!array_is_created(&user->set->plugin_envs)) return; str = t_str_new(256); envs = array_get_modifiable(&user->set->plugin_envs, &count); i_assert((count % 2) == 0); for (i = 0; i < count; i += 2) { if (user->_home == NULL && var_has_key(envs[i+1], 'h', "home") && mail_user_get_home(user, &home) <= 0) { user->error = p_strdup_printf(user->pool, "userdb didn't return a home directory, " "but plugin setting %s used it (%%h): %s", envs[i], envs[i+1]); return; } str_truncate(str, 0); var_expand(str, envs[i+1], mail_user_var_expand_table(user)); envs[i+1] = p_strdup(user->pool, str_c(str)); } }
static int mail_sieve_user_init (struct mail_user *user, struct sieve_storage **svstorage_r) { struct sieve_mail_user *suser = SIEVE_USER_CONTEXT(user); enum sieve_storage_flags storage_flags = SIEVE_STORAGE_FLAG_READWRITE | SIEVE_STORAGE_FLAG_SYNCHRONIZING; struct sieve_environment svenv; i_assert( suser != NULL ); if ( suser->svinst != NULL ) { *svstorage_r = suser->sieve_storage; return suser->sieve_storage != NULL ? 1 : 0; } /* Delayed initialization of sieve storage until it's actually needed */ memset(&svenv, 0, sizeof(svenv)); svenv.username = user->username; (void)mail_user_get_home(user, &svenv.home_dir); svenv.base_dir = user->set->base_dir; svenv.flags = SIEVE_FLAG_HOME_RELATIVE; suser->svinst = sieve_init(&svenv, &mail_sieve_callbacks, user, user->mail_debug); suser->sieve_storage = sieve_storage_create_main (suser->svinst, user, storage_flags, NULL); *svstorage_r = suser->sieve_storage; return suser->sieve_storage != NULL ? 1 : 0; }
const char *sieve_tool_get_homedir (struct sieve_tool *tool) { const char *homedir = NULL; if ( tool->homedir != NULL ) return tool->homedir; if ( tool->mail_user_dovecot != NULL && mail_user_get_home(tool->mail_user_dovecot, &homedir) > 0 ) { return tool->homedir; } sieve_tool_get_user_data(NULL, &homedir); return homedir; }
static const char * mdbox_storage_find_root_dir(const struct mail_namespace *ns) { bool debug = ns->mail_set->mail_debug; const char *home, *path; if (ns->owner != NULL && mail_user_get_home(ns->owner, &home) > 0) { path = t_strconcat(home, "/mdbox", NULL); if (access(path, R_OK|W_OK|X_OK) == 0) { if (debug) i_debug("mdbox: root exists (%s)", path); return path; } if (debug) i_debug("mdbox: access(%s, rwx): failed: %m", path); } return NULL; }
static int doveadm_sieve_cmd_run (struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) { struct doveadm_sieve_cmd_context *ctx = (struct doveadm_sieve_cmd_context *)_ctx; struct sieve_environment svenv; enum sieve_error error; int ret; memset((void*)&svenv, 0, sizeof(svenv)); svenv.username = user->username; (void)mail_user_get_home(user, &svenv.home_dir); svenv.base_dir = user->set->base_dir; svenv.flags = SIEVE_FLAG_HOME_RELATIVE; ctx->svinst = sieve_init (&svenv, &sieve_callbacks, (void *)ctx, user->mail_debug); ctx->storage = sieve_storage_create_main (ctx->svinst, user, SIEVE_STORAGE_FLAG_READWRITE, &error); if ( ctx->storage == NULL ) { switch ( error ) { case SIEVE_ERROR_NOT_FOUND: i_error("Failed to open Sieve storage: Sieve disabled for user"); break; default: i_error("Failed to open Sieve storage."); } doveadm_sieve_cmd_failed_error(ctx, error); ret = -1; } else { i_assert( ctx->v.run != NULL ); ret = ctx->v.run(ctx); sieve_storage_unref(&ctx->storage); } sieve_deinit(&ctx->svinst); return ret; }
static const char *mbox_storage_find_root_dir(const struct mail_namespace *ns) { bool debug = ns->mail_set->mail_debug; const char *home, *path; if (mail_user_get_home(ns->user, &home) <= 0) { if (debug) i_debug("maildir: Home directory not set"); home = ""; } path = t_strconcat(home, "/mail", NULL); if (mbox_storage_is_root_dir(path, debug)) return path; path = t_strconcat(home, "/Mail", NULL); if (mbox_storage_is_root_dir(path, debug)) return path; return NULL; }
struct imap_sieve *imap_sieve_init(struct mail_user *user, const struct lda_settings *lda_set) { struct sieve_environment svenv; struct imap_sieve *isieve; bool debug = user->mail_debug; pool_t pool; pool = pool_alloconly_create("imap_sieve", 256); isieve = p_new(pool, struct imap_sieve, 1); isieve->pool = pool; isieve->user = user; isieve->lda_set = lda_set; isieve->dup_ctx = duplicate_init(user); memset(&svenv, 0, sizeof(svenv)); svenv.username = user->username; (void)mail_user_get_home(user, &svenv.home_dir); svenv.hostname = lda_set->hostname; svenv.base_dir = user->set->base_dir; svenv.flags = SIEVE_FLAG_HOME_RELATIVE; svenv.location = SIEVE_ENV_LOCATION_MS; svenv.delivery_phase = SIEVE_DELIVERY_PHASE_POST; isieve->home_dir = p_strdup(pool, svenv.home_dir); isieve->svinst = sieve_init (&svenv, &mail_sieve_callbacks, isieve, debug); isieve->ext_imapsieve = sieve_extension_replace (isieve->svinst, &imapsieve_extension, TRUE); isieve->master_ehandler = sieve_master_ehandler_create (isieve->svinst, NULL, 0); // FIXME: prefix? sieve_system_ehandler_set(isieve->master_ehandler); sieve_error_handler_accept_infolog(isieve->master_ehandler, TRUE); sieve_error_handler_accept_debuglog(isieve->master_ehandler, debug); return isieve; }
int mail_user_init(struct mail_user *user, const char **error_r) { const struct mail_storage_settings *mail_set; const char *home, *key, *value; bool need_home_dir; need_home_dir = user->_home == NULL && settings_vars_have_key(user->set_info, user->set, 'h', "home", &key, &value); if (need_home_dir && mail_user_get_home(user, &home) <= 0) { user->error = p_strdup_printf(user->pool, "userdb didn't return a home directory, " "but %s used it (%%h): %s", key, value); } /* expand settings after we can expand %h */ settings_var_expand_with_funcs(user->set_info, user->set, user->pool, mail_user_var_expand_table(user), mail_user_var_expand_func_table, user); user->settings_expanded = TRUE; mail_user_expand_plugins_envs(user); /* autocreated users for shared mailboxes need to be fully initialized if they don't exist, since they're going to be used anyway */ if (user->error == NULL || user->nonexistent) { mail_set = mail_user_set_get_storage_set(user); user->mail_debug = mail_set->mail_debug; user->initialized = TRUE; hook_mail_user_created(user); } if (user->error != NULL) { *error_r = t_strdup(user->error); return -1; } return 0; }
int mail_user_init(struct mail_user *user, const char **error_r) { const struct mail_storage_settings *mail_set; const char *home, *key, *value; bool need_home_dir; need_home_dir = user->_home == NULL && settings_vars_have_key(user->set_info, user->set, 'h', "home", &key, &value); /* expand mail_home setting before calling mail_user_get_home() */ settings_var_expand(user->set_info, user->set, user->pool, mail_user_var_expand_table(user)); if (need_home_dir && mail_user_get_home(user, &home) <= 0) { *error_r = t_strdup_printf( "userdb didn't return a home directory, " "but %s used it (%%h): %s", key, value); return -1; } if (mail_user_expand_plugins_envs(user, error_r) < 0) return -1; mail_set = mail_user_set_get_storage_set(user); user->mail_debug = mail_set->mail_debug; user->initialized = TRUE; hook_mail_user_created(user); if (user->error != NULL) { *error_r = t_strdup(user->error); return -1; } return 0; }
struct sieve_instance *sieve_tool_init_finish (struct sieve_tool *tool, bool init_mailstore, bool preserve_root) { enum mail_storage_service_flags storage_service_flags = MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR | MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT | MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS; struct mail_storage_service_input service_input; struct sieve_environment svenv; const char *username = tool->username; const char *homedir = tool->homedir; const char *errstr; master_service_init_finish(master_service); if ( username == NULL ) { sieve_tool_get_user_data(&username, &homedir); username = tool->username = i_strdup(username); if ( tool->homedir != NULL ) i_free(tool->homedir); tool->homedir = i_strdup(homedir); if ( preserve_root ) { storage_service_flags |= MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS; } } else { storage_service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP; } if ( !init_mailstore ) storage_service_flags |= MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES; memset(&service_input, 0, sizeof(service_input)); service_input.module = "mail"; service_input.service = tool->name; service_input.username = username; tool->storage_service = mail_storage_service_init (master_service, NULL, storage_service_flags); if (mail_storage_service_lookup_next (tool->storage_service, &service_input, &tool->service_user, &tool->mail_user_dovecot, &errstr) <= 0) i_fatal("%s", errstr); if ( master_service_set (master_service, "mail_full_filesystem_access=yes") < 0 ) i_unreached(); memset((void *)&svenv, 0, sizeof(svenv)); svenv.username = username; (void)mail_user_get_home(tool->mail_user_dovecot, &svenv.home_dir); svenv.hostname = my_hostdomain(); svenv.base_dir = tool->mail_user_dovecot->set->base_dir; svenv.temp_dir = tool->mail_user_dovecot->set->mail_temp_dir; svenv.location = SIEVE_ENV_LOCATION_MS; svenv.delivery_phase = SIEVE_DELIVERY_PHASE_POST; /* Initialize Sieve Engine */ if ( (tool->svinst=sieve_init (&svenv, &sieve_tool_callbacks, tool, tool->debug)) == NULL ) i_fatal("failed to initialize sieve implementation"); /* Load Sieve plugins */ if ( array_count(&tool->sieve_plugins) > 0 ) { sieve_tool_load_plugins(tool); } /* Set active Sieve extensions */ if ( tool->sieve_extensions != NULL ) { sieve_set_extensions(tool->svinst, tool->sieve_extensions); } else if ( tool->no_config ) { sieve_set_extensions(tool->svinst, NULL); } return tool->svinst; }
static void last_login_mail_user_created(struct mail_user *user) { struct mail_user_vfuncs *v = user->vlast; struct last_login_user *luser; struct dict *dict; struct dict_settings set; struct dict_transaction_context *trans; const char *dict_value, *key_name, *precision, *error; if (user->autocreated) { /* we want to handle only logged in users, not lda's raw user or accessed shared users */ return; } dict_value = mail_user_plugin_getenv(user, "last_login_dict"); if (dict_value == NULL || dict_value[0] == '\0') return; memset(&set, 0, sizeof(set)); set.username = user->username; set.base_dir = user->set->base_dir; if (mail_user_get_home(user, &set.home_dir) <= 0) set.home_dir = NULL; if (dict_init(dict_value, &set, &dict, &error) < 0) { i_error("last_login_dict: dict_init(%s) failed: %s", dict_value, error); return; } luser = p_new(user->pool, struct last_login_user, 1); luser->module_ctx.super = *v; user->vlast = &luser->module_ctx.super; v->deinit = last_login_user_deinit; luser->dict = dict; MODULE_CONTEXT_SET(user, last_login_user_module, luser); key_name = mail_user_plugin_getenv(user, "last_login_key"); if (key_name == NULL) { key_name = t_strdup_printf(LAST_LOGIN_DEFAULT_KEY_PREFIX"%s", user->username); } key_name = t_strconcat(DICT_PATH_SHARED, key_name, NULL); precision = mail_user_plugin_getenv(user, "last_login_precision"); trans = dict_transaction_begin(dict); if (precision == NULL || strcmp(precision, "s") == 0) dict_set(trans, key_name, dec2str(ioloop_time)); else if (strcmp(precision, "ms") == 0) { dict_set(trans, key_name, t_strdup_printf( "%ld%03u", (long)ioloop_timeval.tv_sec, (unsigned int)(ioloop_timeval.tv_usec/1000))); } else if (strcmp(precision, "us") == 0) { dict_set(trans, key_name, t_strdup_printf( "%ld%06u", (long)ioloop_timeval.tv_sec, (unsigned int)ioloop_timeval.tv_usec)); } else if (strcmp(precision, "ns") == 0) { dict_set(trans, key_name, t_strdup_printf( "%ld%06u000", (long)ioloop_timeval.tv_sec, (unsigned int)ioloop_timeval.tv_usec)); } else { i_error("last_login_dict: Invalid last_login_precision '%s'", precision); } dict_transaction_no_slowness_warning(trans); dict_transaction_commit_async(&trans, last_login_dict_commit, user); }