static bool stats_top_round(struct top_context *ctx)
{
#define TOP_CMD "EXPORT\tsession\tconnected\n"
	const char *const *args;
	pool_t tmp_pool;

	if (write_full(ctx->fd, TOP_CMD, strlen(TOP_CMD)) < 0)
		i_fatal("write(%s) failed: %m", ctx->path);

	/* read header */
	if (ctx->headers != NULL) {
		args = read_next_line(ctx->input);
		if (args == NULL)
			i_fatal("read(%s) unexpectedly disconnected", ctx->path);
		if (*args == NULL)
			return TRUE;
		if (str_array_length(args) != ctx->headers_count)
			i_fatal("headers changed");
	} else {
		ctx->headers = p_read_next_line(default_pool, ctx->input);
		if (ctx->headers == NULL)
			i_fatal("read(%s) unexpectedly disconnected", ctx->path);
		if (*ctx->headers == NULL) {
			i_free_and_null(ctx->headers);
			return FALSE;
		}
		ctx->headers_count = str_array_length((void *)ctx->headers);
		if (!stats_header_find(ctx, "last_update", &ctx->last_update_idx))
			i_fatal("last_update header missing");
		if (!stats_header_find(ctx, "user", &ctx->user_idx))
			i_fatal("user header missing");
		stats_top_get_sorting(ctx);
	}

	array_clear(&ctx->lines);
	p_clear(ctx->prev_pool);
	tmp_pool = ctx->prev_pool;
	ctx->prev_pool = ctx->cur_pool;
	ctx->cur_pool = tmp_pool;

	ctx->flip = !ctx->flip;
	stats_read(ctx);
	stats_drop_stale(ctx);

	sort_ctx = ctx;
	array_sort(&ctx->lines, *ctx->lines_sort);
	sort_ctx = NULL;
	return TRUE;
}
Esempio n. 2
0
int connection_verify_version(struct connection *conn,
			      const char *const *args)
{
	unsigned int recv_major_version;

	/* VERSION <tab> service_name <tab> major version <tab> minor version */
	if (str_array_length(args) != 4 ||
	    strcmp(args[0], "VERSION") != 0 ||
	    str_to_uint(args[2], &recv_major_version) < 0 ||
	    str_to_uint(args[3], &conn->minor_version) < 0) {
		i_error("%s didn't reply with a valid VERSION line",
			conn->name);
		return -1;
	}

	if (strcmp(args[1], conn->list->set.service_name_in) != 0) {
		i_error("%s: Connected to wrong socket type. "
			"We want '%s', but received '%s'", conn->name,
			conn->list->set.service_name_in, args[1]);
		return -1;
	}

	if (recv_major_version != conn->list->set.major_version) {
		i_error("%s: Socket supports major version %u, "
			"but we support only %u (mixed old and new binaries?)",
			conn->name, recv_major_version,
			conn->list->set.major_version);
		return -1;
	}
	return 0;
}
Esempio n. 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, *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 stats_read(struct top_context *ctx)
{
	struct top_line *old_line, *line;
	unsigned int i;
	char **args;

	/* read lines */
	while ((args = p_read_next_line(ctx->cur_pool, ctx->input)) != NULL) {
		if (args[0] == NULL) {
			/* end of stats */
			return;
		}
		if (str_array_length((void *)args) != ctx->headers_count)
			i_fatal("read(%s): invalid stats line", ctx->path);

		line = p_new(ctx->cur_pool, struct top_line, 1);
		line->id = args[0];
		line->flip = ctx->flip;
		line->cur_values = p_new(ctx->cur_pool, const char *, ctx->headers_count);
		for (i = 0; i < ctx->headers_count; i++)
			line->cur_values[i] = args[i];

		old_line = hash_table_lookup(ctx->sessions, line->id);
		if (old_line != NULL) {
			stats_line_set_prev_values(ctx, old_line, line);
			array_append(&ctx->lines, &line, 1);
		}
		hash_table_insert(ctx->sessions, line->id, line);
	}

	if (ctx->input->stream_errno != 0)
		i_fatal("read(%s) failed: %m", ctx->path);
	i_fatal("read(%s): unexpected EOF", ctx->path);
}
Esempio n. 5
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);
}
Esempio n. 6
0
int mail_session_connect_parse(const char *const *args, const char **error_r)
{
	struct mail_session *session;
	const char *session_id;
	pid_t pid;
	struct ip_addr ip;
	unsigned int i;

	/* <session id> <username> <service> <pid> [key=value ..] */
	if (str_array_length(args) < 4) {
		*error_r = "CONNECT: Too few parameters";
		return -1;
	}
	session_id = args[0];
	if (str_to_pid(args[3], &pid) < 0) {
		*error_r = t_strdup_printf("CONNECT: Invalid pid %s for session ID %s",
					   args[3], session_id);
		return -1;
	}

	session = hash_table_lookup(mail_sessions_hash, session_id);
	if (session != NULL) {
		*error_r = t_strdup_printf(
			"CONNECT: Duplicate session ID %s for user %s service %s",
			session_id, args[1], args[2]);
		return -1;
	}
	session = i_malloc(sizeof(struct mail_session) + stats_alloc_size());
	session->stats = (void *)(session + 1);
	session->refcount = 1; /* unrefed at disconnect */
	session->id = i_strdup(session_id);
	session->service = str_table_ref(services, args[2]);
	session->pid = pid;
	session->last_update = ioloop_timeval;
	session->to_idle = timeout_add(MAIL_SESSION_IDLE_TIMEOUT_MSECS,
				       mail_session_idle_timeout, session);

	session->user = mail_user_login(args[1]);
	for (i = 3; args[i] != NULL; i++) {
		if (strncmp(args[i], "rip=", 4) == 0 &&
		    net_addr2ip(args[i] + 4, &ip) == 0)
			session->ip = mail_ip_login(&ip);
	}

	hash_table_insert(mail_sessions_hash, session->id, session);
	DLLIST_PREPEND_FULL(&stable_mail_sessions, session,
			    stable_prev, stable_next);
	DLLIST2_APPEND_FULL(&mail_sessions_head, &mail_sessions_tail, session,
			    sorted_prev, sorted_next);
	DLLIST_PREPEND_FULL(&session->user->sessions, session,
			    user_prev, user_next);
	mail_user_ref(session->user);
	if (session->ip != NULL) {
		DLLIST_PREPEND_FULL(&session->ip->sessions, session,
				    ip_prev, ip_next);
		mail_ip_ref(session->ip);
	}
	global_memory_alloc(mail_session_memsize(session));
	return 0;
}
Esempio n. 7
0
static int
client_input_notify(struct doveadm_connection *client, const char *const *args)
{
	struct replicator_user *user;

	/* <username> <flags> <state> */
	if (str_array_length(args) < 3) {
		i_error("%s: NOTIFY: Invalid parameters", client->conn.name);
		return -1;
	}

	user = replicator_queue_add(client->queue, args[0],
				    REPLICATION_PRIORITY_NONE);
	if (args[1][0] == 'f')
		user->last_full_sync = ioloop_time;
	user->last_fast_sync = ioloop_time;
	user->last_update = ioloop_time;

	if (args[2][0] != '\0') {
		i_free(user->state);
		user->state = i_strdup(args[2]);
	}
	o_stream_send_str(client->conn.output, "+\n");
	return 0;
}
static void
search_update_flag_changes(struct dsync_mailbox_exporter *exporter,
                           struct mail *mail, struct dsync_mail_change *change)
{
    const char *const *keywords;
    unsigned int i;
    char type;

    i_assert((change->add_flags & change->remove_flags) == 0);

    change->modseq = mail_get_modseq(mail);
    change->pvt_modseq = mail_get_pvt_modseq(mail);
    change->final_flags = mail_get_flags(mail);

    keywords = mail_get_keywords(mail);
    if (!array_is_created(&change->keyword_changes) &&
            keywords[0] != NULL) {
        p_array_init(&change->keyword_changes, exporter->pool,
                     str_array_length(keywords));
    }
    for (i = 0; keywords[i] != NULL; i++) {
        /* add the final keyword if it's not already there
           as +keyword */
        if (!final_keyword_check(change, keywords[i], &type)) {
            const char *keyword_change =
                p_strdup_printf(exporter->pool, "%c%s",
                                type, keywords[i]);
            array_append(&change->keyword_changes,
                         &keyword_change, 1);
        }
    }
}
Esempio n. 9
0
static void
cmd_director_status_user(struct director_context *ctx, char *argv[])
{
	const char *user = argv[0], *tag = argv[1];
	const char *line, *const *args;
	unsigned int expires;

	director_send(ctx, t_strdup_printf("USER-LOOKUP\t%s\t%s\n", user,
					   tag != NULL ? tag : ""));
	line = i_stream_read_next_line(ctx->input);
	if (line == NULL) {
		i_error("Lookup failed");
		doveadm_exit_code = EX_TEMPFAIL;
		return;
	}

	args = t_strsplit_tab(line);
	if (str_array_length(args) != 4 ||
	    str_to_uint(args[1], &expires) < 0) {
		i_error("Invalid reply from director");
		doveadm_exit_code = EX_PROTOCOL;
		return;
	}

	if (args[0][0] != '\0') {
		printf("Current: %s (expires %s)\n",
		       args[0], unixdate2str(expires));
	} else {
		printf("Current: not assigned\n");
	}
	printf("Hashed: %s\n", args[2]);
	printf("Initial config: %s\n", args[3]);
	director_disconnect(ctx);
}
Esempio n. 10
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;

	if (str_array_length(args) < 3)
		doveadm_mail_help_name("import");
	ctx->src_location = p_strdup(_ctx->pool, args[0]);
	ctx->dest_parent = p_strdup(_ctx->pool, args[1]);
	ctx->ctx.search_args = doveadm_mail_build_search_args(args+2);
}
Esempio n. 11
0
static const char *
file_lock_find_proc_locks(int lock_fd ATTR_UNUSED)
{
	/* do anything except Linux support this? don't bother trying it for
	   OSes we don't know about. */
#ifdef __linux__
	static bool have_proc_locks = TRUE;
	struct stat st;
	char node_buf[MAX_INT_STRLEN*3 + 2 + 1];
	struct istream *input;
	const char *line, *lock_type = "";
	pid_t pid = 0;
	int fd;

	if (!have_proc_locks)
		return FALSE;

	if (fstat(lock_fd, &st) < 0)
		return "";
	i_snprintf(node_buf, sizeof(node_buf), "%02x:%02x:%llu",
		   major(st.st_dev), minor(st.st_dev),
		   (unsigned long long)st.st_ino);
	fd = open("/proc/locks", O_RDONLY);
	if (fd == -1) {
		have_proc_locks = FALSE;
		return "";
	}
	input = i_stream_create_fd_autoclose(&fd, 512);
	while (pid == 0 && (line = i_stream_read_next_line(input)) != NULL) T_BEGIN {
		const char *const *args = t_strsplit_spaces(line, " ");

		/* number: FLOCK/POSIX ADVISORY READ/WRITE pid
		   major:minor:inode region-start region-end */
		if (str_array_length(args) < 8)
			continue;
		if (strcmp(args[5], node_buf) == 0) {
			lock_type = strcmp(args[3], "READ") == 0 ?
				"READ" : "WRITE";
			if (str_to_pid(args[4], &pid) < 0)
				pid = 0;
		}
	} T_END;
	i_stream_destroy(&input);
	if (pid == 0) {
		/* not found */
		return "";
	}
	if (pid == getpid())
		return " (BUG: lock is held by our own process)";
	return t_strdup_printf(" (%s lock held by pid %ld)", lock_type, (long)pid);
#else
	return "";
#endif
}
static void cmd_sieve_activate_init
(struct doveadm_mail_cmd_context *_ctx,
	const char *const args[])
{
	struct doveadm_sieve_activate_cmd_context *ctx =
		(struct doveadm_sieve_activate_cmd_context *)_ctx;

	if (str_array_length(args) != 1)
		doveadm_mail_help_name("sieve activate");
	doveadm_sieve_cmd_scriptnames_check(args);

	ctx->scriptname = p_strdup(ctx->ctx.ctx.pool, args[0]);
}
static void
cmd_mailbox_metadata_unset_init(struct doveadm_mail_cmd_context *_ctx,
				const char *const args[])
{
	struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
	const char *key;

	if (str_array_length(args) != 2)
		doveadm_mail_help_name("mailbox metadata unset");
	cmd_mailbox_metadata_parse_key(args[1], &ctx->key_type, &key);

	ctx->mailbox = p_strdup(_ctx->pool, args[0]);
	ctx->key = p_strdup(_ctx->pool, key);
}
Esempio n. 14
0
static void cmd_director_status(int argc, char *argv[])
{
	struct director_context *ctx;
	const char *line, *const *args;

	ctx = cmd_director_init(argc, argv, "a:t:", cmd_director_status);
	if (argv[optind] != NULL) {
		cmd_director_status_user(ctx, argv+optind);
		return;
	}

	doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
	doveadm_print_header_simple("mail server ip");
	doveadm_print_header_simple("tag");
	doveadm_print_header_simple("vhosts");
	doveadm_print_header_simple("state");
	doveadm_print_header("state-changed", "state changed", 0);
	doveadm_print_header_simple("users");

	director_send(ctx, "HOST-LIST\n");
	while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
		if (*line == '\0')
			break;
		T_BEGIN {
			unsigned int arg_count;
			time_t ts;

			args = t_strsplit_tab(line);
			arg_count = str_array_length(args);
			if (arg_count >= 6) {
				/* ip vhosts users tag updown updown-ts */
				doveadm_print(args[0]); 
				doveadm_print(args[3]);
				doveadm_print(args[1]);
				doveadm_print(args[4][0] == 'D' ? "down" : "up");
				if (str_to_time(args[5], &ts) < 0 ||
				    ts <= 0)
					doveadm_print("-");
				else
					doveadm_print(unixdate2str(ts));
				doveadm_print(args[2]);
			}
		} T_END;
	}
	if (line == NULL) {
		i_error("Director disconnected unexpectedly");
		doveadm_exit_code = EX_TEMPFAIL;
	}
	director_disconnect(ctx);
}
Esempio n. 15
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));
}
Esempio n. 16
0
static int auth_server_input_cont(struct auth_server_connection *conn,
				  const char *const *args)
{
	struct auth_client_request *request;

	if (str_array_length(args) < 2) {
		i_error("BUG: Authentication server sent broken CONT line");
		return -1;
	}

	if (auth_server_lookup_request(conn, args[0], FALSE, &request) < 0)
		return -1;
	auth_client_request_server_input(request, AUTH_REQUEST_STATUS_CONTINUE,
					 args + 1);
	return 0;
}
static void
cmd_mailbox_metadata_get_init(struct doveadm_mail_cmd_context *_ctx,
			      const char *const args[])
{
	struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
	const char *key;

	if (str_array_length(args) != 2)
		doveadm_mail_help_name("mailbox metadata get");
	cmd_mailbox_metadata_parse_key(args[1], &ctx->key_type, &key);

	ctx->mailbox = p_strdup(_ctx->pool, args[0]);
	ctx->key = p_strdup(_ctx->pool, key);
	doveadm_print_header("value", "value",
			     DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
}
Esempio n. 18
0
struct userdb_template *
userdb_template_build(pool_t pool, const char *userdb_name, const char *args)
{
	struct userdb_template *tmpl;
	const char *const *tmp, *key, *value, *nonull_value;
	uid_t uid;
	gid_t gid;

	tmpl = p_new(pool, struct userdb_template, 1);

	tmp = t_strsplit_spaces(args, " ");
	p_array_init(&tmpl->args, pool, str_array_length(tmp));

	for (; *tmp != NULL; tmp++) {
		value = strchr(*tmp, '=');
		if (value == NULL)
			key = *tmp;
		else
			key = t_strdup_until(*tmp, value++);

		nonull_value = value == NULL ? "" : value;
		if (strcasecmp(key, "uid") == 0) {
			uid = userdb_parse_uid(NULL, nonull_value);
			if (uid == (uid_t)-1) {
				i_fatal("%s userdb: Invalid uid: %s",
					userdb_name, nonull_value);
			}
			value = dec2str(uid);
		} else if (strcasecmp(key, "gid") == 0) {
			gid = userdb_parse_gid(NULL, nonull_value);
			if (gid == (gid_t)-1) {
				i_fatal("%s userdb: Invalid gid: %s",
					userdb_name, nonull_value);
			}
			value = dec2str(gid);
		} else if (*key == '\0') {
			i_fatal("%s userdb: Empty key (=%s)",
				userdb_name, nonull_value);
		}
		key = p_strdup(pool, key);
		value = p_strdup(pool, value);

		array_append(&tmpl->args, &key, 1);
		array_append(&tmpl->args, &value, 1);
	}
	return tmpl;
}
static bool
master_input_request(struct auth_master_connection *conn, const char *args)
{
	struct auth_client_connection *client_conn;
	const char *const *list, *const *params;
	unsigned int id, client_pid, client_id;
	uint8_t cookie[MASTER_AUTH_COOKIE_SIZE];
	buffer_t buf;

	/* <id> <client-pid> <client-id> <cookie> [<parameters>] */
	list = t_strsplit_tab(args);
	if (str_array_length(list) < 4 ||
	    str_to_uint(list[0], &id) < 0 ||
	    str_to_uint(list[1], &client_pid) < 0 ||
	    str_to_uint(list[2], &client_id) < 0) {
		i_error("BUG: Master sent broken REQUEST");
		return FALSE;
	}

	buffer_create_from_data(&buf, cookie, sizeof(cookie));
	if (hex_to_binary(list[3], &buf) < 0) {
		i_error("BUG: Master sent broken REQUEST cookie");
		return FALSE;
	}
	params = list + 4;

	client_conn = auth_client_connection_lookup(client_pid);
	if (client_conn == NULL) {
		i_error("Master requested auth for nonexistent client %u",
			client_pid);
		o_stream_nsend_str(conn->output,
				   t_strdup_printf("FAIL\t%u\n", id));
	} else if (memcmp(client_conn->cookie, cookie, sizeof(cookie)) != 0) {
		i_error("Master requested auth for client %u with invalid cookie",
			client_pid);
		o_stream_nsend_str(conn->output,
				   t_strdup_printf("FAIL\t%u\n", id));
	} else if (!auth_request_handler_master_request(
			client_conn->request_handler, conn, id, client_id, params)) {
		i_error("Master requested auth for non-login client %u",
			client_pid);
		o_stream_nsend_str(conn->output,
				   t_strdup_printf("FAIL\t%u\n", id));
	}
	return TRUE;
}
Esempio n. 20
0
struct dsync_message *
dsync_message_dup(pool_t pool, const struct dsync_message *msg)
{
    struct dsync_message *dest;
    const char **keywords;
    unsigned int i, count;

    dest = p_new(pool, struct dsync_message, 1);
    *dest = *msg;
    dest->guid = p_strdup(pool, msg->guid);
    if (msg->keywords != NULL) {
        count = str_array_length(msg->keywords);
        keywords = p_new(pool, const char *, count+1);
        for (i = 0; i < count; i++)
            keywords[i] = p_strdup(pool, msg->keywords[i]);
        dest->keywords = keywords;
    }
Esempio n. 21
0
struct acl_backend *
acl_backend_init(const char *data, struct mailbox_list *list,
		 const char *acl_username, const char *const *groups,
		 bool owner)
{
	struct mail_user *user = mailbox_list_get_user(list);
	struct acl_backend *backend;
	unsigned int i, group_count;

	if (user->mail_debug) {
		i_debug("acl: initializing backend with data: %s", data);
		i_debug("acl: acl username = %s", acl_username);
		i_debug("acl: owner = %d", owner ? 1 : 0);
	}

	group_count = str_array_length(groups);

	if (strncmp(data, "vfile:", 6) == 0)
		data += 6;
	else if (strcmp(data, "vfile") == 0)
		data = "";
	else
		i_fatal("Unknown ACL backend: %s", t_strcut(data, ':'));

	backend = acl_backend_vfile.alloc();
	backend->debug = user->mail_debug;
	backend->v = acl_backend_vfile;
	backend->list = list;
	backend->username = p_strdup(backend->pool, acl_username);
	backend->owner = owner;
	backend->globals_only =
		mail_user_plugin_getenv_bool(user, "acl_globals_only");

	if (group_count > 0) {
		backend->group_count = group_count;
		backend->groups =
			p_new(backend->pool, const char *, group_count);
		for (i = 0; i < group_count; i++) {
			backend->groups[i] = p_strdup(backend->pool, groups[i]);
			if (user->mail_debug)
				i_debug("acl: group added: %s", groups[i]);
		}
		i_qsort(backend->groups, group_count, sizeof(const char *),
			i_strcmp_p);
	}
Esempio n. 22
0
static struct imap_match_glob *
imap_match_init_multiple_real(pool_t pool, const char *const *patterns,
			      bool inboxcase, char separator)
{
	struct imap_match_glob *glob;
	struct imap_match_pattern *match_patterns;
	unsigned int i, len, pos, patterns_count, patterns_data_len = 0;

	patterns_count = str_array_length(patterns);
	match_patterns = p_new(pool, struct imap_match_pattern,
			       patterns_count + 1);

	/* compress the patterns */
	for (i = 0; i < patterns_count; i++) {
		match_patterns[i].pattern = pattern_compress(patterns[i]);
		match_patterns[i].inboxcase = inboxcase &&
			pattern_is_inboxcase(match_patterns[i].pattern,
					     separator);

		patterns_data_len += strlen(match_patterns[i].pattern) + 1;
	}
	patterns_count = i;

	/* now we know how much memory we need */
	glob = p_malloc(pool, sizeof(struct imap_match_glob) +
			patterns_data_len);
	glob->pool = pool;
	glob->sep = separator;

	/* copy pattern strings to our allocated memory */
	for (i = 0, pos = 0; i < patterns_count; i++) {
		len = strlen(match_patterns[i].pattern) + 1;
		i_assert(pos + len <= patterns_data_len);

		/* @UNSAFE */
		memcpy(glob->patterns_data + pos,
		       match_patterns[i].pattern, len);
		match_patterns[i].pattern = glob->patterns_data + pos;
		pos += len;
	}
	glob->patterns = match_patterns;
	return glob;
}
Esempio n. 23
0
static int
client_input_remove(struct doveadm_connection *client, const char *const *args)
{
	struct replicator_user *user;

	/* <username> */
	if (str_array_length(args) != 1) {
		i_error("%s: REMOVE: Invalid parameters", client->conn.name);
		return -1;
	}
	user = replicator_queue_lookup(client->queue, args[0]);
	if (user == NULL)
		o_stream_send_str(client->conn.output, "-User not found\n");
	else {
		replicator_queue_remove(client->queue, &user);
		o_stream_send_str(client->conn.output, "+\n");
	}
	return 0;
}
Esempio n. 24
0
int dsync_deserializer_init(const char *name, const char *const *required_fields,
			    const char *header_line,
			    struct dsync_deserializer **deserializer_r,
			    const char **error_r)
{
	struct dsync_deserializer *deserializer;
	const char **dup_required_fields;
	unsigned int i, required_count;
	pool_t pool;

	*deserializer_r = NULL;

	pool = pool_alloconly_create("dsync deserializer", 1024);
	deserializer = p_new(pool, struct dsync_deserializer, 1);
	deserializer->pool = pool;
	deserializer->name = p_strdup(pool, name);
	deserializer->keys = (void *)p_strsplit_tabescaped(pool, header_line);

	deserializer->required_field_count = required_count =
		required_fields == NULL ? 0 :
		str_array_length(required_fields);
	dup_required_fields = p_new(pool, const char *, required_count + 1);
	deserializer->required_field_indexes =
		p_new(pool, unsigned int, required_count + 1);
	for (i = 0; i < required_count; i++) {
		dup_required_fields[i] =
			p_strdup(pool, required_fields[i]);
		if (!field_find(deserializer->keys, required_fields[i],
				&deserializer->required_field_indexes[i])) {
			*error_r = t_strdup_printf(
				"Header missing required field %s",
				required_fields[i]);
			pool_unref(&pool);
			return -1;
		}
	}
	deserializer->required_fields = dup_required_fields;

	*deserializer_r = deserializer;
	return 0;
}
Esempio n. 25
0
static void stats_metrics_add_set(struct stats_metrics *metrics,
				  const struct stats_metric_settings *set)
{
	struct event_filter_query query;
	struct metric *metric;
	const char *const *fields;

	metric = p_new(metrics->pool, struct metric, 1);
	metric->name = p_strdup(metrics->pool, set->name);
	metric->duration_stats = stats_dist_init();

	fields = t_strsplit_spaces(set->fields, " ");
	metric->fields_count = str_array_length(fields);
	if (metric->fields_count > 0) {
		metric->fields = p_new(metrics->pool, struct metric_field,
				       metric->fields_count);
		for (unsigned int i = 0; i < metric->fields_count; i++) {
			metric->fields[i].field_key =
				p_strdup(metrics->pool, fields[i]);
			metric->fields[i].stats = stats_dist_init();
		}
	}
Esempio n. 26
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));
}
Esempio n. 27
0
static int
client_input_replicate(struct doveadm_connection *client, const char *const *args)
{
	struct replicator_queue_iter *iter;
	struct replicator_user *user;
	const char *usermask;
	enum replication_priority priority;
	unsigned int match_count;

	/* <priority> <username>|<mask> */
	if (str_array_length(args) != 2) {
		i_error("%s: REPLICATE: Invalid parameters", client->conn.name);
		return -1;
	}
	if (replication_priority_parse(args[0], &priority) < 0) {
		o_stream_send_str(client->conn.output, "-Invalid priority\n");
		return 0;
	}
	usermask = args[1];
	if (strchr(usermask, '*') == NULL && strchr(usermask, '?') == NULL) {
		replicator_queue_add(client->queue, usermask, priority);
		o_stream_send_str(client->conn.output, "+1\n");
		return 0;
	}

	match_count = 0;
	iter = replicator_queue_iter_init(client->queue);
	while ((user = replicator_queue_iter_next(iter)) != NULL) {
		if (!wildcard_match(user->username, usermask))
			continue;
		replicator_queue_add(client->queue, user->username, priority);
		match_count++;
	}
	replicator_queue_iter_deinit(&iter);
	o_stream_send_str(client->conn.output,
			  t_strdup_printf("+%u\n", match_count));
	return 0;
}
Esempio n. 28
0
static int
notify_connection_input_line(struct notify_connection *conn, const char *line)
{
	struct notify_sync_request *request;
	const char *const *args;
	enum replication_priority priority;
	unsigned int id;

	/* U \t <username> \t <priority> [\t <sync id>] */
	args = t_strsplit_tabescaped(line);
	if (str_array_length(args) < 2) {
		i_error("notify client sent invalid input: %s", line);
		return -1;
	}
	if (strcmp(args[0], "U") != 0) {
		i_error("notify client sent unknown command: %s", args[0]);
		return -1;
	}
	if (replication_priority_parse(args[2], &priority) < 0) {
		i_error("notify client sent invalid priority: %s", args[2]);
		return -1;
	}
	if (priority != REPLICATION_PRIORITY_SYNC)
		(void)replicator_queue_add(conn->queue, args[1], priority);
	else if (args[3] == NULL || str_to_uint(args[3], &id) < 0) {
		i_error("notify client sent invalid sync id: %s", line);
		return -1;
	} else {
		request = i_new(struct notify_sync_request, 1);
		request->conn = conn;
		request->id = id;
		notify_connection_ref(conn);
		replicator_queue_add_sync(conn->queue, args[1],
					  notify_sync_callback, request);
	}
	return 0;
}
struct passdb_template *passdb_template_build(pool_t pool, const char *args)
{
	struct passdb_template *tmpl;
	const char *const *tmp, *key, *value;

	tmpl = p_new(pool, struct passdb_template, 1);

	tmp = t_strsplit_spaces(args, " ");
	p_array_init(&tmpl->args, pool, str_array_length(tmp));

	for (; *tmp != NULL; tmp++) {
		value = strchr(*tmp, '=');
		if (value == NULL)
			key = *tmp;
		else
			key = t_strdup_until(*tmp, value++);

		key = p_strdup(pool, key);
		value = p_strdup(pool, value);
		array_append(&tmpl->args, &key, 1);
		array_append(&tmpl->args, &value, 1);
	}
	return tmpl;
}
static int
notify_input_line(struct notify_connection *conn, const char *line)
{
    const char *const *args;
    enum replication_priority priority;

    /* <username> \t <priority> */
    args = t_strsplit_tabescaped(line);
    if (str_array_length(args) < 2) {
        i_error("Client sent invalid input");
        return -1;
    }
    if (replication_priority_parse(args[1], &priority) < 0) {
        i_error("Client sent invalid priority: %s", args[1]);
        return -1;
    }
    if (priority != REPLICATION_PRIORITY_SYNC)
        replicator_connection_notify(replicator, args[0], priority);
    else {
        conn->refcount++;
        replicator_connection_notify_sync(replicator, args[0], conn);
    }
    return 0;
}