コード例 #1
0
ファイル: dbox-file-fix.c プロジェクト: via/dovecot-clouddb
static void
dbox_file_copy_metadata(struct dbox_file *file, struct ostream *output,
			bool *have_guid_r)
{
	const char *line;
	uoff_t prev_offset = file->input->v_offset;

	*have_guid_r = FALSE;
	while ((line = i_stream_read_next_line(file->input)) != NULL) {
		if (*line == DBOX_METADATA_OLDV1_SPACE || *line == '\0') {
			/* end of metadata */
			return;
		}
		if (*line < 32) {
			/* broken - possibly a new pre-magic block */
			i_stream_seek(file->input, prev_offset);
			return;
		}
		if (*line == DBOX_METADATA_VIRTUAL_SIZE) {
			/* it may be wrong - recreate it */
			continue;
		}
		if (*line == DBOX_METADATA_GUID)
			*have_guid_r = TRUE;
		o_stream_send_str(output, line);
		o_stream_send_str(output, "\n");
	}
}
コード例 #2
0
ファイル: test-ostream-multiplex.c プロジェクト: bdraco/core
static void test_ostream_multiplex_simple(void)
{
	test_begin("ostream multiplex (simple)");

	const unsigned char expected[] = {
		'\x00','\x00','\x00','\x00','\x05','\x68','\x65',
		'\x6c','\x6c','\x6f','\x01','\x00','\x00','\x00',
		'\x05','\x77','\x6f','\x72','\x6c','\x64'
	};

	buffer_t *result = t_str_new(64);
	struct ostream *os = test_ostream_create(result);
	struct ostream *os2 = o_stream_create_multiplex(os, (size_t)-1);
	struct ostream *os3 = o_stream_multiplex_add_channel(os2, 1);

	test_assert(o_stream_send_str(os2, "hello") == 5);
	test_assert(o_stream_send_str(os3, "world") == 5);

	o_stream_unref(&os3);
	o_stream_unref(&os2);
	o_stream_unref(&os);

	test_assert(sizeof(expected) == result->used);
	test_assert(memcmp(result->data, expected, I_MIN(sizeof(expected),
		    result->used)) == 0);

	test_end();
}
コード例 #3
0
void testsuite_result_print
(const struct sieve_runtime_env *renv)
{
	struct ostream *out;

	out = o_stream_create_fd(1, 0, FALSE);

	o_stream_send_str(out, "\n--");
	sieve_result_print(_testsuite_result, renv->scriptenv, out, NULL);
	o_stream_send_str(out, "--\n\n");

	o_stream_destroy(&out);
}
コード例 #4
0
ファイル: lmtp-client.c プロジェクト: aosm/dovecot
static void lmtp_client_send_handshake(struct lmtp_client *client)
{
	switch (client->protocol) {
	case LMTP_CLIENT_PROTOCOL_LMTP:
		o_stream_send_str(client->output,
			t_strdup_printf("LHLO %s\r\n",
					client->set.my_hostname));
		break;
	case LMTP_CLIENT_PROTOCOL_SMTP:
		o_stream_send_str(client->output,
			t_strdup_printf("EHLO %s\r\n",
					client->set.my_hostname));
		break;
	}
}
コード例 #5
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;
}
コード例 #6
0
ファイル: imap-urlauth-worker.c プロジェクト: manuelm/dovecot
static int client_output(struct client *client)
{
	if (o_stream_flush(client->output) < 0) {
		if (client->ctrl_output != NULL)
			(void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n");
		client_destroy(client);
		return 1;
	}
	timeout_reset(client->to_idle);

	if (client->url != NULL) {
		if (client_run_url(client) < 0) {
			client_destroy(client);
			return 1;
		}

		if (client->url == NULL && client->waiting_input) {
			if (!client_handle_input(client)) {
				/* client got destroyed */
				return 1;
			}
		}
	}

	if (client->url != NULL) {
		/* url not finished yet */
		return 0;
	} else if (client->io == NULL) {
		/* data still in output buffer, get back here to add IO */
		return 0;
	} else {
		return 1;
	}
}
コード例 #7
0
ファイル: auth-worker-client.c プロジェクト: aosm/dovecot
static void auth_worker_send_reply(struct auth_worker_client *client,
				   string_t *str)
{
	if (shutdown_request)
		o_stream_send_str(client->output, "SHUTDOWN\n");
	o_stream_send(client->output, str_data(str), str_len(str));
}
コード例 #8
0
void auth_client_send_cancel(struct auth_client *client, unsigned int id)
{
	const char *str = t_strdup_printf("CANCEL\t%u\n", id);

	if (o_stream_send_str(client->conn->output, str) < 0)
		i_error("Error sending request to auth server: %m");
}
コード例 #9
0
ファイル: lmtp-client.c プロジェクト: jkerihuel/dovecot
static int
lmtp_client_data_next(struct lmtp_client *client, const char *line)
{
	struct lmtp_rcpt *rcpt;
	unsigned int i, count;

	rcpt = array_get_modifiable(&client->recipients, &count);
	for (i = client->rcpt_next_data_idx; i < count; i++) {
		if (rcpt[i].failed) {
			/* already called rcpt_to_callback with failure */
			continue;
		}

		client->rcpt_next_data_idx = i + 1;
		rcpt[i].failed = line[0] != '2';
		rcpt[i].data_callback(!rcpt[i].failed, line, rcpt[i].context);
		if (client->protocol == LMTP_CLIENT_PROTOCOL_LMTP)
			break;
	}
	if (client->rcpt_next_data_idx < count)
		return 0;

	o_stream_send_str(client->output, "QUIT\r\n");
	lmtp_client_close(client);
	return -1;
}
コード例 #10
0
ファイル: mbox-save.c プロジェクト: via/dovecot-clouddb
static int write_from_line(struct mbox_save_context *ctx, time_t received_date,
			   const char *from_envelope)
{
	int ret;

	T_BEGIN {
		const char *line;

		if (from_envelope == NULL) {
			struct mail_storage *storage =
				&ctx->mbox->storage->storage;

			from_envelope =
				strchr(storage->user->username, '@') != NULL ?
				storage->user->username :
				t_strconcat(storage->user->username,
					    "@", my_hostdomain(), NULL);
		} else if (*from_envelope == '\0') {
			/* can't write empty envelope */
			from_envelope = "MAILER-DAEMON";
		}

		/* save in local timezone, no matter what it was given with */
		line = mbox_from_create(from_envelope, received_date);

		if ((ret = o_stream_send_str(ctx->output, line)) < 0)
			write_error(ctx);
	} T_END;
	return ret;
}
コード例 #11
0
static int
master_input_cache_flush(struct auth_master_connection *conn, const char *args)
{
	const char *const *list;
	unsigned int count;

	/* <id> [<user> [<user> [..]] */
	list = t_strsplit_tab(args);
	if (list[0] == NULL) {
		i_error("BUG: doveadm sent broken CACHE-FLUSH");
		return FALSE;
	}

	if (passdb_cache == NULL) {
		/* cache disabled */
		count = 0;
	} else if (list[1] == NULL) {
		/* flush the whole cache */
		count = auth_cache_clear(passdb_cache);
	} else {
		count = auth_cache_clear_users(passdb_cache, list+1);
	}
	(void)o_stream_send_str(conn->output,
		t_strdup_printf("OK\t%s\t%u\n", list[0], count));
	return TRUE;
}
コード例 #12
0
ファイル: imap-urlauth-worker.c プロジェクト: bdraco/dovecot
static int
client_handle_command(struct client *client, const char *cmd,
		      const char *const *args, const char **error_r)
{
	int ret;

	*error_r = NULL;

	/* "URL"["\tbody"]["\tbinary"]["\tbpstruct"]"\t"<url>:
	   fetch URL (meta)data */
	if (strcmp(cmd, "URL") == 0) {
		enum imap_urlauth_fetch_flags url_flags = 0;
		const char *url;

		if (*args == NULL) {
			*error_r = "URL: Missing URL parameter";
			return -1;
		}

		url = *args;
	
		args++;
		while (*args != NULL) {
			if (strcasecmp(*args, "body") == 0)
				url_flags |= IMAP_URLAUTH_FETCH_FLAG_BODY;
			else if (strcasecmp(*args, "binary") == 0)
				url_flags |= IMAP_URLAUTH_FETCH_FLAG_BINARY;
			else if (strcasecmp(*args, "bpstruct") == 0)
				url_flags |= IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE;

			args++;
		}

		if (url_flags == 0)
			url_flags = IMAP_URLAUTH_FETCH_FLAG_BODY;

		T_BEGIN {
			ret = client_fetch_url(client, url, url_flags);
		} T_END;
		return ret;
	}

	/* "END": unselect current user (closes worker) */
	if (strcmp(cmd, "END") == 0) {
		if (args[0] != NULL) {
			*error_r = "END: Invalid number of parameters";
			return -1;
		}

		client->finished = TRUE;
		if (client->ctrl_output != NULL)
			(void)o_stream_send_str(client->ctrl_output, "FINISHED\n");
		client_destroy(client);
		return 0;
	}

	*error_r = t_strconcat("Unknown or inappropriate command: ", cmd, NULL);
	return -1;
}
コード例 #13
0
ファイル: config-connection.c プロジェクト: aosm/dovecot
static void
config_request_output(const char *key, const char *value,
		      enum config_key_type type ATTR_UNUSED, void *context)
{
	struct ostream *output = context;
	const char *p;

	o_stream_send_str(output, key);
	o_stream_send_str(output, "=");
	while ((p = strchr(value, '\n')) != NULL) {
		o_stream_send(output, value, p-value);
		o_stream_send(output, SETTING_STREAM_LF_CHAR, 1);
		value = p+1;
	}
	o_stream_send_str(output, value);
	o_stream_send_str(output, "\n");
}
コード例 #14
0
ファイル: imap-urlauth-worker.c プロジェクト: bdraco/dovecot
static bool client_handle_input(struct client *client)
{
	const char *line, *cmd, *error;
	int ret;

	if (client->url != NULL || client->to_delay != NULL) {
		/* we're still processing a URL. wait until it's
		   finished. */
		io_remove(&client->io);
		client->io = NULL;
		client->waiting_input = TRUE;
		return TRUE;
	}

	if (client->io == NULL) {
		client->io = io_add(client->fd_in, IO_READ,
				    client_input, client);
	}
	client->waiting_input = FALSE;
	timeout_reset(client->to_idle);

	switch (i_stream_read(client->input)) {
	case -1:
		/* disconnected */
		if (client->ctrl_output != NULL)
			(void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n");
		client_destroy(client);
		return FALSE;
	case -2:
		/* line too long, kill it */
		client_abort(client, "Session aborted: Input line too long");
		return FALSE;
	}

	while ((line = i_stream_next_line(client->input)) != NULL) {
		const char *const *args = t_strsplit_tabescaped(line);

		if (args[0] == NULL)
			continue;
		cmd = args[0]; args++;

		if (client->mail_user == NULL)
			ret = client_handle_user_command(client, cmd, args, &error);
		else
			ret = client_handle_command(client, cmd, args, &error);

		if (ret <= 0) {
			if (ret == 0)
				break;
			i_error("Client input error: %s", error);
			client_abort(client, "Session aborted: Unexpected input");
			return FALSE;
		}
	}
	return TRUE;
}
コード例 #15
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;
}
コード例 #16
0
ファイル: lmtp-client.c プロジェクト: aosm/dovecot
static void lmtp_client_send_rcpts(struct lmtp_client *client)
{
	const struct lmtp_rcpt *rcpt;
	unsigned int i, count;

	rcpt = array_get(&client->recipients, &count);
	for (i = client->rcpt_next_send_idx; i < count; i++) {
		o_stream_send_str(client->output,
			t_strdup_printf("RCPT TO:<%s>\r\n", rcpt[i].address));
	}
	client->rcpt_next_send_idx = i;
}
コード例 #17
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;
}
コード例 #18
0
ファイル: lmtp-client.c プロジェクト: aosm/dovecot
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_send_str(client->output, "DATA\r\n");
		return 0;
	}
}
コード例 #19
0
ファイル: cmd-copy.c プロジェクト: aosm/dovecot
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_send_str(client->output, "* OK Hang in there..\r\n");
		o_stream_flush(client->output);
		client->last_output = now;
	}
}
コード例 #20
0
int auth_server_connection_connect(struct auth_server_connection *conn)
{
	const char *handshake;
	int fd;

	i_assert(!conn->connected);
	i_assert(conn->fd == -1);

	conn->last_connect = ioloop_time;
	timeout_remove(&conn->to);

	/* max. 1 second wait here. */
	fd = net_connect_unix_with_retries(conn->client->auth_socket_path,
					   1000);
	if (fd == -1) {
		if (errno == EACCES) {
			i_error("auth: %s",
				eacces_error_get("connect",
					conn->client->auth_socket_path));
		} else {
			i_error("auth: connect(%s) failed: %m",
				conn->client->auth_socket_path);
		}
		return -1;
	}
	conn->fd = fd;
	conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn);
	conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH);
	conn->output = o_stream_create_fd(fd, (size_t)-1);
	conn->connected = TRUE;

	handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
				    AUTH_CLIENT_PROTOCOL_MAJOR_VERSION,
                                    AUTH_CLIENT_PROTOCOL_MINOR_VERSION,
				    conn->client->client_pid);
	if (o_stream_send_str(conn->output, handshake) < 0) {
		i_warning("Error sending handshake to auth server: %s",
			  o_stream_get_error(conn->output));
		auth_server_connection_disconnect(conn,
			o_stream_get_error(conn->output));
		return -1;
	}

	conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT,
			       auth_client_handshake_timeout, conn);
	return 0;
}
コード例 #21
0
ファイル: test-http-server.c プロジェクト: jkerihuel/dovecot
static int
client_handle_request(struct client *client, struct http_request *request)
{
    string_t *str = t_str_new(128);

    if (strcmp(request->method, "GET") != 0) {
        o_stream_send_str(client->conn.output, "HTTP/1.1 501 Not Implemented\r\nAllow: GET\r\n\r\n");
        return 0;
    }
    str_append(str, "HTTP/1.1 200 OK\r\n");
    str_printfa(str, "Date: %s\r\n", http_date_create(ioloop_time));
    str_printfa(str, "Content-Length: %d\r\n", (int)strlen(request->target_raw));
    str_append(str, "Content-Type: text/plain\r\n");
    str_append(str, "\r\n");
    str_append(str, request->target_raw);
    o_stream_send(client->conn.output, str_data(str), str_len(str));
    return 0;
}
コード例 #22
0
static int
imap_hibernate_client_input_args(struct connection *conn,
				 const char *const *args, int fd, pool_t pool)
{
	struct imap_hibernate_client *client =
		(struct imap_hibernate_client *)conn;
	struct imap_client_state state;
	const char *error;

	if (imap_hibernate_client_parse_input(args, pool, &state, &error) < 0) {
		i_error("Failed to parse client input: %s", error);
		o_stream_send_str(conn->output, t_strdup_printf(
			"-Failed to parse client input: %s\n", error));
		return -1;
	}
	client->imap_client = imap_client_create(fd, &state);
	/* the transferred imap client fd is now counted as the client. */
	client->imap_client_created = TRUE;
	return state.have_notify_fd ? 0 : 1;
}
コード例 #23
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 = mail_namespace_get_storage_name(backend->backend.list->ns,
					       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_send_str(output, line);
		} T_END;
	}
コード例 #24
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;
	const char *line, *origin;
	struct istream *input;
	struct ostream *output;
	int fd_in, fd_out;
	mode_t mode;
	gid_t gid;
	bool found, changed = FALSE, failed = FALSE;

	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_permissions(list, NULL, &mode, &gid, &origin);
	fd_out = file_dotlock_open_group(&dotlock_set, path, 0,
					 mode, gid, origin, &dotlock);
	if (fd_out == -1 && errno == ENOENT) {
		/* directory hasn't been created yet. */
		if (mailbox_list_create_parent_dir(list, NULL, path) < 0)
			return -1;
		fd_out = file_dotlock_open_group(&dotlock_set, path, 0,
						 mode, 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);
		(void)file_dotlock_delete(&dotlock);
		return -1;
	}

	input = fd_in == -1 ? NULL :
		i_stream_create_fd(fd_in, list->mailbox_name_max_length+1,
				   TRUE);
	output = o_stream_create_fd_file(fd_out, 0, FALSE);
	o_stream_cork(output);
	found = FALSE;
	while ((line = next_line(list, path, input,
				 &failed, FALSE)) != NULL) {
		if (strcmp(line, name) == 0) {
			found = TRUE;
			if (!set) {
				changed = TRUE;
				continue;
			}
		}

		(void)o_stream_send_str(output, line);
		(void)o_stream_send(output, "\n", 1);
	}

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

	if (changed && !failed) {
		if (o_stream_flush(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;
			}
		}
	}

	if (input != NULL)
		i_stream_destroy(&input);
	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);
}
コード例 #25
0
ファイル: test-iostream-proxy.c プロジェクト: manuelm/dovecot
static
void test_iostream_proxy_simple(void)
{
	size_t bytes;

	test_begin("iostream_proxy");
	int sfdl[2];
	int sfdr[2];

	int counter;

	test_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sfdl) == 0);
	test_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sfdr) == 0);

	fd_set_nonblock(sfdl[0], TRUE);
	fd_set_nonblock(sfdl[1], TRUE);
	fd_set_nonblock(sfdr[0], TRUE);
	fd_set_nonblock(sfdr[1], TRUE);

	struct ioloop *ioloop = io_loop_create();

	struct istream *left_in = i_stream_create_fd(sfdl[1], IO_BLOCK_SIZE);
	struct ostream *left_out = o_stream_create_fd(sfdl[1], IO_BLOCK_SIZE);

	struct istream *right_in = i_stream_create_fd(sfdr[1], IO_BLOCK_SIZE);
	struct ostream *right_out = o_stream_create_fd(sfdr[1], IO_BLOCK_SIZE);

	struct iostream_proxy *proxy;

	proxy = iostream_proxy_create(left_in, left_out, right_in, right_out);
	i_stream_unref(&left_in);
	o_stream_unref(&left_out);
	i_stream_unref(&right_in);
	o_stream_unref(&right_out);

	iostream_proxy_set_completion_callback(proxy, completed, &counter);
	iostream_proxy_start(proxy);

	left_in = i_stream_create_fd(sfdl[0], IO_BLOCK_SIZE);
	left_out = o_stream_create_fd(sfdl[0], IO_BLOCK_SIZE);

	right_in = i_stream_create_fd(sfdr[0], IO_BLOCK_SIZE);
	right_out = o_stream_create_fd(sfdr[0], IO_BLOCK_SIZE);

	test_assert(proxy != NULL);
	test_assert(o_stream_send_str(left_out, "hello, world") > 0);
	o_stream_flush(left_out);
	o_stream_unref(&left_out);
	test_assert(shutdown(sfdl[0], SHUT_WR) == 0);

	counter = 1;
	io_loop_run(ioloop);

	i_stream_read(right_in);
	test_assert(strcmp((const char*)i_stream_get_data(right_in, &bytes), "hello, world") == 0);
	i_stream_skip(right_in, bytes);

	test_assert(o_stream_send_str(right_out, "hello, world") > 0);
	o_stream_flush(right_out);
	o_stream_unref(&right_out);
	test_assert(shutdown(sfdr[0], SHUT_WR) == 0);

	counter = 1;
	io_loop_run(ioloop);

	i_stream_read(left_in);
	test_assert(strcmp((const char*)i_stream_get_data(left_in, &bytes), "hello, world") == 0);
	i_stream_skip(left_in, bytes);

	iostream_proxy_unref(&proxy);

	io_loop_destroy(&ioloop);

	i_stream_unref(&left_in);
	i_stream_unref(&right_in);

	/* close fd */
	close(sfdl[0]);
	close(sfdl[1]);
	close(sfdr[0]);
	close(sfdr[1]);

	test_end();
}
コード例 #26
0
ファイル: imap-urlauth-worker.c プロジェクト: bdraco/dovecot
static void client_ctrl_input(struct client *client)
{
	const char *const *args;
	const char *line;
	int ret;

	timeout_reset(client->to_idle);

	if (client->fd_in == -1 || client->fd_out == -1) {
		if ((ret = client_ctrl_read_fds(client)) <= 0) {
			if (ret < 0)
				client_abort(client, "FD Transfer failed");
			return;
		}
	}

	switch (i_stream_read(client->ctrl_input)) {
	case -1:
		/* disconnected */
		client_destroy(client);
		return;
	case -2:
		/* line too long, kill it */
		client_abort(client,
			     "Control session aborted: Input line too long");
		return;
	}

	if (!client->version_received) {
		if ((line = i_stream_next_line(client->ctrl_input)) == NULL)
			return;

		if (!version_string_verify(line, "imap-urlauth-worker",
				IMAP_URLAUTH_WORKER_PROTOCOL_MAJOR_VERSION)) {
			i_error("imap-urlauth-worker client not compatible with this server "
				"(mixed old and new binaries?) %s", line);
			client_abort(client, "Control session aborted: Version mismatch");
			return;
		}

		client->version_received = TRUE;
		if (o_stream_send_str(client->ctrl_output, "OK\n") < 0) {
			client_destroy(client);
			return;
		}
	}

	if (client->access_received) {
		client_abort(client, "Control session aborted: Unexpected input");
		return;
	}

	if ((line = i_stream_next_line(client->ctrl_input)) == NULL)
		return;

	args = t_strsplit_tabescaped(line);
	if (*args == NULL || strcmp(*args, "ACCESS") != 0) {
		i_error("Invalid control command: %s", str_sanitize(line, 80));
		client_abort(client, "Control session aborted: Invalid command");
		return;
	}
	args++;
	if (*args == NULL) {
		i_error("Invalid ACCESS command: %s", str_sanitize(line, 80));
		client_abort(client, "Control session aborted: Invalid command");
		return;
	}

	i_assert(client->access_user == NULL);
	if (**args != '\0') {
		client->access_user = i_strdup(*args);
		client->access_anonymous = FALSE;
	} else {
		client->access_user = i_strdup("anonymous");
		client->access_anonymous = TRUE;
	}
	i_set_failure_prefix("imap-urlauth[%s](%s): ",
			     my_pid, client->access_user);

	args++;
	while (*args != NULL) {
		/* debug */
		if (strcasecmp(*args, "debug") == 0) {
			client->debug = TRUE;
		/* apps=<access-application>[,<access-application,...] */
		} else if (strncasecmp(*args, "apps=", 5) == 0 &&
			   (*args)[5] != '\0') {
			const char *const *apps = t_strsplit(*args+5, ",");

			while (*apps != NULL) {
				char *app = i_strdup(*apps);

				array_append(&client->access_apps, &app, 1);
				if (client->debug) {
					i_debug("User %s has URLAUTH %s access",
						client->access_user, app);
				}
				apps++;
			}
		} else {
			i_error("Invalid ACCESS parameter: %s", str_sanitize(*args, 80));
			client_abort(client, "Control session aborted: Invalid command");
			return;
		} 
		args++;
	}

	client->access_received = TRUE;

	if (o_stream_send_str(client->ctrl_output, "OK\n") < 0) {
		client_destroy(client);
		return;
	}

	client->input = i_stream_create_fd(client->fd_in, MAX_INBUF_SIZE, FALSE);
	client->output = o_stream_create_fd(client->fd_out, (size_t)-1, FALSE); 
	client->io = io_add(client->fd_in, IO_READ, client_input, client);
	o_stream_set_flush_callback(client->output, client_output, client);

	if (client->debug) {
		i_debug("Worker activated for access by user %s",
			client->access_user);
	}
}
コード例 #27
0
static int
imap_hibernate_client_input_line(struct connection *conn, const char *line)
{
	struct imap_hibernate_client *client =
		(struct imap_hibernate_client *)conn;
	int fd = -1, ret;

	if (!conn->version_received) {
		if (connection_verify_version(conn, t_strsplit_tabescaped(line)) < 0)
			return -1;
		conn->version_received = TRUE;
		return 1;
	}

	if (client->imap_client == NULL) {
		char *const *args;
		pool_t pool;

		fd = i_stream_unix_get_read_fd(conn->input);
		if (fd == -1) {
			i_error("IMAP client fd not received");
			return -1;
		}

		pool = pool_alloconly_create("client cmd", 1024);
		args = p_strsplit_tabescaped(pool, line);
		ret = imap_hibernate_client_input_args(conn, (void *)args, fd, pool);
		if (ret >= 0 && client->debug)
			i_debug("Create client with input: %s", line);
		pool_unref(&pool);
	} else {
		fd = i_stream_unix_get_read_fd(conn->input);
		if (fd == -1) {
			i_error("IMAP notify fd not received (input: %s)", line);
			ret = -1;
		} else if (line[0] != '\0') {
			i_error("Expected empty notify fd line from client, but got: %s", line);
			o_stream_send_str(conn->output,
					  "Expected empty notify fd line");
			ret = -1;
		} else {
			imap_client_add_notify_fd(client->imap_client, fd);
			ret = 1;
		}
	}

	if (ret < 0) {
		if (client->imap_client != NULL)
			imap_client_destroy(&client->imap_client, NULL);
		if (fd != -1)
			i_close_fd(&fd);
		return -1;
	} else if (ret == 0) {
		/* still need to read another fd */
		i_stream_unix_set_read_fd(conn->input);
		o_stream_send_str(conn->output, "+\n");
		return 1;
	} else {
		/* finished - always disconnect the hibernate client
		   afterwards */
		o_stream_send_str(conn->output, "+\n");
		imap_client_create_finish(client->imap_client);
		return -1;
	}
}
コード例 #28
0
static inline void _trace_line_print_empty
(const struct sieve_runtime_env *renv)
{
	o_stream_send_str(renv->trace->stream, "\n");
}
コード例 #29
0
ファイル: config-connection.c プロジェクト: aosm/dovecot
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 = "";

	/* [<args>] */
	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;
		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;
			}
		}
	}

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

	o_stream_cork(conn->output);

	ctx = config_export_init(module, 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_send_str(conn->output,
				t_strdup_printf("service=%s\t", *s));
		}
	}
	if (output.service_uses_local)
		o_stream_send_str(conn->output, "service-uses-local\t");
	if (output.service_uses_remote)
		o_stream_send_str(conn->output, "service-uses-remote\t");
	if (output.used_local)
		o_stream_send_str(conn->output, "used-local\t");
	if (output.used_remote)
		o_stream_send_str(conn->output, "used-remote\t");
	o_stream_send_str(conn->output, "\n");

	if (config_export_finish(&ctx) < 0) {
		config_connection_destroy(conn);
		return -1;
	}
	o_stream_send_str(conn->output, "\n");
	o_stream_uncork(conn->output);
	return 0;
}
コード例 #30
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);
}