예제 #1
0
static int lmtp_client_send_data_cmd(struct lmtp_client *client)
{
	if (client->rcpt_next_receive_idx < array_count(&client->recipients))
		return 0;

	if (client->global_fail_string != NULL || !client->rcpt_to_successes) {
		lmtp_client_fail(client, client->global_fail_string);
		return -1;
	} else {
		client->input_state++;
		o_stream_nsend_str(client->output, "DATA\r\n");
		return 0;
	}
}
예제 #2
0
static void pop3c_client_authenticate1(struct pop3c_client *client)
{
	const struct pop3c_client_settings *set = &client->set;

	if (client->set.debug) {
		if (set->master_user == NULL) {
			i_debug("pop3c(%s): Authenticating as %s",
				client->set.host, set->username);
		} else {
			i_debug("pop3c(%s): Authenticating as %s for user %s",
				client->set.host, set->master_user,
				set->username);
		}
	}

	if (set->master_user == NULL) {
		o_stream_nsend_str(client->output,
			t_strdup_printf("USER %s\r\n", set->username));
		client->state = POP3C_CLIENT_STATE_USER;
	} else {
		client->state = POP3C_CLIENT_STATE_AUTH;
		o_stream_nsend_str(client->output, "AUTH PLAIN\r\n");
	}
}
예제 #3
0
static void client_send_sendalive_if_needed(struct client *client)
{
	time_t now, last_io;

	if (o_stream_get_buffer_used_size(client->output) != 0)
		return;

	now = time(NULL);
	last_io = I_MAX(client->last_input, client->last_output);
	if (now - last_io > MAIL_STORAGE_STAYALIVE_SECS) {
		o_stream_nsend_str(client->output, "* OK Hang in there..\r\n");
		o_stream_nflush(client->output);
		client->last_output = now;
	}
}
예제 #4
0
void pop3c_client_cmd_line_async(struct pop3c_client *client, const char *cmd)
{
	const char *error;

	if (client->state != POP3C_CLIENT_STATE_DONE) {
		i_assert(client->state == POP3C_CLIENT_STATE_DISCONNECTED);
		return;
	}

	if ((client->capabilities & POP3C_CAPABILITY_PIPELINING) == 0) {
		if (pop3c_client_flush_asyncs(client, &error) < 0)
			return;
	}
	o_stream_nsend_str(client->output, cmd);
	client->async_commands++;
}
예제 #5
0
int worker_connection_connect(struct worker_connection *conn)
{
	i_assert(conn->fd == -1);

	conn->fd = net_connect_unix(conn->socket_path);
	if (conn->fd == -1) {
		i_error("connect(%s) failed: %m", conn->socket_path);
		return -1;
	}
	conn->io = io_add(conn->fd, IO_READ, worker_connection_input, conn);
	conn->input = i_stream_create_fd(conn->fd, (size_t)-1);
	conn->output = o_stream_create_fd(conn->fd, (size_t)-1);
	o_stream_set_no_error_handling(conn->output, TRUE);
	o_stream_nsend_str(conn->output, INDEXER_MASTER_HANDSHAKE);
	return 0;
}
예제 #6
0
static int client_export_iter_command(struct client *client)
{
	struct client_export_cmd *cmd = client->cmd_export;
	struct mail_command *command = client->mail_cmd_iter;

	i_assert(cmd->level == MAIL_EXPORT_LEVEL_COMMAND);
	mail_command_unref(&client->mail_cmd_iter);

	if (!cmd->header_sent) {
		o_stream_nsend_str(client->output,
			"cmd\targs\tsession\tuser\tlast_update"MAIL_STATS_HEADER);
		cmd->header_sent = TRUE;
	}

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

		str_truncate(cmd->str, 0);
		str_append_tabescaped(cmd->str, command->name);
		str_append_c(cmd->str, '\t');
		str_append_tabescaped(cmd->str, command->args);
		str_append_c(cmd->str, '\t');
		T_BEGIN {
			str_append(cmd->str,
				   guid_128_to_string(command->session->guid));
			str_append_c(cmd->str, '\t');
			str_append_tabescaped(cmd->str,
					      command->session->user->name);
		} T_END;
		client_export_timeval(cmd->str, &command->last_update);
		client_export_mail_stats(cmd->str, &command->stats);
		str_append_c(cmd->str, '\n');
		o_stream_nsend(client->output, str_data(cmd->str),
			       str_len(cmd->str));
	}

	if (command != NULL) {
		client->mail_cmd_iter = command;
		mail_command_ref(command);
		return 0;
	}
	return 1;
}
예제 #7
0
void master_login_auth_request(struct master_login_auth *auth,
			       const struct master_auth_request *req,
			       master_login_auth_request_callback_t *callback,
			       void *context)
{
	struct master_login_auth_request *login_req;
	unsigned int id;

	if (auth->fd == -1) {
		if (master_login_auth_connect(auth) < 0) {
			/* we couldn't connect to auth now,
			   so we probably can't in future either. */
			master_service_stop_new_connections(master_service);
			callback(NULL, MASTER_AUTH_ERRMSG_INTERNAL_FAILURE,
				 context);
			return;
		}
		o_stream_nsend_str(auth->output,
			t_strdup_printf("VERSION\t%u\t%u\n",
					AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
					AUTH_MASTER_PROTOCOL_MINOR_VERSION));
	}

	id = ++auth->id_counter;
	if (id == 0)
		id++;

	login_req = i_new(struct master_login_auth_request, 1);
	login_req->create_stamp = ioloop_time;
	login_req->id = id;
	login_req->auth_pid = req->auth_pid;
	login_req->client_pid = req->client_pid;
	login_req->auth_id = req->auth_id;
	memcpy(login_req->cookie, req->cookie, sizeof(login_req->cookie));
	login_req->callback = callback;
	login_req->context = context;
	i_assert(hash_table_lookup(auth->requests, POINTER_CAST(id)) == NULL);
	hash_table_insert(auth->requests, POINTER_CAST(id), login_req);
	DLLIST2_APPEND(&auth->request_head, &auth->request_tail, login_req);

	if (auth->to == NULL)
		master_login_auth_set_timeout(auth);

	master_login_auth_send_request(auth, login_req);
}
예제 #8
0
static void replicator_connection_connect(struct replicator_connection *conn)
{
	unsigned int n;
	int fd = -1;

	if (conn->fd != -1)
		return;

	if (conn->port == 0) {
		fd = net_connect_unix(conn->path);
		if (fd == -1)
			i_error("net_connect_unix(%s) failed: %m", conn->path);
	} else {
		for (n = 0; n < conn->ips_count; n++) {
			unsigned int idx = conn->ip_idx;

			conn->ip_idx = (conn->ip_idx + 1) % conn->ips_count;
			fd = net_connect_ip(&conn->ips[idx], conn->port, NULL);
			if (fd != -1)
				break;
			i_error("connect(%s, %u) failed: %m",
				net_ip2addr(&conn->ips[idx]), conn->port);
		}
	}

	if (fd == -1) {
		if (conn->to == NULL) {
			conn->to = timeout_add(REPLICATOR_RECONNECT_MSECS,
					       replicator_connection_connect,
					       conn);
		}
		return;
	}

	if (conn->to != NULL)
		timeout_remove(&conn->to);
	conn->fd = fd;
	conn->io = io_add(fd, IO_READ, replicator_input, conn);
	conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
	conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
	o_stream_set_no_error_handling(conn->output, TRUE);
	o_stream_nsend_str(conn->output, REPLICATOR_HANDSHAKE);
	o_stream_set_flush_callback(conn->output, replicator_output, conn);
}
예제 #9
0
파일: fs-test-async.c 프로젝트: bdraco/core
static void test_fs_async_write(const char *test_name, struct fs *fs)
{
	struct fs_file *file;
	struct test_fs_file *test_file;
	struct ostream *output;
	unsigned int i;

	test_begin(t_strdup_printf("%s: async write", test_name));
	for (i = 0; i < 3; i++) {
		file = fs_file_init(fs, "foo", FS_OPEN_MODE_REPLACE |
				    FS_OPEN_FLAG_ASYNC);
		output = fs_write_stream(file);

		o_stream_nsend_str(output, "12345");
		if (i < 2) {
			test_assert(fs_write_stream_finish(file, &output) == 0);
			test_assert(output == NULL);
			test_assert(fs_write_stream_finish_async(file) == 0);
		}

		test_file = test_fs_file_get(fs, "foo");
		test_file->wait_async = FALSE;

		switch (i) {
		case 0:
			test_assert(fs_write_stream_finish_async(file) > 0);
			test_assert(test_file->contents->used > 0);
			break;
		case 1:
			test_file->io_failure = TRUE;
			test_assert(fs_write_stream_finish_async(file) < 0);
			test_assert(test_file->contents->used == 0);
			break;
		case 2:
			fs_write_stream_abort_error(file, &output, "test");
			test_assert(test_file->contents->used == 0);
			break;
		}
		fs_file_deinit(&file);
	}
	test_end();
}
예제 #10
0
static int client_export_iter_ip(struct client *client)
{
	struct client_export_cmd *cmd = client->cmd_export;
	struct mail_ip *ip = client->mail_ip_iter;

	i_assert(cmd->level == MAIL_EXPORT_LEVEL_IP);
	mail_ip_unref(&client->mail_ip_iter);

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

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

		str_truncate(cmd->str, 0);
		T_BEGIN {
			str_append(cmd->str, net_ip2addr(&ip->ip));
		} T_END;
		str_printfa(cmd->str, "\t%ld", (long)ip->reset_timestamp);
		client_export_timeval(cmd->str, &ip->last_update);
		str_printfa(cmd->str, "\t%u\t%u\t%u",
			    ip->num_logins, ip->num_cmds, ip->num_connected_sessions);
		client_export_mail_stats(cmd->str, &ip->stats);
		str_append_c(cmd->str, '\n');
		o_stream_nsend(client->output, str_data(cmd->str),
			       str_len(cmd->str));
	}

	if (ip != NULL) {
		client->mail_ip_iter = ip;
		mail_ip_ref(ip);
		return 0;
	}
	return 1;
}
예제 #11
0
static int dns_client_input_line(struct dns_client *client, const char *line)
{
	struct ip_addr *ips, ip;
	const char *name;
	unsigned int i, ips_count;
	int ret;

	if (strncmp(line, "IP\t", 3) == 0) {
		ret = net_gethostbyname(line + 3, &ips, &ips_count);
		if (ret == 0 && ips_count == 0) {
			/* shouldn't happen, but fix it anyway.. */
			ret = EAI_NONAME;
		}
		if (ret != 0) {
			o_stream_nsend_str(client->output,
				t_strdup_printf("%d\n", ret));
		} else {
			o_stream_nsend_str(client->output,
				t_strdup_printf("0 %u\n", ips_count));
			for (i = 0; i < ips_count; i++) {
				o_stream_nsend_str(client->output, t_strconcat(
					net_ip2addr(&ips[i]), "\n", NULL));
			}
		}
	} else if (strncmp(line, "NAME\t", 5) == 0) {
		if (net_addr2ip(line+5, &ip) < 0)
			o_stream_nsend_str(client->output, "-1\n");
		else if ((ret = net_gethostbyaddr(&ip, &name)) != 0) {
			o_stream_nsend_str(client->output,
				t_strdup_printf("%d\n", ret));
		} else {
			o_stream_nsend_str(client->output,
				t_strdup_printf("0 %s\n", name));
		}
	} else if (strcmp(line, "QUIT") == 0) {
		return -1;
	} else {
		o_stream_nsend_str(client->output, "Unknown command\n");
	}

	if (client->output->overflow)
		return -1;
	return 0;
}
예제 #12
0
static void auth_worker_send_reply(struct auth_worker_client *client,
				   struct auth_request *request,
				   string_t *str)
{
	time_t cmd_duration = time(NULL) - client->cmd_start;
	const char *p;

	if (worker_restart_request)
		o_stream_nsend_str(client->output, "RESTART\n");
	o_stream_nsend(client->output, str_data(str), str_len(str));
	if (o_stream_nfinish(client->output) < 0 && request != NULL &&
	    cmd_duration > AUTH_WORKER_WARN_DISCONNECTED_LONG_CMD_SECS) {
		p = strchr(str_c(str), '\t');
		p = p == NULL ? "BUG" : t_strcut(p+1, '\t');

		i_warning("Auth master disconnected us while handling "
			  "request for %s for %ld secs (result=%s)",
			  request->user, (long)cmd_duration, p);
	}
}
예제 #13
0
static int client_export_iter_domain(struct client *client)
{
	struct client_export_cmd *cmd = client->cmd_export;
	struct mail_domain *domain = client->mail_domain_iter;

	i_assert(cmd->level == MAIL_EXPORT_LEVEL_DOMAIN);
	mail_domain_unref(&client->mail_domain_iter);

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

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

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

	if (domain != NULL) {
		client->mail_domain_iter = domain;
		mail_domain_ref(domain);
		return 0;
	}
	return 1;
}
예제 #14
0
void server_connection_cmd(struct server_connection *conn, const char *line,
			   struct istream *cmd_input,
			   server_cmd_callback_t *callback, void *context)
{
	i_assert(conn->delayed_cmd == NULL);

	conn->state = SERVER_REPLY_STATE_PRINT;
	if (cmd_input != NULL) {
		i_assert(conn->cmd_input == NULL);
		i_stream_ref(cmd_input);
		conn->cmd_input = cmd_input;
	}
	if (!conn->authenticated)
		conn->delayed_cmd = p_strdup(conn->pool, line);
	else {
		o_stream_nsend_str(conn->output, line);
		server_connection_send_cmd_input(conn);
	}
	conn->callback = callback;
	conn->context = context;
}
예제 #15
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;
}
예제 #16
0
int server_connection_create(struct doveadm_server *server,
			     struct server_connection **conn_r)
{
#define DOVEADM_SERVER_HANDSHAKE "VERSION\tdoveadm-server\t1\t0\n"
	struct server_connection *conn;
	pool_t pool;

	pool = pool_alloconly_create("doveadm server connection", 1024*16);
	conn = p_new(pool, struct server_connection, 1);
	conn->pool = pool;
	conn->server = server;
	conn->fd = doveadm_connect_with_default_port(server->name,
						     doveadm_settings->doveadm_port);
	net_set_nonblock(conn->fd, TRUE);
	conn->io = io_add(conn->fd, IO_READ, server_connection_input, conn);
	conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE);
	conn->output = o_stream_create_fd(conn->fd, (size_t)-1);
	o_stream_set_flush_callback(conn->output, server_connection_output, conn);

	i_stream_set_name(conn->input, server->name);
	o_stream_set_name(conn->output, server->name);

	array_append(&conn->server->connections, &conn, 1);

	if (server_connection_read_settings(conn) < 0 ||
	    server_connection_init_ssl(conn) < 0) {
		server_connection_destroy(&conn);
		return -1;
	}

	o_stream_set_no_error_handling(conn->output, TRUE);
	conn->state = SERVER_REPLY_STATE_DONE;
	o_stream_nsend_str(conn->output, DOVEADM_SERVER_HANDSHAKE);

	*conn_r = conn;
	return 0;
}
예제 #17
0
static int
acllist_append(struct acl_backend_vfile *backend, struct ostream *output,
	       const char *vname)
{
	struct acl_object *aclobj;
	struct acl_object_list_iter *iter;
	struct acl_rights rights;
	struct acl_backend_vfile_acllist acllist;
	const char *name;
	int ret;

	name = mailbox_list_get_storage_name(backend->backend.list, vname);
	acl_cache_flush(backend->backend.cache, name);
	aclobj = acl_object_init_from_name(&backend->backend, name);

	iter = acl_object_list_init(aclobj);
	while ((ret = acl_object_list_next(iter, &rights)) > 0) {
		if (acl_rights_has_nonowner_lookup_changes(&rights))
			break;
	}
	acl_object_list_deinit(&iter);

	if (acl_backend_vfile_object_get_mtime(aclobj, &acllist.mtime) < 0)
		ret = -1;

	if (ret > 0) {
		acllist.name = p_strdup(backend->acllist_pool, name);
		array_append(&backend->acllist, &acllist, 1);

		T_BEGIN {
			const char *line;
			line = t_strdup_printf("%s %s\n",
					       dec2str(acllist.mtime), name);
			o_stream_nsend_str(output, line);
		} T_END;
	}
예제 #18
0
static void
doveadm_mail_cmd_server_run(struct client_connection *conn,
			    struct doveadm_mail_cmd_context *ctx,
			    const struct mail_storage_service_input *input)
{
	const char *error;
	int ret;

	ctx->conn = conn;

	if (ctx->v.preinit != NULL)
		ctx->v.preinit(ctx);

	ret = doveadm_mail_single_user(ctx, input, &error);
	doveadm_mail_server_flush();
	ctx->v.deinit(ctx);
	doveadm_print_flush();
	mail_storage_service_deinit(&ctx->storage_service);

	if (ret < 0) {
		i_error("%s: %s", ctx->cmd->name, error);
		o_stream_nsend(conn->output, "\n-\n", 3);
	} else if (ret == 0) {
		o_stream_nsend_str(conn->output, "\n-NOUSER\n");
	} else if (ctx->exit_code != 0) {
		/* maybe not an error, but not a full success either */
		o_stream_nsend(conn->output, "\n-\n", 3);
	} else {
		o_stream_nsend(conn->output, "\n+\n", 3);
	}
	pool_unref(&ctx->pool);

	/* clear all headers */
	doveadm_print_deinit();
	doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
}
예제 #19
0
static int lmtp_client_input_line(struct lmtp_client *client, const char *line)
{
	int ret, reply_code = 0;

	if ((ret = lmtp_input_get_reply_code(line, &reply_code,
					     client->input_multiline)) <= 0) {
		if (ret == 0)
			return 0;
		lmtp_client_fail(client, line);
		return -1;
	}

	switch (client->input_state) {
	case LMTP_INPUT_STATE_GREET:
	case LMTP_INPUT_STATE_XCLIENT:
		if (reply_code != 220) {
			lmtp_client_fail(client, line);
			return -1;
		}
		lmtp_client_send_handshake(client);
		client->input_state = LMTP_INPUT_STATE_LHLO;
		break;
	case LMTP_INPUT_STATE_LHLO:
	case LMTP_INPUT_STATE_MAIL_FROM:
		if (reply_code != 250) {
			lmtp_client_fail(client, line);
			return -1;
		}
		str_append(client->input_multiline, line);
		lmtp_client_parse_capabilities(client,
			str_c(client->input_multiline));
		if (client->input_state == LMTP_INPUT_STATE_LHLO &&
		    lmtp_client_send_xclient(client)) {
			client->input_state = LMTP_INPUT_STATE_XCLIENT;
			client->xclient_sent = TRUE;
			break;
		}
		if (client->input_state == LMTP_INPUT_STATE_LHLO) {
			o_stream_nsend_str(client->output,
				t_strdup_printf("MAIL FROM:%s\r\n",
						client->set.mail_from));
		}
		client->input_state++;
		lmtp_client_send_rcpts(client);
		break;
	case LMTP_INPUT_STATE_RCPT_TO:
		lmtp_client_rcpt_next(client, line);
		if (client->data_input == NULL)
			break;
		if (lmtp_client_send_data_cmd(client) < 0)
			return -1;
		break;
	case LMTP_INPUT_STATE_DATA_CONTINUE:
		/* Start sending DATA */
		if (strncmp(line, "354", 3) != 0) {
			lmtp_client_fail(client, line);
			return -1;
		}
		client->input_state++;
		if (client->data_header != NULL)
			o_stream_nsend_str(client->output, client->data_header);
		lmtp_client_send_data(client);
		break;
	case LMTP_INPUT_STATE_DATA:
		/* DATA replies */
		if (lmtp_client_data_next(client, line) < 0)
			return -1;
		break;
	}
	return 1;
}
예제 #20
0
int subsfile_set_subscribed(struct mailbox_list *list, const char *path,
			    const char *temp_prefix, const char *name,
			    bool set)
{
	const struct mail_storage_settings *mail_set = list->mail_set;
	struct dotlock_settings dotlock_set;
	struct dotlock *dotlock;
	struct mailbox_permissions perm;
	const char *line, *dir, *fname, *escaped_name;
	struct istream *input = NULL;
	struct ostream *output;
	int fd_in, fd_out;
	enum mailbox_list_path_type type;
	bool found, changed = FALSE, failed = FALSE;
	unsigned int version = 2;

	if (strcasecmp(name, "INBOX") == 0)
		name = "INBOX";

	memset(&dotlock_set, 0, sizeof(dotlock_set));
	dotlock_set.use_excl_lock = mail_set->dotlock_use_excl;
	dotlock_set.nfs_flush = mail_set->mail_nfs_storage;
	dotlock_set.temp_prefix = temp_prefix;
	dotlock_set.timeout = SUBSCRIPTION_FILE_LOCK_TIMEOUT;
	dotlock_set.stale_timeout = SUBSCRIPTION_FILE_CHANGE_TIMEOUT;

	mailbox_list_get_root_permissions(list, &perm);
	fd_out = file_dotlock_open_group(&dotlock_set, path, 0,
					 perm.file_create_mode,
					 perm.file_create_gid,
					 perm.file_create_gid_origin, &dotlock);
	if (fd_out == -1 && errno == ENOENT) {
		/* directory hasn't been created yet. */
		type = list->set.control_dir != NULL ?
			MAILBOX_LIST_PATH_TYPE_CONTROL :
			MAILBOX_LIST_PATH_TYPE_DIR;
		fname = strrchr(path, '/');
		if (fname != NULL) {
			dir = t_strdup_until(path, fname);
			if (mailbox_list_mkdir_root(list, dir, type) < 0)
				return -1;
		}
		fd_out = file_dotlock_open_group(&dotlock_set, path, 0,
						 perm.file_create_mode,
						 perm.file_create_gid,
						 perm.file_create_gid_origin,
						 &dotlock);
	}
	if (fd_out == -1) {
		if (errno == EAGAIN) {
			mailbox_list_set_error(list, MAIL_ERROR_TEMP,
				"Timeout waiting for subscription file lock");
		} else {
			subswrite_set_syscall_error(list, "file_dotlock_open()",
						    path);
		}
		return -1;
	}

	fd_in = nfs_safe_open(path, O_RDONLY);
	if (fd_in == -1 && errno != ENOENT) {
		subswrite_set_syscall_error(list, "open()", path);
		file_dotlock_delete(&dotlock);
		return -1;
	}
	if (fd_in != -1) {
		input = i_stream_create_fd_autoclose(&fd_in, list->mailbox_name_max_length+1);
		i_stream_set_return_partial_line(input, TRUE);
		subsfile_list_read_header(list, input, &version);
	}

	found = FALSE;
	output = o_stream_create_fd_file(fd_out, 0, FALSE);
	o_stream_cork(output);
	if (version >= 2)
		o_stream_send_str(output, version2_header);
	if (version < 2 || name[0] == '\0')
		escaped_name = name;
	else {
		const char *const *tmp;
		char separators[2];
		string_t *str = t_str_new(64);

		separators[0] = mailbox_list_get_hierarchy_sep(list);
		separators[1] = '\0';
		tmp = t_strsplit(name, separators);
		str_append_tabescaped(str, *tmp);
		for (tmp++; *tmp != NULL; tmp++) {
			str_append_c(str, '\t');
			str_append_tabescaped(str, *tmp);
		}
		escaped_name = str_c(str);
	}
	if (input != NULL) {
		while ((line = next_line(list, path, input,
					 &failed, FALSE)) != NULL) {
			if (strcmp(line, escaped_name) == 0) {
				found = TRUE;
				if (!set) {
					changed = TRUE;
					continue;
				}
			}

			o_stream_nsend_str(output, line);
			o_stream_nsend(output, "\n", 1);
		}
		i_stream_destroy(&input);
	}

	if (!failed && set && !found) {
		/* append subscription */
		line = t_strconcat(escaped_name, "\n", NULL);
		o_stream_nsend_str(output, line);
		changed = TRUE;
	}

	if (changed && !failed) {
		if (o_stream_nfinish(output) < 0) {
			subswrite_set_syscall_error(list, "write()", path);
			failed = TRUE;
		} else if (mail_set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
			if (fsync(fd_out) < 0) {
				subswrite_set_syscall_error(list, "fsync()",
							    path);
				failed = TRUE;
			}
		}
	} else {
		o_stream_ignore_last_errors(output);
	}
	o_stream_destroy(&output);

	if (failed || !changed) {
		if (file_dotlock_delete(&dotlock) < 0) {
			subswrite_set_syscall_error(list,
				"file_dotlock_delete()", path);
			failed = TRUE;
		}
	} else {
		enum dotlock_replace_flags flags =
			DOTLOCK_REPLACE_FLAG_VERIFY_OWNER;
		if (file_dotlock_replace(&dotlock, flags) < 0) {
			subswrite_set_syscall_error(list,
				"file_dotlock_replace()", path);
			failed = TRUE;
		}
	}
	return failed ? -1 : (changed ? 1 : 0);
}
예제 #21
0
static int config_connection_request(struct config_connection *conn,
				     const char *const *args)
{
	struct config_export_context *ctx;
	struct master_service_settings_output output;
	struct config_filter filter;
	const char *path, *error, *module, *const *wanted_modules;
	ARRAY(const char *) modules;
	bool is_master = FALSE;

	/* [<args>] */
	t_array_init(&modules, 4);
	memset(&filter, 0, sizeof(filter));
	for (; *args != NULL; args++) {
		if (strncmp(*args, "service=", 8) == 0)
			filter.service = *args + 8;
		else if (strncmp(*args, "module=", 7) == 0) {
			module = *args + 7;
			if (strcmp(module, "master") == 0)
				is_master = TRUE;
			array_append(&modules, &module, 1);
		} else if (strncmp(*args, "lname=", 6) == 0)
			filter.local_name = *args + 6;
		else if (strncmp(*args, "lip=", 4) == 0) {
			if (net_addr2ip(*args + 4, &filter.local_net) == 0) {
				filter.local_bits =
					IPADDR_IS_V4(&filter.local_net) ?
					32 : 128;
			}
		} else if (strncmp(*args, "rip=", 4) == 0) {
			if (net_addr2ip(*args + 4, &filter.remote_net) == 0) {
				filter.remote_bits =
					IPADDR_IS_V4(&filter.remote_net) ?
					32 : 128;
			}
		}
	}
	array_append_zero(&modules);
	wanted_modules = array_count(&modules) == 1 ? NULL :
		array_idx(&modules, 0);

	if (is_master) {
		/* master reads configuration only when reloading settings */
		path = master_service_get_config_path(master_service);
		if (config_parse_file(path, TRUE, NULL, &error) <= 0) {
			o_stream_nsend_str(conn->output,
				t_strconcat("\nERROR ", error, "\n", NULL));
			config_connection_destroy(conn);
			return -1;
		}
	}

	o_stream_cork(conn->output);

	ctx = config_export_init(wanted_modules, CONFIG_DUMP_SCOPE_SET, 0,
				 config_request_output, conn->output);
	config_export_by_filter(ctx, &filter);
	config_export_get_output(ctx, &output);

	if (output.specific_services != NULL) {
		const char *const *s;

		for (s = output.specific_services; *s != NULL; s++) {
			o_stream_nsend_str(conn->output,
				t_strdup_printf("service=%s\t", *s));
		}
	}
	if (output.service_uses_local)
		o_stream_nsend_str(conn->output, "service-uses-local\t");
	if (output.service_uses_remote)
		o_stream_nsend_str(conn->output, "service-uses-remote\t");
	if (output.used_local)
		o_stream_nsend_str(conn->output, "used-local\t");
	if (output.used_remote)
		o_stream_nsend_str(conn->output, "used-remote\t");
	o_stream_nsend_str(conn->output, "\n");

	if (config_export_finish(&ctx) < 0) {
		config_connection_destroy(conn);
		return -1;
	}
	o_stream_nsend_str(conn->output, "\n");
	o_stream_uncork(conn->output);
	return 0;
}
예제 #22
0
static int
imap_master_client_input_args(struct connection *conn, const char *const *args,
			      int fd_client, pool_t pool)
{
	struct imap_master_client *client = (struct imap_master_client *)conn;
	struct client *imap_client;
	struct mail_storage_service_input input;
	struct imap_master_input master_input;
	const char *error;
	int ret;

	if (imap_master_client_parse_input(args, pool, &input, &master_input,
					   &error) < 0) {
		i_error("imap-master: Failed to parse client input: %s", error);
		o_stream_nsend_str(conn->output, t_strdup_printf(
			"-Failed to parse client input: %s\n", error));
		i_close_fd(&fd_client);
		return -1;
	}
	if (imap_master_client_verify(&master_input, fd_client, &error) < 0) {
		i_error("imap-master: Failed to verify client input: %s", error);
		o_stream_nsend_str(conn->output, t_strdup_printf(
			"-Failed to verify client input: %s\n", error));
		i_close_fd(&fd_client);
		return -1;
	}
	/* Send a success notification before we start anything that lasts
	   potentially a long time. imap-hibernate process is waiting for us
	   to answer. Even if we fail later, we log the error anyway. */
	o_stream_nsend_str(conn->output, "+\n");
	(void)o_stream_flush(conn->output);

	/* NOTE: before client_create_from_input() on failures we need to close
	   fd_client, but afterward it gets closed by client_destroy() */
	ret = client_create_from_input(&input, fd_client, fd_client,
				       &imap_client, &error);
	if (ret < 0) {
		i_error("imap-master(%s): Failed to create client: %s",
			input.username, error);
		i_close_fd(&fd_client);
		return -1;
	}
	client->imap_client_created = TRUE;

	if (client_create_finish(imap_client, &error) < 0) {
		i_error("imap-master(%s): %s", input.username, error);
		client_destroy(imap_client, error);
		return -1;
	}
	/* log prefix is set at this point, so we don't need to add the
	   username anymore to the log messages */

	o_stream_nsend(imap_client->output,
		       master_input.client_output->data,
		       master_input.client_output->used);
	if (master_input.client_input->used > 0 &&
	    !i_stream_add_data(imap_client->input,
			       master_input.client_input->data,
			       master_input.client_input->used)) {
		i_error("imap-master: Couldn't add %"PRIuSIZE_T
			" bytes to client's input stream",
			master_input.client_input->used);
		client_destroy(imap_client, "Client initialization failed");
		return -1;
	}
	imap_client->state_import_bad_idle_done =
		master_input.state_import_bad_idle_done;
	imap_client->state_import_idle_continue =
		master_input.state_import_idle_continue;
	if (imap_client->user->mail_debug) {
		if (imap_client->state_import_bad_idle_done)
			i_debug("imap-master: Unhibernated because IDLE was stopped with BAD command");
		else if (imap_client->state_import_idle_continue)
			i_debug("imap-master: Unhibernated to send mailbox changes");
		else
			i_debug("imap-master: Unhibernated because IDLE was stopped with DONE");
	}

	ret = imap_state_import_internal(imap_client, master_input.state->data,
					 master_input.state->used, &error);
	if (ret <= 0) {
		i_error("imap-master: Failed to import client state: %s", error);
		client_destroy(imap_client, "Client state initialization failed");
		return -1;
	}

	if (master_input.tag != NULL)
		imap_state_import_idle_cmd_tag(imap_client, master_input.tag);

	/* make sure all pending input gets handled */
	i_assert(imap_client->to_delayed_input == NULL);
	if (master_input.client_input->used > 0) {
		if (imap_client->user->mail_debug) {
			i_debug("imap-master: Pending client input: '%s'",
				str_sanitize(str_c(master_input.client_input), 128));
		}
		imap_client->to_delayed_input =
			timeout_add(0, client_input, imap_client);
	}

	imap_refresh_proctitle();
	/* we'll always disconnect the client afterwards */
	return -1;
}
예제 #23
0
파일: pop3-proxy.c 프로젝트: bdraco/core
int pop3_proxy_parse_line(struct client *client, const char *line)
{
	struct pop3_client *pop3_client = (struct pop3_client *)client;
	struct ostream *output;
	enum login_proxy_ssl_flags ssl_flags;

	i_assert(!client->destroyed);

	output = login_proxy_get_ostream(client->login_proxy);
	switch (pop3_client->proxy_state) {
	case POP3_PROXY_BANNER:
		/* this is a banner */
		if (strncmp(line, "+OK", 3) != 0) {
			client_log_err(client, t_strdup_printf(
				"proxy: Remote returned invalid banner: %s",
				str_sanitize(line, 160)));
			client_proxy_failed(client, TRUE);
			return -1;
		}
		pop3_client->proxy_xclient =
			strncmp(line+3, " [XCLIENT]", 10) == 0;

		ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
		if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
			if (proxy_send_login(pop3_client, output) < 0) {
				client_proxy_failed(client, TRUE);
				return -1;
			}
		} else {
			o_stream_nsend_str(output, "STLS\r\n");
			pop3_client->proxy_state = POP3_PROXY_STARTTLS;
		}
		return 0;
	case POP3_PROXY_STARTTLS:
		if (strncmp(line, "+OK", 3) != 0) {
			client_log_err(client, t_strdup_printf(
				"proxy: Remote STLS failed: %s",
				str_sanitize(line, 160)));
			client_proxy_failed(client, TRUE);
			return -1;
		}
		if (login_proxy_starttls(client->login_proxy) < 0) {
			client_proxy_failed(client, TRUE);
			return -1;
		}
		/* i/ostreams changed. */
		output = login_proxy_get_ostream(client->login_proxy);
		if (proxy_send_login(pop3_client, output) < 0) {
			client_proxy_failed(client, TRUE);
			return -1;
		}
		return 1;
	case POP3_PROXY_XCLIENT:
		if (strncmp(line, "+OK", 3) != 0) {
			client_log_err(client, t_strdup_printf(
				"proxy: Remote XCLIENT failed: %s",
				str_sanitize(line, 160)));
			client_proxy_failed(client, TRUE);
			return -1;
		}
		pop3_client->proxy_state = client->proxy_sasl_client == NULL ?
			POP3_PROXY_LOGIN1 : POP3_PROXY_LOGIN2;
		return 0;
	case POP3_PROXY_LOGIN1:
		i_assert(client->proxy_sasl_client == NULL);
		if (strncmp(line, "+OK", 3) != 0)
			break;

		/* USER successful, send PASS */
		o_stream_nsend_str(output, t_strdup_printf(
			"PASS %s\r\n", client->proxy_password));
		proxy_free_password(client);
		pop3_client->proxy_state = POP3_PROXY_LOGIN2;
		return 0;
	case POP3_PROXY_LOGIN2:
		if (strncmp(line, "+ ", 2) == 0 &&
		    client->proxy_sasl_client != NULL) {
			/* continue SASL authentication */
			if (pop3_proxy_continue_sasl_auth(client, output,
							  line+2) < 0) {
				client_proxy_failed(client, TRUE);
				return -1;
			}
			return 0;
		}
		if (strncmp(line, "+OK", 3) != 0)
			break;

		/* Login successful. Send this line to client. */
		line = t_strconcat(line, "\r\n", NULL);
		o_stream_nsend_str(client->output, line);

		client_proxy_finish_destroy_client(client);
		return 1;
	case POP3_PROXY_STATE_COUNT:
		i_unreached();
	}

	/* Login failed. Pass through the error message to client.

	   If the backend server isn't Dovecot, the error message may
	   be different from Dovecot's "user doesn't exist" error. This
	   would allow an attacker to find out what users exist in the
	   system.

	   The optimal way to handle this would be to replace the
	   backend's "password failed" error message with Dovecot's
	   AUTH_FAILED_MSG, but this would require a new setting and
	   the sysadmin to actually bother setting it properly.

	   So for now we'll just forward the error message. This
	   shouldn't be a real problem since of course everyone will
	   be using only Dovecot as their backend :) */
	if (strncmp(line, "-ERR ", 5) != 0) {
		client_send_reply(client, POP3_CMD_REPLY_ERROR,
				  AUTH_FAILED_MSG);
	} else {
		client_send_raw(client, t_strconcat(line, "\r\n", NULL));
	}

	if (client->set->auth_verbose) {
		if (strncmp(line, "-ERR ", 5) == 0)
			line += 5;
		client_proxy_log_failure(client, line);
	}
	client->proxy_auth_failed = TRUE;
	client_proxy_failed(client, FALSE);
	return -1;
}
예제 #24
0
static int proxy_send_login(struct pop3_client *client, struct ostream *output)
{
	struct dsasl_client_settings sasl_set;
	const unsigned char *sasl_output;
	unsigned int len;
	const char *mech_name, *error;
	string_t *str;

	i_assert(client->common.proxy_ttl > 1);
	if (client->proxy_xclient &&
	    !client->common.proxy_not_trusted) {
		/* remote supports XCLIENT, send it */
		o_stream_nsend_str(output, t_strdup_printf(
			"XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u\r\n",
			net_ip2addr(&client->common.ip),
			client->common.remote_port,
			client_get_session_id(&client->common),
			client->common.proxy_ttl - 1));
		client->common.proxy_state = POP3_PROXY_XCLIENT;
	} else {
		client->common.proxy_state = POP3_PROXY_LOGIN1;
	}

	str = t_str_new(128);
	if (client->common.proxy_mech == NULL) {
		/* send USER command */
		str_append(str, "USER ");
		str_append(str, client->common.proxy_user);
		str_append(str, "\r\n");
		o_stream_nsend(output, str_data(str), str_len(str));
		return 0;
	}

	i_assert(client->common.proxy_sasl_client == NULL);
	memset(&sasl_set, 0, sizeof(sasl_set));
	sasl_set.authid = client->common.proxy_master_user != NULL ?
		client->common.proxy_master_user : client->common.proxy_user;
	sasl_set.authzid = client->common.proxy_user;
	sasl_set.password = client->common.proxy_password;
	client->common.proxy_sasl_client =
		dsasl_client_new(client->common.proxy_mech, &sasl_set);
	mech_name = dsasl_client_mech_get_name(client->common.proxy_mech);

	str_printfa(str, "AUTH %s ", mech_name);
	if (dsasl_client_output(client->common.proxy_sasl_client,
				&sasl_output, &len, &error) < 0) {
		client_log_err(&client->common, t_strdup_printf(
			"proxy: SASL mechanism %s init failed: %s",
			mech_name, error));
		return -1;
	}
	if (len == 0)
		str_append_c(str, '=');
	else
		base64_encode(sasl_output, len, str);
	str_append(str, "\r\n");
	o_stream_nsend(output, str_data(str), str_len(str));

	proxy_free_password(&client->common);
	if (client->common.proxy_state != POP3_PROXY_XCLIENT)
		client->common.proxy_state = POP3_PROXY_LOGIN2;
	return 0;
}
예제 #25
0
static void cmd_user_ver2(struct doveadm_cmd_context *cctx)
{
    const char * const *optval;

    const char *auth_socket_path = NULL;
    struct auth_master_connection *conn;
    struct authtest_input input;
    const char *show_field = NULL, *expand_field = NULL;
    struct mail_storage_service_ctx *storage_service = NULL;
    bool have_wildcards, userdb_only = FALSE, first = TRUE;
    int ret;

    if (!doveadm_cmd_param_str(cctx, "socket-path", &auth_socket_path))
        auth_socket_path = doveadm_settings->auth_socket_path;

    (void)doveadm_cmd_param_str(cctx, "expand-field", &expand_field);
    (void)doveadm_cmd_param_str(cctx, "field", &show_field);
    (void)doveadm_cmd_param_bool(cctx, "userdb-only", &userdb_only);

    memset(&input, 0, sizeof(input));
    if (doveadm_cmd_param_array(cctx, "auth-info", &optval))
        for(; *optval != NULL; optval++)
            auth_user_info_parse(&input.info, *optval);

    if (!doveadm_cmd_param_array(cctx, "user-mask", &optval)) {
        doveadm_exit_code = EX_USAGE;
        i_error("No user(s) specified");
        return;
    }

    if (expand_field != NULL && userdb_only) {
        i_error("-e can't be used with -u");
        doveadm_exit_code = EX_USAGE;
        return;
    }
    if (expand_field != NULL && show_field != NULL) {
        i_error("-e can't be used with -f");
        doveadm_exit_code = EX_USAGE;
        return;
    }

    conn = doveadm_get_auth_master_conn(auth_socket_path);

    have_wildcards = FALSE;

    for(const char *const *val = optval; *val != NULL; val++) {
        if (strchr(*val, '*') != NULL ||
                strchr(*val, '?') != NULL) {
            have_wildcards = TRUE;
            break;
        }
    }

    if (have_wildcards) {
        cmd_user_list(conn, &input, (char*const*)optval);
        auth_master_deinit(&conn);
        return;
    }

    if (!userdb_only) {
        storage_service = mail_storage_service_init(master_service, NULL,
                          MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP |
                          MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR |
                          MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT |
                          MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS |
                          MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES |
                          MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS);
        mail_storage_service_set_auth_conn(storage_service, conn);
        conn = NULL;
    }

    string_t *json = t_str_new(64);
    o_stream_nsend_str(doveadm_print_ostream, "{");

    input.info.local_ip = cctx->local_ip;
    input.info.local_port = cctx->local_port;
    input.info.remote_ip = cctx->remote_ip;
    input.info.remote_port = cctx->remote_port;

    for(const char *const *val = optval; *val != NULL; val++) {
        str_truncate(json, 0);
        json_append_escaped(json, *val);

        input.username = *val;
        if (first)
            first = FALSE;
        else
            o_stream_nsend_str(doveadm_print_ostream, ",");

        o_stream_nsend_str(doveadm_print_ostream, "\"");
        o_stream_nsend_str(doveadm_print_ostream, str_c(json));
        o_stream_nsend_str(doveadm_print_ostream, "\"");
        o_stream_nsend_str(doveadm_print_ostream, ":{");

        ret = !userdb_only ?
              cmd_user_mail_input(storage_service, &input, show_field, expand_field) :
              cmd_user_input(conn, &input, show_field, TRUE);

        o_stream_nsend_str(doveadm_print_ostream, "}");

        switch (ret) {
        case -1:
            doveadm_exit_code = EX_TEMPFAIL;
            break;
        case 0:
            doveadm_exit_code = EX_NOUSER;
            break;
        }
    }

    o_stream_nsend_str(doveadm_print_ostream,"}");

    if (storage_service != NULL)
        mail_storage_service_deinit(&storage_service);
    if (conn != NULL)
        auth_master_deinit(&conn);
}
예제 #26
0
static int
cmd_user_input(struct auth_master_connection *conn,
               const struct authtest_input *input,
               const char *show_field, bool userdb)
{
    const char *lookup_name = userdb ? "userdb lookup" : "passdb lookup";
    pool_t pool;
    const char *updated_username = NULL, *const *fields, *p;
    int ret;

    pool = pool_alloconly_create("auth master lookup", 1024);

    if (userdb) {
        ret = auth_master_user_lookup(conn, input->username, &input->info,
                                      pool, &updated_username, &fields);
    } else {
        ret = auth_master_pass_lookup(conn, input->username, &input->info,
                                      pool, &fields);
    }
    if (ret < 0) {
        const char *msg;
        if (fields[0] == NULL) {
            msg = t_strdup_printf("\"error\":\"%s failed\"",
                                  lookup_name);
        } else {
            msg = t_strdup_printf("\"error\":\"%s failed: %s\"",
                                  lookup_name,
                                  fields[0]);
        }
        o_stream_nsend_str(doveadm_print_ostream, msg);
        ret = -1;
    } else if (ret == 0) {
        o_stream_nsend_str(doveadm_print_ostream,
                           t_strdup_printf("\"error\":\"%s: user doesn't exist\"",
                                           lookup_name));
    } else if (show_field != NULL) {
        unsigned int show_field_len = strlen(show_field);
        string_t *json_field = t_str_new(show_field_len+1);
        json_append_escaped(json_field, show_field);
        o_stream_nsend_str(doveadm_print_ostream, t_strdup_printf("\"%s\":", str_c(json_field)));
        for (; *fields != NULL; fields++) {
            if (strncmp(*fields, show_field, show_field_len) == 0 &&
                    (*fields)[show_field_len] == '=') {
                string_t *jsonval = t_str_new(32);
                json_append_escaped(jsonval, *fields + show_field_len + 1);
                o_stream_nsend_str(doveadm_print_ostream, "\"");
                o_stream_nsend_str(doveadm_print_ostream, str_c(jsonval));
                o_stream_nsend_str(doveadm_print_ostream, "\"");
            }
        }
    } else {
        string_t *jsonval = t_str_new(64);
        o_stream_nsend_str(doveadm_print_ostream, "\"source\":\"");
        o_stream_nsend_str(doveadm_print_ostream, userdb ? "userdb\"" : "passdb\"");

        if (updated_username != NULL) {
            o_stream_nsend_str(doveadm_print_ostream, ",\"updated_username\":\"");
            str_truncate(jsonval, 0);
            json_append_escaped(jsonval, updated_username);
            o_stream_nsend_str(doveadm_print_ostream, str_c(jsonval));
            o_stream_nsend_str(doveadm_print_ostream, "\"");
        }
        for (; *fields != NULL; fields++) {
            const char *field = *fields;
            if (*field == '\0') continue;
            p = strchr(*fields, '=');
            str_truncate(jsonval, 0);
            if (p != NULL) {
                field = t_strcut(*fields, '=');
            }
            str_truncate(jsonval, 0);
            json_append_escaped(jsonval, field);
            o_stream_nsend_str(doveadm_print_ostream, ",\"");
            o_stream_nsend_str(doveadm_print_ostream, str_c(jsonval));
            o_stream_nsend_str(doveadm_print_ostream, "\":");
            if (p != NULL) {
                str_truncate(jsonval, 0);
                json_append_escaped(jsonval, p+1);
                o_stream_nsend_str(doveadm_print_ostream, "\"");
                o_stream_nsend_str(doveadm_print_ostream, str_c(jsonval));
                o_stream_nsend_str(doveadm_print_ostream, "\"");
            } else {
                o_stream_nsend_str(doveadm_print_ostream, "true");
            }
        }
    }
    return ret;
}
예제 #27
0
static int
pop3c_client_prelogin_input_line(struct pop3c_client *client, const char *line)
{
	bool success = line[0] == '+';
	const char *reply;

	switch (client->state) {
	case POP3C_CLIENT_STATE_CONNECTING:
		if (!success) {
			i_error("pop3c(%s): Server sent invalid banner: %s",
				client->set.host, line);
			return -1;
		}
		pop3c_client_authenticate1(client);
		break;
	case POP3C_CLIENT_STATE_USER:
		if (!success) {
			i_error("pop3c(%s): USER failed: %s",
				client->set.host, line);
			return -1;
		}
		o_stream_nsend_str(client->output,
			t_strdup_printf("PASS %s\r\n", client->set.password));
		client->state = POP3C_CLIENT_STATE_PASS;
		break;
	case POP3C_CLIENT_STATE_AUTH:
		if (line[0] != '+') {
			i_error("pop3c(%s): AUTH PLAIN failed: %s",
				client->set.host, line);
			return -1;
		}
		o_stream_nsend_str(client->output,
			pop3c_client_get_sasl_plain_request(client));
		client->state = POP3C_CLIENT_STATE_PASS;
		break;
	case POP3C_CLIENT_STATE_PASS:
		if (client->login_callback != NULL) {
			reply = strncasecmp(line, "+OK ", 4) == 0 ? line + 4 :
				strncasecmp(line, "-ERR ", 5) == 0 ? line + 5 :
				line;
			client_login_callback(client, success ?
					      POP3C_COMMAND_STATE_OK :
					      POP3C_COMMAND_STATE_ERR, reply);
		} else if (!success) {
			i_error("pop3c(%s): Authentication failed: %s",
				client->set.host, line);
		}
		if (!success)
			return -1;

		o_stream_nsend_str(client->output, "CAPA\r\n");
		client->state = POP3C_CLIENT_STATE_CAPA;
		break;
	case POP3C_CLIENT_STATE_CAPA:
		if (strncasecmp(line, "-ERR", 4) == 0) {
			/* CAPA command not supported. some commands still
			   support UIDL though. */
			client->capabilities |= POP3C_CAPABILITY_UIDL;
			pop3c_client_login_finished(client);
			break;
		} else if (strcmp(line, ".") == 0) {
			pop3c_client_login_finished(client);
			break;
		}
		if (strcasecmp(line, "PIPELINING") == 0)
			client->capabilities |= POP3C_CAPABILITY_PIPELINING;
		else if (strcasecmp(line, "TOP") == 0)
			client->capabilities |= POP3C_CAPABILITY_TOP;
		else if (strcasecmp(line, "UIDL") == 0)
			client->capabilities |= POP3C_CAPABILITY_UIDL;
		break;
	case POP3C_CLIENT_STATE_DISCONNECTED:
	case POP3C_CLIENT_STATE_DONE:
		i_unreached();
	}
	return 0;
}
예제 #28
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;
}