Ejemplo n.º 1
0
int cmd_mail(struct client *client, const char *args)
{
	const char *addr, *const *argv;

	if (client->state.mail_from != NULL) {
		client_send_line(client, "503 5.5.1 MAIL already given");
		return 0;
	}

	if (strncasecmp(args, "FROM:", 5) != 0 ||
	    parse_address(args + 5, &addr, &args) < 0) {
		client_send_line(client, "501 5.5.4 Invalid parameters");
		return 0;
	}

	argv = t_strsplit(args, " ");
	for (; *argv != NULL; argv++) {
		if (strcasecmp(*argv, "BODY=7BIT") == 0)
			client->state.mail_body_7bit = TRUE;
		else if (strcasecmp(*argv, "BODY=8BITMIME") == 0)
			client->state.mail_body_8bitmime = TRUE;
		else {
			client_send_line(client,
				"501 5.5.4 Unsupported options");
			return 0;
		}
	}

	client->state.mail_from = p_strdup(client->state_pool, addr);
	p_array_init(&client->state.rcpt_to, client->state_pool, 64);
	client_send_line(client, "250 2.1.0 OK");
	client_state_set(client, "MAIL FROM");
	return 0;
}
Ejemplo n.º 2
0
void client_cmd_starttls(struct client *client)
{
	if (client->tls) {
		client_send_line(client, CLIENT_CMD_REPLY_BAD,
				 "TLS is already active.");
		return;
	}

	if (!ssl_initialized) {
		client_send_line(client, CLIENT_CMD_REPLY_BAD,
				 "TLS support isn't enabled.");
		return;
	}

	/* remove input handler, SSL proxy gives us a new fd. we also have to
	   remove it in case we have to wait for buffer to be flushed */
	if (client->io != NULL)
		io_remove(&client->io);

	client_send_line(client, CLIENT_CMD_REPLY_OK,
			 "Begin TLS negotiation now.");

	/* uncork the old fd */
	o_stream_uncork(client->output);

	if (o_stream_flush(client->output) <= 0) {
		/* the buffer has to be flushed */
		o_stream_set_flush_pending(client->output, TRUE);
		o_stream_set_flush_callback(client->output,
					    client_output_starttls, client);
	} else {
		client_start_tls(client);
	}
}
Ejemplo n.º 3
0
static const char *get_size(struct client *client, const char *args,
			    uoff_t *size)
{
	uoff_t num, last_num;

	num = 0;
	while (*args != '\0' && *args != ' ') {
		if (*args < '0' || *args > '9') {
			client_send_line(client, "-ERR Invalid size: %s",
					 args);
			return NULL;
		}

		last_num = num;
		num = num*10 + (*args - '0');
		if (num < last_num) {
			client_send_line(client, "-ERR Size too large: %s",
					 args);
			return NULL;
		}
		args++;
	}

	while (*args == ' ') args++;

	*size = num;
	return args;
}
Ejemplo n.º 4
0
static void client_start_tls(struct client *client)
{
	int fd_ssl;

	client_ref(client);
	if (!client_unref(&client) || client->destroyed)
		return;

	fd_ssl = ssl_proxy_alloc(client->fd, &client->ip,
				 client->set, &client->ssl_proxy);
	if (fd_ssl == -1) {
		client_send_line(client, CLIENT_CMD_REPLY_BYE,
				 "TLS initialization failed.");
		client_destroy(client,
			       "Disconnected: TLS initialization failed.");
		return;
	}
	ssl_proxy_set_client(client->ssl_proxy, client);
	ssl_proxy_start(client->ssl_proxy);

	client->starttls = TRUE;
	client->tls = TRUE;
	client->secured = TRUE;
	login_refresh_proctitle();

	client->fd = fd_ssl;
	client->io = io_add(client->fd, IO_READ, client_input, client);
	i_stream_unref(&client->input);
	o_stream_unref(&client->output);
	client_open_streams(client);

	client->v.starttls(client);
}
Ejemplo n.º 5
0
static bool cmd_getquotaroot(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct quota_user *quser = QUOTA_USER_CONTEXT(client->user);
	struct mail_namespace *ns;
	struct mailbox *box;
	struct quota_root_iter *iter;
        struct quota_root *root;
	const char *mailbox, *storage_name, *name;
	string_t *quotaroot_reply, *quota_reply;

	/* <mailbox> */
	if (!client_read_string_args(cmd, 1, &mailbox))
		return FALSE;

	ns = client_find_namespace(cmd, mailbox, &storage_name, NULL);
	if (ns == NULL)
		return TRUE;

	if (quser == NULL) {
		client_send_tagline(cmd, "OK No quota.");
		return TRUE;
	}
	if (ns->owner != NULL && ns->owner != client->user &&
	    !client->user->admin) {
		client_send_tagline(cmd, "NO Not showing other users' quota.");
		return TRUE;
	}

	box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_READONLY |
			    MAILBOX_FLAG_KEEP_RECENT);

	/* build QUOTAROOT reply and QUOTA reply for all quota roots */
	quotaroot_reply = t_str_new(128);
	quota_reply = t_str_new(256);
	str_append(quotaroot_reply, "* QUOTAROOT ");
	imap_quote_append_string(quotaroot_reply, mailbox, FALSE);

	iter = quota_root_iter_init(box);
	while ((root = quota_root_iter_next(iter)) != NULL) {
		str_append_c(quotaroot_reply, ' ');
		name = imap_quota_root_get_name(client->user, ns->owner, root);
		imap_quote_append_string(quotaroot_reply, name, FALSE);

		quota_reply_write(quota_reply, client->user, ns->owner, root);
	}
	quota_root_iter_deinit(&iter);
	mailbox_free(&box);

	/* send replies */
	if (str_len(quota_reply) == 0)
		client_send_tagline(cmd, "OK No quota.");
	else {
		client_send_line(client, str_c(quotaroot_reply));
		o_stream_send(client->output, str_data(quota_reply),
			      str_len(quota_reply));
		client_send_tagline(cmd, "OK Getquotaroot completed.");
	}
	return TRUE;
}
Ejemplo n.º 6
0
static int
lmtp_rcpt_to_is_over_quota(struct client *client,
			   const struct mail_recipient *rcpt)
{
	struct mail_user *user;
	struct mail_namespace *ns;
	struct mailbox *box;
	struct mailbox_status status;
	const char *errstr;
	enum mail_error error;
	int ret;

	if (!client->lmtp_set->lmtp_rcpt_check_quota)
		return 0;

	ret = mail_storage_service_next(storage_service,
					rcpt->service_user, &user);
	if (ret < 0)
		return -1;

	ns = mail_namespace_find_inbox(user->namespaces);
	box = mailbox_alloc(ns->list, "INBOX", 0);
	ret = mailbox_get_status(box, STATUS_CHECK_OVER_QUOTA, &status);
	if (ret < 0) {
		errstr = mailbox_get_last_error(box, &error);
		if (error == MAIL_ERROR_NOSPACE) {
			client_send_line(client, "552 5.2.2 <%s> %s",
					 rcpt->address, errstr);
			ret = 1;
		}
	}
	mailbox_free(&box);
	mail_user_unref(&user);
	return ret;
}
Ejemplo n.º 7
0
bool cmd_idle(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_idle_context *ctx;

	ctx = p_new(cmd->pool, struct cmd_idle_context, 1);
	ctx->cmd = cmd;
	ctx->client = client;
	idle_add_keepalive_timeout(ctx);
	idle_add_hibernate_timeout(ctx);

	if (client->mailbox != NULL)
		mailbox_notify_changes(client->mailbox, idle_callback, ctx);
	if (!client->state_import_idle_continue)
		client_send_line(client, "+ idling");
	else {
		/* continuing an IDLE after hibernation */
		client->state_import_idle_continue = FALSE;
	}

	io_remove(&client->io);
	client->io = io_add_istream(client->input, idle_client_input, ctx);

	cmd->func = cmd_idle_continue;
	cmd->context = ctx;

	/* check immediately if there are changes. if they came before we
	   added mailbox-notifier, we wouldn't see them otherwise. */
	if (client->mailbox != NULL)
		idle_sync_now(client->mailbox, ctx);
	return idle_client_handle_input(ctx, FALSE);
}
Ejemplo n.º 8
0
bool cmd_idle(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_idle_context *ctx;

	ctx = p_new(cmd->pool, struct cmd_idle_context, 1);
	ctx->cmd = cmd;
	ctx->client = client;
	idle_add_keepalive_timeout(ctx);

	if (client->mailbox != NULL)
		mailbox_notify_changes(client->mailbox, idle_callback, ctx);
	client_send_line(client, "+ idling");

	io_remove(&client->io);
	client->io = io_add(i_stream_get_fd(client->input),
			    IO_READ, idle_client_input, ctx);

	cmd->func = cmd_idle_continue;
	cmd->context = ctx;

	/* check immediately if there are changes. if they came before we
	   added mailbox-notifier, we wouldn't see them otherwise. */
	if (client->mailbox != NULL)
		idle_sync_now(client->mailbox, ctx);
	return idle_client_handle_input(ctx, FALSE);
}
Ejemplo n.º 9
0
bool cmd_x_state(struct client_command_context *cmd)
{
	/* FIXME: state importing can cause unnecessarily large memory usage
	   by specifying an old modseq, because the EXPUNGE/FETCH replies
	   aren't currently sent asynchronously. so this command is disabled
	   for now. */
#if 0
	const struct imap_arg *args;
	const char *str, *error;
	buffer_t *state, *state_encoded;
	int ret;

	if (!client_read_args(cmd, 0, 0, &args))
		return FALSE;

	state = buffer_create_dynamic(cmd->pool, 256);
	if (imap_arg_get_astring(&args[0], &str)) {
		if (cmd->client->mailbox != NULL) {
			client_send_tagline(cmd,
				"BAD Can't be used in SELECTED state");
			return TRUE;
		}
		if (base64_decode(str, strlen(str), NULL, state) < 0)
			ret = 0;
		else {
			ret = imap_state_import_external(cmd->client,
				state->data, state->used, &error);
		}
		if (ret < 0) {
			client_send_tagline(cmd, t_strdup_printf(
				"NO Failed to restore state: %s", error));
		} else if (ret == 0) {
			client_send_tagline(cmd, t_strdup_printf(
				"BAD Broken state: %s", error));
		} else {
			client_send_tagline(cmd, "OK State imported.");
		}
		return TRUE;
	} else if (args[0].type == IMAP_ARG_EOL) {
		if (!imap_state_export_external(cmd->client, state, &error)) {
			client_send_tagline(cmd, t_strdup_printf(
				"NO Can't save state: %s", error));
			return TRUE;
		}
		state_encoded = buffer_create_dynamic(cmd->pool,
				MAX_BASE64_ENCODED_SIZE(state->used)+10);
		str_append(state_encoded, "* STATE ");
		base64_encode(state->data, state->used, state_encoded);
		client_send_line(cmd->client, str_c(state_encoded));
		client_send_tagline(cmd, "OK State exported.");
		return TRUE;
	} else {
		client_send_command_error(cmd, "Invalid arguments.");
		return TRUE;
	}
#else
	client_send_command_error(cmd, "Command is disabled for now.");
	return TRUE;
#endif
}
Ejemplo n.º 10
0
bool cmd_enable(struct client_command_context *cmd)
{
	const struct imap_arg *args;
	const char *str;
	string_t *reply;

	if (!client_read_args(cmd, 0, 0, &args))
		return FALSE;

	reply = t_str_new(64);
	str_append(reply, "* ENABLED");
	for (; !IMAP_ARG_IS_EOL(args); args++) {
		if (!imap_arg_get_atom(args, &str)) {
			client_send_command_error(cmd, "Invalid arguments.");
			return TRUE;
		}
		str = t_str_ucase(str);
		if (strcmp(str, "CONDSTORE") == 0) {
			client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE);
			str_append(reply, " CONDSTORE");
		}
		else if (strcmp(str, "QRESYNC") == 0) {
			client_enable(cmd->client, MAILBOX_FEATURE_QRESYNC |
				      MAILBOX_FEATURE_CONDSTORE);
			str_append(reply, " QRESYNC");
		}
	}
	if (str_len(reply) > 9)
		client_send_line(cmd->client, str_c(reply));
	client_send_tagline(cmd, "OK Enabled.");
	return TRUE;
}
Ejemplo n.º 11
0
int client_enable(struct client *client, enum mailbox_feature features)
{
	struct mailbox_status status;
	int ret;

	if ((client->enabled_features & features) == features)
		return 0;

	client->enabled_features |= features;
	if (client->mailbox == NULL)
		return 0;

	ret = mailbox_enable(client->mailbox, features);
	if ((features & MAILBOX_FEATURE_CONDSTORE) != 0 && ret == 0) {
		/* CONDSTORE being enabled while mailbox is selected.
		   Notify client of the latest HIGHESTMODSEQ. */
		ret = mailbox_get_status(client->mailbox,
					 STATUS_HIGHESTMODSEQ, &status);
		if (ret == 0) {
			client_send_line(client, t_strdup_printf(
				"* OK [HIGHESTMODSEQ %llu] Highest",
				(unsigned long long)status.highest_modseq));
		}
	}
	if (ret < 0) {
		client_send_untagged_storage_error(client,
			mailbox_get_storage(client->mailbox));
	}
	return ret;
}
Ejemplo n.º 12
0
bool cmd_capability(struct client_command_context *cmd)
{
	client_send_line(cmd->client, t_strconcat(
		"* CAPABILITY ", str_c(cmd->client->capability_string), NULL));

	client_send_tagline(cmd, "OK Capability completed.");
	return TRUE;
}
Ejemplo n.º 13
0
static void client_kill_idle(struct client *client)
{
	if (client->output_cmd_lock != NULL)
		return;

	client_send_line(client, "* BYE Server shutting down.");
	client_destroy(client, "Server shutting down.");
}
Ejemplo n.º 14
0
void clients_destroy_all(struct mail_storage_service_ctx *storage_service)
{
	while (imap_clients != NULL) {
		client_send_line(imap_clients, "* BYE Server shutting down.");
		mail_storage_service_io_activate_user(imap_clients->service_user);
		client_destroy(imap_clients, "Server shutting down.");
	}
	mail_storage_service_io_deactivate(storage_service);
}
Ejemplo n.º 15
0
void client_destroy_internal_failure(struct client *client)
{
	client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
			 "Internal login failure. "
			 "Refer to server log for more information.");
	client_destroy(client, t_strdup_printf(
		"Internal login failure (pid=%s id=%u)",
		my_pid, client->master_auth_id));
}
Ejemplo n.º 16
0
static void client_idle_timeout(struct client *client)
{
	if (client->cmd != NULL) {
		client_destroy(client,
			"Disconnected for inactivity in reading our output");
	} else {
		client_send_line(client, "-ERR Disconnected for inactivity.");
		client_destroy(client, "Disconnected for inactivity");
	}
}
Ejemplo n.º 17
0
void client_send_mailbox_flags(struct client *client, bool selecting)
{
	struct mailbox_status status;
	unsigned int count = array_count(client->keywords.names);
	const char *const *keywords;
	string_t *str;

	if (!selecting && count == client->keywords.announce_count) {
		/* no changes to keywords and we're not selecting a mailbox */
		return;
	}

	client->keywords.announce_count = count;
	mailbox_get_open_status(client->mailbox, STATUS_PERMANENT_FLAGS,
				&status);

	keywords = count == 0 ? NULL :
		array_idx(client->keywords.names, 0);
	str = t_str_new(128);
	str_append(str, "* FLAGS (");
	imap_write_flags(str, MAIL_FLAGS_NONRECENT, keywords);
	str_append_c(str, ')');
	client_send_line(client, str_c(str));

	if (!status.permanent_keywords)
		keywords = NULL;

	str_truncate(str, 0);
	str_append(str, "* OK [PERMANENTFLAGS (");
	imap_write_flags(str, status.permanent_flags, keywords);
	if (status.allow_new_keywords) {
		if (status.permanent_flags != 0 || keywords != NULL)
			str_append_c(str, ' ');
		str_append(str, "\\*");
	}
	str_append(str, ")] ");

	if (mailbox_is_readonly(client->mailbox))
		str_append(str, "Read-only mailbox.");
	else
		str_append(str, "Flags permitted.");
	client_send_line(client, str_c(str));
}
Ejemplo n.º 18
0
static void
client_send_line_overquota(struct client *client,
			   const struct mail_recipient *rcpt, const char *error)
{
	struct lda_settings *lda_set =
		mail_storage_service_user_get_set(rcpt->service_user)[1];

	client_send_line(client, "%s <%s> %s", lda_set->quota_full_tempfail ?
			 "452 4.2.2" : "552 5.2.2", rcpt->address, error);
}
Ejemplo n.º 19
0
static const char *get_msgnum(struct client *client, const char *args,
			      unsigned int *msgnum)
{
	unsigned int num, last_num;

	num = 0;
	while (*args != '\0' && *args != ' ') {
		if (*args < '0' || *args > '9') {
			client_send_line(client,
				"-ERR Invalid message number: %s", args);
			return NULL;
		}

		last_num = num;
		num = num*10 + (*args - '0');
		if (num < last_num) {
			client_send_line(client,
				"-ERR Message number too large: %s", args);
			return NULL;
		}
		args++;
	}

	if (num == 0 || num > client->messages_count) {
		client_send_line(client,
				 "-ERR There's no message %u.", num);
		return NULL;
	}
	num--;

	if (client->deleted) {
		if (client->deleted_bitmask[num / CHAR_BIT] &
		    (1 << (num % CHAR_BIT))) {
			client_send_line(client, "-ERR Message is deleted.");
			return NULL;
		}
	}

	while (*args == ' ') args++;

	*msgnum = num;
	return args;
}
Ejemplo n.º 20
0
static void client_add_input(struct client *client, const buffer_t *buf)
{
	struct ostream *output;
	struct client_input input;

	if (buf != NULL && buf->used > 0) {
		client_parse_input(buf->data, buf->used, &input);
		if (input.input_size > 0 &&
		    !i_stream_add_data(client->input, input.input,
				       input.input_size))
			i_panic("Couldn't add client input to stream");
	} else {
		/* IMAPLOGINTAG environment is compatible with mailfront */
		memset(&input, 0, sizeof(input));
		input.tag = getenv("IMAPLOGINTAG");
	}

	output = client->output;
	o_stream_ref(output);
	o_stream_cork(output);
	if (input.tag == NULL) {
		client_send_line(client, t_strconcat(
			"* PREAUTH [CAPABILITY ",
			str_c(client->capability_string), "] "
			"Logged in as ", client->user->username, NULL));
	} else if (input.send_untagged_capability) {
		/* client doesn't seem to understand tagged capabilities. send
		   untagged instead and hope that it works. */
		client_send_line(client, t_strconcat("* CAPABILITY ",
			str_c(client->capability_string), NULL));
		client_send_line(client,
				 t_strconcat(input.tag, " OK Logged in", NULL));
	} else {
		client_send_line(client, t_strconcat(
			input.tag, " OK [CAPABILITY ",
			str_c(client->capability_string), "] Logged in", NULL));
	}
	(void)client_handle_input(client);
	o_stream_uncork(output);
	o_stream_unref(&output);
}
Ejemplo n.º 21
0
bool cmd_getscript(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_getscript_context *ctx;
	const char *scriptname;
	enum sieve_error error;

	/* <scriptname> */
	if ( !client_read_string_args(cmd, TRUE, 1, &scriptname) )
		return FALSE;

	ctx = p_new(cmd->pool, struct cmd_getscript_context, 1);
	ctx->cmd = cmd;
	ctx->client = client;
	ctx->storage = client->storage;
	ctx->failed = FALSE;

	ctx->script = sieve_storage_open_script
		(client->storage, scriptname, NULL);
	if (ctx->script == NULL) {
		ctx->failed = TRUE;
		return cmd_getscript_finish(ctx);
	}

	if ( sieve_script_get_stream
		(ctx->script, &ctx->script_stream, &error) < 0 ) {
		if ( error == SIEVE_ERROR_NOT_FOUND )
			sieve_storage_set_error(client->storage, error, "Script does not exist.");
		ctx->failed = TRUE;
		return cmd_getscript_finish(ctx);
	}

	if ( sieve_script_get_size(ctx->script, &ctx->script_size) <= 0 ) {
		sieve_storage_set_critical(ctx->storage,
			"failed to obtain script size for script `%s' from %s",
			sieve_script_name(ctx->script), sieve_script_location(ctx->script));
		ctx->failed = TRUE;
		return cmd_getscript_finish(ctx);
	}

	i_assert(ctx->script_stream->v_offset == 0);

	client_send_line
		(client, t_strdup_printf("{%"PRIuUOFF_T"}", ctx->script_size));

	client->command_pending = TRUE;
	cmd->func = cmd_getscript_continue;
	cmd->context = ctx;

	return cmd_getscript_continue(cmd);
}
Ejemplo n.º 22
0
void client_send_untagged_storage_error(struct client *client,
					struct mail_storage *storage)
{
	const char *error_string;
	enum mail_error error;

	error_string = mail_storage_get_last_error(storage, &error);
	client_send_line(client, t_strconcat("* NO ", error_string, NULL));

	if (client->mailbox != NULL &&
	    mailbox_is_inconsistent(client->mailbox)) {
		/* we can't do forced CLOSE, so have to disconnect */
		client_disconnect_with_error(client,
			"IMAP session state is inconsistent, please relogin.");
	}
}
Ejemplo n.º 23
0
bool cmd_genurlauth(struct client_command_context *cmd)
{
	const struct imap_arg *args;
	string_t *response;
	int ret;

	if (cmd->client->urlauth_ctx == NULL) {
		client_send_command_error(cmd, "URLAUTH disabled.");
		return TRUE;
	}

	if (!client_read_args(cmd, 0, 0, &args))
		return FALSE;

	response = t_str_new(1024);
	str_append(response, "* GENURLAUTH");
	for (;;) {
		const char *url_rump, *mechanism, *url, *error;

		if (IMAP_ARG_IS_EOL(args))
			break;
		if (!imap_arg_get_astring(args++, &url_rump) ||
		    !imap_arg_get_atom(args++, &mechanism)) {
			client_send_command_error(cmd, "Invalid arguments.");
			return FALSE;
		}

		ret = imap_urlauth_generate(cmd->client->urlauth_ctx,
					    mechanism, url_rump, &url, &error);
		if (ret <= 0) {
			if (ret < 0)
				client_send_internal_error(cmd);
			else
				client_send_command_error(cmd, error);
			return TRUE;
		}

		str_append_c(response, ' ');
		imap_append_astring(response, url);
	}

	client_send_line(cmd->client, str_c(response));
	client_send_tagline(cmd, "OK GENURLAUTH completed.");
	return TRUE;
}
Ejemplo n.º 24
0
static void client_add_input(struct client *client, const buffer_t *buf)
{
	struct ostream *output;

	if (buf != NULL && buf->used > 0) {
		if (!i_stream_add_data(client->input, buf->data, buf->used))
			i_panic("Couldn't add client input to stream");
	}

	output = client->output;
	o_stream_ref(output);
	o_stream_cork(output);
	if (!IS_STANDALONE())
		client_send_line(client, "+OK Logged in.");
	(void)client_handle_input(client);
	o_stream_uncork(output);
	o_stream_unref(&output);
}
Ejemplo n.º 25
0
bool cmd_getscript(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_getscript_context *ctx;
	const char *scriptname;
	enum sieve_error error;

	/* <scriptname> */
	if ( !client_read_string_args(cmd, 1, TRUE, &scriptname) )
		return FALSE;

	ctx = p_new(cmd->pool, struct cmd_getscript_context, 1);
	ctx->cmd = cmd;
	ctx->client = client;
	ctx->storage = client->storage;
	ctx->failed = FALSE;
	ctx->script = sieve_storage_script_init(client->storage, scriptname);

	if (ctx->script == NULL) {
		ctx->failed = TRUE;
		return cmd_getscript_finish(ctx);
	}
			
	ctx->script_stream = sieve_script_open(ctx->script, &error);

	if ( ctx->script_stream == NULL ) {
		ctx->failed = TRUE;
		if ( error == SIEVE_ERROR_NOT_FOUND )
			sieve_storage_set_error(client->storage, error, "Script does not exist.");		
		return cmd_getscript_finish(ctx);
	}

	ctx->script_size = sieve_script_get_size(ctx->script);
	ctx->script_offset = 0;	

	client_send_line
		(client, t_strdup_printf("{%"PRIuUOFF_T"}", ctx->script_size));

	client->command_pending = TRUE;
	cmd->func = cmd_getscript_continue;
	cmd->context = ctx;

	return cmd_getscript_continue(cmd);
}
Ejemplo n.º 26
0
int cmd_lhlo(struct client *client, const char *args)
{
	struct rfc822_parser_context parser;
	string_t *domain = t_str_new(128);
	const char *p;
	int ret = 0;

	if (*args == '\0') {
		client_send_line(client, "501 Missing hostname");
		return 0;
	}

	/* domain / address-literal */
	rfc822_parser_init(&parser, (const unsigned char *)args, strlen(args),
			   NULL);
	if (*args != '[')
		ret = rfc822_parse_dot_atom(&parser, domain);
	else {
		for (p = args+1; *p != ']'; p++) {
			if (*p == '\\' || *p == '[')
				break;
		}
		if (strcmp(p, "]") != 0)
			ret = -1;
	}
	if (ret < 0) {
		str_truncate(domain, 0);
		str_append(domain, "invalid");
	}

	client_state_reset(client, "LHLO");
	client_send_line(client, "250-%s", client->my_domain);
	if (master_service_ssl_is_enabled(master_service) &&
	    client->ssl_iostream == NULL)
		client_send_line(client, "250-STARTTLS");
	if (client_is_trusted(client))
		client_send_line(client, "250-XCLIENT ADDR PORT TTL TIMEOUT");
	client_send_line(client, "250-8BITMIME");
	client_send_line(client, "250-ENHANCEDSTATUSCODES");
	client_send_line(client, "250 PIPELINING");

	i_free(client->lhlo);
	client->lhlo = i_strdup(str_c(domain));
	client_state_set(client, "LHLO", "");
	return 0;
}
Ejemplo n.º 27
0
bool cmd_listscripts(struct client_command_context *cmd)
{
    struct client *client = cmd->client;
    struct sieve_storage_list_context *ctx;
    const char *scriptname;
    bool active;
    string_t *str;

    /* no arguments */
    if ( !client_read_no_args(cmd) )
        return FALSE;

    if ( (ctx = sieve_storage_list_init(client->storage))
            == NULL ) {
        client_send_storage_error(client, client->storage);
        return TRUE;
    }

    /* FIXME: This will be quite slow for large script lists. Implement
     * some buffering to fix this. Wont truely be an issue with managesieve
     * though.
     */
    while ((scriptname = sieve_storage_list_next(ctx, &active)) != NULL) {
        T_BEGIN {
            str = t_str_new(128);

            managesieve_quote_append_string(str, scriptname, FALSE);

            if ( active )
                str_append(str, " ACTIVE");

            client_send_line(client, str_c(str));
        } T_END;
    }

    if ( sieve_storage_list_deinit(&ctx) < 0 ) {
        client_send_storage_error(client, client->storage);
        return TRUE;
    }

    client_send_ok(client, "Listscripts completed.");
    return TRUE;
}
Ejemplo n.º 28
0
bool cmd_namespace(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	string_t *str;

	str = t_str_new(256);
	str_append(str, "* NAMESPACE ");

	list_namespaces(client->user->namespaces,
			MAIL_NAMESPACE_TYPE_PRIVATE, str);
	str_append_c(str, ' ');
	list_namespaces(client->user->namespaces,
			MAIL_NAMESPACE_TYPE_SHARED, str);
	str_append_c(str, ' ');
	list_namespaces(client->user->namespaces,
			MAIL_NAMESPACE_TYPE_PUBLIC, str);

	client_send_line(client, str_c(str));
	client_send_tagline(cmd, "OK Namespace completed.");
	return TRUE;
}
Ejemplo n.º 29
0
static bool cmd_getscript_finish(struct cmd_getscript_context *ctx)
{
	struct client *client = ctx->client;

	if ( ctx->script != NULL )
		sieve_script_unref(&ctx->script);

	if ( ctx->failed ) {
		if ( client->output->closed ) {
			client_disconnect(client, "Disconnected");
			return TRUE;
		}

		client_send_storage_error(client, client->storage);
		return TRUE;
	}

	client_send_line(client, "");
	client_send_ok(client, "Getscript completed.");
	return TRUE;
}
Ejemplo n.º 30
0
static int
client_create_from_input(const struct mail_storage_service_input *input,
			 int fd_in, int fd_out, const buffer_t *input_buf,
			 const char **error_r)
{
	const char *lookup_error_str =
		"-ERR [SYS/TEMP] "MAIL_ERRSTR_CRITICAL_MSG"\r\n";
	struct mail_storage_service_user *user;
	struct mail_user *mail_user;
	struct client *client;
	const struct pop3_settings *set;
	const char *error;

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

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

	if (client_create(fd_in, fd_out, input->session_id,
			  mail_user, user, set, &client) < 0)
		return 0;
	if (!IS_STANDALONE())
		client_send_line(client, "+OK Logged in.");
	if (client_init_mailbox(client, &error) == 0)
		client_add_input(client, input_buf);
	else {
		i_error("%s", error);
		client_destroy(client, error);
	}
	return 0;
}