static void cmd_import_deinit(struct doveadm_mail_cmd_context *_ctx)
{
	struct import_cmd_context *ctx = (struct import_cmd_context *)_ctx;

	if (ctx->src_user != NULL)
		mail_user_unref(&ctx->src_user);
}
Beispiel #2
0
static void mail_session_free(struct mail_session *session)
{
	i_assert(session->refcount == 0);

	global_memory_free(mail_session_memsize(session));

	if (session->to_idle != NULL)
		timeout_remove(&session->to_idle);
	if (!session->disconnected)
		hash_table_remove(mail_sessions_hash, session->id);
	DLLIST_REMOVE_FULL(&stable_mail_sessions, session,
			   stable_prev, stable_next);
	DLLIST2_REMOVE_FULL(&mail_sessions_head, &mail_sessions_tail, session,
			    sorted_prev, sorted_next);
	DLLIST_REMOVE_FULL(&session->user->sessions, session,
			   user_prev, user_next);
	mail_user_unref(&session->user);
	if (session->ip != NULL) {
		DLLIST_REMOVE_FULL(&session->ip->sessions, session,
				   ip_prev, ip_next);
		mail_ip_unref(&session->ip);
	}

	str_table_unref(services, &session->service);
	i_free(session->id);
	i_free(session);
}
Beispiel #3
0
static int
lmtp_rcpt_to_is_over_quota(struct client *client,
			   const struct mail_recipient *rcpt)
{
	struct mail_user *user;
	struct mail_namespace *ns;
	struct mailbox *box;
	struct mailbox_status status;
	const char *errstr;
	enum mail_error error;
	int ret;

	if (!client->lmtp_set->lmtp_rcpt_check_quota)
		return 0;

	ret = mail_storage_service_next(storage_service,
					rcpt->service_user, &user);
	if (ret < 0)
		return -1;

	ns = mail_namespace_find_inbox(user->namespaces);
	box = mailbox_alloc(ns->list, "INBOX", 0);
	ret = mailbox_get_status(box, STATUS_CHECK_OVER_QUOTA, &status);
	if (ret < 0) {
		errstr = mailbox_get_last_error(box, &error);
		if (error == MAIL_ERROR_NOSPACE) {
			client_send_line(client, "552 5.2.2 <%s> %s",
					 rcpt->address, errstr);
			ret = 1;
		}
	}
	mailbox_free(&box);
	mail_user_unref(&user);
	return ret;
}
static void client_destroy(struct client *client)
{
	char **app;

	i_set_failure_prefix("imap-urlauth[%s](%s): ",
			     my_pid, client->access_user);

	if (client->url != NULL) {
		/* deinitialize url */
		i_stream_close(client->input);
		o_stream_close(client->output);
		(void)client_run_url(client);
		i_assert(client->url == NULL);
	}

	imap_urlauth_worker_client_count--;
	DLLIST_REMOVE(&imap_urlauth_worker_clients, client);

	if (client->urlauth_ctx != NULL)
		imap_urlauth_deinit(&client->urlauth_ctx);

	if (client->mail_user != NULL)
		mail_user_unref(&client->mail_user);

	if (client->io != NULL)
		io_remove(&client->io);
	if (client->ctrl_io != NULL)
		io_remove(&client->ctrl_io);
	if (client->to_idle != NULL)
		timeout_remove(&client->to_idle);

	if (client->input != NULL)
		i_stream_destroy(&client->input);
	if (client->output != NULL)
		o_stream_destroy(&client->output);

	if (client->ctrl_input != NULL)
		i_stream_destroy(&client->ctrl_input);
	if (client->ctrl_output != NULL)
		o_stream_destroy(&client->ctrl_output);

	if (client->fd_in >= 0)
		net_disconnect(client->fd_in);
	if (client->fd_out >= 0 && client->fd_in != client->fd_out)
		net_disconnect(client->fd_out);
	if (client->fd_ctrl >= 0)
		net_disconnect(client->fd_ctrl);

	if (client->service_user != NULL)
		mail_storage_service_user_free(&client->service_user);
	i_free(client->access_user);
	array_foreach_modifiable(&client->access_apps, app)
		i_free(*app);
	array_free(&client->access_apps);
	i_free(client);

	imap_urlauth_worker_refresh_proctitle();
	master_service_client_connection_destroyed(master_service);
}
Beispiel #5
0
void sieve_tool_deinit(struct sieve_tool **_tool)
{
	struct sieve_tool *tool = *_tool;

	*_tool = NULL;

	/* Deinitialize Sieve engine */
	sieve_deinit(&tool->svinst);

	/* Free options */

	if ( tool->username != NULL )
		i_free(tool->username);
	if ( tool->homedir != NULL )
		i_free(tool->homedir);

	if ( tool->sieve_extensions != NULL )
		i_free(tool->sieve_extensions);
	array_free(&tool->sieve_plugins);

	/* Free raw mail */

	if ( tool->mail_raw != NULL )
		mail_raw_close(&tool->mail_raw);

	if ( tool->mail_raw_user != NULL )
		mail_user_unref(&tool->mail_raw_user);

	/* Free mail service */

	if ( tool->mail_user != NULL )
		mail_user_unref(&tool->mail_user);
	if ( tool->mail_user_dovecot != NULL )
		mail_user_unref(&tool->mail_user_dovecot);

	mail_storage_service_user_free(&tool->service_user);
	mail_storage_service_deinit(&tool->storage_service);

	/* Free sieve tool object */

	i_free(tool->name);
	i_free(tool);

	/* Deinitialize service */
	master_service_deinit(&master_service);
}
static void cmd_copy_deinit(struct doveadm_mail_cmd_context *_ctx)
{
	struct copy_cmd_context *ctx = (struct copy_cmd_context *)_ctx;

	if (ctx->source_user != NULL) {
		mail_storage_service_user_free(&ctx->source_service_user);
		mail_user_unref(&ctx->source_user);
	}
}
static void client_unref_iters(struct client *client)
{
	if (client->mail_cmd_iter != NULL)
		mail_command_unref(&client->mail_cmd_iter);
	if (client->mail_session_iter != NULL)
		mail_session_unref(&client->mail_session_iter);
	if (client->mail_user_iter != NULL)
		mail_user_unref(&client->mail_user_iter);
	if (client->mail_domain_iter != NULL)
		mail_domain_unref(&client->mail_domain_iter);
	if (client->mail_ip_iter != NULL)
		mail_ip_unref(&client->mail_ip_iter);
}
Beispiel #8
0
static int
master_connection_input_line(struct master_connection *conn, const char *line)
{
	const char *const *args = t_strsplit_tabescaped(line);
	struct mail_storage_service_input input;
	struct mail_storage_service_user *service_user;
	struct mail_user *user;
	const char *str, *error;
	unsigned int max_recent_msgs;
	int ret;

	/* <username> <mailbox> <session ID> <max_recent_msgs> [i][o] */
	if (str_array_length(args) != 5 ||
	    str_to_uint(args[3], &max_recent_msgs) < 0 || args[4][0] == '\0') {
		i_error("Invalid input from master: %s", line);
		return -1;
	}

	i_zero(&input);
	input.module = "mail";
	input.service = "indexer-worker";
	input.username = args[0];
	/* if session-id is given, use it as a prefix to a unique session ID.
	   we can't use the session-id directly or stats process will complain
	   about duplicates. (especially LMTP would use the same session-id for
	   multiple users' indexing at the same time.) */
	if (args[2][0] != '\0')
		input.session_id_prefix = args[2];

	if (mail_storage_service_lookup_next(conn->storage_service, &input,
					     &service_user, &user, &error) <= 0) {
		i_error("User %s lookup failed: %s", args[0], error);
		ret = -1;
	} else {
		indexer_worker_refresh_proctitle(user->username, args[1], 0, 0);
		ret = index_mailbox(conn, user, args[1],
				    max_recent_msgs, args[4]);
		/* refresh proctitle before a potentially long-running
		   user unref */
		indexer_worker_refresh_proctitle(user->username, "(deinit)", 0, 0);
		mail_user_unref(&user);
		mail_storage_service_user_unref(&service_user);
		indexer_worker_refresh_proctitle(NULL, NULL, 0, 0);
	}

	str = ret < 0 ? "-1\n" : "100\n";
	return write_full(conn->fd, str, strlen(str));
}
Beispiel #9
0
static int client_export_iter_user(struct client *client)
{
	struct client_export_cmd *cmd = client->cmd_export;
	struct mail_user *user = client->mail_user_iter;

	i_assert(cmd->level == MAIL_EXPORT_LEVEL_USER);
	mail_user_unref(&client->mail_user_iter);

	if (!cmd->header_sent) {
		o_stream_nsend_str(client->output,
			"user\treset_timestamp\tlast_update"
			"\tnum_logins\tnum_cmds"MAIL_STATS_HEADER);
		cmd->header_sent = TRUE;
	}

	for (; user != NULL; user = user->stable_next) {
		if (client_is_busy(client))
			break;
		if (!mail_export_filter_match_user(&cmd->filter, user))
			continue;

		str_truncate(cmd->str, 0);
		str_append_tabescaped(cmd->str, user->name);
		str_printfa(cmd->str, "\t%ld", (long)user->reset_timestamp);
		client_export_timeval(cmd->str, &user->last_update);
		str_printfa(cmd->str, "\t%u\t%u",
			    user->num_logins, user->num_cmds);
		client_export_mail_stats(cmd->str, &user->stats);
		str_append_c(cmd->str, '\n');
		o_stream_nsend(client->output, str_data(cmd->str),
			       str_len(cmd->str));
	}

	if (user != NULL) {
		client->mail_user_iter = user;
		mail_user_ref(user);
		return 0;
	}
	return 1;
}
Beispiel #10
0
static int
master_connection_input_line(struct master_connection *conn, const char *line)
{
    const char *const *args = t_strsplit_tabescaped(line);
    struct mail_storage_service_input input;
    struct mail_storage_service_user *service_user;
    struct mail_user *user;
    const char *str, *error;
    unsigned int max_recent_msgs;
    int ret;

    /* <username> <mailbox> <max_recent_msgs> [i][o] */
    if (str_array_length(args) != 4 ||
            str_to_uint(args[2], &max_recent_msgs) < 0 || args[3][0] == '\0') {
        i_error("Invalid input from master: %s", line);
        return -1;
    }

    memset(&input, 0, sizeof(input));
    input.module = "mail";
    input.service = "indexer-worker";
    input.username = args[0];

    if (mail_storage_service_lookup_next(conn->storage_service, &input,
                                         &service_user, &user, &error) <= 0) {
        i_error("User %s lookup failed: %s", args[0], error);
        ret = -1;
    } else {
        indexer_worker_refresh_proctitle(user->username, args[1], 0, 0);
        ret = index_mailbox(conn, user, args[1],
                            max_recent_msgs, args[3]);
        indexer_worker_refresh_proctitle(NULL, NULL, 0, 0);
        mail_user_unref(&user);
        mail_storage_service_user_free(&service_user);
    }

    str = ret < 0 ? "-1\n" : "100\n";
    return write_full(conn->fd, str, strlen(str));
}
Beispiel #11
0
void client_destroy(struct client *client, const char *prefix,
		    const char *reason)
{
	if (client->destroyed)
		return;
	client->destroyed = TRUE;

	client_disconnect(client, prefix, reason);

	submission_client_count--;
	DLLIST_REMOVE(&submission_clients, client);

	if (client->proxy_conn != NULL)
		smtp_client_connection_close(&client->proxy_conn);

	if (client->anvil_sent) {
		master_service_anvil_send(master_service, t_strconcat(
			"DISCONNECT\t", my_pid, "\tsubmission/",
			mail_user_get_anvil_userip_ident(client->user),
			"\n", NULL));
	}

	if (client->urlauth_ctx != NULL)
		imap_urlauth_deinit(&client->urlauth_ctx);

	mail_user_unref(&client->user);
	mail_storage_service_user_unref(&client->service_user);

	client_state_reset(client);

	i_free(client->session_id);
	i_free(client);

	master_service_client_connection_destroyed(master_service);
	submission_refresh_proctitle();
}
static int
mail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
			       struct mail_storage_service_user *user,
			       struct mail_storage_service_privileges *priv,
			       struct mail_user **mail_user_r,
			       const char **error_r)
{
	const struct mail_storage_settings *mail_set;
	const char *home = priv->home;
	struct mail_user *mail_user;

	/* NOTE: if more user initialization is added, add it also to
	   mail_user_dup() */
	mail_user = mail_user_alloc(user->input.username, user->user_info,
				    user->user_set);
	mail_user->_service_user = user;
	mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
	mail_user_set_vars(mail_user, ctx->service->name,
			   &user->input.local_ip, &user->input.remote_ip);
	mail_user->uid = priv->uid == (uid_t)-1 ? geteuid() : priv->uid;
	mail_user->gid = priv->gid == (gid_t)-1 ? getegid() : priv->gid;
	mail_user->anonymous = user->anonymous;
	mail_user->admin = user->admin;
	mail_user->auth_token = p_strdup(mail_user->pool, user->auth_token);
	mail_user->auth_user = p_strdup(mail_user->pool, user->auth_user);
	mail_user->session_id =
		p_strdup(mail_user->pool, user->input.session_id);
	mail_user->userdb_fields = user->input.userdb_fields == NULL ? NULL :
		p_strarray_dup(mail_user->pool, user->input.userdb_fields);
	mail_user->autoexpunge_enabled =
		(user->flags & MAIL_STORAGE_SERVICE_FLAG_AUTOEXPUNGE) != 0;
	
	mail_set = mail_user_set_get_storage_set(mail_user);

	if (mail_set->mail_debug) {
		string_t *str = t_str_new(64);

		str_printfa(str, "Effective uid=%s, gid=%s, home=%s",
			    dec2str(geteuid()), dec2str(getegid()), home);
		if (*priv->chroot != '\0')
			str_printfa(str, ", chroot=%s", priv->chroot);
		i_debug("%s", str_c(str));
	}

	if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
	    (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) == 0) {
		/* we don't want to write core files to any users' home
		   directories since they could contain information about other
		   users' mails as well. so do no chdiring to home. */
	} else if (*home != '\0' &&
		   (user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
		/* If possible chdir to home directory, so that core file
		   could be written in case we crash. */
		if (chdir(home) < 0) {
			if (errno == EACCES) {
				i_error("%s", eacces_error_get("chdir",
						t_strconcat(home, "/", NULL)));
			} if (errno != ENOENT)
				i_error("chdir(%s) failed: %m", home);
			else if (mail_set->mail_debug)
				i_debug("Home dir not found: %s", home);
		}
	}

	if (mail_user_init(mail_user, error_r) < 0) {
		mail_user_unref(&mail_user);
		return -1;
	}
	if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES) == 0) {
		if (mail_namespaces_init(mail_user, error_r) < 0) {
			mail_user_unref(&mail_user);
			return -1;
		}
	}
	*mail_user_r = mail_user;
	return 0;
}
Beispiel #13
0
static int
cmd_dsync_run_local(struct dsync_cmd_context *ctx, struct mail_user *user,
		    struct dsync_brain *brain, struct dsync_ibc *ibc2,
		    bool *changes_during_sync_r)
{
	struct dsync_brain *brain2;
	struct mail_user *user2;
	struct setting_parser_context *set_parser;
	const char *set_line, *location;
	bool brain1_running, brain2_running, changed1, changed2;
	int ret;

	if (ctx->local_location_from_arg)
		location = ctx->ctx.args[0];
	else {
		i_assert(ctx->local_location != NULL);
		location = ctx->local_location;
	}

	i_set_failure_prefix("dsync(%s): ", user->username);

	/* update mail_location and create another user for the
	   second location. */
	set_parser = mail_storage_service_user_get_settings_parser(ctx->ctx.cur_service_user);
	set_line = t_strconcat("mail_location=", location, NULL);
	if (settings_parse_line(set_parser, set_line) < 0)
		i_unreached();
	ret = mail_storage_service_next(ctx->ctx.storage_service,
					ctx->ctx.cur_service_user, &user2);
	if (ret < 0) {
		ctx->ctx.exit_code = ret == -1 ? EX_TEMPFAIL : EX_CONFIG;
		return -1;
	}
	doveadm_user_init_dsync(user2);

	if (mail_namespaces_get_root_sep(user->namespaces) !=
	    mail_namespaces_get_root_sep(user2->namespaces)) {
		i_error("Mail locations must use the same "
			"virtual mailbox hierarchy separator "
			"(specify separator for the default namespace)");
		ctx->ctx.exit_code = EX_CONFIG;
		mail_user_unref(&user2);
		return -1;
	}
	if (paths_are_equal(user, user2, MAILBOX_LIST_PATH_TYPE_MAILBOX) &&
	    paths_are_equal(user, user2, MAILBOX_LIST_PATH_TYPE_INDEX)) {
		i_error("Both source and destination mail_location "
			"points to same directory: %s",
			mailbox_list_get_root_forced(user->namespaces->list,
						     MAILBOX_LIST_PATH_TYPE_MAILBOX));
		ctx->ctx.exit_code = EX_CONFIG;
		mail_user_unref(&user2);
		return -1;
	}

	brain2 = dsync_brain_slave_init(user2, ibc2, TRUE);
	mail_user_unref(&user2);

	brain1_running = brain2_running = TRUE;
	changed1 = changed2 = TRUE;
	while (brain1_running || brain2_running) {
		if (dsync_brain_has_failed(brain) ||
		    dsync_brain_has_failed(brain2))
			break;

		i_assert(changed1 || changed2);
		brain1_running = dsync_brain_run(brain, &changed1);
		brain2_running = dsync_brain_run(brain2, &changed2);
	}
	*changes_during_sync_r = dsync_brain_has_unexpected_changes(brain2);
	if (dsync_brain_deinit(&brain2) < 0) {
		ctx->ctx.exit_code = EX_TEMPFAIL;
		return -1;
	}
	return 0;
}
static void client_default_destroy(struct client *client, const char *reason)
{
	struct client_command_context *cmd;
	const char *cmd_status = "";

	i_assert(!client->destroyed);
	client->destroyed = TRUE;

	if (!client->disconnected) {
		client->disconnected = TRUE;
		if (reason == NULL) {
			reason = io_stream_get_disconnect_reason(client->input,
								 client->output);
			cmd_status = client_get_commands_status(client);
		}
		i_info("%s%s %s", reason, cmd_status, client_stats(client));
	}

	i_stream_close(client->input);
	o_stream_close(client->output);

	/* finish off all the queued commands. */
	if (client->output_cmd_lock != NULL)
		client_command_cancel(&client->output_cmd_lock);
	while (client->command_queue != NULL) {
		cmd = client->command_queue;
		client_command_cancel(&cmd);
	}
	/* handle the input_lock command last. it might have been waiting on
	   other queued commands (although we probably should just drop the
	   command at that point since it hasn't started running. but this may
	   change in future). */
	if (client->input_lock != NULL)
		client_command_cancel(&client->input_lock);

	if (client->mailbox != NULL) {
		client_search_updates_free(client);
		mailbox_free(&client->mailbox);
	}
	if (client->notify_ctx != NULL)
		imap_notify_deinit(&client->notify_ctx);
	if (client->urlauth_ctx != NULL)
		imap_urlauth_deinit(&client->urlauth_ctx);
	if (client->anvil_sent) {
		master_service_anvil_send(master_service, t_strconcat(
			"DISCONNECT\t", my_pid, "\timap/",
			mail_user_get_anvil_userip_ident(client->user),
			"\n", NULL));
	}
	mail_user_unref(&client->user);

	if (client->free_parser != NULL)
		imap_parser_unref(&client->free_parser);
	if (client->io != NULL)
		io_remove(&client->io);
	if (client->to_idle_output != NULL)
		timeout_remove(&client->to_idle_output);
	if (client->to_delayed_input != NULL)
		timeout_remove(&client->to_delayed_input);
	timeout_remove(&client->to_idle);

	i_stream_destroy(&client->input);
	o_stream_destroy(&client->output);

	net_disconnect(client->fd_in);
	if (client->fd_in != client->fd_out)
		net_disconnect(client->fd_out);

	if (array_is_created(&client->search_saved_uidset))
		array_free(&client->search_saved_uidset);
	if (array_is_created(&client->search_updates))
		array_free(&client->search_updates);
	pool_unref(&client->command_pool);
	mail_storage_service_user_free(&client->service_user);

	imap_client_count--;
	DLLIST_REMOVE(&imap_clients, client);
	pool_unref(&client->pool);

	master_service_client_connection_destroyed(master_service);
	imap_refresh_proctitle();
}
Beispiel #15
0
static int
cmd_user_mail_input(struct mail_storage_service_ctx *storage_service,
                    const struct authtest_input *input,
                    const char *show_field, const char *expand_field)
{
    struct mail_storage_service_input service_input;
    struct mail_storage_service_user *service_user;
    struct mail_user *user;
    const char *error, *const *userdb_fields;
    pool_t pool;
    int ret;

    memset(&service_input, 0, sizeof(service_input));
    service_input.module = "mail";
    service_input.service = input->info.service;
    service_input.username = input->username;
    service_input.local_ip = input->info.local_ip;
    service_input.local_port = input->info.local_port;
    service_input.remote_ip = input->info.remote_ip;
    service_input.remote_port = input->info.remote_port;
    service_input.debug = input->info.debug;

    pool = pool_alloconly_create("userdb fields", 1024);
    mail_storage_service_save_userdb_fields(storage_service, pool,
                                            &userdb_fields);

    if ((ret = mail_storage_service_lookup_next(storage_service, &service_input,
               &service_user, &user,
               &error)) <= 0) {
        pool_unref(&pool);
        if (ret < 0)
            return -1;
        string_t *username = t_str_new(32);
        json_append_escaped(username, input->username);
        o_stream_nsend_str(doveadm_print_ostream,
                           t_strdup_printf("\"error\":\"userdb lookup: user %s doesn't exist\"", str_c(username))
                          );
        return 0;
    }

    if (expand_field == NULL)
        cmd_user_mail_print_fields(input, user, userdb_fields, show_field);
    else {
        string_t *str = t_str_new(128);
        if (var_expand_with_funcs(str, expand_field,
                                  mail_user_var_expand_table(user),
                                  mail_user_var_expand_func_table, user,
                                  &error) <= 0) {
            string_t *str = t_str_new(128);
            str_printfa(str, "\"error\":\"Failed to expand field: ");
            json_append_escaped(str, error);
            str_append_c(str, '"');
            o_stream_nsend(doveadm_print_ostream, str_data(str), str_len(str));
        } else {
            string_t *value = t_str_new(128);
            json_append_escaped(value, expand_field);
            o_stream_nsend_str(doveadm_print_ostream, "\"");
            o_stream_nsend_str(doveadm_print_ostream, str_c(value));
            o_stream_nsend_str(doveadm_print_ostream, "\":\"");
            str_truncate(value, 0);
            json_append_escaped(value, str_c(str));
            o_stream_nsend_str(doveadm_print_ostream, str_c(value));
            o_stream_nsend_str(doveadm_print_ostream, "\"");
        }

    }

    mail_user_unref(&user);
    mail_storage_service_user_free(&service_user);
    pool_unref(&pool);
    return 1;
}