Exemple #1
0
struct istream *iostream_temp_finish(struct ostream **output,
				     size_t max_buffer_size)
{
	struct temp_ostream *tstream =
		(struct temp_ostream *)(*output)->real_stream;
	struct istream *input, *input2;
	uoff_t abs_offset, size;
	const char *for_path;
	int fd;

	if (tstream->name[0] == '\0')
		for_path = "";
	else
		for_path = t_strdup_printf(" for %s", tstream->name);

	if (tstream->dupstream != NULL && !tstream->dupstream->closed) {
		abs_offset = i_stream_get_absolute_offset(tstream->dupstream) -
			tstream->dupstream->v_offset +
			tstream->dupstream_start_offset;
		size = tstream->dupstream_offset -
			tstream->dupstream_start_offset;
		fd = dup(i_stream_get_fd(tstream->dupstream));
		if (fd == -1)
			input = i_stream_create_error_str(errno, "dup() failed: %m");
		else {
			input2 = i_stream_create_fd_autoclose(&fd, max_buffer_size);
			i_stream_seek(input2, abs_offset);
			input = i_stream_create_limit(input2, size);
			i_stream_unref(&input2);
		}
		i_stream_set_name(input, t_strdup_printf(
			"(Temp file in %s%s, from %s)", tstream->temp_path_prefix,
			for_path, i_stream_get_name(tstream->dupstream)));
		i_stream_unref(&tstream->dupstream);
	} else if (tstream->dupstream != NULL) {
		/* return the original failed stream. */
		input = tstream->dupstream;
	} else if (tstream->fd != -1) {
		int fd = tstream->fd;
		input = i_stream_create_fd_autoclose(&tstream->fd, max_buffer_size);
		i_stream_set_name(input, t_strdup_printf(
			"(Temp file fd %d in %s%s, %"PRIuUOFF_T" bytes)",
			fd, tstream->temp_path_prefix, for_path, tstream->fd_size));
	} else {
		input = i_stream_create_from_data(tstream->buf->data,
						  tstream->buf->used);
		i_stream_set_name(input, t_strdup_printf(
			"(Temp buffer in %s%s, %"PRIuSIZE_T" bytes)",
			tstream->temp_path_prefix, for_path, tstream->buf->used));
		i_stream_add_destroy_callback(input, iostream_temp_buf_destroyed,
					      tstream->buf);
		tstream->buf = NULL;
	}
	o_stream_destroy(output);
	return input;
}
Exemple #2
0
static int
cydir_mail_get_stream(struct mail *_mail, struct message_size *hdr_size,
		      struct message_size *body_size, struct istream **stream_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	const char *path;
	int fd;

	if (mail->data.stream == NULL) {
		mail->mail.stats_open_lookup_count++;
		path = cydir_mail_get_path(_mail);
		fd = open(path, O_RDONLY);
		if (fd == -1) {
			if (errno == ENOENT)
				mail_set_expunged(_mail);
			else {
				mail_storage_set_critical(_mail->box->storage,
					"open(%s) failed: %m", path);
			}
			return -1;
		}
		mail->data.stream = i_stream_create_fd(fd, 0, TRUE);
		i_stream_set_name(mail->data.stream, path);
		index_mail_set_read_buffer_size(_mail, mail->data.stream);
		if (mail->mail.v.istream_opened != NULL) {
			if (mail->mail.v.istream_opened(_mail, stream_r) < 0)
				return -1;
		}
	}

	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
}
Exemple #3
0
static int zlib_mailbox_open_input(struct mailbox *box)
{
	const struct compression_handler *handler;
	struct istream *input;
	struct stat st;
	int fd;

	handler = compression_lookup_handler_from_ext(box->name);
	if (handler == NULL || handler->create_istream == NULL)
		return 0;

	if (mail_storage_is_mailbox_file(box->storage)) {
		/* looks like a compressed single file mailbox. we should be
		   able to handle this. */
		const char *box_path = mailbox_get_path(box);

		fd = open(box_path, O_RDONLY);
		if (fd == -1) {
			/* let the standard handler figure out what to do
			   with the failure */
			return 0;
		}
		if (fstat(fd, &st) == 0 && S_ISDIR(st.st_mode)) {
			i_close_fd(&fd);
			return 0;
		}
		input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
		i_stream_set_name(input, box_path);
		box->input = handler->create_istream(input, TRUE);
		i_stream_unref(&input);
		box->flags |= MAILBOX_FLAG_READONLY;
	}
	return 0;
}
Exemple #4
0
static void connection_init_streams(struct connection *conn)
{
	const struct connection_settings *set = &conn->list->set;

	i_assert(conn->io == NULL);
	i_assert(conn->input == NULL);
	i_assert(conn->output == NULL);
	i_assert(conn->to == NULL);

	conn->version_received = set->major_version == 0;

	if (set->input_max_size != 0) {
		conn->input = i_stream_create_fd(conn->fd_in,
						 set->input_max_size, FALSE);
		i_stream_set_name(conn->input, conn->name);
	}
	if (set->output_max_size != 0) {
		conn->output = o_stream_create_fd(conn->fd_out,
						  set->output_max_size, FALSE);
		o_stream_set_no_error_handling(conn->output, TRUE);
		o_stream_set_name(conn->output, conn->name);
	}
	conn->io = io_add(conn->fd_in, IO_READ, *conn->list->v.input, conn);
	if (set->input_idle_timeout_secs != 0) {
		conn->to = timeout_add(set->input_idle_timeout_secs*1000,
				       connection_idle_timeout, conn);
	}
	if (set->major_version != 0 && !set->dont_send_version) {
		o_stream_nsend_str(conn->output, t_strdup_printf(
			"VERSION\t%s\t%u\t%u\n", set->service_name_out,
			set->major_version, set->minor_version));
	}
}
Exemple #5
0
struct istream *tee_i_stream_create_child(struct tee_istream *tee)
{
	struct tee_child_istream *tstream;
	struct istream *ret, *input = tee->input;

	tstream = i_new(struct tee_child_istream, 1);
	tstream->tee = tee;

	tstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
	tstream->istream.iostream.close = i_stream_tee_close;
	tstream->istream.iostream.destroy = i_stream_tee_destroy;
	tstream->istream.iostream.set_max_buffer_size =
		i_stream_tee_set_max_buffer_size;

	tstream->istream.read = i_stream_tee_read;
	tstream->istream.stat = i_stream_tee_stat;
	tstream->istream.sync = i_stream_tee_sync;

	tstream->next = tee->children;
	tee->children = tstream;

	ret = i_stream_create(&tstream->istream, input, i_stream_get_fd(input));
	i_stream_set_name(&tstream->istream.istream, i_stream_get_name(input));
	/* we keep the reference in tee stream, no need for extra references */
	i_stream_unref(&input);
	return ret;
}
Exemple #6
0
int mbox_file_open_stream(struct mbox_mailbox *mbox)
{
	if (mbox->mbox_stream != NULL)
		return 0;

	if (mbox->mbox_file_stream != NULL) {
		/* read-only mbox stream */
		i_assert(mbox->mbox_fd == -1 && mbox_is_backend_readonly(mbox));
	} else {
		if (mbox->mbox_fd == -1) {
			if (mbox_file_open(mbox) < 0)
				return -1;
		}

		if (mbox->mbox_writeonly) {
			mbox->mbox_file_stream =
				i_stream_create_from_data("", 0);
		} else {
			mbox->mbox_file_stream =
				i_stream_create_fd(mbox->mbox_fd,
						   MBOX_READ_BLOCK_SIZE);
			i_stream_set_init_buffer_size(mbox->mbox_file_stream,
						      MBOX_READ_BLOCK_SIZE);
		}
		i_stream_set_name(mbox->mbox_file_stream,
				  mailbox_get_path(&mbox->box));
	}

	mbox->mbox_stream = i_stream_create_raw_mbox(mbox->mbox_file_stream);
	if (mbox->mbox_lock_type != F_UNLCK)
		istream_raw_mbox_set_locked(mbox->mbox_stream);
	return 0;
}
Exemple #7
0
void connection_init_from_streams(struct connection_list *list,
			    struct connection *conn, const char *name,
			    struct istream *input, struct ostream *output)
{
	i_assert(name != NULL);

	conn->list = list;
	conn->name = i_strdup(name);
	conn->fd_in = i_stream_get_fd(input);
	conn->fd_out = o_stream_get_fd(output);

	i_assert(conn->fd_in >= 0);
	i_assert(conn->fd_out >= 0);
	i_assert(conn->io == NULL);
	i_assert(conn->input == NULL);
	i_assert(conn->output == NULL);
	i_assert(conn->to == NULL);

	conn->input = input;
	i_stream_ref(conn->input);
	i_stream_set_name(conn->input, conn->name);

	conn->output = output;
	o_stream_ref(conn->output);
	o_stream_set_no_error_handling(conn->output, TRUE);
	o_stream_set_name(conn->output, conn->name);

	conn->io = io_add_istream(conn->input, *list->v.input, conn);
	
	DLLIST_PREPEND(&list->connections, conn);
	list->connections_count++;

	if (list->v.client_connected != NULL)
		list->v.client_connected(conn, TRUE);
}
Exemple #8
0
struct istream *i_stream_create_file(const char *path, size_t max_buffer_size)
{
	struct istream *input;

	input = i_stream_create_file_common(-1, path, max_buffer_size, TRUE);
	i_stream_set_name(input, path);
	return input;
}
Exemple #9
0
static int copy_to_temp_file(struct seekable_istream *sstream)
{
	struct istream_private *stream = &sstream->istream;
	const char *path;
	const unsigned char *buffer;
	size_t size;
	int fd;

	fd = sstream->fd_callback(&path, sstream->context);
	if (fd == -1)
		return -1;

	/* copy our currently read buffer to it */
	i_assert(stream->pos <= sstream->buffer_peak);
	if (write_full(fd, stream->buffer, sstream->buffer_peak) < 0) {
		if (!ENOSPACE(errno))
			i_error("istream-seekable: write_full(%s) failed: %m", path);
		i_close_fd(&fd);
		return -1;
	}
	sstream->temp_path = i_strdup(path);
	sstream->write_peak = sstream->buffer_peak;

	sstream->fd = fd;
	sstream->fd_input = i_stream_create_fd_autoclose(&fd,
		I_MAX(stream->pos, sstream->istream.max_buffer_size));
	i_stream_set_name(sstream->fd_input, t_strdup_printf(
		"(seekable temp-istream for: %s)", i_stream_get_name(&stream->istream)));

	/* read back the data we just had in our buffer */
	for (;;) {
		buffer = i_stream_get_data(sstream->fd_input, &size);
		if (size >= stream->pos)
			break;

		ssize_t ret;
		if ((ret = i_stream_read_memarea(sstream->fd_input)) <= 0) {
			i_assert(ret != 0);
			i_assert(ret != -2);
			i_error("istream-seekable: Couldn't read back "
				"in-memory input %s: %s",
				i_stream_get_name(&stream->istream),
				i_stream_get_error(sstream->fd_input));
			i_stream_destroy(&sstream->fd_input);
			i_close_fd(&sstream->fd);
			return -1;
		}
	}
	/* Set the max buffer size only after we've already read everything
	   into memory. For example with istream-data it's possible that
	   more data exists in buffer than max_buffer_size. */
	i_stream_set_max_buffer_size(sstream->fd_input,
				     sstream->istream.max_buffer_size);
	stream->buffer = buffer;
	i_stream_free_buffer(&sstream->istream);
	return 0;
}
Exemple #10
0
static int
cmd_setmetadata_entry(struct imap_setmetadata_context *ctx,
                      const char *entry_name,
                      const struct imap_arg *entry_value)
{
    struct istream *inputs[2];
    struct mail_attribute_value value;
    string_t *path;
    int ret;

    switch (entry_value->type) {
    case IMAP_ARG_NIL:
    case IMAP_ARG_ATOM:
    case IMAP_ARG_STRING:
        /* we have the value already */
        if (ctx->failed)
            return 1;
        memset(&value, 0, sizeof(value));
        value.value = imap_arg_as_nstring(entry_value);
        ret = imap_metadata_set(ctx->trans, entry_name, &value);
        if (ret < 0) {
            /* delay reporting the failure so we'll finish
               reading the command input */
            ctx->storage_failure = TRUE;
            ctx->failed = TRUE;
        }
        return 1;
    case IMAP_ARG_LITERAL_SIZE:
        o_stream_nsend(ctx->cmd->client->output, "+ OK\r\n", 6);
        o_stream_nflush(ctx->cmd->client->output);
        o_stream_uncork(ctx->cmd->client->output);
        o_stream_cork(ctx->cmd->client->output);
    /* fall through */
    case IMAP_ARG_LITERAL_SIZE_NONSYNC:
        i_free(ctx->entry_name);
        ctx->entry_name = i_strdup(entry_name);
        ctx->entry_value_len = imap_arg_as_literal_size(entry_value);

        inputs[0] = i_stream_create_limit(ctx->cmd->client->input,
                                          ctx->entry_value_len);
        inputs[1] = NULL;

        path = t_str_new(128);
        mail_user_set_get_temp_prefix(path, ctx->cmd->client->user->set);
        ctx->input = i_stream_create_seekable_path(inputs,
                     METADATA_MAX_INMEM_SIZE, str_c(path));
        i_stream_set_name(ctx->input, i_stream_get_name(inputs[0]));
        i_stream_unref(&inputs[0]);
        return cmd_setmetadata_entry_read_stream(ctx);
    case IMAP_ARG_LITERAL:
    case IMAP_ARG_LIST:
    case IMAP_ARG_EOL:
        break;
    }
    i_unreached();
}
Exemple #11
0
struct istream *i_stream_create_file(const char *path, size_t max_buffer_size)
{
	struct file_istream *fstream;
	struct istream *input;

	fstream = i_new(struct file_istream, 1);
	input = i_stream_create_file_common(fstream, -1, path,
					    max_buffer_size, TRUE);
	i_stream_set_name(input, path);
	return input;
}
Exemple #12
0
static int
pop3c_mail_get_stream(struct mail *_mail, bool get_body,
		      struct message_size *hdr_size,
		      struct message_size *body_size, struct istream **stream_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)_mail->box;
	enum pop3c_capability capa;
	const char *name, *cmd, *error;
	struct istream *input;

	if (get_body && mail->data.stream != NULL) {
		name = i_stream_get_name(mail->data.stream);
		if (strncmp(name, "RETR", 4) == 0) {
			/* we've fetched the body */
		} else if (strncmp(name, "TOP", 3) == 0) {
			/* we've fetched the header, but we need the body
			   now too */
			index_mail_close_streams(mail);
		} else {
			i_panic("Unexpected POP3 stream name: %s", name);
		}
	}

	if (mail->data.stream == NULL) {
		capa = pop3c_client_get_capabilities(mbox->client);
		if (get_body || (capa & POP3C_CAPABILITY_TOP) == 0) {
			cmd = t_strdup_printf("RETR %u\r\n", _mail->seq);
			get_body = TRUE;
		} else {
			cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq);
		}
		if (pop3c_client_cmd_stream(mbox->client, cmd,
					    &input, &error) < 0) {
			mail_storage_set_error(mbox->box.storage,
				!pop3c_client_is_connected(mbox->client) ?
				MAIL_ERROR_TEMP : MAIL_ERROR_EXPUNGED, error);
			return -1;
		}
		mail->data.stream = input;
		if (mail->mail.v.istream_opened != NULL) {
			if (mail->mail.v.istream_opened(_mail,
							&mail->data.stream) < 0) {
				index_mail_close_streams(mail);
				return -1;
			}
		}
		i_stream_set_name(mail->data.stream, t_strcut(cmd, '\r'));
		if (get_body)
			pop3c_mail_cache_size(mail);
	}
	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
}
struct mail_raw *mail_raw_open_data
(struct mail_user *ruser, string_t *mail_data)
{
	struct mail_raw *mailr;
	struct istream *input;

	input = i_stream_create_from_data(str_data(mail_data), str_len(mail_data));
	i_stream_set_name(input, "data");

	mailr = mail_raw_create(ruser, input, NULL, NULL, (time_t)-1);

	i_stream_unref(&input);

	return mailr;
}
Exemple #14
0
struct istream *i_stream_create_error(int stream_errno)
{
	struct istream_private *stream;

	stream = i_new(struct istream_private, 1);
	stream->istream.closed = TRUE;
	stream->istream.readable_fd = FALSE;
	stream->istream.blocking = TRUE;
	stream->istream.seekable = TRUE;
	stream->istream.eof = TRUE;
	stream->istream.stream_errno = stream_errno;
	i_stream_create(stream, NULL, -1);
	i_stream_set_name(&stream->istream, "(error)");
	return &stream->istream;
}
static int copy_to_temp_file(struct seekable_istream *sstream)
{
    struct istream_private *stream = &sstream->istream;
    const char *path;
    const unsigned char *buffer;
    size_t size;
    int fd;

    fd = sstream->fd_callback(&path, sstream->context);
    if (fd == -1)
        return -1;

    /* copy our currently read buffer to it */
    if (write_full(fd, sstream->membuf->data, sstream->membuf->used) < 0) {
        if (!ENOSPACE(errno))
            i_error("istream-seekable: write_full(%s) failed: %m", path);
        i_close_fd(&fd);
        return -1;
    }
    sstream->temp_path = i_strdup(path);
    sstream->write_peak = sstream->membuf->used;

    sstream->fd = fd;
    sstream->fd_input =
        i_stream_create_fd_autoclose(&fd, sstream->istream.max_buffer_size);
    i_stream_set_name(sstream->fd_input, t_strdup_printf(
                          "(seekable temp-istream for: %s)", i_stream_get_name(&stream->istream)));

    /* read back the data we just had in our buffer */
    i_stream_seek(sstream->fd_input, stream->istream.v_offset);
    for (;;) {
        buffer = i_stream_get_data(sstream->fd_input, &size);
        if (size >= stream->pos)
            break;

        if (i_stream_read(sstream->fd_input) <= 0) {
            i_error("istream-seekable: Couldn't read back "
                    "in-memory input %s",
                    i_stream_get_name(&stream->istream));
            i_stream_destroy(&sstream->fd_input);
            return -1;
        }
    }
    stream->buffer = buffer;
    stream->pos = size;
    buffer_free(&sstream->membuf);
    return 0;
}
Exemple #16
0
static struct istream *
i_stream_create_file_common(int fd, const char *path,
			    size_t max_buffer_size, bool autoclose_fd)
{
	struct file_istream *fstream;
	struct istream *input;
	struct stat st;
	bool is_file;

	fstream = i_new(struct file_istream, 1);
	fstream->autoclose_fd = autoclose_fd;

	fstream->istream.iostream.close = i_stream_file_close;
	fstream->istream.max_buffer_size = max_buffer_size;
	fstream->istream.read = i_stream_file_read;
	fstream->istream.seek = i_stream_file_seek;
	fstream->istream.sync = i_stream_file_sync;
	fstream->istream.stat = i_stream_file_stat;

	/* if it's a file, set the flags properly */
	if (fd == -1)
		is_file = TRUE;
	else if (fstat(fd, &st) < 0)
		is_file = FALSE;
	else if (S_ISREG(st.st_mode))
		is_file = TRUE;
	else if (!S_ISDIR(st.st_mode))
		is_file = FALSE;
	else {
		/* we're trying to open a directory.
		   we're not designed for it. */
		io_stream_set_error(&fstream->istream.iostream,
			"%s is a directory, can't read it as file",
			path != NULL ? path : t_strdup_printf("<fd %d>", fd));
		fstream->istream.istream.stream_errno = EISDIR;
		is_file = FALSE;
	}
	if (is_file) {
		fstream->file = TRUE;
		fstream->istream.istream.blocking = TRUE;
		fstream->istream.istream.seekable = TRUE;
	}
	fstream->istream.istream.readable_fd = TRUE;

	input = i_stream_create(&fstream->istream, NULL, fd);
	i_stream_set_name(input, is_file ? "(file)" : "(fd)");
	return input;
}
Exemple #17
0
static struct istream *
maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
		  bool *deleted_r)
{
	struct istream *input;
	const char *path;
	struct maildir_open_context ctx;

	*deleted_r = FALSE;

	ctx.fd = -1;
	ctx.path = NULL;

	mail->transaction->stats.open_lookup_count++;
	if (!mail->saving) {
		if (maildir_file_do(mbox, mail->uid, do_open, &ctx) < 0)
			return NULL;
	} else {
		path = maildir_save_file_get_path(mail->transaction, mail->seq);
		if (do_open(mbox, path, &ctx) <= 0)
			return NULL;
	}

	if (ctx.fd == -1) {
		*deleted_r = TRUE;
		return NULL;
	}

	input = i_stream_create_fd_autoclose(&ctx.fd, 0);
	if (input->stream_errno == EISDIR) {
		i_stream_destroy(&input);
		if (maildir_lose_unexpected_dir(&mbox->storage->storage,
						ctx.path) >= 0)
			*deleted_r = TRUE;
	} else {
		i_stream_set_name(input, ctx.path);
		index_mail_set_read_buffer_size(mail, input);
	}
	i_free(ctx.path);
	return input;
}
Exemple #18
0
struct client_connection *
client_connection_create(int fd, int listen_fd, bool ssl)
{
	struct client_connection *conn;
	const char *ip;
	pool_t pool;

	pool = pool_alloconly_create("doveadm client", 1024*16);
	conn = p_new(pool, struct client_connection, 1);
	conn->pool = pool;
	conn->fd = fd;
	conn->io = io_add(fd, IO_READ, client_connection_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);

	(void)net_getsockname(fd, &conn->local_ip, &conn->local_port);
	(void)net_getpeername(fd, &conn->remote_ip, &conn->remote_port);

	i_stream_set_name(conn->input, net_ip2addr(&conn->remote_ip));
	o_stream_set_name(conn->output, net_ip2addr(&conn->remote_ip));

	ip = net_ip2addr(&conn->remote_ip);
	if (ip[0] != '\0')
		i_set_failure_prefix("doveadm(%s): ", ip);

	if (client_connection_read_settings(conn) < 0) {
		client_connection_destroy(&conn);
		return NULL;
	}
	if (ssl) {
		if (client_connection_init_ssl(conn) < 0) {
			client_connection_destroy(&conn);
			return NULL;
		}
	}
	client_connection_send_auth_handshake(conn, listen_fd);
	return conn;
}
Exemple #19
0
static void cmd_dump_dbox(int argc ATTR_UNUSED, char *argv[])
{
	struct istream *input;
	int fd;
	unsigned int hdr_size;
	bool ret;

	fd = open(argv[1], O_RDONLY);
	if (fd < 0)
		i_fatal("open(%s) failed: %m", argv[1]);

	input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
	i_stream_set_name(input, argv[1]);
	hdr_size = dump_file_hdr(input);
	do {
		printf("\n");
		T_BEGIN {
			ret = dump_msg(input, hdr_size);
		} T_END;
	} while (ret);
	i_stream_destroy(&input);
}
Exemple #20
0
static int
cydir_mail_get_stream(struct mail *_mail, bool get_body ATTR_UNUSED,
		      struct message_size *hdr_size,
		      struct message_size *body_size,
		      struct istream **stream_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct istream *input;
	const char *path;
	int fd;

	if (mail->data.stream == NULL) {
		_mail->transaction->stats.open_lookup_count++;
		path = cydir_mail_get_path(_mail);
		fd = open(path, O_RDONLY);
		if (fd == -1) {
			if (errno == ENOENT)
				mail_set_expunged(_mail);
			else {
				mail_storage_set_critical(_mail->box->storage,
					"open(%s) failed: %m", path);
			}
			return -1;
		}
		input = i_stream_create_fd(fd, 0, TRUE);
		i_stream_set_name(input, path);
		index_mail_set_read_buffer_size(_mail, input);
		if (mail->mail.v.istream_opened != NULL) {
			if (mail->mail.v.istream_opened(_mail, &input) < 0) {
				i_stream_unref(&input);
				return -1;
			}
		}
		mail->data.stream = input;
	}

	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
}
Exemple #21
0
struct istream *
i_stream_create_fs_file(struct fs_file **file, size_t max_buffer_size)
{
    struct fs_file_istream *fstream;
    struct istream *input;

    fstream = i_new(struct fs_file_istream, 1);
    fstream->file = *file;
    fstream->istream.iostream.close = i_stream_fs_file_close;
    fstream->istream.max_buffer_size = max_buffer_size;
    fstream->istream.read = i_stream_fs_file_read;
    fstream->istream.stream_size_passthrough = TRUE;

    fstream->istream.istream.blocking =
        ((*file)->flags & FS_OPEN_FLAG_ASYNC) == 0;
    fstream->istream.istream.seekable =
        ((*file)->flags & FS_OPEN_FLAG_SEEKABLE) != 0;

    input = i_stream_create(&fstream->istream, NULL, -1);
    i_stream_set_name(input, fs_file_path(*file));
    *file = NULL;
    return input;
}
Exemple #22
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;
}
Exemple #23
0
static int
openssl_iostream_create(struct ssl_iostream_context *ctx, const char *source,
                        const struct ssl_iostream_settings *set,
                        struct istream **input, struct ostream **output,
                        struct ssl_iostream **iostream_r)
{
    struct ssl_iostream *ssl_io;
    SSL *ssl;
    BIO *bio_int, *bio_ext;
    int ret;

    ssl = SSL_new(ctx->ssl_ctx);
    if (ssl == NULL) {
        i_error("SSL_new() failed: %s", openssl_iostream_error());
        return -1;
    }

    /* BIO pairs use default buffer sizes (17 kB in OpenSSL 0.9.8e).
       Each of the BIOs have one "write buffer". BIO_write() copies data
       to them, while BIO_read() reads from the other BIO's write buffer
       into the given buffer. The bio_int is used by OpenSSL and bio_ext
       is used by this library. */
    if (BIO_new_bio_pair(&bio_int, 0, &bio_ext, 0) != 1) {
        i_error("BIO_new_bio_pair() failed: %s",
                openssl_iostream_error());
        SSL_free(ssl);
        return -1;
    }

    ssl_io = i_new(struct ssl_iostream, 1);
    ssl_io->refcount = 1;
    ssl_io->ctx = ctx;
    ssl_io->ssl = ssl;
    ssl_io->bio_ext = bio_ext;
    ssl_io->plain_input = *input;
    ssl_io->plain_output = *output;
    ssl_io->source = i_strdup(source);
    /* bio_int will be freed by SSL_free() */
    SSL_set_bio(ssl_io->ssl, bio_int, bio_int);
    SSL_set_ex_data(ssl_io->ssl, dovecot_ssl_extdata_index, ssl_io);

    T_BEGIN {
        ret = openssl_iostream_set(ssl_io, set);
    } T_END;
    if (ret < 0) {
        openssl_iostream_free(ssl_io);
        return -1;
    }

    o_stream_uncork(ssl_io->plain_output);

    *input = openssl_i_stream_create_ssl(ssl_io);
    *output = openssl_o_stream_create_ssl(ssl_io);
    i_stream_set_name(*input, t_strconcat("SSL ",
                                          i_stream_get_name(ssl_io->plain_input), NULL));
    o_stream_set_name(*output, t_strconcat("SSL ",
                                           o_stream_get_name(ssl_io->plain_output), NULL));

    if (ssl_io->plain_output->real_stream->error_handling_disabled)
        o_stream_set_no_error_handling(*output, TRUE);

    ssl_io->ssl_output = *output;
    *iostream_r = ssl_io;
    return 0;
}
Exemple #24
0
static int
http_client_request_continue_payload(struct http_client_request **_req,
	const unsigned char *data, size_t size)
{
	struct ioloop *prev_ioloop = current_ioloop;
	struct http_client_request *req = *_req;
	struct http_client_connection *conn = req->conn;
	struct http_client *client = req->client;
	int ret;

	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
		req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
	i_assert(req->payload_input == NULL);

	if (conn != NULL)
		http_client_connection_ref(conn);
	http_client_request_ref(req);
	req->payload_wait = TRUE;

	if (data == NULL) {
		req->payload_input = NULL;
		if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT)
			http_client_request_finish_payload_out(req);
	} else { 
		req->payload_input = i_stream_create_from_data(data, size);
		i_stream_set_name(req->payload_input, "<HTTP request payload>");
	}
	req->payload_size = 0;
	req->payload_chunked = TRUE;

	if (req->state == HTTP_REQUEST_STATE_NEW)
		http_client_request_submit(req);

	/* Wait for payload data to be written */

	i_assert(client->ioloop == NULL);
	client->ioloop = io_loop_create();
	http_client_switch_ioloop(client);
	if (client->set.dns_client != NULL)
		dns_client_switch_ioloop(client->set.dns_client);

	while (req->state < HTTP_REQUEST_STATE_PAYLOAD_IN) {
		http_client_request_debug(req, "Waiting for request to finish");
		
		if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT)
			o_stream_set_flush_pending(req->payload_output, TRUE);
		io_loop_run(client->ioloop);

		if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT &&
			req->payload_input->eof) {
			i_stream_unref(&req->payload_input);
			req->payload_input = NULL;
			break;
		}
	}

	io_loop_set_current(prev_ioloop);
	http_client_switch_ioloop(client);
	if (client->set.dns_client != NULL)
		dns_client_switch_ioloop(client->set.dns_client);
	io_loop_set_current(client->ioloop);
	io_loop_destroy(&client->ioloop);

	switch (req->state) {
	case HTTP_REQUEST_STATE_PAYLOAD_IN:
	case HTTP_REQUEST_STATE_FINISHED:
		ret = 1;
		break;
	case HTTP_REQUEST_STATE_ABORTED:
		ret = -1;
		break;
	default:
		ret = 0;
		break;
	}

	req->payload_wait = FALSE;

	/* callback may have messed with our pointer,
	   so unref using local variable */	
	if (!http_client_request_unref(&req))
		*_req = NULL;

	if (conn != NULL)
		http_client_connection_unref(&conn);

	/* Return status */
	return ret;
}
struct client *client_create(int fd_in, int fd_out, const char *session_id,
			     struct mail_user *user,
			     struct mail_storage_service_user *service_user,
			     const struct imap_settings *set)
{
	const struct mail_storage_settings *mail_set;
	struct client *client;
	const char *ident;
	pool_t pool;
	bool explicit_capability = FALSE;

	/* always use nonblocking I/O */
	net_set_nonblock(fd_in, TRUE);
	net_set_nonblock(fd_out, TRUE);

	pool = pool_alloconly_create("imap client", 2048);
	client = p_new(pool, struct client, 1);
	client->pool = pool;
	client->v = imap_client_vfuncs;
	client->set = set;
	client->service_user = service_user;
	client->session_id = p_strdup(pool, session_id);
	client->fd_in = fd_in;
	client->fd_out = fd_out;
	client->input = i_stream_create_fd(fd_in,
					   set->imap_max_line_length, FALSE);
	client->output = o_stream_create_fd(fd_out, (size_t)-1, FALSE);
	o_stream_set_no_error_handling(client->output, TRUE);
	i_stream_set_name(client->input, "<imap client>");
	o_stream_set_name(client->output, "<imap client>");

	o_stream_set_flush_callback(client->output, client_output, client);

	p_array_init(&client->module_contexts, client->pool, 5);
	client->io = io_add_istream(client->input, client_input, client);
        client->last_input = ioloop_time;
	client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
				      client_idle_timeout, client);

	client->command_pool =
		pool_alloconly_create(MEMPOOL_GROWING"client command", 1024*2);
	client->user = user;
	client->notify_count_changes = TRUE;
	client->notify_flag_changes = TRUE;

	mail_namespaces_set_storage_callbacks(user->namespaces,
					      &mail_storage_callbacks, client);

	client->capability_string =
		str_new(client->pool, sizeof(CAPABILITY_STRING)+64);

	if (*set->imap_capability == '\0')
		str_append(client->capability_string, CAPABILITY_STRING);
	else if (*set->imap_capability != '+') {
		explicit_capability = TRUE;
		str_append(client->capability_string, set->imap_capability);
	} else {
		str_append(client->capability_string, CAPABILITY_STRING);
		str_append_c(client->capability_string, ' ');
		str_append(client->capability_string, set->imap_capability + 1);
	}
	if (user->fuzzy_search && !explicit_capability) {
		/* Enable FUZZY capability only when it actually has
		   a chance of working */
		str_append(client->capability_string, " SEARCH=FUZZY");
	}

	mail_set = mail_user_set_get_storage_set(user);
	if (mail_set->mailbox_list_index && !explicit_capability) {
		/* NOTIFY is enabled only when mailbox list indexes are
		   enabled, although even that doesn't necessarily guarantee
		   it always */
		str_append(client->capability_string, " NOTIFY");
	}

	if (*set->imap_urlauth_host != '\0' &&
	    *mail_set->mail_attribute_dict != '\0') {
		/* Enable URLAUTH capability only when dict is
		   configured correctly */
		client_init_urlauth(client);
		if (!explicit_capability)
			str_append(client->capability_string, " URLAUTH URLAUTH=BINARY");
	}
	if (set->imap_metadata && *mail_set->mail_attribute_dict != '\0') {
		client->imap_metadata_enabled = TRUE;
		if (!explicit_capability)
			str_append(client->capability_string, " METADATA");
	}
	if (!explicit_capability && user_has_special_use_mailboxes(user)) {
		/* Advertise SPECIAL-USE only if there are actually some
		   SPECIAL-USE flags in mailbox configuration. */
		str_append(client->capability_string, " SPECIAL-USE");
	}

	ident = mail_user_get_anvil_userip_ident(client->user);
	if (ident != NULL) {
		master_service_anvil_send(master_service, t_strconcat(
			"CONNECT\t", my_pid, "\timap/", ident, "\n", NULL));
		client->anvil_sent = TRUE;
	}

	imap_client_count++;
	DLLIST_PREPEND(&imap_clients, client);
	if (hook_client_created != NULL)
		hook_client_created(&client);

	imap_refresh_proctitle();
	return client;
}
Exemple #26
0
static int cmd_filter_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{	
	const struct sieve_extension *this_ext = renv->oprtn->ext;
	unsigned int is_test = 0;
	struct sieve_stringlist *args_list = NULL;
	enum sieve_error error = SIEVE_ERROR_NONE;
	string_t *pname = NULL;
	const char *program_name = NULL;
	const char *const *args = NULL;
	struct istream *newmsg = NULL;
	struct sieve_extprogram *sprog;
	int ret;

	/*
	 * Read operands
	 */

	/* The is_test flag */

	if ( !sieve_binary_read_byte(renv->sblock, address, &is_test) ) {
		sieve_runtime_trace_error(renv, "invalid is_test flag");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	/* Optional operands */	

	if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, NULL) != 0 ) 
		return ret;

	/* Fixed operands */

	if ( (ret=sieve_extprogram_command_read_operands
		(renv, address, &pname, &args_list)) <= 0 )
		return ret;

	program_name = str_c(pname);
	if ( args_list != NULL &&
		sieve_stringlist_read_all(args_list, pool_datastack_create(), &args) < 0 ) {
		sieve_runtime_trace_error(renv, "failed to read args operand");
		return args_list->exec_status;
	}

	/*
	 * Perform operation
	 */

	/* Trace */

	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "filter action");
	sieve_runtime_trace_descend(renv);
	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS,
		"execute program `%s'", str_sanitize(program_name, 128));

	sprog = sieve_extprogram_create
		(this_ext, renv->scriptenv, renv->msgdata, "filter", program_name, args,
			&error);

	if ( sprog != NULL ) {
		struct mail *mail = sieve_message_get_mail(renv->msgctx);

		if ( sieve_extprogram_set_input_mail(sprog, mail) < 0 ) {
			sieve_extprogram_destroy(&sprog);
			return sieve_runtime_mail_error(renv, mail,
				"filter action: failed to read input message");
		}
		sieve_extprogram_set_output_seekable(sprog);
		ret = sieve_extprogram_run(sprog);
	} else {
		ret = -1;
	}

	if ( ret > 0 )
		newmsg = sieve_extprogram_get_output_seekable(sprog);
	if ( sprog != NULL )
		sieve_extprogram_destroy(&sprog);

	if ( ret > 0 && newmsg != NULL ) {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"executed program successfully");

		i_stream_set_name(newmsg,
			t_strdup_printf("filter %s output", program_name));
		newmsg->blocking = TRUE;
		if ( (ret=sieve_message_substitute(renv->msgctx, newmsg)) >= 0 ) {
			sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
				"changed message");
		} else {
			sieve_runtime_critical(renv, NULL, "filter action",
				"filter action: failed to substitute message"); 
		}

		i_stream_unref(&newmsg);

	} else if ( ret < 0 ) {
		if ( error == SIEVE_ERROR_NOT_FOUND ) {
			sieve_runtime_error(renv, NULL,
				"filter action: program `%s' not found",
				str_sanitize(program_name, 80));
		} else {
			sieve_extprogram_exec_error(renv->ehandler,
				sieve_runtime_get_full_command_location(renv),
				"filter action: failed to execute to program `%s'",
				str_sanitize(program_name, 80));
		}

	} else {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"filter action: program indicated false result");
	}

	if ( is_test > 0 ) {
		sieve_interpreter_set_test_result(renv->interp, ( ret > 0 ));

		return SIEVE_EXEC_OK;
	}

	return ( ret >= 0 ? SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE );
}