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) ) {
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; }
static bool arg_testsuite_string_validate (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, struct sieve_command *cmd) { enum { ST_NONE, ST_OPEN, ST_SUBSTITUTION, ST_PARAM, ST_CLOSE } state = ST_NONE; pool_t pool = sieve_ast_pool((*arg)->ast); struct sieve_arg_catenated_string *catstr = NULL; string_t *str = sieve_ast_argument_str(*arg); const char *p, *strstart, *substart = NULL; const char *strval = (const char *) str_data(str); const char *strend = strval + str_len(str); bool result = TRUE; string_t *subs_name = t_str_new(256); string_t *subs_param = t_str_new(256); T_BEGIN { /* Initialize substitution structure */ p = strval; strstart = p; while ( result && p < strend ) { switch ( state ) { /* Nothing found yet */ case ST_NONE: if ( *p == '%' ) { substart = p; state = ST_OPEN; str_truncate(subs_name, 0); str_truncate(subs_param, 0); } p++; break; /* Got '%' */ case ST_OPEN: if ( *p == '{' ) { state = ST_SUBSTITUTION; p++; } else state = ST_NONE; break; /* Got '%{' */ case ST_SUBSTITUTION: state = ST_PARAM; while ( *p != '}' && *p != ':' ) { if ( !i_isalnum(*p) ) { state = ST_NONE; break; } str_append_c(subs_name, *p); p++; } break; /* Got '%{name' */ case ST_PARAM: if ( *p == ':' ) { p++; while ( *p != '}' ) { str_append_c(subs_param, *p); p++; } } state = ST_CLOSE; break; /* Finished parsing param, expecting '}' */ case ST_CLOSE: if ( *p == '}' ) { struct sieve_ast_argument *strarg; /* We now know that the substitution is valid */ if ( catstr == NULL ) { catstr = sieve_arg_catenated_string_create(*arg); } /* Add the substring that is before the substitution to the * variable-string AST. */ if ( substart > strstart ) { string_t *newstr = str_new(pool, substart - strstart); str_append_n(newstr, strstart, substart - strstart); strarg = sieve_ast_argument_string_create_raw ((*arg)->ast, newstr, (*arg)->source_line); sieve_arg_catenated_string_add_element(catstr, strarg); /* Give other substitution extensions a chance to do their work */ if ( !sieve_validator_argument_activate_super (valdtr, cmd, strarg, FALSE) ) { result = FALSE; break; } } strarg = testsuite_substitution_argument_create (valdtr, (*arg)->ast, (*arg)->source_line, str_c(subs_name), str_c(subs_param)); if ( strarg != NULL ) sieve_arg_catenated_string_add_element(catstr, strarg); else { sieve_argument_validate_error(valdtr, *arg, "unknown testsuite substitution type '%s'", str_c(subs_name)); } strstart = p + 1; substart = strstart; p++; } /* Finished, reset for the next substitution */ state = ST_NONE; } } } T_END; /* Bail out early if substitution is invalid */ if ( !result ) return FALSE; /* Check whether any substitutions were found */ if ( catstr == NULL ) { /* No substitutions in this string, pass it on to any other substution * extension. */ return sieve_validator_argument_activate_super(valdtr, cmd, *arg, TRUE); } /* Add the final substring that comes after the last substitution to the * variable-string AST. */ if ( strend > strstart ) { struct sieve_ast_argument *strarg; string_t *newstr = str_new(pool, strend - strstart); str_append_n(newstr, strstart, strend - strstart); strarg = sieve_ast_argument_string_create_raw ((*arg)->ast, newstr, (*arg)->source_line); sieve_arg_catenated_string_add_element(catstr, strarg); /* Give other substitution extensions a chance to do their work */ if ( !sieve_validator_argument_activate_super (valdtr, cmd, strarg, FALSE) ) return FALSE; } return TRUE; }
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; }
bool ext_imap4flags_command_validate (struct sieve_validator *valdtr, struct sieve_command *cmd) { struct sieve_ast_argument *arg = cmd->first_positional; struct sieve_ast_argument *arg2; const struct sieve_extension *var_ext; /* Check arguments */ if ( arg == NULL ) { sieve_command_validate_error(valdtr, cmd, "the %s %s expects at least one argument, but none was found", sieve_command_identifier(cmd), sieve_command_type_name(cmd)); return FALSE; } if ( sieve_ast_argument_type(arg) != SAAT_STRING && sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) { sieve_argument_validate_error(valdtr, arg, "the %s %s expects either a string (variable name) or " "a string-list (list of flags) as first argument, but %s was found", sieve_command_identifier(cmd), sieve_command_type_name(cmd), sieve_ast_argument_name(arg)); return FALSE; } arg2 = sieve_ast_argument_next(arg); if ( arg2 != NULL ) { /* First, check syntax sanity */ if ( sieve_ast_argument_type(arg) != SAAT_STRING ) { if ( sieve_command_is(cmd, tst_hasflag) ) { if ( sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) { sieve_argument_validate_error(valdtr, arg, "if a second argument is specified for the hasflag, the first " "must be a string-list (variable-list), but %s was found", sieve_ast_argument_name(arg)); return FALSE; } } else { sieve_argument_validate_error(valdtr, arg, "if a second argument is specified for the %s %s, the first " "must be a string (variable name), but %s was found", sieve_command_identifier(cmd), sieve_command_type_name(cmd), sieve_ast_argument_name(arg)); return FALSE; } } /* Then, check whether the second argument is permitted */ var_ext = sieve_ext_variables_get_extension(cmd->ext->svinst); if ( var_ext == NULL || !sieve_ext_variables_is_active(var_ext, valdtr) ) { sieve_argument_validate_error(valdtr,arg, "the %s %s only allows for the specification of a " "variable name when the variables extension is active", sieve_command_identifier(cmd), sieve_command_type_name(cmd)); return FALSE; } if ( !sieve_variable_argument_activate (var_ext, valdtr, cmd, arg, !sieve_command_is(cmd, tst_hasflag) ) ) return FALSE; if ( sieve_ast_argument_type(arg2) != SAAT_STRING && sieve_ast_argument_type(arg2) != SAAT_STRING_LIST ) { sieve_argument_validate_error(valdtr, arg2, "the %s %s expects a string list (list of flags) as " "second argument when two arguments are specified, " "but %s was found", sieve_command_identifier(cmd), sieve_command_type_name(cmd), sieve_ast_argument_name(arg2)); return FALSE; } } else arg2 = arg; if ( !sieve_validator_argument_activate(valdtr, cmd, arg2, FALSE) ) return FALSE; if ( !sieve_command_is(cmd, tst_hasflag) && sieve_argument_is_string_literal(arg2) ) { struct ext_imap4flags_iter fiter; const char *flag; /* Warn the user about validity of verifiable flags */ ext_imap4flags_iter_init(&fiter, sieve_ast_argument_str(arg)); while ( (flag=ext_imap4flags_iter_get_flag(&fiter)) != NULL ) { if ( !sieve_ext_imap4flags_flag_is_valid(flag) ) { sieve_argument_validate_warning(valdtr, arg, "IMAP flag '%s' specified for the %s command is invalid " "and will be ignored (only first invalid is reported)", str_sanitize(flag, 64), sieve_command_identifier(cmd)); break; } } } return TRUE; }
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; }
static bool cmd_report_validate (struct sieve_validator *valdtr, struct sieve_command *cmd) { struct sieve_ast_argument *arg = cmd->first_positional; /* type */ if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "feedback-type", 1, SAAT_STRING) ) { return FALSE; } if ( !sieve_validator_argument_activate (valdtr, cmd, arg, FALSE) ) return FALSE; if ( sieve_argument_is_string_literal(arg) ) { string_t *fbtype = sieve_ast_argument_str(arg); const char *feedback_type; T_BEGIN { /* Check feedback type */ feedback_type = ext_vnd_report_parse_feedback_type (str_c(fbtype)); if ( feedback_type == NULL ) { sieve_argument_validate_error(valdtr, arg, "specified feedback type `%s' is invalid", str_sanitize(str_c(fbtype),128)); } } T_END; if ( feedback_type == NULL ) return FALSE; } arg = sieve_ast_argument_next(arg); /* message */ if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "message", 2, SAAT_STRING) ) { return FALSE; } if ( !sieve_validator_argument_activate (valdtr, cmd, arg, FALSE) ) return FALSE; arg = sieve_ast_argument_next(arg); /* address */ if ( !sieve_validate_positional_argument (valdtr, cmd, arg, "address", 3, SAAT_STRING) ) { return FALSE; } if ( !sieve_validator_argument_activate (valdtr, cmd, arg, FALSE) ) return FALSE; /* We can only assess the validity of the outgoing address when it is * a string literal. For runtime-generated strings this needs to be * done at runtime. */ if ( sieve_argument_is_string_literal(arg) ) { string_t *address = sieve_ast_argument_str(arg); const char *error; const char *norm_address; T_BEGIN { /* Verify and normalize the address to 'local_part@domain' */ norm_address = sieve_address_normalize(address, &error); if ( norm_address == NULL ) { sieve_argument_validate_error(valdtr, arg, "specified redirect address `%s' is invalid: %s", str_sanitize(str_c(address),128), error); } else { /* Replace string literal in AST */ sieve_ast_argument_string_setc(arg, norm_address); } } T_END; return ( norm_address != NULL ); } return TRUE; }