From 5148ded7268b569fd5e720f90b44645c83ac3e9e Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Mon, 16 Aug 2021 15:47:01 +0200 Subject: fincy new scanner/parser for config rules + fixed a few bugs along the way + fixed related unittests --- src/Makefile.frag | 2 + src/config.m4 | 5 +- src/php_snuffleupagus.h | 1 + src/sp_config.c | 311 ++++++----- src/sp_config.h | 171 +++--- src/sp_config_keywords.c | 606 ++++++++------------- src/sp_config_keywords.h | 31 +- src/sp_config_scanner.h | 25 + src/sp_config_scanner.re | 139 +++++ src/sp_config_utils.c | 103 ---- src/sp_config_utils.h | 3 - src/sp_disabled_functions.c | 33 +- src/sp_execute.c | 6 +- src/sp_network_utils.c | 6 +- src/sp_pcre_compat.c | 3 +- src/sp_unserialize.c | 3 +- src/sp_utils.c | 13 +- src/sp_utils.h | 4 +- .../encrypt_regexp_cookies_bad_regexp.phpt | 4 +- .../broken_configuration_php8/broken_conf.phpt | 3 +- .../broken_configuration_php8/broken_conf2.phpt | 3 +- .../broken_conf_allow_broken_disabled.phpt | 2 +- .../broken_conf_allow_broken_enabled.phpt | 2 +- .../broken_conf_config_regexp.phpt | 5 +- ...broken_conf_config_regexp_no_closing_paren.phpt | 5 +- ...f_cookie_encryption_without_encryption_key.phpt | 3 +- ...ken_conf_cookie_encryption_without_env_var.phpt | 3 +- .../broken_conf_eval.phpt | 2 +- .../broken_conf_expecting_bool.phpt | 3 +- .../broken_conf_invalid_cidr_value.phpt | 5 +- .../broken_conf_invalid_filename.phpt | 3 +- .../broken_conf_invalid_log_media.phpt | 3 +- .../broken_conf_invalid_type.phpt | 3 +- .../broken_conf_key_value.phpt | 4 +- .../broken_conf_line_empty_string.phpt | 3 +- .../broken_conf_line_no_closing.phpt | 3 +- .../broken_conf_lots_of_quotes.phpt | 3 +- .../broken_conf_missing_script.phpt | 3 +- .../broken_conf_mutually_exclusive.phpt | 5 +- .../broken_conf_mutually_exclusive11.phpt | 5 +- .../broken_conf_mutually_exclusive12.phpt | 5 +- .../broken_conf_mutually_exclusive2.phpt | 5 +- .../broken_conf_mutually_exclusive3.phpt | 5 +- .../broken_conf_mutually_exclusive4.phpt | 4 +- .../broken_conf_mutually_exclusive5.phpt | 4 +- .../broken_conf_mutually_exclusive6.phpt | 5 +- .../broken_conf_mutually_exclusive7.phpt | 5 +- .../broken_conf_mutually_exclusive8.phpt | 5 +- .../broken_conf_readonly_exec.phpt | 3 +- .../broken_conf_samesite.phpt | 3 +- .../broken_conf_session_encryption.phpt | 3 +- .../broken_conf_shown_in_phpinfo.phpt | 5 +- .../broken_conf_truncated.phpt | 3 +- .../broken_conf_unserialize.phpt | 5 +- .../broken_conf_upload_validation.phpt | 3 +- .../broken_conf_weird_keyword.phpt | 3 +- .../broken_conf_wrapper_whitelist.phpt | 3 +- .../broken_conf_wrong_quotes.phpt | 3 +- .../broken_configuration_php8/broken_regexp.phpt | 5 +- .../encrypt_regexp_cookies_bad_regexp.phpt | 4 +- .../encrypt_cookies_no_env.phpt | 2 +- .../encrypt_cookies_no_key.phpt | 2 +- .../encrypt_regexp_cookies_no_env.phpt | 2 +- .../encrypt_regexp_cookies_no_key.phpt | 2 +- src/tests/dump_request/dump_eval_blacklist.phpt | 2 +- src/tests/eval_blacklist/eval_backlist.phpt | 2 +- .../eval_backlist_call_user_func.phpt | 2 +- .../eval_blacklist/eval_backlist_chained.phpt | 2 +- src/tests/eval_blacklist/eval_backlist_list.phpt | 2 +- .../eval_blacklist/eval_backlist_simulation.phpt | 2 +- .../eval_blacklist/nested_eval_blacklist.phpt | 2 +- .../eval_blacklist/nested_eval_blacklist2.phpt | 2 +- 72 files changed, 766 insertions(+), 879 deletions(-) create mode 100644 src/Makefile.frag create mode 100644 src/sp_config_scanner.h create mode 100644 src/sp_config_scanner.re (limited to 'src') diff --git a/src/Makefile.frag b/src/Makefile.frag new file mode 100644 index 0000000..c8458ea --- /dev/null +++ b/src/Makefile.frag @@ -0,0 +1,2 @@ +$(srcdir)/sp_config_scanner.c: $(srcdir)/sp_config_scanner.re + @$(RE2C) $(RE2C_FLAGS) --no-generation-date -bc -o $@ $< diff --git a/src/config.m4 b/src/config.m4 index 9778820..6f462af 100644 --- a/src/config.m4 +++ b/src/config.m4 @@ -7,7 +7,7 @@ sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c" sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c" sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c sp_sloppy.c sp_wrapper.c" -sources="$sources sp_ini.c sp_php_compat.c" +sources="$sources sp_ini.c sp_php_compat.c sp_config_scanner.c" PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, [ --enable-snuffleupagus Enable snuffleupagus support]) @@ -40,3 +40,6 @@ if test "$PHP_SNUFFLEUPAGUS" = "yes"; then fi PHP_NEW_EXTENSION(snuffleupagus, $sources, $ext_shared,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) fi + +PHP_PROG_RE2C() +PHP_ADD_MAKEFILE_FRAGMENT() diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index 928095d..91ee8a6 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h @@ -70,6 +70,7 @@ typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); #include "sp_list.h" #include "sp_tree.h" #include "sp_var_parser.h" +#include "sp_config_scanner.h" #include "sp_config.h" #include "sp_config_utils.h" #include "sp_config_keywords.h" diff --git a/src/sp_config.c b/src/sp_config.c index 37c749b..4d96bbe 100644 --- a/src/sp_config.c +++ b/src/sp_config.c @@ -4,102 +4,140 @@ #include "php_snuffleupagus.h" -size_t sp_line_no; - -static sp_config_tokens const sp_func[] = { - {.func = parse_unserialize, .token = SP_TOKEN_UNSERIALIZE_HMAC}, - {.func = parse_random, .token = SP_TOKEN_HARDEN_RANDOM}, - {.func = parse_log_media, .token = SP_TOKEN_LOG_MEDIA}, - {.func = parse_disabled_functions, .token = SP_TOKEN_DISABLE_FUNC}, - {.func = parse_readonly_exec, .token = SP_TOKEN_READONLY_EXEC}, - {.func = parse_global_strict, .token = SP_TOKEN_GLOBAL_STRICT}, - {.func = parse_upload_validation, .token = SP_TOKEN_UPLOAD_VALIDATION}, - {.func = parse_cookie, .token = SP_TOKEN_COOKIE_ENCRYPTION}, - {.func = parse_global, .token = SP_TOKEN_GLOBAL}, - {.func = parse_auto_cookie_secure, .token = SP_TOKEN_AUTO_COOKIE_SECURE}, - {.func = parse_disable_xxe, .token = SP_TOKEN_DISABLE_XXE}, - {.func = parse_eval_blacklist, .token = SP_TOKEN_EVAL_BLACKLIST}, - {.func = parse_eval_whitelist, .token = SP_TOKEN_EVAL_WHITELIST}, - {.func = parse_session, .token = SP_TOKEN_SESSION_ENCRYPTION}, - {.func = parse_sloppy_comparison, .token = SP_TOKEN_SLOPPY_COMPARISON}, - {.func = parse_wrapper_whitelist, .token = SP_TOKEN_ALLOW_WRAPPERS}, - {.func = parse_ini_protection, .token = ".ini_protection"}, - {.func = parse_ini_entry, .token = ".ini"}, - {NULL, NULL}}; - -/* Top level keyword parsing */ - -static int parse_line(char *line) { - char *ptr = line; - - while (*ptr == ' ' || *ptr == '\t') { - ++ptr; - } - if (!*ptr || *ptr == '#' || *ptr == ';') { - return 0; +static zend_result sp_process_config_root(sp_parsed_keyword *parsed_rule) { + sp_config_keyword sp_func[] = { + {parse_unserialize, SP_TOKEN_UNSERIALIZE_HMAC, SNUFFLEUPAGUS_G(config).config_unserialize}, + {parse_enable, SP_TOKEN_HARDEN_RANDOM, &(SNUFFLEUPAGUS_G(config).config_random->enable)}, + {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SNUFFLEUPAGUS_G(config).log_media)}, + {parse_disabled_functions, SP_TOKEN_DISABLE_FUNC, NULL}, + {parse_readonly_exec, SP_TOKEN_READONLY_EXEC, SNUFFLEUPAGUS_G(config).config_readonly_exec}, + {parse_enable, SP_TOKEN_GLOBAL_STRICT, &(SNUFFLEUPAGUS_G(config).config_global_strict->enable)}, + {parse_upload_validation, SP_TOKEN_UPLOAD_VALIDATION, SNUFFLEUPAGUS_G(config).config_upload_validation}, + {parse_cookie, SP_TOKEN_COOKIE_ENCRYPTION, NULL}, + {parse_global, SP_TOKEN_GLOBAL, NULL}, + {parse_enable, SP_TOKEN_AUTO_COOKIE_SECURE, &(SNUFFLEUPAGUS_G(config).config_auto_cookie_secure->enable)}, + {parse_enable, SP_TOKEN_DISABLE_XXE, &(SNUFFLEUPAGUS_G(config).config_disable_xxe->enable)}, + {parse_eval_filter_conf, SP_TOKEN_EVAL_BLACKLIST, &(SNUFFLEUPAGUS_G(config).config_eval->blacklist)}, + {parse_eval_filter_conf, SP_TOKEN_EVAL_WHITELIST, &(SNUFFLEUPAGUS_G(config).config_eval->whitelist)}, + {parse_session, SP_TOKEN_SESSION_ENCRYPTION, SNUFFLEUPAGUS_G(config).config_session}, + {parse_enable, SP_TOKEN_SLOPPY_COMPARISON, &(SNUFFLEUPAGUS_G(config).config_sloppy->enable)}, + {parse_wrapper_whitelist, SP_TOKEN_ALLOW_WRAPPERS, SNUFFLEUPAGUS_G(config).config_wrapper}, + {parse_ini_protection, SP_TOKEN_INI_PROTECTION, SNUFFLEUPAGUS_G(config).config_ini}, + {parse_ini_entry, SP_TOKEN_INI, SNUFFLEUPAGUS_G(config).config_unserialize}, + {NULL, NULL, NULL}}; + return sp_process_rule(parsed_rule, sp_func); +} + +zend_result sp_parse_config(const char *filename) { + FILE *fd = fopen(filename, "rb"); + if (fd == NULL) { + sp_log_err("config", "Could not open configuration file %s : %s", filename, strerror(errno)); + return FAILURE; } - if (strncmp(ptr, SP_TOKEN_BASE, strlen(SP_TOKEN_BASE))) { - sp_log_err("config", "Invalid configuration prefix for '%s' on line %zu", - line, sp_line_no); - return -1; + size_t step = 8192; + size_t max_len = step, len = 0; + zend_string *data = zend_string_alloc(max_len, 0); + char *ptr = ZSTR_VAL(data); + + size_t bytes; + while ((bytes = fread(ptr, 1, max_len - len, fd))) { + len += bytes; + if (max_len - len <= 0) { + max_len += step; + data = zend_string_extend(data, max_len, 0); + ptr = ZSTR_VAL(data) + len; + } else { + ptr += bytes; + } } - ptr += strlen(SP_TOKEN_BASE); + fclose(fd); + + data = zend_string_truncate(data, len, 0); + ZSTR_VAL(data)[len] = 0; + + int ret = sp_config_scan(ZSTR_VAL(data), sp_process_config_root); + + zend_string_release_ex(data, 0); + + return ret; +} + - for (size_t i = 0; sp_func[i].func; i++) { - if (!strncmp(sp_func[i].token, ptr, strlen(sp_func[i].token))) { - return sp_func[i].func(ptr + strlen(sp_func[i].token)); +zend_result sp_process_rule(sp_parsed_keyword *parsed_rule, sp_config_keyword *config_keywords) { + for (sp_parsed_keyword *kw = parsed_rule; kw->kw; kw++) { + bool found_kw = false; + for (sp_config_keyword *ckw = config_keywords; ckw->func; ckw++) { + if (kw->kwlen == strlen(ckw->token) && !strncmp(kw->kw, ckw->token, kw->kwlen)) { + if (ckw->func) { + int ret = ckw->func(ckw->token, kw, ckw->retval); + switch (ret) { + case SP_PARSER_SUCCESS: + break; + case SP_PARSER_ERROR: + return FAILURE; + case SP_PARSER_STOP: + return SUCCESS; + } + } + found_kw = true; + break; + } + } + + if (!found_kw) { + zend_string *kwname = zend_string_init(kw->kw, kw->kwlen, 0); + sp_log_err("config", "Unexpected keyword '%s' on line %d", ZSTR_VAL(kwname), kw->lineno); + zend_string_release_ex(kwname, 0); + return FAILURE; } } - sp_log_err("config", "Invalid configuration section '%s' on line %zu", line, - sp_line_no); - return -1; + return SUCCESS; } -/* keyword parsing */ #define CHECK_DUPLICATE_KEYWORD(retval) \ if (*(void**)(retval)) { \ - sp_log_err("config", "duplicate %s) on line %zu near `%s`", keyword, sp_line_no, line); \ - return -1; } + sp_log_err("config", "duplicate keyword '%s' on line %zu", token, kw->lineno); \ + return SP_PARSER_ERROR; } -int parse_empty(char *restrict line, char *restrict keyword, void *retval) { +SP_PARSEKW_FN(parse_empty) { + if (kw->arglen) { + sp_log_err("config", "Unexpected argument for keyword '%s' - it should be '%s()' on line %zu", token, token, kw->lineno); + return SP_PARSER_ERROR; + } + if (kw->argtype != SP_ARGTYPE_EMPTY) { + sp_log_err("config", "Missing paranthesis for keyword '%s' - it should be '%s()' on line %zu", token, token, kw->lineno); + return SP_PARSER_ERROR; + } *(bool *)retval = true; - return 0; + return SP_PARSER_SUCCESS; } -int parse_list(char *restrict line, char *restrict keyword, void *list_ptr) { - CHECK_DUPLICATE_KEYWORD(list_ptr); - zend_string *value = NULL; - sp_list_node **list = list_ptr; - char *token, *tmp; +SP_PARSEKW_FN(parse_list) { + CHECK_DUPLICATE_KEYWORD(retval); - size_t consumed = 0; - value = get_param(&consumed, line, SP_TYPE_STR, keyword); - if (!value) { - return -1; - } + sp_list_node **list = retval; + char *tok, *tmp; + + SP_PARSE_ARG(value); tmp = ZSTR_VAL(value); while (1) { - token = strsep(&tmp, ","); - if (token == NULL) { + tok = strsep(&tmp, ","); + if (tok == NULL) { break; } - *list = sp_list_insert(*list, zend_string_init(token, strlen(token), 1)); + *list = sp_list_insert(*list, zend_string_init(tok, strlen(tok), 1)); } + zend_string_release(value); - pefree(value, 1); - return consumed; + return SP_PARSER_SUCCESS; } -int parse_php_type(char *restrict line, char *restrict keyword, void *retval) { - size_t consumed = 0; - zend_string *value = get_param(&consumed, line, SP_TYPE_STR, keyword); - if (!value) { - return -1; - } +SP_PARSEKW_FN(parse_php_type) { + SP_PARSE_ARG(value); if (zend_string_equals_literal_ci(value, "undef")) { *(sp_php_type *)retval = SP_PHP_TYPE_UNDEF; @@ -124,113 +162,88 @@ int parse_php_type(char *restrict line, char *restrict keyword, void *retval) { } else if (zend_string_equals_literal_ci(value, "reference")) { *(sp_php_type *)retval = SP_PHP_TYPE_REFERENCE; } else { - pefree(value, 1); - sp_log_err("error", - "%s) is expecting a valid php type ('false', 'true'," + zend_string_release(value); + sp_log_err("error", ".%s() is expecting a valid php type ('false', 'true'," " 'array'. 'object', 'long', 'double', 'null', 'resource', " - "'reference', 'undef') on line %zu", - keyword, sp_line_no); - return -1; + "'reference', 'undef') on line %zu", token, kw->lineno); + return SP_PARSER_ERROR; } - pefree(value, 1); - return consumed; + zend_string_release(value); + return SP_PARSER_SUCCESS; } -int parse_str(char *restrict line, char *restrict keyword, void *retval) { + +SP_PARSEKW_FN(parse_str) { CHECK_DUPLICATE_KEYWORD(retval); - zend_string *value = NULL; + SP_PARSE_ARG(value); - size_t consumed = 0; - value = get_param(&consumed, line, SP_TYPE_STR, keyword); - if (value) { - *(zend_string **)retval = value; - return consumed; - } - return -1; + *(zend_string **)retval = value; + + return SP_PARSER_SUCCESS; } -int parse_cidr(char *restrict line, char *restrict keyword, void *retval) { - CHECK_DUPLICATE_KEYWORD(retval); +SP_PARSEKW_FN(parse_int) { + int ret = SP_PARSER_SUCCESS; + SP_PARSE_ARG(value); - size_t consumed = 0; - zend_string *value = get_param(&consumed, line, SP_TYPE_STR, keyword); + char *endptr; + errno = 0; + *(int*)retval = (int)strtoimax(ZSTR_VAL(value), &endptr, 10); + if (errno != 0 || !endptr || endptr == ZSTR_VAL(value)) { + sp_log_err("config", "Failed to parse arg '%s' of `%s` on line %zu", ZSTR_VAL(value), token, kw->lineno); + ret = SP_PARSER_ERROR; + } + zend_string_release(value); + return ret; +} + +SP_PARSEKW_FN(parse_ulong) { + int ret = SP_PARSER_SUCCESS; + SP_PARSE_ARG(value); - if (!value) { - sp_log_err("config", "%s doesn't contain a valid cidr on line %zu", line, sp_line_no); - return -1; + char *endptr; + errno = 0; + *(u_long*)retval = (u_long)strtoul(ZSTR_VAL(value), &endptr, 10); + if (errno != 0 || !endptr || endptr == ZSTR_VAL(value)) { + sp_log_err("config", "Failed to parse arg '%s' of `%s` on line %zu", ZSTR_VAL(value), token, kw->lineno); + ret = SP_PARSER_ERROR; } + zend_string_release(value); + return ret; +} + +SP_PARSEKW_FN(parse_cidr) { + CHECK_DUPLICATE_KEYWORD(retval); + SP_PARSE_ARG(value); sp_cidr *cidr = pecalloc(sizeof(sp_cidr), 1, 1); if (0 != get_ip_and_cidr(ZSTR_VAL(value), cidr)) { pefree(cidr, 1); - *(sp_cidr **)retval = NULL; - return -1; + cidr = NULL; } *(sp_cidr **)retval = cidr; - return consumed; + return cidr ? SP_PARSER_SUCCESS : SP_PARSER_ERROR; } -int parse_regexp(char *restrict line, char *restrict keyword, void *retval) { +SP_PARSEKW_FN(parse_regexp) { /* TODO: Do we want to use pcre_study? * (http://www.pcre.org/original/doc/html/pcre_study.html) * maybe not: http://sljit.sourceforge.net/pcre.html*/ CHECK_DUPLICATE_KEYWORD(retval); + SP_PARSE_ARG(value); - size_t consumed = 0; - zend_string *value = get_param(&consumed, line, SP_TYPE_STR, keyword); - - if (value) { - sp_pcre *compiled_re = sp_pcre_compile(ZSTR_VAL(value)); - if (NULL != compiled_re) { - *(sp_pcre **)retval = compiled_re; - return consumed; - } - } - char *closing_paren = strchr(line, ')'); - if (NULL != closing_paren) { - closing_paren[0] = '\0'; + sp_pcre *compiled_re = sp_pcre_compile(ZSTR_VAL(value)); + if (!compiled_re) { + sp_log_err("config", "Invalid regexp '%s' for '.%s()' on line %zu", ZSTR_VAL(value), token, kw->lineno); + zend_string_release_ex(value, 1); + return SP_PARSER_ERROR; } - sp_log_err("config", - "'%s)' is expecting a valid regexp, and not '%s' on line %zu", - keyword, line, sp_line_no); - return -1; -} -int sp_parse_config(const char *conf_file) { - FILE *fd = fopen(conf_file, "r"); - char *lineptr = NULL; - size_t n = 0; - sp_line_no = 1; + *(sp_pcre **)retval = compiled_re; - if (fd == NULL) { - sp_log_err("config", "Could not open configuration file %s : %s", conf_file, - strerror(errno)); - return FAILURE; - } - - while (getline(&lineptr, &n, fd) > 0) { - /* We trash the terminal `\n`. This simplify the display of logs. */ - if (lineptr[strlen(lineptr) - 1] == '\n') { - if (strlen(lineptr) >= 2 && lineptr[strlen(lineptr) - 2] == '\r') { - lineptr[strlen(lineptr) - 2] = '\0'; - } else { - lineptr[strlen(lineptr) - 1] = '\0'; - } - } - if (parse_line(lineptr) == -1) { - fclose(fd); - free(lineptr); - return FAILURE; - } - free(lineptr); - lineptr = NULL; - n = 0; - sp_line_no++; - } - fclose(fd); - return SUCCESS; + return SP_PARSER_SUCCESS; } void sp_free_disabled_function(void *data) { @@ -292,4 +305,4 @@ void sp_free_ini_entry(void *data) { sp_pcre_free(entry->regexp); sp_free_zstr(entry->msg); sp_free_zstr(entry->set); -} \ No newline at end of file +} diff --git a/src/sp_config.h b/src/sp_config.h index 0ba2e7f..fd6dc15 100644 --- a/src/sp_config.h +++ b/src/sp_config.h @@ -5,15 +5,6 @@ #include #include -extern size_t sp_line_no; - -typedef enum { - SP_TYPE_STR = 0, - SP_TYPE_REGEXP, - SP_TYPE_INT, - SP_TYPE_EMPTY -} sp_type; - typedef enum { SP_PHP_TYPE_UNDEF = IS_UNDEF, SP_PHP_TYPE_NULL = IS_NULL, @@ -214,99 +205,115 @@ typedef struct { sp_config_disabled_functions *config_disabled_functions_reg_ret; } sp_config; -typedef struct { - int (*func)(char *, char *, void *); - char *token; - void *retval; -} sp_config_functions; +#define SP_PARSE_FN_(fname, kwvar) int fname(char *token, sp_parsed_keyword *kwvar, void *retval) +#define SP_PARSE_FN(fname) SP_PARSE_FN_(fname, parsed_rule) +#define SP_PARSEKW_FN(fname) SP_PARSE_FN_(fname, kw) typedef struct { - int (*func)(char *); + SP_PARSE_FN((*func)); char *token; -} sp_config_tokens; - -#define SP_TOKEN_BASE "sp" - -#define SP_TOKEN_AUTO_COOKIE_SECURE ".auto_cookie_secure" -#define SP_TOKEN_COOKIE_ENCRYPTION ".cookie" -#define SP_TOKEN_SESSION_ENCRYPTION ".session" -#define SP_TOKEN_DISABLE_FUNC ".disable_function" -#define SP_TOKEN_GLOBAL ".global" -#define SP_TOKEN_GLOBAL_STRICT ".global_strict" -#define SP_TOKEN_HARDEN_RANDOM ".harden_random" -#define SP_TOKEN_READONLY_EXEC ".readonly_exec" -#define SP_TOKEN_UNSERIALIZE_HMAC ".unserialize_hmac" -#define SP_TOKEN_UPLOAD_VALIDATION ".upload_validation" -#define SP_TOKEN_DISABLE_XXE ".disable_xxe" -#define SP_TOKEN_EVAL_BLACKLIST ".eval_blacklist" -#define SP_TOKEN_EVAL_WHITELIST ".eval_whitelist" -#define SP_TOKEN_SLOPPY_COMPARISON ".sloppy_comparison" -#define SP_TOKEN_ALLOW_WRAPPERS ".wrappers_whitelist" -#define SP_TOKEN_INI ".ini" + void *retval; +} sp_config_keyword; + +#define SP_PARSER_SUCCESS 0 +#define SP_PARSER_ERROR -1 +#define SP_PARSER_STOP 1 + +// #define SP_TOKEN_BASE "sp" + +#define SP_TOKEN_AUTO_COOKIE_SECURE "auto_cookie_secure" +#define SP_TOKEN_COOKIE_ENCRYPTION "cookie" +#define SP_TOKEN_SESSION_ENCRYPTION "session" +#define SP_TOKEN_DISABLE_FUNC "disable_function" +#define SP_TOKEN_GLOBAL "global" +#define SP_TOKEN_GLOBAL_STRICT "global_strict" +#define SP_TOKEN_HARDEN_RANDOM "harden_random" +#define SP_TOKEN_READONLY_EXEC "readonly_exec" +#define SP_TOKEN_UNSERIALIZE_HMAC "unserialize_hmac" +#define SP_TOKEN_UPLOAD_VALIDATION "upload_validation" +#define SP_TOKEN_DISABLE_XXE "disable_xxe" +#define SP_TOKEN_EVAL_BLACKLIST "eval_blacklist" +#define SP_TOKEN_EVAL_WHITELIST "eval_whitelist" +#define SP_TOKEN_SLOPPY_COMPARISON "sloppy_comparison" +#define SP_TOKEN_ALLOW_WRAPPERS "wrappers_whitelist" +#define SP_TOKEN_INI_PROTECTION "ini_protection" +#define SP_TOKEN_INI "ini" // common tokens -#define SP_TOKEN_ENABLE ".enable(" -#define SP_TOKEN_DISABLE ".disable(" -#define SP_TOKEN_SIMULATION ".simulation(" -#define SP_TOKEN_TRUE "1" -#define SP_TOKEN_FALSE "0" -#define SP_TOKEN_DUMP ".dump(" -#define SP_TOKEN_ALIAS ".alias(" -#define SP_TOKEN_ALLOW ".allow(" -#define SP_TOKEN_DROP ".drop(" - -#define SP_TOKEN_END_PARAM ')' +#define SP_TOKEN_ENABLE "enable" +#define SP_TOKEN_DISABLE "disable" +#define SP_TOKEN_SIMULATION "simulation" +#define SP_TOKEN_SIM "sim" +// #define SP_TOKEN_TRUE "1" +// #define SP_TOKEN_FALSE "0" +#define SP_TOKEN_DUMP "dump" +#define SP_TOKEN_ALIAS "alias" +#define SP_TOKEN_ALLOW "allow" +#define SP_TOKEN_DROP "drop" // disable_function -#define SP_TOKEN_CIDR ".cidr(" -#define SP_TOKEN_FILENAME ".filename(" -#define SP_TOKEN_FILENAME_REGEXP ".filename_r(" -#define SP_TOKEN_FUNCTION ".function(" -#define SP_TOKEN_FUNCTION_REGEXP ".function_r(" -#define SP_TOKEN_HASH ".hash(" -#define SP_TOKEN_LOCAL_VAR ".var(" -#define SP_TOKEN_PARAM ".param(" -#define SP_TOKEN_PARAM_REGEXP ".param_r(" -#define SP_TOKEN_PARAM_TYPE ".param_type(" -#define SP_TOKEN_RET ".ret(" -#define SP_TOKEN_RET_REGEXP ".ret_r(" -#define SP_TOKEN_RET_TYPE ".ret_type(" -#define SP_TOKEN_VALUE ".value(" -#define SP_TOKEN_VALUE_REGEXP ".value_r(" -#define SP_TOKEN_KEY ".key(" -#define SP_TOKEN_KEY_REGEXP ".key_r(" -#define SP_TOKEN_VALUE_ARG_POS ".pos(" -#define SP_TOKEN_LINE_NUMBER ".line(" +#define SP_TOKEN_CIDR "cidr" +#define SP_TOKEN_FILENAME "filename" +#define SP_TOKEN_FILENAME_REGEXP "filename_r" +#define SP_TOKEN_FUNCTION "function" +#define SP_TOKEN_FUNCTION_REGEXP "function_r" +#define SP_TOKEN_HASH "hash" +#define SP_TOKEN_LOCAL_VAR "var" +#define SP_TOKEN_PARAM "param" +#define SP_TOKEN_PARAM_REGEXP "param_r" +#define SP_TOKEN_PARAM_TYPE "param_type" +#define SP_TOKEN_RET "ret" +#define SP_TOKEN_RET_REGEXP "ret_r" +#define SP_TOKEN_RET_TYPE "ret_type" +#define SP_TOKEN_VALUE "value" +#define SP_TOKEN_VALUE_REGEXP "value_r" +#define SP_TOKEN_KEY "key" +#define SP_TOKEN_KEY_REGEXP "key_r" +#define SP_TOKEN_VALUE_ARG_POS "pos" +#define SP_TOKEN_LINE_NUMBER "line" // cookies encryption -#define SP_TOKEN_NAME ".name(" -#define SP_TOKEN_NAME_REGEXP ".name_r(" +#define SP_TOKEN_NAME "name" +#define SP_TOKEN_NAME_REGEXP "name_r" // cookies samesite -#define SP_TOKEN_SAMESITE ".samesite(" -#define SP_TOKEN_ENCRYPT ".encrypt(" +#define SP_TOKEN_SAMESITE "samesite" +#define SP_TOKEN_ENCRYPT "encrypt" #define SP_TOKEN_SAMESITE_LAX "Lax" #define SP_TOKEN_SAMESITE_STRICT "Strict" // Global configuration options -#define SP_TOKEN_ENCRYPTION_KEY ".secret_key(" -#define SP_TOKEN_ENV_VAR ".cookie_env_var(" -#define SP_TOKEN_LOG_MEDIA ".log_media(" +#define SP_TOKEN_ENCRYPTION_KEY "secret_key" +#define SP_TOKEN_ENV_VAR "cookie_env_var" +#define SP_TOKEN_LOG_MEDIA "log_media" // upload_validator -#define SP_TOKEN_UPLOAD_SCRIPT ".script(" +#define SP_TOKEN_UPLOAD_SCRIPT "script" + +#define SP_TOKEN_LIST "list" + +zend_result sp_process_rule(sp_parsed_keyword *parsed_rule, sp_config_keyword *config_keywords); + +zend_result sp_parse_config(const char *filename); -#define SP_TOKEN_LIST ".list(" +#define SP_PARSE_CHECK_ARG_EXISTS(value) \ +if (!value) { \ + sp_log_err("config", "Missing argument to keyword '%s' - it should be '%s(\"...\")' on line %zu", token, token, kw->lineno); \ + return SP_PARSER_ERROR; \ +} -int sp_parse_config(const char *); -int parse_array(sp_disabled_function *); +#define SP_PARSE_ARG(value) \ + zend_string *value = sp_get_arg_string(kw); \ + SP_PARSE_CHECK_ARG_EXISTS(value); -int parse_str(char *restrict, char *restrict, void *); -int parse_regexp(char *restrict, char *restrict, void *); -int parse_empty(char *restrict, char *restrict, void *); -int parse_cidr(char *restrict, char *restrict, void *); -int parse_php_type(char *restrict, char *restrict, void *); -int parse_list(char *restrict, char *restrict, void *); +SP_PARSEKW_FN(parse_str); +SP_PARSEKW_FN(parse_regexp); +SP_PARSEKW_FN(parse_empty); +SP_PARSEKW_FN(parse_int); +SP_PARSEKW_FN(parse_ulong); +SP_PARSEKW_FN(parse_php_type); +SP_PARSEKW_FN(parse_cidr); +SP_PARSEKW_FN(parse_list); // cleanup void sp_free_disabled_function(void *data); diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index a177a5e..8084698 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c @@ -2,311 +2,236 @@ #define SP_SET_ENABLE_DISABLE(enable, disable, varname) \ if (((varname) || enable) && disable) { \ - sp_log_err("config", "A rule can't be enabled and disabled on line %zu", sp_line_no); \ - return -1; \ + sp_log_err("config", "A rule can't be enabled and disabled on line %zu", parsed_rule->lineno); \ + return SP_PARSER_ERROR; \ } \ if (enable || disable) { \ (varname) = (enable || !disable); \ } -static int parse_enable(char *line, bool *restrict retval, - bool *restrict simulation) { +#define SP_PROCESS_CONFIG_KEYWORDS(CMD) if (sp_process_rule(&(parsed_rule[1]), config_keywords) != SUCCESS) { CMD; } +#define SP_PROCESS_CONFIG_KEYWORDS_ERR() SP_PROCESS_CONFIG_KEYWORDS(return SP_PARSER_ERROR) + +SP_PARSE_FN(parse_enable) { bool enable = false, disable = false; - sp_config_functions sp_config_funcs[] = { + sp_config_keyword config_keywords[] = { {parse_empty, SP_TOKEN_ENABLE, &(enable)}, {parse_empty, SP_TOKEN_DISABLE, &(disable)}, - {parse_empty, SP_TOKEN_SIMULATION, simulation}, {0, 0, 0}}; - int ret = parse_keywords(sp_config_funcs, line); - - if (0 != ret) { - return ret; - } + SP_PROCESS_CONFIG_KEYWORDS_ERR(); - SP_SET_ENABLE_DISABLE(enable, disable, *retval); + SP_SET_ENABLE_DISABLE(enable, disable, *(bool*)retval); - return ret; + return SP_PARSER_STOP; } -int parse_session(char *line) { - sp_config_session *session = pecalloc(sizeof(sp_config_session), 1, 0); +SP_PARSE_FN(parse_session) { + sp_config_session *cfg = retval; - sp_config_functions sp_config_funcs_session_encryption[] = { - {parse_empty, SP_TOKEN_ENCRYPT, &(session->encrypt)}, - {parse_empty, SP_TOKEN_SIMULATION, &(session->simulation)}, + sp_config_keyword config_keywords[] = { + {parse_empty, SP_TOKEN_ENCRYPT, &(cfg->encrypt)}, + {parse_empty, SP_TOKEN_SIMULATION, &(cfg->simulation)}, + {parse_empty, SP_TOKEN_SIM, &(cfg->simulation)}, {0, 0, 0}}; - int ret = parse_keywords(sp_config_funcs_session_encryption, line); - if (0 != ret) { - return ret; - } + + SP_PROCESS_CONFIG_KEYWORDS_ERR(); #if (!HAVE_PHP_SESSION || defined(COMPILE_DL_SESSION)) - sp_log_err( - "config", + sp_log_err("config", "You're trying to use the session cookie encryption feature " "on line %zu without having session support statically built into PHP. " "This isn't supported, see " - "https://github.com/jvoisin/snuffleupagus/issues/278 for details.", - sp_line_no); - pefree(session, 0); - return -1; + "https://github.com/jvoisin/snuffleupagus/issues/278 for details.", parsed_rule->lineno); + return SP_PARSER_ERROR; #endif - if (session->encrypt) { - if (0 == (SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)) { - sp_log_err( - "config", - "You're trying to use the session cookie encryption feature " - "on line %zu without having set the `.cookie_env_var` option in" - "`sp.global`: please set it first", - sp_line_no); - pefree(session, 0); - return -1; - } else if (0 == - (SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)) { - sp_log_err("config", - "You're trying to use the session cookie encryption feature " - "on line %zu without having set the `.secret_key` option in" - "`sp.global`: please set it first", - sp_line_no); - pefree(session, 0); - return -1; + if (cfg->encrypt) { + if (!SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var) { + sp_log_err("config", "You're trying to use the session cookie encryption feature " + "on line %zu without having set the `.cookie_env_var` option in " + "`sp.global`: please set it first", parsed_rule->lineno); + return SP_PARSER_ERROR; + } else if (!SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key) { + sp_log_err("config", "You're trying to use the session cookie encryption feature " + "on line %zu without having set the `.secret_key` option in " + "`sp.global`: please set it first", parsed_rule->lineno); + return SP_PARSER_ERROR; } } - SNUFFLEUPAGUS_G(config).config_session->encrypt = session->encrypt; - SNUFFLEUPAGUS_G(config).config_session->simulation = session->simulation; - pefree(session, 0); - return ret; -} - -int parse_random(char *line) { - return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_random->enable), - NULL); + return SP_PARSER_STOP; } -int parse_log_media(char *line) { - size_t consumed = 0; - zend_string *value = - get_param(&consumed, line, SP_TYPE_STR, SP_TOKEN_LOG_MEDIA); - - if (value) { - if (!strcmp(ZSTR_VAL(value), "php")) { - SNUFFLEUPAGUS_G(config).log_media = SP_ZEND; - return 0; - } else if (!strcmp(ZSTR_VAL(value), "syslog")) { - SNUFFLEUPAGUS_G(config).log_media = SP_SYSLOG; - return 0; - } +SP_PARSEKW_FN(parse_log_media) { + SP_PARSE_ARG(value); + + if (!strcmp(ZSTR_VAL(value), "php")) { + *(char*)retval = SP_ZEND; + zend_string_release_ex(value, 1); + return SP_PARSER_SUCCESS; + } else if (!strcmp(ZSTR_VAL(value), "syslog")) { + *(char*)retval = SP_SYSLOG; + zend_string_release_ex(value, 1); + return SP_PARSER_SUCCESS; } - sp_log_err("config", "%s) only supports 'syslog' or 'php', on line %zu", - SP_TOKEN_LOG_MEDIA, sp_line_no); - return -1; -} - -int parse_sloppy_comparison(char *line) { - return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_sloppy->enable), - NULL); -} -int parse_disable_xxe(char *line) { - return parse_enable( - line, &(SNUFFLEUPAGUS_G(config).config_disable_xxe->enable), NULL); -} - -int parse_auto_cookie_secure(char *line) { - return parse_enable( - line, &(SNUFFLEUPAGUS_G(config).config_auto_cookie_secure->enable), NULL); -} + sp_log_err("config", "." SP_TOKEN_LOG_MEDIA "() only supports 'syslog' or 'php' on line %zu", kw->lineno); -int parse_global_strict(char *line) { - return parse_enable( - line, &(SNUFFLEUPAGUS_G(config).config_global_strict->enable), NULL); + return SP_PARSER_ERROR; } -int parse_unserialize(char *line) { +SP_PARSE_FN(parse_unserialize) { bool enable = false, disable = false; - sp_config_unserialize *unserialize = - SNUFFLEUPAGUS_G(config).config_unserialize; + sp_config_unserialize *cfg = (sp_config_unserialize*)retval; - sp_config_functions sp_config_funcs[] = { + sp_config_keyword config_keywords[] = { {parse_empty, SP_TOKEN_ENABLE, &(enable)}, {parse_empty, SP_TOKEN_DISABLE, &(disable)}, - {parse_empty, SP_TOKEN_SIMULATION, &(unserialize->simulation)}, - {parse_str, SP_TOKEN_DUMP, &(unserialize->dump)}, + {parse_empty, SP_TOKEN_SIMULATION, &(cfg->simulation)}, + {parse_empty, SP_TOKEN_SIM, &(cfg->simulation)}, + {parse_str, SP_TOKEN_DUMP, &(cfg->dump)}, {0, 0, 0}}; - unserialize->textual_representation = zend_string_init(line, strlen(line), 1); + SP_PROCESS_CONFIG_KEYWORDS_ERR(); - int ret = parse_keywords(sp_config_funcs, line); - if (0 != ret) { - return ret; - } + SP_SET_ENABLE_DISABLE(enable, disable, cfg->enable); - SP_SET_ENABLE_DISABLE(enable, disable, SNUFFLEUPAGUS_G(config).config_unserialize->enable); + cfg->textual_representation = sp_get_textual_representation(parsed_rule); - return ret; + return SP_PARSER_STOP; } -int parse_readonly_exec(char *line) { +SP_PARSE_FN(parse_readonly_exec) { bool enable = false, disable = false; - sp_config_readonly_exec *readonly_exec = - SNUFFLEUPAGUS_G(config).config_readonly_exec; + sp_config_readonly_exec *cfg = (sp_config_readonly_exec*)retval; - sp_config_functions sp_config_funcs[] = { + sp_config_keyword config_keywords[] = { {parse_empty, SP_TOKEN_ENABLE, &(enable)}, {parse_empty, SP_TOKEN_DISABLE, &(disable)}, - {parse_empty, SP_TOKEN_SIMULATION, &(readonly_exec->simulation)}, - {parse_str, SP_TOKEN_DUMP, &(readonly_exec->dump)}, + {parse_empty, SP_TOKEN_SIMULATION, &(cfg->simulation)}, + {parse_empty, SP_TOKEN_SIM, &(cfg->simulation)}, + {parse_str, SP_TOKEN_DUMP, &(cfg->dump)}, {0, 0, 0}}; - readonly_exec->textual_representation = - zend_string_init(line, strlen(line), 1); - int ret = parse_keywords(sp_config_funcs, line); + SP_PROCESS_CONFIG_KEYWORDS_ERR(); - if (0 != ret) { - return ret; - } + cfg->textual_representation = sp_get_textual_representation(parsed_rule); - SP_SET_ENABLE_DISABLE(enable, disable, SNUFFLEUPAGUS_G(config).config_readonly_exec->enable); + SP_SET_ENABLE_DISABLE(enable, disable, cfg->enable); - return ret; + return SP_PARSER_STOP; } -int parse_global(char *line) { - sp_config_functions sp_config_funcs_global[] = { - {parse_str, SP_TOKEN_ENCRYPTION_KEY, - &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)}, - {parse_str, SP_TOKEN_ENV_VAR, - &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)}, +SP_PARSE_FN(parse_global) { + sp_config_keyword config_keywords[] = { + {parse_str, SP_TOKEN_ENCRYPTION_KEY, &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)}, + {parse_str, SP_TOKEN_ENV_VAR, &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)}, + {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SNUFFLEUPAGUS_G(config).log_media)}, {0, 0, 0}}; - return parse_keywords(sp_config_funcs_global, line); + + SP_PROCESS_CONFIG_KEYWORDS_ERR(); + return SP_PARSER_STOP; } -static int parse_eval_filter_conf(char *line, sp_list_node **list) { - sp_config_eval *eval = SNUFFLEUPAGUS_G(config).config_eval; +SP_PARSE_FN(parse_eval_filter_conf) { + sp_config_eval *cfg = SNUFFLEUPAGUS_G(config).config_eval; - sp_config_functions sp_config_funcs[] = { - {parse_list, SP_TOKEN_LIST, list}, - {parse_empty, SP_TOKEN_SIMULATION, - &(SNUFFLEUPAGUS_G(config).config_eval->simulation)}, - {parse_str, SP_TOKEN_DUMP, &(SNUFFLEUPAGUS_G(config).config_eval->dump)}, + sp_config_keyword config_keywords[] = { + {parse_list, SP_TOKEN_LIST, retval}, + {parse_empty, SP_TOKEN_SIMULATION, &(cfg->simulation)}, + {parse_empty, SP_TOKEN_SIM, &(cfg->simulation)}, + {parse_str, SP_TOKEN_DUMP, &(cfg->dump)}, {0, 0, 0}}; - eval->textual_representation = zend_string_init(line, strlen(line), 1); + SP_PROCESS_CONFIG_KEYWORDS_ERR(); - int ret = parse_keywords(sp_config_funcs, line); - if (0 != ret) { - return ret; - } + cfg->textual_representation = sp_get_textual_representation(parsed_rule); - return SUCCESS; + return SP_PARSER_STOP; } -int parse_wrapper_whitelist(char *line) { - SNUFFLEUPAGUS_G(config).config_wrapper->enabled = true; - sp_config_functions sp_config_funcs[] = { - {parse_list, SP_TOKEN_LIST, - &SNUFFLEUPAGUS_G(config).config_wrapper->whitelist}, +SP_PARSE_FN(parse_wrapper_whitelist) { + sp_config_wrapper *cfg = (sp_config_wrapper*)retval; + + sp_config_keyword config_keywords[] = { + {parse_list, SP_TOKEN_LIST, &cfg->whitelist}, {0, 0, 0}}; - int ret = parse_keywords(sp_config_funcs, line); - if (0 != ret) { - return ret; - } - return SUCCESS; -} -int parse_eval_blacklist(char *line) { - return parse_eval_filter_conf( - line, &SNUFFLEUPAGUS_G(config).config_eval->blacklist); -} + SP_PROCESS_CONFIG_KEYWORDS_ERR(); + + cfg->enabled = true; -int parse_eval_whitelist(char *line) { - return parse_eval_filter_conf( - line, &SNUFFLEUPAGUS_G(config).config_eval->whitelist); + return SP_PARSER_STOP; } -int parse_cookie(char *line) { +SP_PARSE_FN(parse_cookie) { int ret = 0; zend_string *samesite = NULL; sp_cookie *cookie = pecalloc(sizeof(sp_cookie), 1, 1); - sp_config_functions sp_config_funcs_cookie_encryption[] = { + sp_config_keyword config_keywords[] = { {parse_str, SP_TOKEN_NAME, &(cookie->name)}, {parse_regexp, SP_TOKEN_NAME_REGEXP, &(cookie->name_r)}, {parse_str, SP_TOKEN_SAMESITE, &samesite}, {parse_empty, SP_TOKEN_ENCRYPT, &cookie->encrypt}, {parse_empty, SP_TOKEN_SIMULATION, &cookie->simulation}, + {parse_empty, SP_TOKEN_SIM, &cookie->simulation}, {0, 0, 0}}; - ret = parse_keywords(sp_config_funcs_cookie_encryption, line); - if (0 != ret) { - return ret; - } + SP_PROCESS_CONFIG_KEYWORDS(goto err); if (cookie->encrypt) { - if (0 == (SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)) { - sp_log_err( - "config", - "You're trying to use the cookie encryption feature" - "on line %zu without having set the `.cookie_env_var` option in" - "`sp.global`: please set it first", - sp_line_no); - return -1; - } else if (0 == - (SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)) { - sp_log_err( - "config", - "You're trying to use the cookie encryption feature" - "on line %zu without having set the `.encryption_key` option in" - "`sp.global`: please set it first", - sp_line_no); - return -1; + if (!SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var) { + sp_log_err("config", "You're trying to use the cookie encryption feature on line %zu " + "without having set the `." SP_TOKEN_ENV_VAR "` option in`sp.global`: please set it first", parsed_rule->lineno); + goto err; + } else if (!SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key) { + sp_log_err("config", "You're trying to use the cookie encryption feature " + "on line %zu without having set the `." SP_TOKEN_ENCRYPTION_KEY "` option in " + "`sp." SP_TOKEN_GLOBAL "`: please set it first", parsed_rule->lineno); + goto err; } } else if (!samesite) { - sp_log_err("config", - "You must specify a at least one action to a cookie on line " - "%zu", - sp_line_no); - return -1; + sp_log_err("config", "You must specify a at least one action to a cookie on line %zu", parsed_rule->lineno); + goto err; } if ((!cookie->name || 0 == ZSTR_LEN(cookie->name)) && !cookie->name_r) { - sp_log_err("config", - "You must specify a cookie name/regexp on line " - "%zu", - sp_line_no); - return -1; + sp_log_err("config", "You must specify a cookie name/regexp on line %zu", parsed_rule->lineno); + goto err; } if (cookie->name && cookie->name_r) { - sp_log_err("config", - "name and name_r are mutually exclusive on line " - "%zu", - sp_line_no); - return -1; + sp_log_err("config", "name and name_r are mutually exclusive on line %zu", parsed_rule->lineno); + goto err; } if (samesite) { if (zend_string_equals_literal_ci(samesite, SP_TOKEN_SAMESITE_LAX)) { cookie->samesite = lax; - } else if (zend_string_equals_literal_ci(samesite, - SP_TOKEN_SAMESITE_STRICT)) { + } else if (zend_string_equals_literal_ci(samesite, SP_TOKEN_SAMESITE_STRICT)) { cookie->samesite = strict; } else { - sp_log_err( - "config", - "%s is an invalid value to samesite (expected %s or %s) on line " - "%zu", - ZSTR_VAL(samesite), SP_TOKEN_SAMESITE_LAX, SP_TOKEN_SAMESITE_STRICT, - sp_line_no); - return -1; + sp_log_err("config", "'%s' is an invalid value to samesite (expected " SP_TOKEN_SAMESITE_LAX " or " SP_TOKEN_SAMESITE_STRICT ") on line %zu", + ZSTR_VAL(samesite), parsed_rule->lineno); + goto err; } } - SNUFFLEUPAGUS_G(config).config_cookie->cookies = - sp_list_insert(SNUFFLEUPAGUS_G(config).config_cookie->cookies, cookie); - return SUCCESS; + + SNUFFLEUPAGUS_G(config).config_cookie->cookies = sp_list_insert(SNUFFLEUPAGUS_G(config).config_cookie->cookies, cookie); + + return SP_PARSER_STOP; + +err: + if (samesite) { + zend_string_release(samesite); + } + if (cookie) { + sp_free_cookie(cookie); + pefree(cookie, 1); + } + return SP_PARSER_ERROR; } -int add_df_to_hashtable(HashTable *ht, sp_disabled_function *df) { +static int add_df_to_hashtable(HashTable *ht, sp_disabled_function *df) { zval *list = zend_hash_find(ht, df->function); if (NULL == list) { @@ -317,19 +242,19 @@ int add_df_to_hashtable(HashTable *ht, sp_disabled_function *df) { return SUCCESS; } -int parse_disabled_functions(char *line) { - int ret = 0; - bool enable = true, disable = false, allow = false, drop = false; - zend_string *pos = NULL, *var = NULL, *param = NULL; - zend_string *line_number = NULL; +SP_PARSE_FN(parse_disabled_functions) { + int ret = SP_PARSER_ERROR; + bool enable = false, disable = false, allow = false, drop = false; + zend_string *var = NULL, *param = NULL; sp_disabled_function *df = pecalloc(sizeof(*df), 1, 1); df->pos = -1; - sp_config_functions sp_config_funcs_disabled_functions[] = { + sp_config_keyword config_keywords[] = { {parse_empty, SP_TOKEN_ENABLE, &(enable)}, {parse_empty, SP_TOKEN_DISABLE, &(disable)}, {parse_str, SP_TOKEN_ALIAS, &(df->alias)}, {parse_empty, SP_TOKEN_SIMULATION, &(df->simulation)}, + {parse_empty, SP_TOKEN_SIM, &(df->simulation)}, {parse_str, SP_TOKEN_FILENAME, &(df->filename)}, {parse_regexp, SP_TOKEN_FILENAME_REGEXP, &(df->r_filename)}, {parse_str, SP_TOKEN_FUNCTION, &(df->function)}, @@ -350,23 +275,21 @@ int parse_disabled_functions(char *line) { {parse_regexp, SP_TOKEN_RET_REGEXP, &(df->r_ret)}, {parse_php_type, SP_TOKEN_RET_TYPE, &(df->ret_type)}, {parse_str, SP_TOKEN_LOCAL_VAR, &(var)}, - {parse_str, SP_TOKEN_VALUE_ARG_POS, &(pos)}, - {parse_str, SP_TOKEN_LINE_NUMBER, &(line_number)}, + {parse_int, SP_TOKEN_VALUE_ARG_POS, &(df->pos)}, + {parse_ulong, SP_TOKEN_LINE_NUMBER, &(df->line)}, {0, 0, 0}}; - ret = parse_keywords(sp_config_funcs_disabled_functions, line); + SP_PROCESS_CONFIG_KEYWORDS(goto out); - if (0 != ret) { - goto out; + SP_SET_ENABLE_DISABLE(enable, disable, enable); + if (disable) { + ret = SP_PARSER_STOP; goto out; } #define MUTUALLY_EXCLUSIVE(X, Y, STR1, STR2) \ if (X && Y) { \ - sp_log_err("config", \ - "Invalid configuration line: 'sp.disabled_functions%s': " \ - "'.%s' and '.%s' are mutually exclusive on line %zu", \ - line, STR1, STR2, sp_line_no); \ - ret = -1; goto out; \ + sp_log_err("config", "Invalid configuration line for 'sp.disabled_functions': '.%s' and '.%s' are mutually exclusive on line %zu", STR1, STR2, parsed_rule->lineno); \ + goto out; \ } MUTUALLY_EXCLUSIVE(df->value, df->r_value, "value", "value_r"); @@ -374,8 +297,8 @@ int parse_disabled_functions(char *line) { MUTUALLY_EXCLUSIVE(df->filename, df->r_filename, "filename", "filename_r"); MUTUALLY_EXCLUSIVE(df->ret, df->r_ret, "ret", "ret_r"); MUTUALLY_EXCLUSIVE(df->key, df->r_key, "key", "key_r"); - MUTUALLY_EXCLUSIVE(pos, param, "pos", "param"); - MUTUALLY_EXCLUSIVE(pos, df->r_param, "pos", "param_r"); + MUTUALLY_EXCLUSIVE((df->pos >= 0), param, "pos", "param"); + MUTUALLY_EXCLUSIVE((df->pos >= 0), df->r_param, "pos", "param_r"); MUTUALLY_EXCLUSIVE(param, df->r_param, "param", "param_r"); MUTUALLY_EXCLUSIVE((df->r_key || df->key), (df->r_value || df->value), "key", "value"); MUTUALLY_EXCLUSIVE((df->r_ret || df->ret || df->ret_type), (df->r_param || param), "ret", "param"); @@ -385,52 +308,21 @@ int parse_disabled_functions(char *line) { #undef MUTUALLY_EXCLUSIVE if (!(df->r_function || df->function)) { - sp_log_err("config", - "Invalid configuration line: 'sp.disabled_functions%s':" - " must take a function name on line %zu", - line, sp_line_no); - ret = -1; goto out; + sp_log_err("config", "Invalid configuration line: 'sp.disabled_functions': must take a function name on line %zu", parsed_rule->lineno); + goto out; } if (df->filename && (*ZSTR_VAL(df->filename) != '/') && (0 != strncmp(ZSTR_VAL(df->filename), "phar://", strlen("phar://")))) { - sp_log_err( - "config", - "Invalid configuration line: 'sp.disabled_functions%s':" - "'.filename' must be an absolute path or a phar archive on line %zu", - line, sp_line_no); - ret = -1; goto out; + sp_log_err("config", "Invalid configuration line: 'sp.disabled_functions': '.filename' must be an absolute path or a phar archive on line %zu", parsed_rule->lineno); + goto out; } if (!(allow ^ drop)) { - sp_log_err("config", - "Invalid configuration line: 'sp.disabled_functions%s': The " - "rule must either be a `drop` or `allow` one on line %zu", - line, sp_line_no); - ret = -1; goto out; - } - - if (pos) { - errno = 0; - char *endptr; - df->pos = (int)strtol(ZSTR_VAL(pos), &endptr, 10); - if (errno != 0 || endptr == ZSTR_VAL(pos)) { - sp_log_err("config", "Failed to parse arg '%s' of `pos` on line %zu", - ZSTR_VAL(pos), sp_line_no); - ret = -1; goto out; - } + sp_log_err("config", "Invalid configuration line: 'sp.disabled_functions': The rule must either be a `drop` or `allow` one on line %zu", parsed_rule->lineno); + goto out; } - if (line_number) { - errno = 0; - char *endptr; - df->line = (unsigned int)strtoul(ZSTR_VAL(line_number), &endptr, 10); - if (errno != 0 || endptr == ZSTR_VAL(line_number)) { - sp_log_err("config", "Failed to parse arg '%s' of `line` on line %zu", - ZSTR_VAL(line_number), sp_line_no); - ret = -1; goto out; - } - } df->allow = allow; - df->textual_representation = zend_string_init(line, strlen(line), 1); + df->textual_representation = sp_get_textual_representation(parsed_rule); if (df->function) { df->functions_list = parse_functions_list(ZSTR_VAL(df->function)); @@ -450,33 +342,23 @@ int parse_disabled_functions(char *line) { df->param = sp_parse_var(ZSTR_VAL(param)); } if (!df->param) { - sp_log_err("config", "Invalid value '%s' for `param` on line %zu", - ZSTR_VAL(param), sp_line_no); - ret = -1; goto out; + sp_log_err("config", "Invalid value '%s' for `param` on line %zu", ZSTR_VAL(param), parsed_rule->lineno); + goto out; } } - if (var) { if (ZSTR_LEN(var)) { df->var = sp_parse_var(ZSTR_VAL(var)); if (!df->var) { - sp_log_err("config", "Invalid value '%s' for `var` on line %zu", - ZSTR_VAL(var), sp_line_no); - ret = -1; goto out; + sp_log_err("config", "Invalid value '%s' for `var` on line %zu", ZSTR_VAL(var), parsed_rule->lineno); + goto out; } } else { - sp_log_err("config", "Empty value in `var` on line %zu", sp_line_no); - ret = -1; goto out; + sp_log_err("config", "Empty value in `var` on line %zu", parsed_rule->lineno); + goto out; } } - if (true == disable || 0 != ret) { - out: - sp_free_disabled_function(df); - pefree(df, 1); - return ret; - } - if (df->function && zend_string_equals_literal(df->function, "print")) { zend_string_release(df->function); df->function = zend_string_init("echo", sizeof("echo") - 1, 1); @@ -484,148 +366,136 @@ int parse_disabled_functions(char *line) { if (df->function && !df->functions_list) { if (df->ret || df->r_ret || df->ret_type) { - add_df_to_hashtable(SNUFFLEUPAGUS_G(config).config_disabled_functions_ret, - df); + add_df_to_hashtable(SNUFFLEUPAGUS_G(config).config_disabled_functions_ret, df); } else { - add_df_to_hashtable(SNUFFLEUPAGUS_G(config).config_disabled_functions, - df); + add_df_to_hashtable(SNUFFLEUPAGUS_G(config).config_disabled_functions, df); } } else { if (df->ret || df->r_ret || df->ret_type) { - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg_ret->disabled_functions = - sp_list_insert( - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg_ret->disabled_functions, - df); + SNUFFLEUPAGUS_G(config).config_disabled_functions_reg_ret->disabled_functions = sp_list_insert(SNUFFLEUPAGUS_G(config).config_disabled_functions_reg_ret->disabled_functions, df); } else { - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg->disabled_functions = - sp_list_insert(SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg->disabled_functions, - df); + SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions = sp_list_insert(SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions, df); } } + return SP_PARSER_STOP; + +out: + if (df) { + sp_free_disabled_function(df); + pefree(df, 1); + } + if (param) { zend_string_release(param); } + if (var) { zend_string_release(var); } + return ret; } -int parse_upload_validation(char *line) { +SP_PARSE_FN(parse_upload_validation) { bool disable = false, enable = false; - sp_config_functions sp_config_funcs_upload_validation[] = { - {parse_str, SP_TOKEN_UPLOAD_SCRIPT, - &(SNUFFLEUPAGUS_G(config).config_upload_validation->script)}, - {parse_empty, SP_TOKEN_SIMULATION, - &(SNUFFLEUPAGUS_G(config).config_upload_validation->simulation)}, + sp_config_upload_validation *cfg = (sp_config_upload_validation*)retval; + + sp_config_keyword config_keywords[] = { {parse_empty, SP_TOKEN_ENABLE, &(enable)}, {parse_empty, SP_TOKEN_DISABLE, &(disable)}, + {parse_str, SP_TOKEN_UPLOAD_SCRIPT, &(cfg->script)}, + {parse_empty, SP_TOKEN_SIMULATION, &(cfg->simulation)}, + {parse_empty, SP_TOKEN_SIM, &(cfg->simulation)}, {0, 0, 0}}; - int ret = parse_keywords(sp_config_funcs_upload_validation, line); - - if (0 != ret) { - return ret; - } + SP_PROCESS_CONFIG_KEYWORDS_ERR(); + SP_SET_ENABLE_DISABLE(enable, disable, cfg->enable); - SP_SET_ENABLE_DISABLE(enable, disable, SNUFFLEUPAGUS_G(config).config_upload_validation->enable); - - zend_string const *script = - SNUFFLEUPAGUS_G(config).config_upload_validation->script; - - if (!script) { - sp_log_err("config", - "The `script` directive is mandatory in '%s' on line %zu", line, - sp_line_no); - return -1; - } else if (-1 == access(ZSTR_VAL(script), F_OK)) { - sp_log_err("config", "The `script` (%s) doesn't exist on line %zu", - ZSTR_VAL(script), sp_line_no); - return -1; - } else if (-1 == access(ZSTR_VAL(script), X_OK)) { - sp_log_err("config", "The `script` (%s) isn't executable on line %zu", - ZSTR_VAL(script), sp_line_no); - return -1; + if (!cfg->script) { + sp_log_err("config", "The `script` directive is mandatory in '.%s' on line %zu", token, parsed_rule->lineno); + return SP_PARSER_ERROR; + } else if (-1 == access(ZSTR_VAL(cfg->script), F_OK)) { + sp_log_err("config", "The `script` (%s) doesn't exist on line %zu", ZSTR_VAL(cfg->script), parsed_rule->lineno); + return SP_PARSER_ERROR; + } else if (-1 == access(ZSTR_VAL(cfg->script), X_OK)) { + sp_log_err("config", "The `script` (%s) isn't executable on line %zu", ZSTR_VAL(cfg->script), parsed_rule->lineno); + return SP_PARSER_ERROR; } - return ret; + return SP_PARSER_STOP; } -int parse_ini_protection(char *line) { +SP_PARSE_FN(parse_ini_protection) { bool disable = false, enable = false; bool rw = false, ro = false; // rw is ignored, but declaring .policy_rw is valid for readability - sp_config_ini *cfg = SNUFFLEUPAGUS_G(config).config_ini; - sp_config_functions sp_config_ini_protection[] = { - {parse_empty, SP_TOKEN_ENABLE, &(enable)}, - {parse_empty, SP_TOKEN_DISABLE, &(disable)}, - {parse_empty, SP_TOKEN_SIMULATION, &cfg->simulation}, - {parse_empty, ".policy_readonly(", &ro}, - {parse_empty, ".policy_ro(", &ro}, - {parse_empty, ".policy_readwrite(", &rw}, - {parse_empty, ".policy_rw(", &rw}, - {parse_empty, ".policy_silent_ro(", &cfg->policy_silent_ro}, - {parse_empty, ".policy_silent_fail(", &cfg->policy_silent_fail}, - {parse_empty, ".policy_no_log(", &cfg->policy_silent_fail}, - {parse_empty, ".policy_drop(", &cfg->policy_drop}, + sp_config_ini *cfg = (sp_config_ini*)retval; + sp_config_keyword config_keywords[] = { + {parse_empty, "enable", &(enable)}, + {parse_empty, "disable", &(disable)}, + {parse_empty, "simulation", &cfg->simulation}, + {parse_empty, "sim", &cfg->simulation}, + {parse_empty, "policy_readonly", &ro}, + {parse_empty, "policy_ro", &ro}, + {parse_empty, "policy_readwrite", &rw}, + {parse_empty, "policy_rw", &rw}, + {parse_empty, "policy_silent_ro", &cfg->policy_silent_ro}, + {parse_empty, "policy_silent_fail", &cfg->policy_silent_fail}, + {parse_empty, "policy_no_log", &cfg->policy_silent_fail}, + {parse_empty, "policy_drop", &cfg->policy_drop}, {0, 0, 0}}; - int ret = parse_keywords(sp_config_ini_protection, line); - if (ret) { return ret; } + SP_PROCESS_CONFIG_KEYWORDS_ERR(); SP_SET_ENABLE_DISABLE(enable, disable, cfg->enable); if (ro && rw) { - sp_log_err("config", "rule cannot be both read-write and read-only on line %zu", sp_line_no); - return -1; + sp_log_err("config", "rule cannot be both read-write and read-only on line %zu", parsed_rule->lineno); + return SP_PARSER_ERROR; } cfg->policy_readonly = ro; if (cfg->policy_silent_fail && cfg->policy_drop) { - sp_log_err("config", "policy cannot be drop and silent at the same time on line %zu", sp_line_no); - return -1; + sp_log_err("config", "policy cannot be drop and silent at the same time on line %zu", parsed_rule->lineno); + return SP_PARSER_ERROR; } - return ret; + return SP_PARSER_STOP; } -int parse_ini_entry(char *line) { +SP_PARSE_FN(parse_ini_entry) { sp_ini_entry *entry = pecalloc(sizeof(sp_ini_entry), 1, 1); bool rw = false, ro = false; - sp_config_functions sp_config_ini_protection[] = { - {parse_empty, SP_TOKEN_SIMULATION, &entry->simulation}, - {parse_str, ".key(", &entry->key}, - {parse_str, ".msg(", &entry->msg}, - {parse_str, ".set(", &entry->set}, - {parse_str, ".min(", &entry->min}, - {parse_str, ".max(", &entry->max}, - {parse_regexp, ".regexp(", &entry->regexp}, - {parse_empty, ".readonly(", &ro}, - {parse_empty, ".ro(", &ro}, - {parse_empty, ".readwrite(", &rw}, - {parse_empty, ".rw(", &rw}, - {parse_empty, ".drop(", &entry->drop}, - {parse_empty, ".allow_null(", &entry->allow_null}, + sp_config_keyword config_keywords[] = { + {parse_empty, "simulation", &entry->simulation}, + {parse_empty, "sim", &entry->simulation}, + {parse_str, "key", &entry->key}, + {parse_str, "msg", &entry->msg}, + {parse_str, "set", &entry->set}, + {parse_str, "min", &entry->min}, + {parse_str, "max", &entry->max}, + {parse_regexp, "regexp", &entry->regexp}, + {parse_empty, "readonly", &ro}, + {parse_empty, "ro", &ro}, + {parse_empty, "readwrite", &rw}, + {parse_empty, "rw", &rw}, + {parse_empty, "drop", &entry->drop}, + {parse_empty, "allow_null", &entry->allow_null}, {0, 0, 0}}; - int ret = parse_keywords(sp_config_ini_protection, line); - if (ret) { goto err; } + SP_PROCESS_CONFIG_KEYWORDS(goto err); - if (!entry->key) { - sp_log_err("config", "A .key() must be provided on line %zu", sp_line_no); - ret = -1; goto err; + if (!entry->key) { + sp_log_err("config", "A .key() must be provided on line %zu", parsed_rule->lineno); + goto err; } if (ro && rw) { - sp_log_err("config", "rule cannot be both read-write and read-only on line %zu", sp_line_no); - ret = -1; goto err; + sp_log_err("config", "rule cannot be both read-write and read-only on line %zu", parsed_rule->lineno); + goto err; } entry->access = ro - rw; zend_hash_add_ptr(SNUFFLEUPAGUS_G(config).config_ini->entries, entry->key, entry); - return ret; + return SP_PARSER_STOP; err: if (entry) { sp_free_ini_entry(entry); pefree(entry, 1); } - return ret; + return SP_PARSER_ERROR; } \ No newline at end of file diff --git a/src/sp_config_keywords.h b/src/sp_config_keywords.h index b90c06c..01eb0d1 100644 --- a/src/sp_config_keywords.h +++ b/src/sp_config_keywords.h @@ -2,23 +2,18 @@ #define SP_CONFIG_KEYWORDS_H #include "php_snuffleupagus.h" -int parse_random(char *line); -int parse_disable_xxe(char *line); -int parse_auto_cookie_secure(char *line); -int parse_global_strict(char *line); -int parse_global(char *line); -int parse_cookie(char *line); -int parse_unserialize(char *line); -int parse_readonly_exec(char *line); -int parse_disabled_functions(char *line); -int parse_upload_validation(char *line); -int parse_eval_blacklist(char *line); -int parse_eval_whitelist(char *line); -int parse_session(char *line); -int parse_sloppy_comparison(char *line); -int parse_wrapper_whitelist(char *line); -int parse_log_media(char *line); -int parse_ini_protection(char *line); -int parse_ini_entry(char *line); +SP_PARSE_FN(parse_enable); +SP_PARSE_FN(parse_global); +SP_PARSE_FN(parse_cookie); +SP_PARSE_FN(parse_unserialize); +SP_PARSE_FN(parse_readonly_exec); +SP_PARSE_FN(parse_disabled_functions); +SP_PARSE_FN(parse_upload_validation); +SP_PARSE_FN(parse_eval_filter_conf); +SP_PARSE_FN(parse_session); +SP_PARSE_FN(parse_wrapper_whitelist); +SP_PARSE_FN(parse_log_media); +SP_PARSE_FN(parse_ini_protection); +SP_PARSE_FN(parse_ini_entry); #endif // __SP_CONFIG_KEYWORDS_H diff --git a/src/sp_config_scanner.h b/src/sp_config_scanner.h new file mode 100644 index 0000000..3284713 --- /dev/null +++ b/src/sp_config_scanner.h @@ -0,0 +1,25 @@ + +#ifndef SP_CONFIG_SCANNER_H +#define SP_CONFIG_SCANNER_H + +typedef enum { + SP_ARGTYPE_UNKNOWN = 0, + SP_ARGTYPE_NONE, + SP_ARGTYPE_EMPTY, + SP_ARGTYPE_STR +} sp_argtype; + +typedef struct { + char *kw; // keyword points directly to the parsed input text and as such is not null-terminated + size_t kwlen; + char *arg; // optional argument / can be not null terminated + size_t arglen; + sp_argtype argtype; + long lineno; +} sp_parsed_keyword; + +zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_keyword*)); +zend_string *sp_get_arg_string(sp_parsed_keyword *kw); +zend_string *sp_get_textual_representation(sp_parsed_keyword *parsed_rule); + +#endif \ No newline at end of file diff --git a/src/sp_config_scanner.re b/src/sp_config_scanner.re new file mode 100644 index 0000000..075c343 --- /dev/null +++ b/src/sp_config_scanner.re @@ -0,0 +1,139 @@ +#include "php_snuffleupagus.h" + +/*!types:re2c*/ + +#define cs_error_log(fmt, ...) sp_log_err("config", fmt, ##__VA_ARGS__) + +zend_string *sp_get_arg_string(sp_parsed_keyword *kw) { + if (!kw || !kw->arg) { + return NULL; + } + zend_string *ret = zend_string_init(kw->arg, kw->arglen, 1); + char *pin, *pout; + pin = pout = ZSTR_VAL(ret); + char *pend = pin + ZSTR_LEN(ret); + + while (pin < pend) { + if (*pin == '\\') { + pin++; + } + *pout = *pin; + pin++; pout++; + } + + if (pin != pout) { + size_t len = pout - ZSTR_VAL(ret); + ret = zend_string_truncate(ret, len, 1); + ZSTR_VAL(ret)[len] = 0; + } + + return ret; +} + +zend_string *sp_get_textual_representation(sp_parsed_keyword *parsed_rule) { + // a rule is "sp.keyword...keyword(arg);\0" + size_t len = 3; // sp + ; + sp_parsed_keyword *kw; + for (kw = parsed_rule; kw->kw; kw++) { + len++; // . + len += kw->kwlen; + if (kw->argtype == SP_ARGTYPE_EMPTY) { + len += 2; // () + } else if (kw->argtype == SP_ARGTYPE_STR) { + len += 4; + len += kw->arglen; + } + } + zend_string *ret = zend_string_alloc(len, 1); + char *ptr = ZSTR_VAL(ret); + memcpy(ptr, "sp", 2); ptr += 2; + for (kw = parsed_rule; kw->kw; kw++) { + *ptr++ = '.'; + memcpy(ptr, kw->kw, kw->kwlen); ptr += kw->kwlen; + if (kw->argtype == SP_ARGTYPE_EMPTY || kw->argtype == SP_ARGTYPE_STR || kw->argtype == SP_ARGTYPE_UNKNOWN) { + *ptr++ = '('; + } + if (kw->argtype == SP_ARGTYPE_STR && kw->arg) { + *ptr++ = '"'; + memcpy(ptr, kw->arg, kw->arglen); ptr += kw->arglen; + *ptr++ = '"'; + } + if (kw->argtype == SP_ARGTYPE_EMPTY || kw->argtype == SP_ARGTYPE_STR || kw->argtype == SP_ARGTYPE_UNKNOWN) { + *ptr++ = ')'; + } + } + *ptr++ = ';'; + *ptr = 0; + return ret; +} + +zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_keyword*)) +{ + const char *YYCURSOR = data; + const char *YYMARKER, *t1, *t2, *t3, *t4; + /*!stags:re2c format = 'const char *@@;\n'; */ + + const int max_keywords = 16; + sp_parsed_keyword parsed_rule[max_keywords+1]; + int kw_i = 0; + + int cond = yycinit; + long lineno = 1; + + /*!re2c + re2c:define:YYCTYPE = char; + // re2c:define:YYCURSOR = data; + re2c:yyfill:enable = 0; + re2c:flags:tags = 1; + re2c:api:style = free-form; + re2c:define:YYGETCONDITION = "cond"; + re2c:define:YYSETCONDITION = "cond = @@;"; + + end = "\x00"; + nl = "\r"?"\n"; + ws = [ \t]; + keyword = [a-zA-Z_][a-zA-Z0-9_]*; + string = "\"" ("\\\"" | [^"\r\n])* "\""; + + * { cs_error_log("Parser error on line %d", lineno); return FAILURE; } + ws+ { goto yyc_init; } + [;#] .* { goto yyc_init; } + nl { lineno++; goto yyc_init; } + "sp" { kw_i = 0; goto yyc_rule; } + end { return SUCCESS; } + + ws+ { goto yyc_rule; } + nl / ( nl | ws )* "." { lineno++; goto yyc_rule; } + "." @t1 keyword @t2 ( "(" @t3 string? @t4 ")" )? { + if (kw_i == max_keywords) { + cs_error_log("Too many keywords in rule (more than %d) on line %d", max_keywords, lineno); + return FAILURE; + } + sp_parsed_keyword kw = {.kw = (char*)t1, .kwlen = t2-t1, .arg = (char*)t3, .arglen = t4-t3, .argtype = SP_ARGTYPE_UNKNOWN, .lineno = lineno}; + if (t3 && t4) { + if (t3 == t4) { + kw.argtype = SP_ARGTYPE_EMPTY; + } else if (t4-t2 >= 2) { + kw.arg = (char*)t3 + 1; + kw.arglen = t4 - t3 - 2; + kw.argtype = SP_ARGTYPE_STR; + } + } else { + kw.argtype = SP_ARGTYPE_NONE; + } + parsed_rule[kw_i++] = kw; + goto yyc_rule; + } + ";" { + end_of_rule: + parsed_rule[kw_i++] = (sp_parsed_keyword){0, 0, 0, 0, 0, 0}; + if (process_rule && process_rule(parsed_rule) != SUCCESS) { + return FAILURE; + } + goto yyc_init; + } + * { goto end_of_rule; } + + */ + return FAILURE; +} \ No newline at end of file diff --git a/src/sp_config_utils.c b/src/sp_config_utils.c index bc7b405..e93ef31 100644 --- a/src/sp_config_utils.c +++ b/src/sp_config_utils.c @@ -1,108 +1,5 @@ #include "php_snuffleupagus.h" -int parse_keywords(sp_config_functions *funcs, char *line) { - int value_len = 0; - const char *original_line = line; - for (size_t i = 0; funcs[i].func; i++) { - if (!strncmp(funcs[i].token, line, strlen(funcs[i].token))) { - line += strlen(funcs[i].token); - value_len = funcs[i].func(line, funcs[i].token, funcs[i].retval) + 1; - if (value_len == 0) { // bad parameter - return -1; - } - line += value_len; - i = -1; // we start the loop again - } - } - while (*line == ';' || *line == '\t' || *line == ' ') { - line++; - } - - if (*line == '#') { - return 0; - } - - if (*line) { - sp_log_err("config", "Trailing chars '%s' at the end of '%s' on line %zu", - line, original_line, sp_line_no); - return -1; - } - return 0; -} - -zend_string *get_param(size_t *consumed, char *restrict line, sp_type type, - const char *restrict keyword) { - enum { IN_ESCAPE, NONE } state = NONE; - char *original_line = line; - size_t j = 0; - - zend_string *ret = NULL; - if (NULL == line || '\0' == *line) { - goto err; - } - - ret = zend_string_alloc(strlen(line) + 1, 1); - - /* The first char of a string is always '"', since they MUST be quoted. */ - if ('"' == *line) { - line++; - } else { - goto err; - } - - for (size_t i = 0; line[i] && j < strlen(original_line) - 2; i++) { - switch (line[i]) { - case '"': - /* A double quote at this point is either: - - at the very end of the string. - - escaped - */ - if ((state == NONE) && (line[i + 1] == SP_TOKEN_END_PARAM)) { - /* The `+2` if for - 1. the terminal double-quote - 2. the SP_TOKEN_END_PARAM - */ - *consumed = i + 2; - // Make sure that the string we return is the right size, - // as it can be smaller than strlen(line) - ret = zend_string_truncate(ret, j, 1); - // truncate does not add a \0 - ZSTR_VAL(ret)[ZSTR_LEN(ret)] = 0; - return ret; - } else if (state == IN_ESCAPE) { - break; // we're on an escped double quote - } else { - goto err; - } - case '\\': - if (state == NONE) { - state = IN_ESCAPE; - continue; - } - default: - break; - } - if (state == IN_ESCAPE) { - state = NONE; - } - ZSTR_VAL(ret)[j++] = line[i]; - } -err: - if (0 == j) { - sp_log_err("error", "A valid string as parameter is expected on line %zu", - sp_line_no); - } else { - sp_log_err("error", - "There is an issue with the parsing of '%s': it doesn't look " - "like a valid string on line %zu", - original_line ? original_line : "NULL", sp_line_no); - } - line = NULL; - if (ret) { - zend_string_release(ret); - } - return NULL; -} sp_list_node *parse_functions_list(char *value) { static const char *sep = ">"; diff --git a/src/sp_config_utils.h b/src/sp_config_utils.h index a63cadc..64817a0 100644 --- a/src/sp_config_utils.h +++ b/src/sp_config_utils.h @@ -1,9 +1,6 @@ #ifndef SP_CONFIG_UTILS #define SP_CONFIG_UTILS -int parse_keywords(sp_config_functions *, char *); -zend_string *get_param(size_t *, char *restrict, sp_type, const char *restrict); -int array_to_list(char **, sp_list_node **); sp_list_node *parse_functions_list(char *value); #endif /* SP_CONFIG_UTILS */ diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 84d8acf..ebb7d3f 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c @@ -69,28 +69,22 @@ static bool is_functions_list_matching(zend_execute_data* execute_data, return false; } -static bool is_local_var_matching( - zend_execute_data* execute_data, - const sp_disabled_function* const config_node) { +static bool is_local_var_matching(zend_execute_data* execute_data, const sp_disabled_function* const config_node) { zval* var_value = {0}; var_value = sp_get_var_value(execute_data, config_node->var, false); if (var_value) { if (Z_TYPE_P(var_value) == IS_ARRAY) { if (config_node->key || config_node->r_key) { - if (sp_match_array_key(var_value, config_node->key, - config_node->r_key)) { + if (sp_match_array_key(var_value, config_node->key, config_node->r_key)) { return true; } - } else if (sp_match_array_value(var_value, config_node->value, - config_node->r_value)) { + } else if (sp_match_array_value(var_value, config_node->value, config_node->r_value)) { return true; } } else { - zend_string const* const var_value_str = - sp_zval_to_zend_string(var_value); - bool match = sp_match_value(var_value_str, config_node->value, - config_node->r_value); + zend_string const* const var_value_str = sp_zval_to_zend_string(var_value); + bool match = sp_match_value(var_value_str, config_node->value, config_node->r_value); if (true == match) { return true; @@ -555,24 +549,19 @@ ZEND_FUNCTION(eval_blacklist_callback) { zend_string_release(tmp); if (SNUFFLEUPAGUS_G(in_eval) > 0) { - zend_string* filename = get_eval_filename(zend_get_executed_filename()); - const int line_number = zend_get_executed_lineno(TSRMLS_C); + // zend_string* filename = get_eval_filename(zend_get_executed_filename()); + // const int line_number = zend_get_executed_lineno(TSRMLS_C); const sp_config_eval* config_eval = SNUFFLEUPAGUS_G(config).config_eval; if (config_eval->dump) { - sp_log_request(config_eval->dump, config_eval->textual_representation, - SP_TOKEN_EVAL_BLACKLIST); + sp_log_request(config_eval->dump, config_eval->textual_representation); } if (config_eval->simulation) { - sp_log_simulation("eval", - "A call to %s was tried in eval, in %s:%d, logging it.", - current_function_name, ZSTR_VAL(filename), line_number); + sp_log_simulation("eval", "A call to '%s' was tried in eval. logging it.", current_function_name); } else { - sp_log_drop("eval", - "A call to %s was tried in eval, in %s:%d, dropping it.", - current_function_name, ZSTR_VAL(filename), line_number); + sp_log_drop("eval", "A call to '%s' was tried in eval. dropping it.", current_function_name); } - efree(filename); + // efree(filename); } whitelisted: diff --git a/src/sp_execute.c b/src/sp_execute.c index 7d078b0..8795e5f 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c @@ -14,8 +14,7 @@ ZEND_COLD static inline void terminate_if_writable(const char *filename) { if (0 == access(filename, W_OK)) { if (config_ro_exec->dump) { sp_log_request(config_ro_exec->dump, - config_ro_exec->textual_representation, - SP_TOKEN_READONLY_EXEC); + config_ro_exec->textual_representation); } if (true == config_ro_exec->simulation) { sp_log_simulation("readonly_exec", @@ -75,8 +74,7 @@ is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { if (EXPECTED(NULL != current_function)) { if (UNEXPECTED(false == check_is_in_eval_whitelist(current_function))) { if (config_eval->dump) { - sp_log_request(config_eval->dump, config_eval->textual_representation, - SP_TOKEN_EVAL_WHITELIST); + sp_log_request(config_eval->dump, config_eval->textual_representation); } if (config_eval->simulation) { sp_log_simulation( diff --git a/src/sp_network_utils.c b/src/sp_network_utils.c index 5b4fd95..0a26254 100644 --- a/src/sp_network_utils.c +++ b/src/sp_network_utils.c @@ -85,9 +85,7 @@ int get_ip_and_cidr(char *ip, sp_cidr *cidr) { char *mask = strchr(ip, '/'); if (NULL == mask) { - sp_log_err( - "config", - "'%s' isn't a valid network mask, it seems that you forgot a '/'.", ip); + sp_log_err("config", "'%s' isn't a valid network mask, it seems that you forgot a '/'.", ip); return -1; } @@ -117,7 +115,7 @@ int get_ip_and_cidr(char *ip, sp_cidr *cidr) { ip[mask - ip] = '/'; if (cidr->ip_version < 0) { - sp_log_err("cidr_match", "Weird ip (%s) family", ip); + sp_log_err("config", "Weird ip (%s) family", ip); return -1; } diff --git a/src/sp_pcre_compat.c b/src/sp_pcre_compat.c index 2b9f08d..657e650 100644 --- a/src/sp_pcre_compat.c +++ b/src/sp_pcre_compat.c @@ -24,8 +24,7 @@ sp_pcre* sp_pcre_compile(const char* const pattern) { #endif if (NULL == ret) { - sp_log_err("config", "Failed to compile '%s': %s on line %zu.", pattern, - pcre_error, sp_line_no); + sp_log_err("config", "Failed to compile '%s': %s.", pattern, pcre_error); } return ret; } diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c index 06636ad..82b2cef 100644 --- a/src/sp_unserialize.c +++ b/src/sp_unserialize.c @@ -89,8 +89,7 @@ PHP_FUNCTION(sp_unserialize) { } else { if (config_unserialize->dump) { sp_log_request(config_unserialize->dump, - config_unserialize->textual_representation, - SP_TOKEN_UNSERIALIZE_HMAC); + config_unserialize->textual_representation); } if (true == config_unserialize->simulation) { sp_log_simulation("unserialize", "Invalid HMAC for %s", serialized_str); diff --git a/src/sp_utils.c b/src/sp_utils.c index 949d6ba..c4209de 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c @@ -123,9 +123,7 @@ static int construct_filename(char* filename, return 0; } -int sp_log_request(const zend_string* restrict folder, - const zend_string* restrict text_repr, - char const* const from) { +int sp_log_request(const zend_string* restrict folder, const zend_string* restrict text_repr) { FILE* file; const char* current_filename = zend_get_executed_filename(TSRMLS_C); const int current_line = zend_get_executed_lineno(TSRMLS_C); @@ -146,7 +144,7 @@ int sp_log_request(const zend_string* restrict folder, return -1; } - fprintf(file, "RULE: sp%s%s\n", from, ZSTR_VAL(text_repr)); + fprintf(file, "RULE: %s\n", ZSTR_VAL(text_repr)); fprintf(file, "FILE: %s:%d\n", current_filename, current_line); @@ -285,8 +283,7 @@ void sp_log_disable(const char* restrict path, const char* restrict arg_name, const int sim = config_node->simulation; if (dump) { - sp_log_request(config_node->dump, config_node->textual_representation, - SP_TOKEN_DISABLE_FUNC); + sp_log_request(config_node->dump, config_node->textual_representation); } if (arg_name) { char* char_repr = NULL; @@ -329,8 +326,7 @@ void sp_log_disable_ret(const char* restrict path, char* char_repr = NULL; if (dump) { - sp_log_request(dump, config_node->textual_representation, - SP_TOKEN_DISABLE_FUNC); + sp_log_request(dump, config_node->textual_representation); } if (ret_value) { char_repr = zend_string_to_char(ret_value); @@ -479,7 +475,6 @@ void unhook_functions(HashTable *ht) { bool check_is_in_eval_whitelist(const zend_string* const function_name) { const sp_list_node* it = SNUFFLEUPAGUS_G(config).config_eval->whitelist; - if (!it) { return false; } diff --git a/src/sp_utils.h b/src/sp_utils.h index c0ddbe4..ef626a3 100644 --- a/src/sp_utils.h +++ b/src/sp_utils.h @@ -85,9 +85,7 @@ bool hook_function(const char *, HashTable *, zif_handler); void unhook_functions(HashTable *ht); int hook_regexp(const sp_pcre *, HashTable *, zif_handler); bool check_is_in_eval_whitelist(const zend_string *const function_name); -int sp_log_request(const zend_string *restrict folder, - const zend_string *restrict text_repr, - char const *const from); +int sp_log_request(const zend_string *restrict folder, const zend_string *restrict text_repr); bool sp_zend_string_equals(const zend_string *s1, const zend_string *s2); #endif /* SP_UTILS_H */ diff --git a/src/tests/broken_configuration/encrypt_regexp_cookies_bad_regexp.phpt b/src/tests/broken_configuration/encrypt_regexp_cookies_bad_regexp.phpt index 7a8c909..5383df6 100644 --- a/src/tests/broken_configuration/encrypt_regexp_cookies_bad_regexp.phpt +++ b/src/tests/broken_configuration/encrypt_regexp_cookies_bad_regexp.phpt @@ -17,6 +17,6 @@ EOF; --EXPECT-- Fatal error: [snuffleupagus][127.0.0.1][config][log] Invalid configuration file in Unknown on line 0 -Fatal error: [snuffleupagus][127.0.0.1][config][log] Failed to compile '^super_co[a-z+$': missing terminating ] for character class on line 2. in Unknown on line 0 +Fatal error: [snuffleupagus][127.0.0.1][config][log] Failed to compile '^super_co[a-z+$': missing terminating ] for character class. in Unknown on line 0 -Fatal error: [snuffleupagus][127.0.0.1][config][log] '.name_r()' is expecting a valid regexp, and not '"^super_co[a-z+$"' on line 2 in Unknown on line 0 +Fatal error: [snuffleupagus][127.0.0.1][config][log] Invalid regexp '^super_co[a-z+$' for '.name_r()' on line 2 in Unknown on line 0 diff --git a/src/tests/broken_configuration_php8/broken_conf.phpt b/src/tests/broken_configuration_php8/broken_conf.phpt index 7dde7d6..9a5a5ab 100644 --- a/src/tests/broken_configuration_php8/broken_conf.phpt +++ b/src/tests/broken_configuration_php8/broken_conf.phpt @@ -7,8 +7,7 @@ Broken configuration sp.configuration_file={PWD}/config/broken_conf.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration prefix for 'this is a broken line' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Parser error on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf2.phpt b/src/tests/broken_configuration_php8/broken_conf2.phpt index bf337b4..94ebc01 100644 --- a/src/tests/broken_configuration_php8/broken_conf2.phpt +++ b/src/tests/broken_configuration_php8/broken_conf2.phpt @@ -7,8 +7,7 @@ Broken configuration sp.configuration_file={PWD}/config/broken_conf2.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration section 'sp.wrong' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Unexpected keyword 'wrong' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_allow_broken_disabled.phpt b/src/tests/broken_configuration_php8/broken_conf_allow_broken_disabled.phpt index 9dd0c66..ad3aa08 100644 --- a/src/tests/broken_configuration_php8/broken_conf_allow_broken_disabled.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_allow_broken_disabled.phpt @@ -12,7 +12,7 @@ echo 1337; ?> --EXPECT-- -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration prefix for 'this is a broken line' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Parser error on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_allow_broken_enabled.phpt b/src/tests/broken_configuration_php8/broken_conf_allow_broken_enabled.phpt index eccc8a8..0f71408 100644 --- a/src/tests/broken_configuration_php8/broken_conf_allow_broken_enabled.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_allow_broken_enabled.phpt @@ -12,5 +12,5 @@ echo 1337; ?> --EXPECT-- -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration prefix for 'this is a broken line' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Parser error on line 1 in Unknown on line 0 1337 diff --git a/src/tests/broken_configuration_php8/broken_conf_config_regexp.phpt b/src/tests/broken_configuration_php8/broken_conf_config_regexp.phpt index 76ef208..c4eec17 100644 --- a/src/tests/broken_configuration_php8/broken_conf_config_regexp.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_config_regexp.phpt @@ -7,10 +7,9 @@ Broken configuration sp.configuration_file={PWD}/config/broken_config_regexp.ini --FILE-- --EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Failed to compile '*.': quantifier does not follow a repeatable item. in Unknown on line 0 -Fatal error: [snuffleupagus][0.0.0.0][config][log] Failed to compile '*.': %s on line 1. in Unknown on line 0 - -Fatal error: [snuffleupagus][0.0.0.0][config][log] '.filename_r()' is expecting a valid regexp, and not '"*."' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid regexp '*.' for '.filename_r()' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_config_regexp_no_closing_paren.phpt b/src/tests/broken_configuration_php8/broken_conf_config_regexp_no_closing_paren.phpt index 5bdca06..2629ba5 100644 --- a/src/tests/broken_configuration_php8/broken_conf_config_regexp_no_closing_paren.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_config_regexp_no_closing_paren.phpt @@ -7,10 +7,7 @@ Broken configuration - regexp without a closing parenthesis sp.configuration_file={PWD}/config/broken_config_regexp_no_closing_paren.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] There is an issue with the parsing of '"*."': it doesn't look like a valid string on line 1 in Unknown on line 0 - -Fatal error: [snuffleupagus][0.0.0.0][config][log] '.filename_r()' is expecting a valid regexp, and not '"*."' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'filename_r' - it should be 'filename_r("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_cookie_encryption_without_encryption_key.phpt b/src/tests/broken_configuration_php8/broken_conf_cookie_encryption_without_encryption_key.phpt index 0447320..6213041 100644 --- a/src/tests/broken_configuration_php8/broken_conf_cookie_encryption_without_encryption_key.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_cookie_encryption_without_encryption_key.phpt @@ -7,8 +7,7 @@ Broken configuration - encrypted cookie without encryption key sp.configuration_file={PWD}/config/broken_conf_cookie_encryption_without_encryption_key.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the cookie encryption featureon line 2 without having set the `.encryption_key` option in`sp.global`: please set it first in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the cookie encryption feature on line 2 without having set the `.secret_key` option in `sp.global`: please set it first in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_cookie_encryption_without_env_var.phpt b/src/tests/broken_configuration_php8/broken_conf_cookie_encryption_without_env_var.phpt index 204430d..25371dd 100644 --- a/src/tests/broken_configuration_php8/broken_conf_cookie_encryption_without_env_var.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_cookie_encryption_without_env_var.phpt @@ -7,8 +7,7 @@ Broken configuration - encrypted cookie with without cookie env var sp.configuration_file={PWD}/config/broken_conf_cookie_encryption_without_env_var.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the cookie encryption featureon line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] You're trying to use the cookie encryption feature on line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_eval.phpt b/src/tests/broken_configuration_php8/broken_conf_eval.phpt index 1a6ad4d..f45aabf 100644 --- a/src/tests/broken_configuration_php8/broken_conf_eval.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_eval.phpt @@ -8,7 +8,7 @@ sp.configuration_file={PWD}/config/broken_conf_eval.ini --FILE-- --EXPECT-- -Fatal error: [snuffleupagus][0.0.0.0][error][log] There is an issue with the parsing of '"cos,sin': it doesn't look like a valid string on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'list' - it should be 'list("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_expecting_bool.phpt b/src/tests/broken_configuration_php8/broken_conf_expecting_bool.phpt index 682a4f5..419d687 100644 --- a/src/tests/broken_configuration_php8/broken_conf_expecting_bool.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_expecting_bool.phpt @@ -7,8 +7,7 @@ Bad boolean value in configuration sp.configuration_file={PWD}/config/broken_conf_expecting_bool.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Trailing chars '337);' at the end of '.enable(1337);' on line 5 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing paranthesis for keyword 'enable' - it should be 'enable()' on line 5 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_invalid_cidr_value.phpt b/src/tests/broken_configuration_php8/broken_conf_invalid_cidr_value.phpt index dbe5414..31140dc 100644 --- a/src/tests/broken_configuration_php8/broken_conf_invalid_cidr_value.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_invalid_cidr_value.phpt @@ -8,10 +8,7 @@ Broken configuration, invalid cidr value sp.configuration_file={PWD}/config/broken_conf_invalid_cidr_value.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] A valid string as parameter is expected on line 1 in Unknown on line 0 - -Fatal error: [snuffleupagus][0.0.0.0][config][log] " doesn't contain a valid cidr on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'cidr' - it should be 'cidr("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_invalid_filename.phpt b/src/tests/broken_configuration_php8/broken_conf_invalid_filename.phpt index cb78f85..da40235 100644 --- a/src/tests/broken_configuration_php8/broken_conf_invalid_filename.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_invalid_filename.phpt @@ -7,8 +7,7 @@ Broken configuration filename without absolute path sp.configuration_file={PWD}/config/broken_conf_invalid_filename.ini --FILE-- --EXPECTF-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("sprintf").filename("wrong file name").drop();':'.filename' must be an absolute path or a phar archive on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line%a: '.filename' must be an absolute path or a phar archive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_invalid_log_media.phpt b/src/tests/broken_configuration_php8/broken_conf_invalid_log_media.phpt index 68581b6..fda609d 100644 --- a/src/tests/broken_configuration_php8/broken_conf_invalid_log_media.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_invalid_log_media.phpt @@ -7,8 +7,7 @@ Broken configuration filename with improper log media sp.configuration_file={PWD}/config/broken_conf_invalid_log_media.ini --FILE-- --EXPECTF-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] .log_media() only supports 'syslog' or 'php', on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] .log_media() only supports 'syslog' or 'php' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_invalid_type.phpt b/src/tests/broken_configuration_php8/broken_conf_invalid_type.phpt index 188d610..9e35170 100644 --- a/src/tests/broken_configuration_php8/broken_conf_invalid_type.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_invalid_type.phpt @@ -7,8 +7,7 @@ Broken conf with wrong type sp.configuration_file={PWD}/config/broken_conf_invalid_type.ini --FILE-- --EXPECTF-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] There is an issue with the parsing of '"totally_wrong"_type")': it doesn't look like a valid string on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'ret_type' - it should be 'ret_type("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_key_value.phpt b/src/tests/broken_configuration_php8/broken_conf_key_value.phpt index 24c60bc..909aae1 100644 --- a/src/tests/broken_configuration_php8/broken_conf_key_value.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_key_value.phpt @@ -6,8 +6,8 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_key_value.ini --FILE-- ---EXPECT-- -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("system").var("").value("").key("").drop();': '.key' and '.value' are mutually exclusive on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line%a: '.key' and '.value' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_line_empty_string.phpt b/src/tests/broken_configuration_php8/broken_conf_line_empty_string.phpt index 2d370ac..5702f43 100644 --- a/src/tests/broken_configuration_php8/broken_conf_line_empty_string.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_line_empty_string.phpt @@ -7,8 +7,7 @@ Configuration line with an empty string sp.configuration_file={PWD}/config/broken_conf_line_empty_string.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] A valid string as parameter is expected on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'name' - it should be 'name("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_line_no_closing.phpt b/src/tests/broken_configuration_php8/broken_conf_line_no_closing.phpt index d3c826f..1a0a392 100644 --- a/src/tests/broken_configuration_php8/broken_conf_line_no_closing.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_line_no_closing.phpt @@ -7,8 +7,7 @@ Configuration line without closing parenthese sp.configuration_file={PWD}/config/broken_conf_line_no_closing.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] There is an issue with the parsing of '"123"': it doesn't look like a valid string on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'name' - it should be 'name("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_lots_of_quotes.phpt b/src/tests/broken_configuration_php8/broken_conf_lots_of_quotes.phpt index e599e62..27135ca 100644 --- a/src/tests/broken_configuration_php8/broken_conf_lots_of_quotes.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_lots_of_quotes.phpt @@ -7,8 +7,7 @@ Configuration line with too many quotes sp.configuration_file={PWD}/config/broken_conf_lots_of_quotes.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] There is an issue with the parsing of '"this\"is a weird\"\"\"cookie\"name"");': it doesn't look like a valid string on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'name' - it should be 'name("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_missing_script.phpt b/src/tests/broken_configuration_php8/broken_conf_missing_script.phpt index 2ddb70f..bb44f15 100644 --- a/src/tests/broken_configuration_php8/broken_conf_missing_script.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_missing_script.phpt @@ -10,8 +10,7 @@ sp.configuration_file={PWD}/config/broken_conf_missing_script.ini echo 1; ?> --EXPECTF-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] The `script` directive is mandatory in '.enable();' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] The `script` directive is mandatory in '.upload_validation' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive.phpt index e362893..f331eee 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive.phpt @@ -6,9 +6,8 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive.ini --FILE-- ---EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("system").param("id").value("42").value_r("^id$").drop();': '.value' and '.value_r' are mutually exclusive on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line%a: '.value' and '.value_r' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive11.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive11.phpt index 39766e1..93fc581 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive11.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive11.phpt @@ -6,9 +6,8 @@ Broken configuration - ret and var are mutually exclusives --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive11.ini --FILE-- ---EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("strcmp").drop().ret("hip").var("hop");': '.ret' and '.var' are mutually exclusive on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line for '%a': '.ret' and '.var' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive12.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive12.phpt index ebca290..24162df 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive12.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive12.phpt @@ -6,9 +6,8 @@ Broken configuration - ret and value are mutually exclusive --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive12.ini --FILE-- ---EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("strcmp").drop().ret("hip").value("hop");': '.ret' and '.value' are mutually exclusive on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line for '%a': '.ret' and '.value' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive2.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive2.phpt index 52b36e0..35c4de1 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive2.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive2.phpt @@ -6,9 +6,8 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive2.ini --FILE-- ---EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("system").function_r("system").param("id").value("42").drop();': '.function' and '.function_r' are mutually exclusive on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line%a: '.function' and '.function_r' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive3.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive3.phpt index cf65e7d..fd6e0b4 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive3.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive3.phpt @@ -6,9 +6,8 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive3.ini --FILE-- ---EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("system").param("id").value("42").filename_r("^id$").filename("pouet.txt").drop();': '.filename' and '.filename_r' are mutually exclusive on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line%a: '.filename' and '.filename_r' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive4.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive4.phpt index 41dc60e..80370f6 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive4.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive4.phpt @@ -6,9 +6,9 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive4.ini --FILE-- ---EXPECT-- +--EXPECTF-- -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("system").param("id").value("42").param_r("^id$").drop();': '.param' and '.param_r' are mutually exclusive on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line%a: '.param' and '.param_r' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive5.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive5.phpt index 9cab6cd..3087a17 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive5.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive5.phpt @@ -6,9 +6,9 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive5.ini --FILE-- ---EXPECT-- +--EXPECTF-- -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("system").ret("0").drop().ret_r("^0$");': '.ret' and '.ret_r' are mutually exclusive on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line%a: '.ret' and '.ret_r' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive6.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive6.phpt index 406f818..2099a4b 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive6.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive6.phpt @@ -6,9 +6,8 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive6.ini --FILE-- ---EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("system").param("id").value("42").ret_r("^0$").drop();': '.ret' and '.param' are mutually exclusive on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line for '%a': '.ret' and '.param' are mutually exclusive on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive7.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive7.phpt index ff7f415..f0b44da 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive7.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive7.phpt @@ -6,9 +6,8 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive7.ini --FILE-- ---EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.function("system").ret("0").drop().allow();': The rule must either be a `drop` or `allow` one on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: '%a': The rule must either be a `drop` or `allow` one on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive8.phpt b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive8.phpt index 6ccd508..8f6c246 100644 --- a/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive8.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_mutually_exclusive8.phpt @@ -6,9 +6,8 @@ Broken configuration --INI-- sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive8.ini --FILE-- ---EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: 'sp.disabled_functions.ret("0").drop();': must take a function name on line 1 in Unknown on line 0 +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration line: '%a': must take a function name on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_readonly_exec.phpt b/src/tests/broken_configuration_php8/broken_conf_readonly_exec.phpt index 7e74683..5107ede 100644 --- a/src/tests/broken_configuration_php8/broken_conf_readonly_exec.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_readonly_exec.phpt @@ -10,8 +10,7 @@ sp.configuration_file={PWD}/config/broken_conf_readonly_exec.ini echo 1; ?> --EXPECTF-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Trailing chars '234);' at the end of '.enable(1234);' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing paranthesis for keyword 'enable' - it should be 'enable()' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_samesite.phpt b/src/tests/broken_configuration_php8/broken_conf_samesite.phpt index c905fd8..63075d0 100644 --- a/src/tests/broken_configuration_php8/broken_conf_samesite.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_samesite.phpt @@ -7,8 +7,7 @@ Bad config, invalid samesite type. sp.configuration_file={PWD}/config/broken_conf_cookie_samesite.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] nop is an invalid value to samesite (expected Lax or Strict) on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] 'nop' is an invalid value to samesite (expected Lax or Strict) on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_session_encryption.phpt b/src/tests/broken_configuration_php8/broken_conf_session_encryption.phpt index 886eb13..cc7369a 100644 --- a/src/tests/broken_configuration_php8/broken_conf_session_encryption.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_session_encryption.phpt @@ -7,8 +7,7 @@ Broken config, session encryption sp.configuration_file={PWD}/config/broken_conf_session_encryption.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Trailing chars 'nvalid value :/);' at the end of '.encrypt(invalid value :/);' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing paranthesis for keyword 'encrypt' - it should be 'encrypt()' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_shown_in_phpinfo.phpt b/src/tests/broken_configuration_php8/broken_conf_shown_in_phpinfo.phpt index 2503943..23a8e53 100644 --- a/src/tests/broken_configuration_php8/broken_conf_shown_in_phpinfo.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_shown_in_phpinfo.phpt @@ -18,10 +18,9 @@ if (strstr($info, 'Valid config => no') !== FALSE) { } ?> --EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Failed to compile '*.': quantifier does not follow a repeatable item. in Unknown on line 0 -Fatal error: [snuffleupagus][0.0.0.0][config][log] Failed to compile '*.': %s on line 1. in Unknown on line 0 - -Fatal error: [snuffleupagus][0.0.0.0][config][log] '.filename_r()' is expecting a valid regexp, and not '"*."' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid regexp '*.' for '.filename_r()' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_truncated.phpt b/src/tests/broken_configuration_php8/broken_conf_truncated.phpt index 059dcac..ff821f4 100644 --- a/src/tests/broken_configuration_php8/broken_conf_truncated.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_truncated.phpt @@ -7,8 +7,7 @@ Bad boolean value in configuration sp.configuration_file={PWD}/config/config_broken_conf_truncated.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] A valid string as parameter is expected on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'param' - it should be 'param("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_unserialize.phpt b/src/tests/broken_configuration_php8/broken_conf_unserialize.phpt index 327b622..5e6c28e 100644 --- a/src/tests/broken_configuration_php8/broken_conf_unserialize.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_unserialize.phpt @@ -9,9 +9,8 @@ sp.configuration_file={PWD}/config/broken_conf_unserialize.ini ---EXPECTF-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Trailing chars '234);' at the end of '.enable(1234);' on line 1 in Unknown on line 0 +--EXPECT-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing paranthesis for keyword 'enable' - it should be 'enable()' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_upload_validation.phpt b/src/tests/broken_configuration_php8/broken_conf_upload_validation.phpt index d022e3e..31afff9 100644 --- a/src/tests/broken_configuration_php8/broken_conf_upload_validation.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_upload_validation.phpt @@ -10,8 +10,7 @@ sp.configuration_file={PWD}/../broken_configuration/config/broken_conf_upload_va echo 1; ?> --EXPECTF-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] A valid string as parameter is expected on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'script' - it should be 'script("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_weird_keyword.phpt b/src/tests/broken_configuration_php8/broken_conf_weird_keyword.phpt index 75c2e0e..6082f42 100644 --- a/src/tests/broken_configuration_php8/broken_conf_weird_keyword.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_weird_keyword.phpt @@ -7,8 +7,7 @@ Bad config, unknown keyword sp.configuration_file={PWD}/config/broken_conf_weird_keyword.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Trailing chars '.not_a_valid_keyword("test");' at the end of '.enable().not_a_valid_keyword("test");' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Unexpected keyword 'not_a_valid_keyword' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_wrapper_whitelist.phpt b/src/tests/broken_configuration_php8/broken_conf_wrapper_whitelist.phpt index 0011a6e..1f2d9da 100644 --- a/src/tests/broken_configuration_php8/broken_conf_wrapper_whitelist.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_wrapper_whitelist.phpt @@ -11,8 +11,7 @@ sp.allow_broken_configuration=Off echo 1337; ?> --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][config][log] Trailing chars '.invalid_param();' at the end of '.invalid_param();' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Unexpected keyword 'invalid_param' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_conf_wrong_quotes.phpt b/src/tests/broken_configuration_php8/broken_conf_wrong_quotes.phpt index b073369..d3cf9e0 100644 --- a/src/tests/broken_configuration_php8/broken_conf_wrong_quotes.phpt +++ b/src/tests/broken_configuration_php8/broken_conf_wrong_quotes.phpt @@ -7,8 +7,7 @@ Configuration line with too many quotes sp.configuration_file={PWD}/config/broken_conf_wrong_quotes.ini --FILE-- --EXPECT-- - -Fatal error: [snuffleupagus][0.0.0.0][error][log] There is an issue with the parsing of '"\)': it doesn't look like a valid string on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Missing argument to keyword 'name' - it should be 'name("...")' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/broken_regexp.phpt b/src/tests/broken_configuration_php8/broken_regexp.phpt index 877f801..7461d57 100644 --- a/src/tests/broken_configuration_php8/broken_regexp.phpt +++ b/src/tests/broken_configuration_php8/broken_regexp.phpt @@ -7,10 +7,9 @@ Broken regexp sp.configuration_file={PWD}/config/broken_regexp.ini --FILE-- --EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][config][log] Failed to compile '^$[': missing terminating ] for character class. in Unknown on line 0 -Fatal error: [snuffleupagus][0.0.0.0][config][log] Failed to compile '^$[': missing terminating ] for character class on line 1. in Unknown on line 0 - -Fatal error: [snuffleupagus][0.0.0.0][config][log] '.value_r()' is expecting a valid regexp, and not '"^$["' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid regexp '^$[' for '.value_r()' on line 1 in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/broken_configuration_php8/encrypt_regexp_cookies_bad_regexp.phpt b/src/tests/broken_configuration_php8/encrypt_regexp_cookies_bad_regexp.phpt index 7a8c909..5383df6 100644 --- a/src/tests/broken_configuration_php8/encrypt_regexp_cookies_bad_regexp.phpt +++ b/src/tests/broken_configuration_php8/encrypt_regexp_cookies_bad_regexp.phpt @@ -17,6 +17,6 @@ EOF; --EXPECT-- Fatal error: [snuffleupagus][127.0.0.1][config][log] Invalid configuration file in Unknown on line 0 -Fatal error: [snuffleupagus][127.0.0.1][config][log] Failed to compile '^super_co[a-z+$': missing terminating ] for character class on line 2. in Unknown on line 0 +Fatal error: [snuffleupagus][127.0.0.1][config][log] Failed to compile '^super_co[a-z+$': missing terminating ] for character class. in Unknown on line 0 -Fatal error: [snuffleupagus][127.0.0.1][config][log] '.name_r()' is expecting a valid regexp, and not '"^super_co[a-z+$"' on line 2 in Unknown on line 0 +Fatal error: [snuffleupagus][127.0.0.1][config][log] Invalid regexp '^super_co[a-z+$' for '.name_r()' on line 2 in Unknown on line 0 diff --git a/src/tests/cookies_encryption_warning/encrypt_cookies_no_env.phpt b/src/tests/cookies_encryption_warning/encrypt_cookies_no_env.phpt index 015c159..a01c352 100644 --- a/src/tests/cookies_encryption_warning/encrypt_cookies_no_env.phpt +++ b/src/tests/cookies_encryption_warning/encrypt_cookies_no_env.phpt @@ -18,4 +18,4 @@ EOF; --EXPECT-- Fatal error: [snuffleupagus][127.0.0.1][config][log] Invalid configuration file in Unknown on line 0 -Fatal error: [snuffleupagus][127.0.0.1][config][log] You're trying to use the cookie encryption featureon line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 +Fatal error: [snuffleupagus][127.0.0.1][config][log] You're trying to use the cookie encryption feature on line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 diff --git a/src/tests/cookies_encryption_warning/encrypt_cookies_no_key.phpt b/src/tests/cookies_encryption_warning/encrypt_cookies_no_key.phpt index 42f5509..c47389c 100644 --- a/src/tests/cookies_encryption_warning/encrypt_cookies_no_key.phpt +++ b/src/tests/cookies_encryption_warning/encrypt_cookies_no_key.phpt @@ -18,4 +18,4 @@ EOF; --EXPECT-- Fatal error: [snuffleupagus][127.0.0.1][config][log] Invalid configuration file in Unknown on line 0 -Fatal error: [snuffleupagus][127.0.0.1][config][log] You're trying to use the cookie encryption featureon line 2 without having set the `.encryption_key` option in`sp.global`: please set it first in Unknown on line 0 +Fatal error: [snuffleupagus][127.0.0.1][config][log] You're trying to use the cookie encryption feature on line 2 without having set the `.secret_key` option in `sp.global`: please set it first in Unknown on line 0 diff --git a/src/tests/cookies_encryption_warning/encrypt_regexp_cookies_no_env.phpt b/src/tests/cookies_encryption_warning/encrypt_regexp_cookies_no_env.phpt index 163cb26..1fe4074 100644 --- a/src/tests/cookies_encryption_warning/encrypt_regexp_cookies_no_env.phpt +++ b/src/tests/cookies_encryption_warning/encrypt_regexp_cookies_no_env.phpt @@ -18,4 +18,4 @@ EOF; --EXPECT-- Fatal error: [snuffleupagus][127.0.0.1][config][log] Invalid configuration file in Unknown on line 0 -Fatal error: [snuffleupagus][127.0.0.1][config][log] You're trying to use the cookie encryption featureon line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 +Fatal error: [snuffleupagus][127.0.0.1][config][log] You're trying to use the cookie encryption feature on line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0 diff --git a/src/tests/cookies_encryption_warning/encrypt_regexp_cookies_no_key.phpt b/src/tests/cookies_encryption_warning/encrypt_regexp_cookies_no_key.phpt index df31f2e..0da0dbe 100644 --- a/src/tests/cookies_encryption_warning/encrypt_regexp_cookies_no_key.phpt +++ b/src/tests/cookies_encryption_warning/encrypt_regexp_cookies_no_key.phpt @@ -18,4 +18,4 @@ EOF; --EXPECT-- Fatal error: [snuffleupagus][127.0.0.1][config][log] Invalid configuration file in Unknown on line 0 -Fatal error: [snuffleupagus][127.0.0.1][config][log] You're trying to use the cookie encryption featureon line 2 without having set the `.encryption_key` option in`sp.global`: please set it first in Unknown on line 0 +Fatal error: [snuffleupagus][127.0.0.1][config][log] You're trying to use the cookie encryption feature on line 2 without having set the `.secret_key` option in `sp.global`: please set it first in Unknown on line 0 diff --git a/src/tests/dump_request/dump_eval_blacklist.phpt b/src/tests/dump_request/dump_eval_blacklist.phpt index 07c17f2..b8192a7 100644 --- a/src/tests/dump_request/dump_eval_blacklist.phpt +++ b/src/tests/dump_request/dump_eval_blacklist.phpt @@ -36,5 +36,5 @@ if ($res[3] != "GET:get_a='data_get_a' get_b='data_get_b' \n") { --EXPECTF-- Outside of eval: 1337 1337 1337 -Warning: [snuffleupagus][0.0.0.0][eval][simulation] A call to strtoupper was tried in eval, in %a/dump_eval_blacklist.php:1, logging it. in %a/dump_eval_blacklist.php(9) : eval()'d code on line 1 +Warning: [snuffleupagus][0.0.0.0][eval][simulation] A call to 'strtoupper' was tried in eval. logging it. in %a(9) : eval()'d code on line 1 After eval: 1234 diff --git a/src/tests/eval_blacklist/eval_backlist.phpt b/src/tests/eval_blacklist/eval_backlist.phpt index fa32b4b..2953efc 100644 --- a/src/tests/eval_blacklist/eval_backlist.phpt +++ b/src/tests/eval_blacklist/eval_backlist.phpt @@ -14,4 +14,4 @@ echo "After eval: $a\n"; --EXPECTF-- Outside of eval: 1337 1337 1337 -Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to strtoupper was tried in eval, in %a/eval_backlist.php:1, dropping it. in %a/eval_backlist.php(4) : eval()'d code on line 1 +Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to 'strtoupper' was tried in eval. dropping it. in %a/eval_backlist.php(4) : eval()'d code on line 1 diff --git a/src/tests/eval_blacklist/eval_backlist_call_user_func.phpt b/src/tests/eval_blacklist/eval_backlist_call_user_func.phpt index 4c37263..546a53a 100644 --- a/src/tests/eval_blacklist/eval_backlist_call_user_func.phpt +++ b/src/tests/eval_blacklist/eval_backlist_call_user_func.phpt @@ -11,4 +11,4 @@ eval(' ') ?> --EXPECTF-- -Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to strtoupper was tried in eval, in %s/eval_backlist_call_user_func.php:%d, dropping it. in %s/eval_backlist_call_user_func.php(%d) : eval()'d code on line %d +Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to 'strtoupper' was tried in eval. dropping it. in %s/eval_backlist_call_user_func.php(%d) : eval()'d code on line %d diff --git a/src/tests/eval_blacklist/eval_backlist_chained.phpt b/src/tests/eval_blacklist/eval_backlist_chained.phpt index 820ef1d..1afb860 100644 --- a/src/tests/eval_blacklist/eval_backlist_chained.phpt +++ b/src/tests/eval_blacklist/eval_backlist_chained.phpt @@ -13,4 +13,4 @@ eval(' ') ?> --EXPECTF-- -Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to strtoupper was tried in eval, in %s/eval_backlist_chained.php:%d, dropping it. in %s/eval_backlist_chained.php(%d) : eval()'d code on line %d +Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to 'strtoupper' was tried in eval. dropping it. in %s/eval_backlist_chained.php(%d) : eval()'d code on line %d diff --git a/src/tests/eval_blacklist/eval_backlist_list.phpt b/src/tests/eval_blacklist/eval_backlist_list.phpt index 725a9bb..1efd453 100644 --- a/src/tests/eval_blacklist/eval_backlist_list.phpt +++ b/src/tests/eval_blacklist/eval_backlist_list.phpt @@ -14,4 +14,4 @@ echo "After eval: $a\n"; --EXPECTF-- Outside of eval: 1337 1337 1337 -Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to strtoupper was tried in eval, in %a/eval_backlist_list.php:1, dropping it. in %a/eval_backlist_list.php(4) : eval()'d code on line 1 +Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to 'strtoupper' was tried in eval. dropping it. in %a/eval_backlist_list.php(4) : eval()'d code on line 1 diff --git a/src/tests/eval_blacklist/eval_backlist_simulation.phpt b/src/tests/eval_blacklist/eval_backlist_simulation.phpt index f09370d..0cc02b2 100644 --- a/src/tests/eval_blacklist/eval_backlist_simulation.phpt +++ b/src/tests/eval_blacklist/eval_backlist_simulation.phpt @@ -14,5 +14,5 @@ echo "After eval: $a\n"; --EXPECTF-- Outside of eval: 1337 1337 1337 -Warning: [snuffleupagus][0.0.0.0][eval][simulation] A call to strtoupper was tried in eval, in %a/eval_backlist_simulation.php:1, logging it. in %a/eval_backlist_simulation.php(4) : eval()'d code on line 1 +Warning: [snuffleupagus][0.0.0.0][eval][simulation] A call to 'strtoupper' was tried in eval. logging it. in %a/eval_backlist_simulation.php(4) : eval()'d code on line 1 After eval: 1234 diff --git a/src/tests/eval_blacklist/nested_eval_blacklist.phpt b/src/tests/eval_blacklist/nested_eval_blacklist.phpt index 8ff0b6d..a06b66b 100644 --- a/src/tests/eval_blacklist/nested_eval_blacklist.phpt +++ b/src/tests/eval_blacklist/nested_eval_blacklist.phpt @@ -26,4 +26,4 @@ Inception lvl 1... Inception lvl 2... Inception lvl 3... -Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to strtoupper was tried in eval, in %a/nested_eval_blacklist.php(5) : eval()'d code(4) : eval()'d code:3, dropping it. in %a/nested_eval_blacklist.php(5) : eval()'d code(4) : eval()'d code(4) : eval()'d code on line 3 +Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to 'strtoupper' was tried in eval. dropping it. in %a/nested_eval_blacklist.php(5) : eval()'d code(4) : eval()'d code(4) : eval()'d code on line 3 diff --git a/src/tests/eval_blacklist/nested_eval_blacklist2.phpt b/src/tests/eval_blacklist/nested_eval_blacklist2.phpt index 37f8967..63e56b1 100644 --- a/src/tests/eval_blacklist/nested_eval_blacklist2.phpt +++ b/src/tests/eval_blacklist/nested_eval_blacklist2.phpt @@ -26,4 +26,4 @@ Inception lvl 1... Inception lvl 2... Inception lvl 3... -Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to strtoupper was tried in eval, in %a/nested_eval_blacklist2.php(5) : eval()'d code:7, dropping it. in %a/nested_eval_blacklist2.php(5) : eval()'d code(4) : eval()'d code on line 7 +Fatal error: [snuffleupagus][0.0.0.0][eval][drop] A call to 'strtoupper' was tried in eval. dropping it. in %a/nested_eval_blacklist2.php(5) : eval()'d code(4) : eval()'d code on line 7 -- cgit v1.3