Example #1
0
static int
client_create_from_input(const struct mail_storage_service_input *input,
			 int fd_in, int fd_out, const buffer_t *input_buf,
			 const char **error_r)
{
	const char *lookup_error_str =
		"-ERR [SYS/TEMP] "MAIL_ERRSTR_CRITICAL_MSG"\r\n";
	struct mail_storage_service_user *user;
	struct mail_user *mail_user;
	struct client *client;
	const struct pop3_settings *set;

	if (mail_storage_service_lookup_next(storage_service, input,
					     &user, &mail_user, error_r) <= 0) {
		(void)write(fd_out, lookup_error_str, strlen(lookup_error_str));
		return -1;
	}
	restrict_access_allow_coredumps(TRUE);

	set = mail_storage_service_user_get_set(user)[1];
	if (set->verbose_proctitle)
		verbose_proctitle = TRUE;

	if (client_create(fd_in, fd_out, input->session_id,
			  mail_user, user, set, &client) == 0)
		client_add_input(client, input_buf);
	return 0;
}
Example #2
0
static int
client_create_from_input(const struct mail_storage_service_input *input,
			 const struct master_login_client *login_client,
			 int fd_in, int fd_out, const buffer_t *input_buf,
			 const char **error_r)
{
	struct mail_storage_service_user *user;
	struct mail_user *mail_user;
	struct client *client;
	struct imap_settings *set;
	enum mail_auth_request_flags flags;

	if (mail_storage_service_lookup_next(storage_service, input,
					     &user, &mail_user, error_r) <= 0)
		return -1;
	restrict_access_allow_coredumps(TRUE);

	set = mail_storage_service_user_get_set(user)[1];
	if (set->verbose_proctitle)
		verbose_proctitle = TRUE;

	settings_var_expand(&imap_setting_parser_info, set, mail_user->pool,
			    mail_user_var_expand_table(mail_user));

	client = client_create(fd_in, fd_out, input->session_id,
			       mail_user, user, set);
	T_BEGIN {
		client_add_input(client, input_buf);
	} T_END;

	flags = login_client->auth_req.flags;
	if ((flags & MAIL_AUTH_REQUEST_FLAG_TLS_COMPRESSION) != 0)
		client->tls_compression = TRUE;
	return 0;
}
Example #3
0
static void cmd_import_init(struct doveadm_mail_cmd_context *_ctx,
			    const char *const args[])
{
	struct import_cmd_context *ctx = (struct import_cmd_context *)_ctx;
	struct mail_storage_service_input input;
	struct mail_storage_service_user *service_user;
	struct mail_user *user;
	const char *src_location, *error;

	if (str_array_length(args) < 3)
		doveadm_mail_help_name("import");
	src_location = args[0];
	ctx->dest_parent = p_strdup(_ctx->pool, args[1]);
	ctx->ctx.search_args = doveadm_mail_build_search_args(args+2);

	/* create a user for accessing the source storage */
	memset(&input, 0, sizeof(input));
	input.module = "mail";
	input.username = "******";
	input.flags_override_add = MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES |
		MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS;
	input.flags_override_remove = MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
	if (mail_storage_service_lookup_next(ctx->ctx.storage_service, &input,
					     &service_user, &user, &error) < 0)
		i_fatal("Import user initialization failed: %s", error);
	if (mail_namespaces_init_location(user, src_location, &error) < 0)
		i_fatal("Import namespace initialization failed: %s", error);

	ctx->src_user = user;
	mail_storage_service_user_free(&service_user);
}
static void cmd_import_init(struct doveadm_mail_cmd_context *_ctx,
			    const char *const args[])
{
	struct import_cmd_context *ctx = (struct import_cmd_context *)_ctx;
	struct mail_storage_service_input input;
	struct mail_storage_service_user *service_user;
	struct mail_user *user;
	const char *src_location, *error, *userdb_fields[2];

	if (str_array_length(args) < 3)
		doveadm_mail_help_name("import");
	src_location = args[0];
	ctx->dest_parent = p_strdup(_ctx->pool, args[1]);
	ctx->ctx.search_args = doveadm_mail_build_search_args(args+2);

	/* @UNSAFE */
	userdb_fields[0] = t_strconcat("mail=", src_location, NULL);
	userdb_fields[1] = NULL;

	/* create a user for accessing the source storage */
	memset(&input, 0, sizeof(input));
	input.module = "module";
	input.username = "******";
	input.no_userdb_lookup = TRUE;
	input.userdb_fields = userdb_fields;
	if (mail_storage_service_lookup_next(ctx->ctx.storage_service, &input,
					     &service_user, &user, &error) < 0)
		i_fatal("Import user initialization failed: %s", error);
	ctx->src_user = user;
	mail_storage_service_user_free(&service_user);
}
static void
cmd_copy_alloc_source_user(struct copy_cmd_context *ctx, const char *username)
{
	struct mail_storage_service_input input;
	const char *error;

	input = ctx->ctx.storage_service_input;
	input.username = username;

	if (mail_storage_service_lookup_next(ctx->ctx.storage_service, &input,
					     &ctx->source_service_user,
					     &ctx->source_user,
					     &error) < 0)
		i_fatal("Couldn't lookup user %s: %s", input.username, error);
}
Example #6
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));
}
Example #7
0
static int
client_create_from_input(const struct mail_storage_service_input *input,
			 int fd_in, int fd_out, const buffer_t *input_buf,
			 const char **error_r)
{
	const char *lookup_error_str =
		"-ERR [SYS/TEMP] "MAIL_ERRSTR_CRITICAL_MSG"\r\n";
	struct mail_storage_service_user *user;
	struct mail_user *mail_user;
	struct client *client;
	const struct pop3_settings *set;
	const char *error;

	if (mail_storage_service_lookup_next(storage_service, input,
					     &user, &mail_user, error_r) <= 0) {
		if (write(fd_out, lookup_error_str, strlen(lookup_error_str)) < 0) {
			/* ignored */
		}
		return -1;
	}
	restrict_access_allow_coredumps(TRUE);

	set = mail_storage_service_user_get_set(user)[1];
	if (set->verbose_proctitle)
		verbose_proctitle = TRUE;

	if (client_create(fd_in, fd_out, input->session_id,
			  mail_user, user, set, &client) < 0)
		return 0;
	if (!IS_STANDALONE())
		client_send_line(client, "+OK Logged in.");
	if (client_init_mailbox(client, &error) == 0)
		client_add_input(client, input_buf);
	else {
		i_error("%s", error);
		client_destroy(client, error);
	}
	return 0;
}
Example #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> <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));
}
Example #9
0
static void cmd_import_init_source_user(struct import_cmd_context *ctx)
{
	struct mail_storage_service_input input;
	struct mail_storage_service_user *service_user;
	struct mail_user *user;
	const char *error;

	/* create a user for accessing the source storage */
	memset(&input, 0, sizeof(input));
	input.module = "mail";
	input.username = "******";
	input.flags_override_add = MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES |
		MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS;
	input.flags_override_remove = MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
	if (mail_storage_service_lookup_next(ctx->ctx.storage_service, &input,
					     &service_user, &user, &error) < 0)
		i_fatal("Import user initialization failed: %s", error);
	if (mail_namespaces_init_location(user, ctx->src_location, &error) < 0)
		i_fatal("Import namespace initialization failed: %s", error);

	ctx->src_user = user;
	mail_storage_service_user_free(&service_user);
}
Example #10
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;
}
Example #11
0
static int
client_handle_user_command(struct client *client, const char *cmd,
			   const char *const *args, const char **error_r)
{
	struct mail_storage_service_input input;
	struct imap_urlauth_worker_settings *set;
	struct mail_storage_service_user *user;
	struct imap_urlauth_config config;
	struct mail_user *mail_user;
	const char *error;
	unsigned int count;
	int ret;

	/* "USER\t"<username> */
	*error_r = NULL;

	/* check command syntax */
	if (strcmp(cmd, "USER") != 0) {
		*error_r = t_strconcat("Unknown or inappropriate command: ",
				       cmd, NULL);
		return -1;
	}

	if (args[0] == NULL || args[1] != NULL) {
		*error_r = "USER: Invalid number of parameters";
		return -1;
	}

	/* lookup user */
	memset(&input, 0, sizeof(input));
	input.module = "imap-urlauth-worker";
	input.service = "imap-urlauth-worker";
	input.username = args[0];

	if (client->debug)
		i_debug("Looking up user %s", input.username);

	ret = mail_storage_service_lookup_next(storage_service, &input,
					       &user, &mail_user, &error);
	if (ret < 0) {
		i_error("Failed to lookup user %s: %s", input.username, error);
		client_abort(client, "Session aborted: Failed to lookup user");
		return 0;
	} else if (ret == 0) {
		if (client->debug)
			i_debug("User %s doesn't exist", input.username);

		client_send_line(client, "NO");
		timeout_remove(&client->to_delay);
		return 1;
	}

	client->debug = mail_user->mail_debug =
		client->debug || mail_user->mail_debug;

	/* drop privileges */
	restrict_access_allow_coredumps(TRUE);

	set = mail_storage_service_user_get_set(user)[1];
	settings_var_expand(&imap_urlauth_worker_setting_parser_info, set,
			    mail_user->pool,
			    mail_user_var_expand_table(mail_user));

	if (set->verbose_proctitle) {
		verbose_proctitle = TRUE;
		imap_urlauth_worker_refresh_proctitle();
	}

	client->service_user = user;
	client->mail_user = mail_user;
	client->set = set;

	if (client->debug) {
		i_debug("Found user account `%s' on behalf of user `%s'",
			mail_user->username, client->access_user);
	}

	/* initialize urlauth context */
	if (*set->imap_urlauth_host == '\0') {
		i_error("imap_urlauth_host setting is not configured for user %s",
			mail_user->username);
		client_send_line(client, "NO");
		client_abort(client, "Session aborted: URLAUTH not configured");
		return 0;
	}

	memset(&config, 0, sizeof(config));
	config.url_host = set->imap_urlauth_host;
	config.url_port = set->imap_urlauth_port;
	config.access_user = client->access_user;
	config.access_anonymous = client->access_anonymous;
	config.access_applications =
		(const void *)array_get(&client->access_apps, &count);
		
	client->urlauth_ctx = imap_urlauth_init(client->mail_user, &config);
	if (client->debug) {
		i_debug("Providing access to user account `%s' on behalf of `%s'",
			mail_user->username, client->access_user);
	}

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

	client_send_line(client, "OK");
	return 1;
}
Example #12
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;
}