Esempio n. 1
0
const char *ext_enotify_runtime_get_method_capability
(const struct sieve_runtime_env *renv,
	string_t *method_uri, const char *capability)
{
	const struct sieve_enotify_method *method;
	const char *uri_body;
	const char *result = NULL;

	/* Get method */
	method = ext_enotify_get_method(renv, method_uri, &uri_body);
	if ( method == NULL ) return NULL;

	/* Get requested capability */
	if ( method->def != NULL &&
		method->def->runtime_get_method_capability != NULL ) {
		struct sieve_enotify_env nenv;

		memset(&nenv, 0, sizeof(nenv));
		nenv.svinst = renv->svinst;
		nenv.method = method;
		nenv.ehandler = sieve_prefix_ehandler_create
			(renv->ehandler, sieve_runtime_get_full_command_location(renv),
				"notify_method_capability test");

		/* Execute method function to acquire capability value */
		result = method->def->runtime_get_method_capability
			(&nenv, str_c(method_uri), uri_body, capability);
		sieve_error_handler_unref(&nenv.ehandler);
	}

	return result;
}
Esempio n. 2
0
bool cmd_setactive(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct sieve_storage *storage = client->storage;
	const char *scriptname;
	struct sieve_script *script;
	int ret;

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

	/* Activate, or .. */
	if ( *scriptname != '\0' ) {
		string_t *errors = NULL;
		const char *errormsg = NULL;
		bool warnings = FALSE;
		bool success = TRUE;

		script = sieve_storage_open_script
			(storage, scriptname, NULL);
		if ( script == NULL ) {
			client_send_storage_error(client, storage);
			return TRUE;
		}

		if ( sieve_script_is_active(script) <= 0 ) {
			/* Script is first being activated; compile it again without the UPLOAD
			 * flag.
			 */
			T_BEGIN {
				struct sieve_error_handler *ehandler;
				enum sieve_compile_flags cpflags =
					SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_ACTIVATED;
				struct sieve_binary *sbin;
				enum sieve_error error;

				/* Prepare error handler */
				errors = str_new(default_pool, 1024);
				ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE,
					client->set->managesieve_max_compile_errors);

				/* Compile */
				if ( (sbin=sieve_compile_script
					(script, ehandler, cpflags, &error)) == NULL ) {
					if (error != SIEVE_ERROR_NOT_VALID) {
						errormsg = sieve_script_get_last_error(script, &error);
						if ( error == SIEVE_ERROR_NONE )
							errormsg = NULL;
					}
					success = FALSE;
				} else {
					sieve_close(&sbin);
				}

				warnings = ( sieve_get_warnings(ehandler) > 0 );
				sieve_error_handler_unref(&ehandler);
			} T_END;
		}
static int
cmd_sieve_activate_run(struct doveadm_sieve_cmd_context *_ctx)
{
	struct doveadm_sieve_activate_cmd_context *ctx =
		(struct doveadm_sieve_activate_cmd_context *)_ctx;
	struct sieve_storage *storage = _ctx->storage;
	struct sieve_script *script;
	enum sieve_error error;
	int ret = 0;

	script = sieve_storage_open_script
		(storage, ctx->scriptname, NULL);
	if ( script == NULL ) {
		i_error("Failed to activate Sieve script: %s",
			sieve_storage_get_last_error(storage, &error));
		doveadm_sieve_cmd_failed_error(_ctx, error);
		return -1;
	}

	if ( sieve_script_is_active(script) <= 0 ) {
		/* Script is first being activated; compile it again without the UPLOAD
		 * flag.
		 */
		struct sieve_error_handler *ehandler;
		enum sieve_compile_flags cpflags =
			SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_ACTIVATED;
		struct sieve_binary *sbin;
		enum sieve_error error;

		/* Compile */
		ehandler = sieve_master_ehandler_create(ctx->ctx.svinst, NULL, 0);
		if ( (sbin=sieve_compile_script
			(script, ehandler, cpflags, &error)) == NULL ) {
			doveadm_sieve_cmd_failed_error(_ctx, error);
			ret = -1;
		} else {
			sieve_close(&sbin);
		}
		sieve_error_handler_unref(&ehandler);
	}

	/* Activate only when script is valid (or already active) */
	if ( ret == 0 ) {
		/* Refresh activation no matter what; this can also resolve some erroneous
		 * situations.
		 */
		ret = sieve_script_activate(script, (time_t)-1);
		if ( ret < 0 ) {
			i_error("Failed to activate Sieve script: %s",
				sieve_storage_get_last_error(storage, &error));
			doveadm_sieve_cmd_failed_error(_ctx, error);
			ret = -1;
		}
	}

	sieve_script_unref(&script);
	return ret;
}
Esempio n. 4
0
struct sieve_binary *sieve_tool_script_open
(struct sieve_instance *svinst, const char *filename)
{
	struct sieve_error_handler *ehandler;
	struct sieve_binary *sbin;

	ehandler = sieve_stderr_ehandler_create(svinst, 0);
	sieve_error_handler_accept_infolog(ehandler, TRUE);

	if ( (sbin = sieve_open
		(svinst, filename, NULL, ehandler, 0, NULL)) == NULL ) {
		sieve_error_handler_unref(&ehandler);
		i_fatal("failed to compile sieve script");
	}

	sieve_error_handler_unref(&ehandler);

	sieve_save(sbin, FALSE, NULL);
	return sbin;
}
Esempio n. 5
0
static int _ext_enotify_option_check
(void *context, struct sieve_ast_argument *arg)
{
	struct _ext_enotify_option_check_context *optn_context =
		(struct _ext_enotify_option_check_context *) context;
	struct sieve_validator *valdtr = optn_context->valdtr;
	const struct sieve_enotify_method *method = optn_context->method;
	struct sieve_enotify_env nenv;
	const char *option = sieve_ast_argument_strc(arg);
	const char *opt_name = NULL, *opt_value = NULL;
	bool check = TRUE;
	int result = 1;

	/* Compose log structure */
	memset(&nenv, 0, sizeof(nenv));
	nenv.svinst = optn_context->svinst;
	nenv.method = method;
	nenv.ehandler = sieve_prefix_ehandler_create
		(sieve_validator_error_handler(valdtr),
			sieve_error_script_location
				(sieve_validator_script(valdtr), arg->source_line),
			"notify command");

	/* Parse option */
	if ( !sieve_argument_is_string_literal(arg) ) {
		/* Variable string: partial option parse
		 *
		 * If the string item is not a string literal, it cannot be validated fully
		 * at compile time. We can however check whether the '=' is in the string
		 * specification and whether the part before the '=' is a valid option name.
		 * In that case, the method option check function is called with the value
		 * parameter equal to NULL, meaning that it should only check the validity
		 * of the option itself and not the assigned value.
		 */
		if ( !ext_enotify_option_parse(NULL, option, TRUE, &opt_name, &opt_value) )
			check = FALSE;
	} else {
		/* Literal string: full option parse */
		if ( !ext_enotify_option_parse
			(&nenv, option, FALSE, &opt_name, &opt_value) )
			result = -1;
	}

	/* Call method's option check function */
	if ( result > 0 && check && method->def != NULL &&
		method->def->compile_check_option != NULL ) {
		result = ( method->def->compile_check_option
			(&nenv, opt_name, opt_value) ? 1 : -1 );
	}

	sieve_error_handler_unref(&nenv.ehandler);

	return result;
}
Esempio n. 6
0
void sieve_generator_free(struct sieve_generator **gentr)
{
	sieve_ast_unref(&(*gentr)->genenv.ast);

	sieve_error_handler_unref(&(*gentr)->ehandler);
	sieve_binary_debug_writer_deinit(&(*gentr)->dwriter);

	if ( (*gentr)->genenv.sbin != NULL )
		sieve_binary_unref(&(*gentr)->genenv.sbin);

	pool_unref(&((*gentr)->pool));

	*gentr = NULL;
}
Esempio n. 7
0
void imap_sieve_deinit(struct imap_sieve **_isieve)
{
    struct imap_sieve *isieve = *_isieve;

    *_isieve = NULL;

    sieve_error_handler_unref(&isieve->master_ehandler);

    if (isieve->storage != NULL)
        sieve_storage_unref(&isieve->storage);
    sieve_extension_unregister(isieve->ext_imapsieve);
    sieve_deinit(&isieve->svinst);

    duplicate_deinit(&isieve->dup_ctx);

    pool_unref(&isieve->pool);
}
Esempio n. 8
0
struct sieve_binary *sieve_tool_script_compile
(struct sieve_instance *svinst, const char *filename, const char *name)
{
	struct sieve_error_handler *ehandler;
	struct sieve_binary *sbin;

	ehandler = sieve_stderr_ehandler_create(svinst, 0);
	sieve_error_handler_accept_infolog(ehandler, TRUE);
	sieve_error_handler_accept_debuglog(ehandler, svinst->debug);

	if ( (sbin = sieve_compile
		(svinst, filename, name, ehandler, 0, NULL)) == NULL )
		i_error("failed to compile sieve script '%s'", filename);

	sieve_error_handler_unref(&ehandler);

	return sbin;
}
Esempio n. 9
0
bool ext_enotify_runtime_method_validate
(const struct sieve_runtime_env *renv, string_t *method_uri)
{
	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;
	bool result = TRUE;

	/* Get the method */

	if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL )
		return FALSE;

	if ( (method=ext_enotify_method_find(this_ext, scheme)) == NULL )
		return FALSE;

	/* Validate the provided URI */

	if ( method->def != NULL && method->def->runtime_check_uri != NULL ) {
		struct sieve_enotify_env nenv;

		memset(&nenv, 0, sizeof(nenv));
		nenv.svinst = renv->svinst;
		nenv.method = method;
		nenv.ehandler = sieve_prefix_ehandler_create
			(renv->ehandler, sieve_runtime_get_full_command_location(renv),
				"valid_notify_method test");

		/* Use the method check function to validate the URI */
		result = method->def->runtime_check_uri(&nenv, str_c(method_uri), uri);

		sieve_error_handler_unref(&nenv.ehandler);
	}

	return result;
}
Esempio n. 10
0
static bool cmd_putscript_finish_parsing(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_putscript_context *ctx = cmd->context;
	const struct managesieve_arg *args;
	int ret;

	/* if error occurs, the CRLF is already read. */
	client->input_skip_line = FALSE;

	/* <script literal> */
	ret = managesieve_parser_read_args(ctx->save_parser, 0, 0, &args);
	if (ret == -1 || client->output->closed) {
		if (ctx->storage != NULL)
			client_send_command_error(cmd, NULL);
		cmd_putscript_finish(ctx);
		return TRUE;
	}
	if (ret < 0) {
		/* need more data */
		return FALSE;
	}

	if ( MANAGESIEVE_ARG_IS_EOL(&args[0]) ) {
		struct sieve_script *script;
		bool success = TRUE;

		/* Eat away the trailing CRLF */
		client->input_skip_line = TRUE;

		/* Obtain script object for uploaded script */
		script = sieve_storage_save_get_tempscript(ctx->save_ctx);

		/* Check result */
		if ( script == NULL ) {
			client_send_storage_error(client, ctx->storage);
			cmd_putscript_finish(ctx);
			return TRUE;
		}

		/* If quoted string, the size was not known until now */
		if ( ctx->script_size == 0 ) {
			if (sieve_script_get_size(script, &ctx->script_size) < 0) {
				client_send_storage_error(client, ctx->storage);
				cmd_putscript_finish(ctx);
				return TRUE;
			}
			/* Check quota; max size is already checked */
			if ( ctx->scriptname != NULL && !managesieve_quota_check_all
					(client, ctx->scriptname, ctx->script_size) ) {
				cmd_putscript_finish(ctx);
				return TRUE;
			}
		}

		/* Try to compile script */
		T_BEGIN {
			struct sieve_error_handler *ehandler;
			enum sieve_compile_flags cpflags =
				SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED;
			struct sieve_binary *sbin;
			enum sieve_error error;
			string_t *errors;

			/* Mark this as an activation when we are replacing the active script */
			if ( sieve_storage_save_will_activate(ctx->save_ctx) ) {
				cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED;
			}

			/* Prepare error handler */
			errors = str_new(default_pool, 1024);
			ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE,
				client->set->managesieve_max_compile_errors);

			/* Compile */
			if ( (sbin=sieve_compile_script
				(script, ehandler, cpflags, &error)) == NULL ) {
				if ( error != SIEVE_ERROR_NOT_VALID ) {
					const char *errormsg =
						sieve_script_get_last_error(script, &error);
					if ( error != SIEVE_ERROR_NONE )
						client_send_no(client, errormsg);
					else
						client_send_no(client, str_c(errors));
				} else {
					client_send_no(client, str_c(errors));
				}
				success = FALSE;
			} else {
				sieve_close(&sbin);

				/* Commit to save only when this is a putscript command */
				if ( ctx->scriptname != NULL ) {
					ret = sieve_storage_save_commit(&ctx->save_ctx);

					/* Check commit */
					if (ret < 0) {
						client_send_storage_error(client, ctx->storage);
						success = FALSE;
					}
				}
			}

			/* Finish up */
			cmd_putscript_finish(ctx);

			/* Report result to user */
			if ( success ) {
				if ( ctx->scriptname != NULL ) {
					client->put_count++;
					client->put_bytes += ctx->script_size;
				} else {
					client->check_count++;
					client->check_bytes += ctx->script_size;
				}

				if ( sieve_get_warnings(ehandler) > 0 )
					client_send_okresp(client, "WARNINGS", str_c(errors));
				else {
					if ( ctx->scriptname != NULL )
						client_send_ok(client, "PUTSCRIPT completed.");
					else
						client_send_ok(client, "Script checked successfully.");
				}
			}

			sieve_error_handler_unref(&ehandler);
			str_free(&errors);
		} T_END;

		return TRUE;
	}

	client_send_command_error(cmd, "Too many command arguments.");
	cmd_putscript_finish(ctx);
	return TRUE;
}
Esempio n. 11
0
int ext_enotify_runtime_check_operands
(const struct sieve_runtime_env *renv,
	string_t *method_uri, string_t *message, string_t *from,
	struct sieve_stringlist *options,
	const struct sieve_enotify_method **method_r, void **method_context)
{
	const struct sieve_enotify_method *method;
	const char *uri_body;

	/* Get method */
	method = ext_enotify_get_method(renv, method_uri, &uri_body);
	if ( method == NULL ) return SIEVE_EXEC_FAILURE;

	/* Check provided operands */
	if ( method->def != NULL && method->def->runtime_check_operands != NULL ) {
		struct sieve_enotify_env nenv;
		int result = SIEVE_EXEC_OK;

		memset(&nenv, 0, sizeof(nenv));
		nenv.svinst = renv->svinst;
		nenv.method = method;
		nenv.ehandler = sieve_prefix_ehandler_create
			(renv->ehandler, sieve_runtime_get_full_command_location(renv),
				"notify action");

		/* Execute check function */
		if ( method->def->runtime_check_operands
			(&nenv, str_c(method_uri), uri_body, message, from,
				sieve_result_pool(renv->result), method_context) ) {

			/* Check any provided options */
			if ( options != NULL ) {
				string_t *option = NULL;
				int ret;

				/* Iterate through all provided options */
				while ( (ret=sieve_stringlist_next_item(options, &option)) > 0 ) {
					const char *opt_name = NULL, *opt_value = NULL;

					/* Parse option into <optionname> and <value> */
					if ( ext_enotify_option_parse
						(&nenv, str_c(option), FALSE, &opt_name, &opt_value) ) {

						/* Set option */
						if ( method->def->runtime_set_option != NULL ) {
							(void) method->def->runtime_set_option
								(&nenv, *method_context, opt_name, opt_value);
						}
					}
				}

				/* Check for binary corruptions encountered during string list iteration
				 */
				if ( ret >= 0 ) {
					*method_r = method;
				} else {
					/* Binary corrupt */
					sieve_runtime_trace_error
						(renv, "invalid item in options string list");
					result = SIEVE_EXEC_BIN_CORRUPT;
				}

			} else {
				/* No options */
				*method_r = method;
			}

		} else {
			/* Operand check failed */
			result = SIEVE_EXEC_FAILURE;
		}

		sieve_error_handler_unref(&nenv.ehandler);
		return result;
	}

	/* No check function defined: a most unlikely situation */
	*method_context = NULL;
	*method_r = method;
	return SIEVE_EXEC_OK;
}
Esempio n. 12
0
bool ext_enotify_compile_check_arguments
(struct sieve_validator *valdtr, struct sieve_command *cmd,
	struct sieve_ast_argument *uri_arg, struct sieve_ast_argument *msg_arg,
	struct sieve_ast_argument *from_arg, struct sieve_ast_argument *options_arg)
{
	const struct sieve_extension *this_ext = cmd->ext;
	struct sieve_instance *svinst = this_ext->svinst;
	const char *uri = sieve_ast_argument_strc(uri_arg);
	const char *scheme;
	const struct sieve_enotify_method *method;
	struct sieve_enotify_env nenv;
	bool result = TRUE;

	/* If the uri string is not a constant literal, we cannot determine which
	 * method is used, so we bail out successfully and defer checking to runtime.
	 */
	if ( !sieve_argument_is_string_literal(uri_arg) )
		return TRUE;

	/* Parse scheme part of URI */
	if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL ) {
		sieve_argument_validate_error(valdtr, uri_arg,
			"notify command: invalid scheme part for method URI '%s'",
			str_sanitize(sieve_ast_argument_strc(uri_arg), 80));
		return FALSE;
	}

	/* Find used method with the parsed scheme identifier */
	if ( (method=ext_enotify_method_find(this_ext, scheme)) == NULL ) {
		sieve_argument_validate_error(valdtr, uri_arg,
			"notify command: invalid method '%s'", scheme);
		return FALSE;
	}

	if ( method->def == NULL ) return TRUE;

	/* Compose log structure */
	memset(&nenv, 0, sizeof(nenv));
	nenv.svinst = svinst;
	nenv.method = method;

	/* Check URI itself */
	if ( result && method->def->compile_check_uri != NULL ) {
		/* Set log location to location of URI argument */
		nenv.ehandler = sieve_prefix_ehandler_create
		(sieve_validator_error_handler(valdtr),
			sieve_error_script_location
				(sieve_validator_script(valdtr), uri_arg->source_line),
			"notify command");

		/* Execute method check function */
		result = method->def->compile_check_uri
			(&nenv, sieve_ast_argument_strc(uri_arg), uri);
	}

	/* Check :message argument */
	if ( result && msg_arg != NULL && sieve_argument_is_string_literal(msg_arg)
		&& method->def->compile_check_message != NULL ) {
		/* Set log location to location of :message argument */
		sieve_error_handler_unref(&nenv.ehandler);
		nenv.ehandler = sieve_prefix_ehandler_create
		(sieve_validator_error_handler(valdtr),
			sieve_error_script_location
				(sieve_validator_script(valdtr), msg_arg->source_line),
			"notify command");

		/* Execute method check function */
		result = method->def->compile_check_message
			(&nenv, sieve_ast_argument_str(msg_arg));
	}

	/* Check :from argument */
	if ( result && from_arg != NULL && sieve_argument_is_string_literal(from_arg)
		&& method->def->compile_check_from != NULL ) {
		/* Set log location to location of :from argument */
		sieve_error_handler_unref(&nenv.ehandler);
		nenv.ehandler = sieve_prefix_ehandler_create
		(sieve_validator_error_handler(valdtr),
			sieve_error_script_location
				(sieve_validator_script(valdtr), from_arg->source_line),
				"notify command");

		/* Execute method check function */
		result = method->def->compile_check_from
			(&nenv, sieve_ast_argument_str(from_arg));
	}

	sieve_error_handler_unref(&nenv.ehandler);

	/* Check :options argument */
	if ( result && options_arg != NULL ) {
		struct sieve_ast_argument *option = options_arg;
		struct _ext_enotify_option_check_context optn_context =
			{ svinst, valdtr, method };

		/* Parse and check options */
		result = ( sieve_ast_stringlist_map
			(&option, (void *) &optn_context, _ext_enotify_option_check) > 0 );

		/* Discard argument if options are not accepted by method */
		if ( result && method->def->compile_check_option == NULL ) {
			sieve_argument_validate_warning(valdtr, options_arg,
				"notify command: method '%s' accepts no options", scheme);
			(void)sieve_ast_arguments_detach(options_arg,1);
		}
	}

	return result;
}
Esempio n. 13
0
void sieve_errors_deinit(struct sieve_instance *svinst)
{
	sieve_error_handler_unref(&svinst->system_ehandler);
}