static bool
auth_client_handle_line(struct auth_client_connection *conn, const char *line)
{
	if (strncmp(line, "AUTH\t", 5) == 0) {
		if (conn->auth->set->debug) {
			i_debug("client in: %s",
				auth_line_hide_pass(conn, line));
		}
		return auth_request_handler_auth_begin(conn->request_handler,
						       line + 5);
	}
	if (strncmp(line, "CONT\t", 5) == 0) {
		if (conn->auth->set->debug) {
			i_debug("client in: %s",
				cont_line_hide_pass(conn, line));
		}
		return auth_request_handler_auth_continue(conn->request_handler,
							  line + 5);
	}
	if (strncmp(line, "CANCEL\t", 7) == 0) {
		if (conn->auth->set->debug)
			i_debug("client in: %s", line);
		return auth_client_cancel(conn, line + 7);
	}

	i_error("BUG: Authentication client sent unknown command: %s",
		str_sanitize(line, 80));
	return FALSE;
}
Esempio n. 2
0
void test_str_sanitize(void)
{
	static struct str_sanitize_test tests[] = {
		{ NULL,    2, NULL },
		{ "",      2, NULL },
		{ "a",     2, NULL },
		{ "ab",    2, NULL },
		{ "abc",   2, "..." },
		{ "abcd",  3, "..." },
		{ "abcde", 4, "a..." },
		{ "с",    10, NULL },
		{ "с",     1, NULL },
		{ "\001x\x1fy\x81", 10, "?x?y?" }
	};
	const char *str;
	unsigned int i;

	test_begin("str_sanitize");
	for (i = 0; i < N_ELEMENTS(tests); i++) {
		str = str_sanitize(tests[i].str, tests[i].max_len);
		if (tests[i].sanitized != NULL)
			test_assert_idx(null_strcmp(str, tests[i].sanitized) == 0, i);
		else
			test_assert_idx(str == tests[i].str, i);
	}
	test_end();
}
Esempio n. 3
0
const char *CUnpacker::GetString(int SanitizeType)
{
	if(m_Error)
		return "";

	if(m_pCurrent >= m_pEnd)
	{
		m_Error = 1;
		return "";
	}

	char *pPtr = (char *)m_pCurrent;
	while(*m_pCurrent) // skip the string
	{
		m_pCurrent++;
		if(m_pCurrent == m_pEnd)
		{
			m_Error = 1;
			return "";
		}
	}
	m_pCurrent++;

	// sanitize all strings
	if(SanitizeType&SANITIZE)
		str_sanitize(pPtr);
	else if(SanitizeType&SANITIZE_CC)
		str_sanitize_cc(pPtr);
	return SanitizeType&SKIP_START_WHITESPACES ? str_utf8_skip_whitespaces(pPtr) : pPtr;
}
Esempio n. 4
0
static int cmd_error_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	string_t *message;
	int ret;

	/*
	 * Read operands
	 */

	/* Read message */

	if ( (ret=sieve_opr_string_read(renv, address, "message", &message)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "error \"%s\"",
		str_sanitize(str_c(message), 80));

	sieve_runtime_error(renv, NULL, "%s", str_c(message));

	return SIEVE_EXEC_FAILURE;
}
Esempio n. 5
0
static bool cmd_fileinto_validate
(struct sieve_validator *valdtr, struct sieve_command *cmd)
{
	struct sieve_ast_argument *arg = cmd->first_positional;

	if ( !sieve_validate_positional_argument
		(valdtr, cmd, arg, "folder", 1, SAAT_STRING) ) {
		return FALSE;
	}

	if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) )
		return FALSE;

	/* Check name validity when folder argument is not a variable */
	if ( sieve_argument_is_string_literal(arg) ) {
		const char *folder = sieve_ast_argument_strc(arg), *error;

		if ( !sieve_mailbox_check_name(folder, &error) ) {
			sieve_command_validate_error(valdtr, cmd,
				"invalid folder name `%s' specified for fileinto command: %s",
				str_sanitize(folder, 256), error);
			return FALSE;
		}
	}

	return TRUE;
}
Esempio n. 6
0
static const struct sieve_enotify_method *ext_enotify_get_method
(const struct sieve_runtime_env *renv, string_t *method_uri,
	const char **uri_body_r)
{
	const struct sieve_extension *this_ext = renv->oprtn->ext;
	const struct sieve_enotify_method *method;
	const char *uri = str_c(method_uri);
	const char *scheme;

	/* Parse part before ':' of the uri (the scheme) and use it to identify
	 * notify method.
	 */
	if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL ) {
		sieve_runtime_error(renv, NULL,
			"invalid scheme part for method URI '%s'",
			str_sanitize(str_c(method_uri), 80));
		return NULL;
	}

	/* Find the notify method */
	if ( (method=ext_enotify_method_find(this_ext, scheme)) == NULL ) {
		sieve_runtime_error(renv, NULL,
			"invalid notify method '%s'", scheme);
		return NULL;
	}

	/* Return the parse pointer and the found method */
	*uri_body_r = uri;
	return method;
}
Esempio n. 7
0
static const struct var_expand_table *
get_var_expand_table(struct mail *mail, const char *reason,
		     const char *recipient)
{
	static struct var_expand_table static_tab[] = {
		{ 'n', NULL, "crlf" },
		{ 'r', NULL, "reason" },
		{ 's', NULL, "subject" },
		{ 't', NULL, "to" },
		{ '\0', NULL, NULL }
	};
	struct var_expand_table *tab;
	const char *subject;

	tab = t_malloc(sizeof(static_tab));
	memcpy(tab, static_tab, sizeof(static_tab));

	tab[0].value = "\r\n";
	tab[1].value = reason;
	if (mail_get_first_header(mail, "Subject", &subject) <= 0)
		subject = "";
	tab[2].value = str_sanitize(subject, 80);
	tab[3].value = recipient;

	return tab;
}
Esempio n. 8
0
static const struct var_expand_table *
get_var_expand_table(struct client *client)
{
	struct var_expand_table *tab;

	tab = t_malloc(sizeof(login_var_expand_empty_tab));
	memcpy(tab, login_var_expand_empty_tab,
	       sizeof(login_var_expand_empty_tab));

	if (client->virtual_user != NULL)
		get_var_expand_users(tab, client->virtual_user);
	tab[3].value = login_binary->protocol;
	tab[4].value = getenv("HOME");
	tab[5].value = net_ip2addr(&client->local_ip);
	tab[6].value = net_ip2addr(&client->ip);
	tab[7].value = my_pid;
	tab[8].value = client->auth_mech_name == NULL ? NULL :
		str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
	tab[9].value = dec2str(client->local_port);
	tab[10].value = dec2str(client->remote_port);
	if (!client->tls) {
		tab[11].value = client->secured ? "secured" : NULL;
		tab[12].value = "";
	} else {
		const char *ssl_state =
			ssl_proxy_is_handshaked(client->ssl_proxy) ?
			"TLS" : "TLS handshaking";
		const char *ssl_error =
			ssl_proxy_get_last_error(client->ssl_proxy);

		tab[11].value = ssl_error == NULL ? ssl_state :
			t_strdup_printf("%s: %s", ssl_state, ssl_error);
		tab[12].value =
			ssl_proxy_get_security_string(client->ssl_proxy);
	}
	tab[13].value = client->mail_pid == 0 ? "" :
		dec2str(client->mail_pid);
	tab[14].value = client_get_session_id(client);
	tab[15].value = net_ip2addr(&client->real_local_ip);
	tab[16].value = net_ip2addr(&client->real_remote_ip);
	tab[17].value = dec2str(client->real_local_port);
	tab[18].value = dec2str(client->real_remote_port);
	if (client->virtual_user_orig != NULL)
		get_var_expand_users(tab+19, client->virtual_user_orig);
	else {
		tab[19].value = tab[0].value;
		tab[20].value = tab[1].value;
		tab[21].value = tab[2].value;
	}
	if (client->virtual_auth_user != NULL)
		get_var_expand_users(tab+22, client->virtual_auth_user);
	else {
		tab[22].value = tab[19].value;
		tab[23].value = tab[20].value;
		tab[24].value = tab[21].value;
	}
	tab[25].value = client->listener_name;
	return tab;
}
Esempio n. 9
0
static void mail_log_append_mailbox_name(string_t *str, struct mail *mail)
{
	const char *mailbox_str;

	mailbox_str = mailbox_get_vname(mail->box);
	str_printfa(str, "box=%s",
		    str_sanitize(mailbox_str, MAILBOX_NAME_LOG_LEN));
}
const char *imap_id_args_get_log_reply(const struct imap_arg *args,
				       const char *settings)
{
	const char *const *keys, *key, *value;
	string_t *reply;
	bool log_all;

	if (settings == NULL || *settings == '\0')
		return NULL;
	if (!imap_arg_get_list(args, &args))
		return NULL;

	log_all = strcmp(settings, "*") == 0;
	reply = t_str_new(256);
	keys = t_strsplit_spaces(settings, " ");
	while (!IMAP_ARG_IS_EOL(&args[0]) &&
	       !IMAP_ARG_IS_EOL(&args[1])) {
		if (!imap_arg_get_string(args, &key)) {
			/* broken input */
			args += 2;
			continue;
		}
		args++;
		if (strlen(key) > 30) {
			/* broken: ID spec requires fields to be max. 30
			   octets */
			args++;
			continue;
		}

		if (log_all || str_array_icase_find(keys, key)) {
			if (!imap_arg_get_nstring(args, &value))
				value = "";
			else if (value == NULL)
				value = "NIL";
			if (str_len(reply) > 0)
				str_append(reply, ", ");
			str_append(reply, str_sanitize(key, 30));
			str_append_c(reply, '=');
			str_append(reply, str_sanitize(value, 80));
		}
		args++;
	}
	return str_len(reply) == 0 ? NULL : str_c(reply);
}
static int tst_exists_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct sieve_stringlist *hdr_list;
	struct mail *mail = sieve_message_get_mail(renv->msgctx);
	string_t *hdr_item;
	bool matched;
	int ret;

	/*
	 * Read operands
	 */

	/* Read header-list */
	if ( (ret=sieve_opr_stringlist_read(renv, address, "header-list", &hdr_list))
		<= 0 )
		return ret;

	/*
	 * Perfrom test
	 */

	sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "exists test");
	sieve_runtime_trace_descend(renv);

	/* Iterate through all requested headers to match (must find all specified) */
	hdr_item = NULL;
	matched = TRUE;
	while ( matched &&
		(ret=sieve_stringlist_next_item(hdr_list, &hdr_item)) > 0 ) {
		const char *const *headers;

		if ( mail_get_headers(mail, str_c(hdr_item), &headers) < 0 ||
			headers[0] == NULL ) {
			matched = FALSE;
		}

		sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING,
        	"header `%s' %s", str_sanitize(str_c(hdr_item), 80),
			( matched ? "exists" : "is missing" ));
	}

	if ( matched )
		sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, "all headers exist");
	else
		sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, "headers are missing");

	/* Set test result for subsequent conditional jump */
	if ( ret >= 0 ) {
		sieve_interpreter_set_test_result(renv->interp, matched);
		return SIEVE_EXEC_OK;
	}

	sieve_runtime_trace_error(renv, "invalid header-list item");
	return SIEVE_EXEC_BIN_CORRUPT;
}
Esempio n. 12
0
static void
mail_log_append_mail_header(string_t *str, struct mail *mail,
			    const char *name, const char *header)
{
	const char *value;

	if (mail_get_first_header(mail, header, &value) <= 0)
		value = "";
	str_printfa(str, "%s=%s", name, str_sanitize(value, HEADER_LOG_LEN));
}
Esempio n. 13
0
void test_str_sanitize(void)
{
	static struct str_sanitize_test tests[] = {
		{ NULL,    2, NULL },
		{ "",      2, NULL },
		{ "a",     2, NULL },
		{ "ab",    2, NULL },
		{ "abc",   2, "..." },
		{ "abcd",  3, "..." },
		{ "abcde", 4, "a..." },
		{ "\xD1\x81",     1, "..." },
		{ "\xD1\x81",     2, "\xD1\x81" },
		{ "\xD1\x81",     3, NULL },
		{ "\xC3\xA4\xC3\xA4zyxa", 1, "..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 2, "..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 3, "..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 4, "..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 5, "\xC3\xA4..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 6, "\xC3\xA4..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 7, "\xC3\xA4\xC3\xA4..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 8, "\xC3\xA4\xC3\xA4zyxa" },
		{ "\001x\x1fy\x81", 10, "?x?y?" }
	};
	const char *str;
	string_t *str2;
	unsigned int i;

	test_begin("str_sanitize");
	for (i = 0; i < N_ELEMENTS(tests); i++) {
		str = str_sanitize(tests[i].str, tests[i].max_len);
		if (tests[i].sanitized != NULL)
			test_assert_idx(null_strcmp(str, tests[i].sanitized) == 0, i);
		else
			test_assert_idx(str == tests[i].str, i);
	}
	test_end();

	test_begin("str_sanitize_append");
	str2 = t_str_new(128);
	for (i = 0; i < N_ELEMENTS(tests); i++) {
		if (tests[i].str == NULL)
			continue;
		str_truncate(str2, 0);
		str_append(str2, "1234567890");
		str_sanitize_append(str2, tests[i].str, tests[i].max_len);

		test_assert_idx(strncmp(str_c(str2), "1234567890", 10) == 0, i);
		if (tests[i].sanitized != NULL)
			test_assert_idx(strcmp(str_c(str2)+10, tests[i].sanitized) == 0, i);
		else
			test_assert_idx(strcmp(str_c(str2)+10, tests[i].str) == 0, i);
	}
	test_end();
}
Esempio n. 14
0
static void mail_log_append_mailbox_name(string_t *str, struct mailbox *box)
{
	const char *mailbox_str;

	/* most operations are for INBOX, and POP3 has only INBOX,
	   so don't add it. */
	mailbox_str = mailbox_get_name(box);
	if (strcmp(mailbox_str, "INBOX") != 0) {
		str_printfa(str, "box=%s, ",
			    str_sanitize(mailbox_str, MAILBOX_NAME_LOG_LEN));
	}
}
Esempio n. 15
0
static int ext_fileinto_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct sieve_side_effects_list *slist = NULL;
	string_t *folder;
	bool folder_literal;
	bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS);
	int ret = 0;

	/*
	 * Read operands
	 */

	/* Optional operands (side effects only) */
	if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, &slist) != 0 )
		return ret;

	/* Folder operand */
	if ( (ret=sieve_opr_string_read_ex
		(renv, address, "folder", FALSE, &folder, &folder_literal)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	if ( trace ) {
		sieve_runtime_trace(renv, 0, "fileinto action");
		sieve_runtime_trace_descend(renv);
	}

	if ( !folder_literal && !uni_utf8_str_is_valid(str_c(folder)) ) {
		sieve_runtime_error(renv, NULL,
			"folder name specified for fileinto command is not utf-8: %s",
			str_c(folder));
		return SIEVE_EXEC_FAILURE;
	}


	if ( trace ) {
		sieve_runtime_trace(renv, 0, "store message in mailbox `%s'",
			str_sanitize(str_c(folder), 80));
	}

	/* Add action to result */
	if ( sieve_act_store_add_to_result
		(renv, slist, str_c(folder)) < 0 )
		return SIEVE_EXEC_FAILURE;

	sieve_message_snapshot(renv->msgctx);

	return SIEVE_EXEC_OK;
}
static bool
auth_postfix_input_line(struct auth_postfix_connection *conn, const char *line)
{
	if (conn->auth->set->debug)
		i_debug("postfix in: %s", line);

	if (strncasecmp(line, "get ", 4) == 0)
		return postfix_input_user(conn, line + 4);

	i_error("BUG: Unknown command in postfix socket: %s",
		str_sanitize(line, 80));
	return FALSE;
}
static void
get_var_expand_users(struct var_expand_table *tab, const char *user)
{
	unsigned int i;

	tab[0].value = user;
	tab[1].value = t_strcut(user, '@');
	tab[2].value = strchr(user, '@');
	if (tab[2].value != NULL) tab[2].value++;

	for (i = 0; i < 3; i++)
		tab[i].value = str_sanitize(tab[i].value, 80);
}
Esempio n. 18
0
static bool tag_comparator_validate
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
	struct sieve_command *cmd)
{
	struct sieve_ast_argument *tag = *arg;
	const struct sieve_comparator *cmp;

	/* Skip tag */
	*arg = sieve_ast_argument_next(*arg);

	/* Check syntax:
	 *   ":comparator" <comparator-name: string>
	 */
	if ( !sieve_validate_tag_parameter
		(valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) {
		return FALSE;
	}

	/* FIXME: We can currently only handle string literal argument, so
	 * variables are not allowed.
	 */
	if ( !sieve_argument_is_string_literal(*arg) ) {
		sieve_argument_validate_error(valdtr, *arg,
			"this Sieve implementation currently only supports "
			"a literal string argument for the :comparator tag");
		return FALSE;
	}

	/* Get comparator from registry */
	cmp = sieve_comparator_create(valdtr, cmd, sieve_ast_argument_strc(*arg));

	if ( cmp == NULL ) {
		sieve_argument_validate_error(valdtr, *arg,
			"unknown comparator '%s'",
			str_sanitize(sieve_ast_argument_strc(*arg),80));

		return FALSE;
	}

	/* String argument not needed during code generation, so detach it from
	 * argument list
	 */
	*arg = sieve_ast_arguments_detach(*arg, 1);

	/* Store comparator in context */
	tag->argument->data = (void *) cmp;

	return TRUE;
}
struct sieve_variable *ext_include_variable_import_global
(struct sieve_validator *valdtr, struct sieve_command *cmd,
	const char *variable)
{
	const struct sieve_extension *this_ext = cmd->ext;
	struct sieve_ast *ast = cmd->ast_node->ast;
	struct ext_include_ast_context *ctx =
		ext_include_get_ast_context(this_ext, ast);
	struct ext_include_context *ectx = ext_include_get_context(this_ext);
	struct sieve_variable_scope *local_scope;
	struct sieve_variable_scope *global_scope = ctx->global_vars;
	struct sieve_variable *global_var = NULL, *local_var;

	/* Sanity safeguard */
	i_assert ( ctx->global_vars != NULL );

	if ( !sieve_variable_identifier_is_valid(variable) ) {
		sieve_command_validate_error(valdtr, cmd,
			"invalid variable identifier '%s'", str_sanitize(variable,80));
		return NULL;
	}

	/* Get/Declare the variable in the global scope */
	global_var = sieve_variable_scope_get_variable(global_scope, variable, TRUE);

	/* Check whether scope is over its size limit */
	if ( global_var == NULL ) {
		sieve_command_validate_error(valdtr, cmd,
			"declaration of new global variable '%s' exceeds the limit "
			"(max variables: %u)",
			variable, sieve_variables_get_max_scope_size());
		return NULL;
	}

	/* Import the global variable into the local script scope */
	local_scope = sieve_ext_variables_get_local_scope(ectx->var_ext, valdtr);

	local_var = sieve_variable_scope_get_variable(local_scope, variable, FALSE);
	if ( local_var != NULL && local_var->ext != this_ext ) {
		/* FIXME: indicate location of conflicting set statement */
		sieve_command_validate_error(valdtr, cmd,
			"declaration of new global variable '%s' conflicts with earlier local "
			"use", variable);
		return NULL;
	}

	return sieve_variable_scope_import(local_scope, global_var);
}
static int _read_extensions(struct sieve_binary_block *sblock)
{
	struct sieve_binary *sbin = sblock->sbin;
	sieve_size_t offset = 0;
	unsigned int i, count;
	bool result = 1;

	if ( !sieve_binary_read_unsigned(sblock, &offset, &count) )
		return -1;

	for ( i = 0; result > 0 && i < count; i++ ) {
		T_BEGIN {
			string_t *extension;
			const struct sieve_extension *ext;
			unsigned int version;

			if ( sieve_binary_read_string(sblock, &offset, &extension) ) {
				ext = sieve_extension_get_by_name(sbin->svinst, str_c(extension));

				if ( ext == NULL ) {
					sieve_sys_error(sbin->svinst,
						"binary open: binary %s requires unknown extension `%s'",
						sbin->path, str_sanitize(str_c(extension), 128));
					result = 0;
				} else {
					struct sieve_binary_extension_reg *ereg = NULL;

					(void) sieve_binary_extension_register(sbin, ext, &ereg);
					if ( !sieve_binary_read_unsigned(sblock, &offset, &version) ||
						!sieve_binary_read_unsigned(sblock, &offset, &ereg->block_id) ) {
						result = -1;
					} else if ( !sieve_extension_version_is(ext, version) ) {
						sieve_sys_debug(sbin->svinst,
							"binary open: binary %s was compiled with different version "
							"of the `%s' extension (compiled v%d, expected v%d;"
							"automatically fixed when re-compiled)", sbin->path,
							sieve_extension_name(ext), version, sieve_extension_version(ext));
						result = 0;
					}
				}
			}	else
				result = -1;
		} T_END;
	}

	return result;
}
Esempio n. 21
0
static bool cmd_vacation_validate_string_tag
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
	struct sieve_command *cmd)
{
	struct sieve_ast_argument *tag = *arg;
	struct cmd_vacation_context_data *ctx_data =
		(struct cmd_vacation_context_data *) cmd->data;

	/* Detach the tag itself */
	*arg = sieve_ast_arguments_detach(*arg,1);

	/* Check syntax:
	 *   :subject string
	 *   :from string
	 *   :handle string
	 */
	if ( !sieve_validate_tag_parameter
		(valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) {
		return FALSE;
	}

	if ( sieve_argument_is(tag, vacation_from_tag) ) {
		if ( sieve_argument_is_string_literal(*arg) ) {
			string_t *address = sieve_ast_argument_str(*arg);
			const char *error;
	 		bool result;

	 		T_BEGIN {
	 			result = sieve_address_validate(address, &error);

				if ( !result ) {
					sieve_argument_validate_error(valdtr, *arg,
						"specified :from address '%s' is invalid for vacation action: %s",
						str_sanitize(str_c(address), 128), error);
				}
			} T_END;

			if ( !result )
				return FALSE;
		}

		ctx_data->from = sieve_ast_argument_str(*arg);

		/* Skip parameter */
		*arg = sieve_ast_argument_next(*arg);

	} else if ( sieve_argument_is(tag, vacation_subject_tag) ) {
Esempio n. 22
0
static int proxy_input_banner(struct imap_client *client,
			      struct ostream *output, const char *line)
{
	const char *const *capabilities = NULL;
	string_t *str;
	int ret;

	if (!str_begins(line, "* OK ")) {
		client_log_err(&client->common, t_strdup_printf(
			"proxy: Remote returned invalid banner: %s",
			str_sanitize(line, 160)));
		return -1;
	}

	str = t_str_new(128);
	if (str_begins(line + 5, "[CAPABILITY ")) {
		capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
		if (str_array_icase_find(capabilities, "SASL-IR"))
			client->proxy_sasl_ir = TRUE;
		if (str_array_icase_find(capabilities, "LOGINDISABLED"))
			client->proxy_logindisabled = TRUE;
		i_free(client->proxy_backend_capability);
		client->proxy_backend_capability =
			i_strdup(t_strcut(line + 5 + 12, ']'));
		if (str_array_icase_find(capabilities, "ID") &&
		    !client->common.proxy_not_trusted) {
			client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_ID;
			proxy_write_id(client, str);
			if (client->common.proxy_nopipelining) {
				/* write login or starttls after I OK */
				o_stream_nsend(output, str_data(str), str_len(str));
				return 0;
			}
		}
	}

	if ((ret = proxy_write_starttls(client, str)) < 0) {
		return -1;
	} else if (ret == 0) {
		if (proxy_write_login(client, str) < 0)
			return -1;
	}

	o_stream_nsend(output, str_data(str), str_len(str));
	return 0;
}
Esempio n. 23
0
static int proxy_input_banner(struct imap_client *client,
			      struct ostream *output, const char *line)
{
	enum login_proxy_ssl_flags ssl_flags;
	const char *const *capabilities = NULL;
	string_t *str;

	if (strncmp(line, "* OK ", 5) != 0) {
		client_log_err(&client->common, t_strdup_printf(
			"proxy: Remote returned invalid banner: %s",
			str_sanitize(line, 160)));
		return -1;
	}

	str = t_str_new(128);
	if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) {
		capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
		if (str_array_icase_find(capabilities, "ID"))
			proxy_write_id(client, str);
		if (str_array_icase_find(capabilities, "SASL-IR"))
			client->proxy_sasl_ir = TRUE;
		if (str_array_icase_find(capabilities, "LOGINDISABLED"))
			client->proxy_logindisabled = TRUE;
		i_free(client->proxy_backend_capability);
		client->proxy_backend_capability =
			i_strdup(t_strcut(line + 5 + 12, ']'));
	}

	ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
	if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) {
		if (capabilities != NULL &&
		    !str_array_icase_find(capabilities, "STARTTLS")) {
			client_log_err(&client->common,
				"proxy: Remote doesn't support STARTTLS");
			return -1;
		}
		str_append(str, "S STARTTLS\r\n");
	} else {
		if (proxy_write_login(client, str) < 0)
			return -1;
	}

	o_stream_nsend(output, str_data(str), str_len(str));
	return 0;
}
static int _arg_validate
(void *context, struct sieve_ast_argument *item)
{
	struct _arg_validate_context *actx = (struct _arg_validate_context *) context;

	if ( sieve_argument_is_string_literal(item) ) {
		string_t *arg = sieve_ast_argument_str(item);

		if ( !sieve_extprogram_arg_is_valid(arg) ) {
			sieve_argument_validate_error(actx->valdtr, item,
				"%s %s: specified external program argument `%s' is invalid",
				sieve_command_identifier(actx->cmd), sieve_command_type_name(actx->cmd),
				str_sanitize(str_c(arg), 128));

			return FALSE;
		}
	}

	return TRUE;
}
int sieve_extprogram_command_read_operands
(const struct sieve_runtime_env *renv, sieve_size_t *address,
	string_t **pname_r, struct sieve_stringlist **args_list_r)
{	
	string_t *arg;
	int ret;

	/*
	 * Read fixed operands
	 */

	if ( (ret=sieve_opr_string_read
		(renv, address, "program-name", pname_r)) <= 0 )
		return ret;

	if ( (ret=sieve_opr_stringlist_read_ex
		(renv, address, "arguments", TRUE, args_list_r)) <= 0 )
		return ret;
		
	/*
	 * Check operands
	 */

	arg = NULL;
	while ( *args_list_r != NULL &&
		(ret=sieve_stringlist_next_item(*args_list_r, &arg)) > 0 ) {
		if ( !sieve_extprogram_arg_is_valid(arg) ) {
			sieve_runtime_error(renv, NULL,
				"specified :args item `%s' is invalid",
				str_sanitize(str_c(arg), 128));
			return SIEVE_EXEC_FAILURE;
		}
	}

	if ( ret < 0 ) {
		sieve_runtime_trace_error(renv, "invalid args-list item");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	return SIEVE_EXEC_OK;
}
const char *unpacker_get_string(UNPACKER *p)
{
	char *ptr;
	if(p->error || p->current >= p->end)
		return "";
		
	ptr = (char *)p->current;
	while(*p->current) /* skip the string */
	{
		p->current++;
		if(p->current == p->end)
		{
			packing_error(p);
			return "";
		}
	}
	p->current++;
	
	/* sanitize all strings */
	str_sanitize(ptr);
	return ptr;
}
Esempio n. 27
0
static int http_header_parse(struct http_header_parser *parser)
{
	int ret;

	/* RFC 7230, Section 3.2: Header Fields

	   'header'       = *( header-field CRLF ) CRLF
	                  ; Actually part of HTTP-message syntax

	   header-field   = field-name ":" OWS field-value OWS
	   field-name     = token
	   field-value    = *( field-content / obs-fold )
	   field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
	   field-vchar    = VCHAR / obs-text
	   obs-fold       = CRLF 1*( SP / HTAB )
	                  ; obsolete line folding
	                  ; see Section 3.2.4
	 */

	for (;;) {
		switch (parser->state) {
		case HTTP_HEADER_PARSE_STATE_INIT:
			buffer_set_used_size(parser->value_buf, 0);
			str_truncate(parser->name, 0);
			if (*parser->cur == '\r') {
				/* last CRLF */
				parser->cur++;
				parser->state = HTTP_HEADER_PARSE_STATE_EOH;
				if (parser->cur == parser->end)
					return 0;
				break;
			} else if (*parser->cur == '\n') {
				/* last LF */
				parser->state = HTTP_HEADER_PARSE_STATE_EOH;
				break;
			}
			/* next line */
			parser->state = HTTP_HEADER_PARSE_STATE_NAME;
			/* fall through */
		case HTTP_HEADER_PARSE_STATE_NAME:
			if ((ret=http_header_parse_name(parser)) <= 0)
				return ret;
			parser->state = HTTP_HEADER_PARSE_STATE_COLON;
			/* fall through */
		case HTTP_HEADER_PARSE_STATE_COLON:
			if (*parser->cur != ':') {
				parser->error = t_strdup_printf
					("Expected ':' after header field name '%s', but found %s",
						str_sanitize(str_c(parser->name),64),
						_chr_sanitize(*parser->cur));
				return -1;
			}
			parser->cur++;
			if (str_len(parser->name) == 0) {
				parser->error = "Empty header field name";
				return -1;
			}
			if (++parser->field_count > parser->limits.max_fields) {
				parser->error = "Excessive number of header fields";
				return -1;
			}
			parser->state = HTTP_HEADER_PARSE_STATE_OWS;
			/* fall through */
		case HTTP_HEADER_PARSE_STATE_OWS:
			if ((ret=http_header_parse_ows(parser)) <= 0)
				return ret;
			parser->state = HTTP_HEADER_PARSE_STATE_CONTENT;
			/* fall through */
		case HTTP_HEADER_PARSE_STATE_CONTENT:
			if ((ret=http_header_parse_content(parser)) <= 0)
				return ret;
			parser->state = HTTP_HEADER_PARSE_STATE_CR;
			/* fall through */
		case HTTP_HEADER_PARSE_STATE_CR:
			if (*parser->cur == '\r') {
				parser->cur++;
			} else if (*parser->cur != '\n') {
				parser->error = t_strdup_printf
					("Invalid character %s in content of header field '%s'",
						_chr_sanitize(*parser->cur),
						str_sanitize(str_c(parser->name),64));
				return -1;
			}
			parser->state = HTTP_HEADER_PARSE_STATE_LF;
			if (parser->cur == parser->end)
				return 0;
			/* fall through */
		case HTTP_HEADER_PARSE_STATE_LF:
			if (*parser->cur != '\n') {
				parser->error = t_strdup_printf
					("Expected LF after CR at end of header field '%s', but found %s",
						str_sanitize(str_c(parser->name),64),
						_chr_sanitize(*parser->cur));
				return -1;
			}
			parser->cur++;
			parser->state = HTTP_HEADER_PARSE_STATE_NEW_LINE;
			if (parser->cur == parser->end)
				return 0;
			/* fall through */
		case HTTP_HEADER_PARSE_STATE_NEW_LINE:
			if (*parser->cur == ' ' || *parser->cur == '\t') {
				/* obs-fold */
				buffer_append_c(parser->value_buf, ' ');
				parser->state = HTTP_HEADER_PARSE_STATE_OWS;
				break;
			} 
			/* next header line */
			parser->state = HTTP_HEADER_PARSE_STATE_INIT;
			return 1;
		case HTTP_HEADER_PARSE_STATE_EOH:
			if (*parser->cur != '\n') {
				parser->error = t_strdup_printf
					("Encountered stray CR at beginning of header line, followed by %s",
						_chr_sanitize(*parser->cur));
				return -1;
			}
			/* header fully parsed */
			parser->cur++;
			return 1;

		default:
			i_unreached();
		}
	}

	i_unreached();
	return -1;
}
static int tst_mailboxexists_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	struct sieve_stringlist *mailbox_names;
	string_t *mailbox_item;
	bool trace = FALSE;
	bool all_exist = TRUE;
	int ret;

	/*
	 * Read operands
	 */

	/* Read notify uris */
	if ( (ret=sieve_opr_stringlist_read
		(renv, address, "mailbox-names", &mailbox_names)) <= 0 )
		return ret;

	/*
	 * Perform operation
	 */

	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS) ) {
		sieve_runtime_trace(renv, 0, "mailboxexists test");
		sieve_runtime_trace_descend(renv);

		trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING);
	}

	if ( renv->scriptenv->user != NULL ) {
		int ret;

		mailbox_item = NULL;
		while ( (ret=sieve_stringlist_next_item(mailbox_names, &mailbox_item)) > 0 )
			{
			struct mail_namespace *ns;
			const char *mailbox = str_c(mailbox_item);
			struct mailbox *box;

			/* Find the namespace */
			ns = mail_namespace_find(renv->scriptenv->user->namespaces, mailbox);
			if ( ns == NULL) {
				if ( trace ) {
					sieve_runtime_trace(renv, 0, "mailbox `%s' not found",
						str_sanitize(mailbox, 80));
				}

				all_exist = FALSE;
				break;
			}

			/* Open the box */
			box = mailbox_alloc(ns->list, mailbox, 0);
			if ( mailbox_open(box) < 0 ) {
				if ( trace ) {
					sieve_runtime_trace(renv, 0, "mailbox `%s' cannot be opened",
						str_sanitize(mailbox, 80));
				}

				all_exist = FALSE;
				mailbox_free(&box);
				break;
			}

			/* Also fail when it is readonly */
			if ( mailbox_is_readonly(box) ) {
				if ( trace ) {
					sieve_runtime_trace(renv, 0, "mailbox `%s' is read-only",
						str_sanitize(mailbox, 80));
				}

				all_exist = FALSE;
				mailbox_free(&box);
				break;
			}

			/* FIXME: check acl for 'p' or 'i' ACL permissions as required by RFC */

			if ( trace ) {
				sieve_runtime_trace(renv, 0, "mailbox `%s' exists",
					str_sanitize(mailbox, 80));
			}

			/* Close mailbox */
			mailbox_free(&box);
		}

		if ( ret < 0 ) {
			sieve_runtime_trace_error(renv, "invalid mailbox name item");
			return SIEVE_EXEC_BIN_CORRUPT;
		}
	}

	if ( trace ) {
		if ( all_exist )
			sieve_runtime_trace(renv, 0, "all mailboxes are available");
		else
			sieve_runtime_trace(renv, 0, "some mailboxes are unavailable");
	}

	sieve_interpreter_set_test_result(renv->interp, all_exist);
	return SIEVE_EXEC_OK;
}
Esempio n. 29
0
int imap_proxy_parse_line(struct client *client, const char *line)
{
	struct imap_client *imap_client = (struct imap_client *)client;
	struct ostream *output;
	string_t *str;
	const unsigned char *data;
	unsigned int data_len;
	const char *error;
	int ret;

	i_assert(!client->destroyed);

	output = login_proxy_get_ostream(client->login_proxy);
	if (!imap_client->proxy_seen_banner) {
		/* this is a banner */
		client->proxy_state = IMAP_PROXY_STATE_BANNER;
		imap_client->proxy_seen_banner = TRUE;
		if (proxy_input_banner(imap_client, output, line) < 0) {
			client_proxy_failed(client, TRUE);
			return -1;
		}
		return 0;
	} else if (*line == '+') {
		/* AUTHENTICATE started. finish it. */
		if (client->proxy_sasl_client == NULL) {
			/* used literals with LOGIN command, just ignore. */
			return 0;
		}
		client->proxy_state = IMAP_PROXY_STATE_AUTH_CONTINUE;

		str = t_str_new(128);
		if (line[1] != ' ' ||
		    base64_decode(line+2, strlen(line+2), NULL, str) < 0) {
			client_log_err(client,
				"proxy: Server sent invalid base64 data in AUTHENTICATE response");
			client_proxy_failed(client, TRUE);
			return -1;
		}
		ret = dsasl_client_input(client->proxy_sasl_client,
					 str_data(str), str_len(str), &error);
		if (ret == 0) {
			ret = dsasl_client_output(client->proxy_sasl_client,
						  &data, &data_len, &error);
		}
		if (ret < 0) {
			client_log_err(client, t_strdup_printf(
				"proxy: Server sent invalid authentication data: %s",
				error));
			client_proxy_failed(client, TRUE);
			return -1;
		}
		i_assert(ret == 0);

		str_truncate(str, 0);
		base64_encode(data, data_len, str);
		str_append(str, "\r\n");

		o_stream_nsend(output, str_data(str), str_len(str));
		return 0;
	} else if (strncmp(line, "S ", 2) == 0) {
		if (strncmp(line, "S OK ", 5) != 0) {
			/* STARTTLS failed */
			client_log_err(client, t_strdup_printf(
				"proxy: Remote STARTTLS failed: %s",
				str_sanitize(line + 5, 160)));
			client_proxy_failed(client, TRUE);
			return -1;
		}
		/* STARTTLS successful, begin TLS negotiation. */
		client->proxy_state = IMAP_PROXY_STATE_STARTTLS;
		if (login_proxy_starttls(client->login_proxy) < 0) {
			client_proxy_failed(client, TRUE);
			return -1;
		}
		/* i/ostreams changed. */
		output = login_proxy_get_ostream(client->login_proxy);
		str = t_str_new(128);
		if (proxy_write_login(imap_client, str) < 0) {
			client_proxy_failed(client, TRUE);
			return -1;
		}
		o_stream_nsend(output, str_data(str), str_len(str));
		return 1;
	} else if (strncmp(line, "L OK ", 5) == 0) {
		/* Login successful. Send this line to client. */
		client->proxy_state = IMAP_PROXY_STATE_LOGIN;
		str = t_str_new(128);
		client_send_login_reply(imap_client, str, line + 5);
		o_stream_nsend(client->output, str_data(str), str_len(str));

		(void)client_skip_line(imap_client);
		client_proxy_finish_destroy_client(client);
		return 1;
	} else if (strncmp(line, "L ", 2) == 0) {
		line += 2;
		if (client->set->auth_verbose) {
			const char *log_line = line;

			if (strncasecmp(log_line, "NO ", 3) == 0)
				log_line += 3;
			client_proxy_log_failure(client, log_line);
		}
#define STR_NO_IMAP_RESP_CODE_AUTHFAILED "NO ["IMAP_RESP_CODE_AUTHFAILED"]"
		if (strncmp(line, STR_NO_IMAP_RESP_CODE_AUTHFAILED,
			    strlen(STR_NO_IMAP_RESP_CODE_AUTHFAILED)) == 0) {
			/* the remote sent a generic "authentication failed"
			   error. replace it with our one, so that in case
			   the remote is sending a different error message
			   an attacker can't find out what users exist in
			   the system. */
			client_send_reply_code(client, IMAP_CMD_REPLY_NO,
					       IMAP_RESP_CODE_AUTHFAILED,
					       AUTH_FAILED_MSG);
		} else if (strncmp(line, "NO [", 4) == 0) {
			/* remote sent some other resp-code. forward it. */
			client_send_raw(client, t_strconcat(
				imap_client->cmd_tag, " ", line, "\r\n", NULL));
		} else {
			/* there was no [resp-code], so remote isn't Dovecot
			   v1.2+. we could either forward the line as-is and
			   leak information about what users exist in this
			   system, or we could hide other errors than password
			   failures. since other errors are pretty rare,
			   it's safer to just hide them. they're still
			   available in logs though. */
			client_send_reply_code(client, IMAP_CMD_REPLY_NO,
					       IMAP_RESP_CODE_AUTHFAILED,
					       AUTH_FAILED_MSG);
		}

		client->proxy_auth_failed = TRUE;
		client_proxy_failed(client, FALSE);
		return -1;
	} else if (strncasecmp(line, "* CAPABILITY ", 13) == 0) {
		i_free(imap_client->proxy_backend_capability);
		imap_client->proxy_backend_capability = i_strdup(line + 13);
		return 0;
	} else if (strncmp(line, "C ", 2) == 0) {
		/* Reply to CAPABILITY command we sent */
		client->proxy_state = IMAP_PROXY_STATE_CAPABILITY;
		if (strncmp(line, "C OK ", 5) == 0 &&
		    client->proxy_password != NULL) {
			/* pipelining was disabled, send the login now. */
			str = t_str_new(128);
			if (proxy_write_login(imap_client, str) < 0)
				return -1;
			o_stream_nsend(output, str_data(str), str_len(str));
			return 1;
		}
		return 0;
	} else if (strncasecmp(line, "I ", 2) == 0) {
		/* Reply to ID command we sent, ignore it unless
		   pipelining is disabled, in which case send
		   either STARTTLS or login */
		client->proxy_state = IMAP_PROXY_STATE_ID;

		if (client->proxy_nopipelining) {
			str = t_str_new(128);
			if ((ret = proxy_write_starttls(imap_client, str)) < 0) {
				return -1;
			} else if (ret == 0) {
				if (proxy_write_login(imap_client, str) < 0)
					return -1;
			}
			o_stream_nsend(output, str_data(str), str_len(str));
			return 1;
		}
		return 0;
	} else if (strncasecmp(line, "* ID ", 5) == 0) {
		/* Reply to ID command we sent, ignore it */
		return 0;
	} else if (strncmp(line, "* ", 2) == 0) {
		/* untagged reply. just forward it. */
		client_send_raw(client, t_strconcat(line, "\r\n", NULL));
		return 0;
	} else {
		/* tagged reply, shouldn't happen. */
		client_log_err(client, t_strdup_printf(
			"proxy: Unexpected input, ignoring: %s",
			str_sanitize(line, 160)));
		return 0;
	}
}
bool sieve_extprogram_command_validate
(struct sieve_validator *valdtr, struct sieve_command *cmd)
{
	struct sieve_ast_argument *arg = cmd->first_positional;
	struct sieve_ast_argument *stritem;
	struct _arg_validate_context actx;
	string_t *program_name;

	if ( arg == NULL ) {
		sieve_command_validate_error(valdtr, cmd, 
			"the %s %s expects at least one positional argument, but none was found", 
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	/* <program-name: string> argument */

	if ( !sieve_validate_positional_argument
		(valdtr, cmd, arg, "program-name", 1, SAAT_STRING) ) {
		return FALSE;
	}
	
	if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) )
		return FALSE;

	/* Variables are not allowed */
	if ( !sieve_argument_is_string_literal(arg) ) {
		sieve_argument_validate_error(valdtr, arg, 
			"the %s %s requires a constant string "
			"for its program-name argument",
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	/* Check program name */
	program_name = sieve_ast_argument_str(arg);
	if ( !sieve_extprogram_name_is_valid(program_name) ) {
 		sieve_argument_validate_error(valdtr, arg,
			"%s %s: invalid program name '%s'",
			sieve_command_identifier(cmd), sieve_command_type_name(cmd),
			str_sanitize(str_c(program_name), 80));
		return FALSE;
	}

	/* Optional <arguments: string-list> argument */

	arg = sieve_ast_argument_next(arg);
	if ( arg == NULL )
		return TRUE;

	if ( !sieve_validate_positional_argument
		(valdtr, cmd, arg, "arguments", 2, SAAT_STRING_LIST) ) {
		return FALSE;
	}

	if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) )
		return FALSE;

	/* Check arguments */
	actx.valdtr = valdtr;
	actx.cmd = cmd;
	stritem = arg;
	if ( sieve_ast_stringlist_map
		(&stritem, (void *)&actx, _arg_validate) <= 0 ) {
		return FALSE;
	}

	if ( sieve_ast_argument_next(arg) != NULL ) {
		sieve_command_validate_error(valdtr, cmd, 
			"the %s %s expects at most two positional arguments, but more were found", 
			sieve_command_identifier(cmd), sieve_command_type_name(cmd));
		return FALSE;
	}

	return TRUE;
}