Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #4
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;
}
Beispiel #5
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
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);
	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;
}
Beispiel #10
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;
}
Beispiel #11
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;
}
Beispiel #12
0
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);
}