From 54c352c1b5aa08b187dd1e52e544709cad2b0fee Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Thu, 23 Sep 2021 12:23:40 +0200 Subject: config is stack allocated now + some code improvements (see details) * for easier memory manegement, the entire sp_config struct was merged into snuffleupagus_globals and allocated on stack where possible * SNUFFLEUPAGUS_G() can be written as SPG(), which is faster to type and easier to read * execution_depth is re-initialized to 0 for each request * function calls with inline string and length parameters consistently use ZEND_STRL instead of sizeof()-1 * execution is actually hooked if recursion protection is enabled * some line breaks were removed to make the code more readable --- src/php_snuffleupagus.h | 41 ++++++++- src/snuffleupagus.c | 201 +++++++++++++++++--------------------------- src/sp_config.c | 30 +++---- src/sp_config.h | 34 -------- src/sp_config_keywords.c | 38 ++++----- src/sp_cookie_encryption.c | 6 +- src/sp_crypt.c | 9 +- src/sp_disabled_functions.c | 46 +++------- src/sp_execute.c | 64 +++++--------- src/sp_harden_rand.c | 6 +- src/sp_ifilter.c | 4 +- src/sp_ini.c | 6 +- src/sp_session.c | 6 +- src/sp_sloppy.c | 2 +- src/sp_unserialize.c | 23 ++--- src/sp_upload_validation.c | 12 +-- src/sp_utils.c | 18 ++-- src/sp_utils.h | 4 +- src/sp_wrapper.c | 9 +- 19 files changed, 228 insertions(+), 331 deletions(-) (limited to 'src') diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index bcb613c..308031b 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h @@ -106,11 +106,44 @@ extern zend_module_entry snuffleupagus_module_entry; #endif ZEND_BEGIN_MODULE_GLOBALS(snuffleupagus) -size_t in_eval; -sp_config config; +// sp_config config; +// --- snuffleupagus config +sp_config_random config_random; +sp_config_sloppy config_sloppy; +sp_config_unserialize config_unserialize; +sp_config_readonly_exec config_readonly_exec; +sp_config_upload_validation config_upload_validation; +sp_config_cookie config_cookie; +sp_config_auto_cookie_secure config_auto_cookie_secure; +sp_config_global_strict config_global_strict; +sp_config_disable_xxe config_disable_xxe; +sp_config_eval config_eval; +sp_config_wrapper config_wrapper; +sp_config_session config_session; +sp_config_ini config_ini; +char config_log_media; +u_long config_max_execution_depth; +bool config_server_encode; +bool config_server_strip; +zend_string *config_encryption_key; +zend_string *config_cookies_env_var; + +HashTable *config_disabled_functions; +HashTable *config_disabled_functions_hooked; +HashTable *config_disabled_functions_ret; +HashTable *config_disabled_functions_ret_hooked; +sp_config_disabled_functions config_disabled_functions_reg; +sp_config_disabled_functions config_disabled_functions_reg_ret; + +bool hook_execute; + +// --- ini options +bool allow_broken_configuration; + +// --- runtime/state variables int is_config_valid; // 1 = valid, 0 = invalid, -1 = none +size_t in_eval; u_long execution_depth; -bool allow_broken_configuration; HashTable *disabled_functions_hook; HashTable *sp_internal_functions_hook; HashTable *sp_eval_blacklist_functions_hook; @@ -118,6 +151,8 @@ ZEND_END_MODULE_GLOBALS(snuffleupagus) ZEND_EXTERN_MODULE_GLOBALS(snuffleupagus) #define SNUFFLEUPAGUS_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(snuffleupagus, v) +#define SPG(v) SNUFFLEUPAGUS_G(v) +#define SPCFG(v) SPG(config_##v) #if defined(ZTS) && defined(COMPILE_DL_SNUFFLEUPAGUS) ZEND_TSRMLS_CACHE_EXTERN() diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index 84ab171..6fd6f25 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c @@ -30,7 +30,7 @@ static inline void sp_op_array_handler(zend_op_array *const op) { if (NULL == op->filename || op->fn_flags & ZEND_ACC_STRICT_TYPES) { return; } else { - if (true == SNUFFLEUPAGUS_G(config).config_global_strict->enable) { + if (SPCFG(global_strict).enable) { op->fn_flags |= ZEND_ACC_STRICT_TYPES; } } @@ -41,16 +41,15 @@ ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) static PHP_INI_MH(StrictMode) { TSRMLS_FETCH(); - SNUFFLEUPAGUS_G(allow_broken_configuration) = false; + SPG(allow_broken_configuration) = false; if (new_value && zend_string_equals_literal(new_value, "1")) { - SNUFFLEUPAGUS_G(allow_broken_configuration) = true; + SPG(allow_broken_configuration) = true; } return SUCCESS; } PHP_INI_BEGIN() -PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, - OnUpdateConfiguration) +PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, OnUpdateConfiguration) PHP_INI_ENTRY("sp.allow_broken_configuration", "0", PHP_INI_SYSTEM, StrictMode) PHP_INI_END() @@ -106,47 +105,28 @@ static PHP_GINIT_FUNCTION(snuffleupagus) { snuffleupagus_globals->is_config_valid = SP_CONFIG_NONE; snuffleupagus_globals->in_eval = 0; -#define SP_INIT(F) \ - snuffleupagus_globals->config.F = \ - pecalloc(sizeof(*(snuffleupagus_globals->config.F)), 1, 1); - SP_INIT(config_random); - SP_INIT(config_sloppy); - SP_INIT(config_unserialize); - SP_INIT(config_readonly_exec); - SP_INIT(config_upload_validation); - SP_INIT(config_cookie); - SP_INIT(config_snuffleupagus); - SP_INIT(config_auto_cookie_secure); - SP_INIT(config_global_strict); - SP_INIT(config_disable_xxe); - SP_INIT(config_eval); - SP_INIT(config_wrapper); - SP_INIT(config_session); - SP_INIT(config_ini); - SP_INIT(config_disabled_functions_reg); - SP_INIT(config_disabled_functions_reg_ret); -#undef SP_INIT - #define SP_INIT_HT(F) \ snuffleupagus_globals->F = pemalloc(sizeof(*(snuffleupagus_globals->F)), 1); \ - zend_hash_init(snuffleupagus_globals->F, 10, NULL, NULL, 1); + zend_hash_init(snuffleupagus_globals->F, 10, NULL, NULL, 1); SP_INIT_HT(disabled_functions_hook); SP_INIT_HT(sp_internal_functions_hook); SP_INIT_HT(sp_eval_blacklist_functions_hook); - SP_INIT_HT(config.config_disabled_functions); - SP_INIT_HT(config.config_disabled_functions_hooked); - SP_INIT_HT(config.config_disabled_functions_ret); - SP_INIT_HT(config.config_disabled_functions_ret_hooked); - SP_INIT_HT(config.config_ini->entries); + SP_INIT_HT(config_disabled_functions); + SP_INIT_HT(config_disabled_functions_hooked); + SP_INIT_HT(config_disabled_functions_ret); + SP_INIT_HT(config_disabled_functions_ret_hooked); + SP_INIT_HT(config_ini.entries); #undef SP_INIT_HT -#define SP_INIT_NULL(F) snuffleupagus_globals->config.F = NULL; - SP_INIT_NULL(config_disabled_functions_reg->disabled_functions); - SP_INIT_NULL(config_disabled_functions_reg_ret->disabled_functions); - SP_INIT_NULL(config_cookie->cookies); - SP_INIT_NULL(config_eval->blacklist); - SP_INIT_NULL(config_eval->whitelist); - SP_INIT_NULL(config_wrapper->whitelist); +#define SP_INIT_NULL(F) snuffleupagus_globals->F = NULL; + SP_INIT_NULL(config_encryption_key); + SP_INIT_NULL(config_cookies_env_var); + SP_INIT_NULL(config_disabled_functions_reg.disabled_functions); + SP_INIT_NULL(config_disabled_functions_reg_ret.disabled_functions); + SP_INIT_NULL(config_cookie.cookies); + SP_INIT_NULL(config_eval.blacklist); + SP_INIT_NULL(config_eval.whitelist); + SP_INIT_NULL(config_wrapper.whitelist); #undef SP_INIT_NULL } @@ -159,10 +139,10 @@ PHP_MINIT_FUNCTION(snuffleupagus) { PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { sp_log_debug("(MSHUTDOWN)"); - unhook_functions(SNUFFLEUPAGUS_G(sp_internal_functions_hook)); - unhook_functions(SNUFFLEUPAGUS_G(disabled_functions_hook)); - unhook_functions(SNUFFLEUPAGUS_G(sp_eval_blacklist_functions_hook)); - if (SNUFFLEUPAGUS_G(config).config_ini->enable) { sp_unhook_ini(); } + unhook_functions(SPG(sp_internal_functions_hook)); + unhook_functions(SPG(disabled_functions_hook)); + unhook_functions(SPG(sp_eval_blacklist_functions_hook)); + if (SPCFG(ini).enable) { sp_unhook_ini(); } UNREGISTER_INI_ENTRIES(); return SUCCESS; @@ -189,57 +169,37 @@ static PHP_GSHUTDOWN_FUNCTION(snuffleupagus) { FREE_HT(sp_eval_blacklist_functions_hook); #define FREE_HT_LIST(F) \ - free_disabled_functions_hashtable(snuffleupagus_globals->config.F); \ - FREE_HT(config.F); + free_disabled_functions_hashtable(snuffleupagus_globals->F); \ + FREE_HT(F); FREE_HT_LIST(config_disabled_functions); FREE_HT_LIST(config_disabled_functions_hooked); FREE_HT_LIST(config_disabled_functions_ret); FREE_HT_LIST(config_disabled_functions_ret_hooked); #undef FREE_HT_LIST - free_config_ini_entries(snuffleupagus_globals->config.config_ini->entries); - FREE_HT(config.config_ini->entries); + free_config_ini_entries(snuffleupagus_globals->config_ini.entries); + FREE_HT(config_ini.entries); #undef FREE_HT -#define FREE_LST_DISABLE(L) \ - sp_list_free(snuffleupagus_globals->config.L, sp_free_disabled_function); - FREE_LST_DISABLE(config_disabled_functions_reg->disabled_functions); - FREE_LST_DISABLE(config_disabled_functions_reg_ret->disabled_functions); -#undef FREE_LST_DISABLE - - sp_list_free(snuffleupagus_globals->config.config_cookie->cookies, sp_free_cookie); + sp_list_free(snuffleupagus_globals->config_disabled_functions_reg.disabled_functions, sp_free_disabled_function); + sp_list_free(snuffleupagus_globals->config_disabled_functions_reg_ret.disabled_functions, sp_free_disabled_function); + sp_list_free(snuffleupagus_globals->config_cookie.cookies, sp_free_cookie); -#define FREE_LST(L) sp_list_free(snuffleupagus_globals->config.L, sp_free_zstr); - FREE_LST(config_eval->blacklist); - FREE_LST(config_eval->whitelist); - FREE_LST(config_wrapper->whitelist); +#define FREE_LST(L) sp_list_free(snuffleupagus_globals->L, sp_free_zstr); + FREE_LST(config_eval.blacklist); + FREE_LST(config_eval.whitelist); + FREE_LST(config_wrapper.whitelist); #undef FREE_LST -#define FREE_CFG(C) pefree(snuffleupagus_globals->config.C, 1); -#define FREE_CFG_ZSTR(C) sp_free_zstr(snuffleupagus_globals->config.C); - FREE_CFG(config_random); - FREE_CFG(config_sloppy); - FREE_CFG_ZSTR(config_unserialize->dump); - FREE_CFG_ZSTR(config_unserialize->textual_representation); - FREE_CFG(config_unserialize); - FREE_CFG(config_readonly_exec); - FREE_CFG_ZSTR(config_upload_validation->script); - FREE_CFG(config_upload_validation); - FREE_CFG(config_cookie); - FREE_CFG(config_snuffleupagus); - FREE_CFG(config_auto_cookie_secure); - FREE_CFG(config_global_strict); - FREE_CFG(config_disable_xxe); - FREE_CFG_ZSTR(config_eval->dump); - FREE_CFG_ZSTR(config_eval->textual_representation); - FREE_CFG(config_eval); - FREE_CFG(config_wrapper); - FREE_CFG(config_session); - FREE_CFG(config_ini); - FREE_CFG(config_disabled_functions_reg); - FREE_CFG(config_disabled_functions_reg_ret); -#undef FREE_CFG +// #define FREE_CFG(C) pefree(snuffleupagus_globals->config.C, 1); +#define FREE_CFG_ZSTR(C) sp_free_zstr(snuffleupagus_globals->C); + FREE_CFG_ZSTR(config_unserialize.dump); + FREE_CFG_ZSTR(config_unserialize.textual_representation); + FREE_CFG_ZSTR(config_upload_validation.script); + FREE_CFG_ZSTR(config_eval.dump); + FREE_CFG_ZSTR(config_eval.textual_representation); +// #undef FREE_CFG #undef FREE_CFG_ZSTR #ifdef SP_DEBUG_STDERR @@ -251,35 +211,32 @@ static PHP_GSHUTDOWN_FUNCTION(snuffleupagus) { } PHP_RINIT_FUNCTION(snuffleupagus) { - SNUFFLEUPAGUS_G(execution_depth) = 0; + SPG(execution_depth) = 0; + SPG(in_eval) = 0; - const sp_config_wrapper *const config_wrapper = - SNUFFLEUPAGUS_G(config).config_wrapper; + const sp_config_wrapper *const config_wrapper = &(SPCFG(wrapper)); #if defined(COMPILE_DL_SNUFFLEUPAGUS) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); #endif - if (!SNUFFLEUPAGUS_G(allow_broken_configuration)) { - if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_INVALID) { + if (!SPG(allow_broken_configuration)) { + if (SPG(is_config_valid) == SP_CONFIG_INVALID) { sp_log_err("config", "Invalid configuration file"); - } else if (SNUFFLEUPAGUS_G(is_config_valid) == SP_CONFIG_NONE) { + } else if (SPG(is_config_valid) == SP_CONFIG_NONE) { sp_log_warn("config", "No configuration specificed via sp.configuration_file"); } } - // We need to disable wrappers loaded by extensions loaded after - // SNUFFLEUPAGUS. + // We need to disable wrappers loaded by extensions loaded after SNUFFLEUPAGUS. if (config_wrapper->enabled && - zend_hash_num_elements(php_stream_get_url_stream_wrappers_hash()) != - config_wrapper->num_wrapper) { + zend_hash_num_elements(php_stream_get_url_stream_wrappers_hash()) != config_wrapper->num_wrapper) { sp_disable_wrapper(); } - if (NULL != SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key) { - if (NULL != SNUFFLEUPAGUS_G(config).config_cookie->cookies) { - zend_hash_apply_with_arguments( - Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]), decrypt_cookie, 0); + if (NULL != SPCFG(encryption_key)) { + if (NULL != SPCFG(cookie).cookies) { + zend_hash_apply_with_arguments(Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]), decrypt_cookie, 0); } } return SUCCESS; @@ -289,7 +246,7 @@ PHP_RSHUTDOWN_FUNCTION(snuffleupagus) { return SUCCESS; } PHP_MINFO_FUNCTION(snuffleupagus) { const char *valid_config; - switch (SNUFFLEUPAGUS_G(is_config_valid)) { + switch (SPG(is_config_valid)) { case SP_CONFIG_VALID: valid_config = "yes"; break; @@ -303,7 +260,7 @@ PHP_MINFO_FUNCTION(snuffleupagus) { php_info_print_table_start(); php_info_print_table_row( 2, "snuffleupagus support", - SNUFFLEUPAGUS_G(is_config_valid) ? "enabled" : "disabled"); + SPG(is_config_valid) ? "enabled" : "disabled"); php_info_print_table_row(2, "Version", PHP_SNUFFLEUPAGUS_VERSION "-sng (with Suhosin-NG patches)"); php_info_print_table_row(2, "Valid config", valid_config); php_info_print_table_end(); @@ -328,14 +285,14 @@ static PHP_INI_MH(OnUpdateConfiguration) { glob_t globbuf; if (0 != glob(config_file, GLOB_NOCHECK, NULL, &globbuf)) { - SNUFFLEUPAGUS_G(is_config_valid) = SP_CONFIG_INVALID; + SPG(is_config_valid) = SP_CONFIG_INVALID; globfree(&globbuf); return FAILURE; } for (size_t i = 0; globbuf.gl_pathv[i]; i++) { if (sp_parse_config(globbuf.gl_pathv[i]) != SUCCESS) { - SNUFFLEUPAGUS_G(is_config_valid) = SP_CONFIG_INVALID; + SPG(is_config_valid) = SP_CONFIG_INVALID; globfree(&globbuf); return FAILURE; } @@ -343,34 +300,34 @@ static PHP_INI_MH(OnUpdateConfiguration) { globfree(&globbuf); } - SNUFFLEUPAGUS_G(is_config_valid) = SP_CONFIG_VALID; + SPG(is_config_valid) = SP_CONFIG_VALID; - if ((SNUFFLEUPAGUS_G(config).config_sloppy->enable)) { + if (SPCFG(sloppy).enable) { hook_sloppy(); } - if (SNUFFLEUPAGUS_G(config).config_random->enable) { + if (SPCFG(random).enable) { hook_rand(); } - if (SNUFFLEUPAGUS_G(config).config_upload_validation->enable) { + if (SPCFG(upload_validation).enable) { hook_upload(); } - if (SNUFFLEUPAGUS_G(config).config_disable_xxe->enable == 0) { + if (SPCFG(disable_xxe).enable == 0) { hook_libxml_disable_entity_loader(); } - if (SNUFFLEUPAGUS_G(config).config_wrapper->enabled) { + if (SPCFG(wrapper).enabled) { hook_stream_wrappers(); } - if (SNUFFLEUPAGUS_G(config).config_session->encrypt || SNUFFLEUPAGUS_G(config).config_session->sid_min_length || SNUFFLEUPAGUS_G(config).config_session->sid_max_length) { + if (SPCFG(session).encrypt || SPCFG(session).sid_min_length || SPCFG(session).sid_max_length) { hook_session(); } - if (NULL != SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key) { - if (SNUFFLEUPAGUS_G(config).config_unserialize->enable) { + if (NULL != SPCFG(encryption_key)) { + if (SPCFG(unserialize).enable) { hook_serialize(); } } @@ -379,13 +336,13 @@ static PHP_INI_MH(OnUpdateConfiguration) { hook_execute(); hook_cookies(); - if (SNUFFLEUPAGUS_G(config).config_ini->enable) { + if (SPCFG(ini).enable) { sp_hook_ini(); } sp_hook_register_server_variables(); - if (true == SNUFFLEUPAGUS_G(config).config_global_strict->enable) { + if (SPCFG(global_strict).enable) { if (!zend_get_extension(PHP_SNUFFLEUPAGUS_EXTNAME)) { zend_extension_entry.startup = NULL; zend_register_extension(&zend_extension_entry, NULL); @@ -395,26 +352,18 @@ static PHP_INI_MH(OnUpdateConfiguration) { } // If `zend_write_default` is not NULL it is already hooked. - if ((zend_hash_str_find( - SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked, "echo", - sizeof("echo") - 1) || - zend_hash_str_find( - SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, "echo", - sizeof("echo") - 1)) && + if ((zend_hash_str_find(SPCFG(disabled_functions_hooked), ZEND_STRL("echo")) || + zend_hash_str_find(SPCFG(disabled_functions_ret_hooked), ZEND_STRL("echo"))) && NULL == zend_write_default && zend_write != hook_echo) { zend_write_default = zend_write; zend_write = hook_echo; } - SNUFFLEUPAGUS_G(config).hook_execute = - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg->disabled_functions || - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg_ret->disabled_functions || - zend_hash_num_elements( - SNUFFLEUPAGUS_G(config).config_disabled_functions) || - zend_hash_num_elements( - SNUFFLEUPAGUS_G(config).config_disabled_functions_ret); + SPG(hook_execute) = SPCFG(max_execution_depth) > 0 || + SPCFG(disabled_functions_reg).disabled_functions || + SPCFG(disabled_functions_reg_ret).disabled_functions || + (SPCFG(disabled_functions) && zend_hash_num_elements(SPCFG(disabled_functions))) || + (SPCFG(disabled_functions) && zend_hash_num_elements(SPCFG(disabled_functions_ret))); return SUCCESS; } diff --git a/src/sp_config.c b/src/sp_config.c index 4d96bbe..ec6c5a8 100644 --- a/src/sp_config.c +++ b/src/sp_config.c @@ -7,24 +7,24 @@ 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_unserialize, SP_TOKEN_UNSERIALIZE_HMAC, &(SPCFG(unserialize))}, + {parse_enable, SP_TOKEN_HARDEN_RANDOM, &(SPCFG(random).enable)}, + {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SPCFG(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_readonly_exec, SP_TOKEN_READONLY_EXEC, &(SPCFG(readonly_exec))}, + {parse_enable, SP_TOKEN_GLOBAL_STRICT, &(SPCFG(global_strict).enable)}, + {parse_upload_validation, SP_TOKEN_UPLOAD_VALIDATION, &(SPCFG(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}, + {parse_enable, SP_TOKEN_AUTO_COOKIE_SECURE, &(SPCFG(auto_cookie_secure).enable)}, + {parse_enable, SP_TOKEN_DISABLE_XXE, &(SPCFG(disable_xxe).enable)}, + {parse_eval_filter_conf, SP_TOKEN_EVAL_BLACKLIST, &(SPCFG(eval).blacklist)}, + {parse_eval_filter_conf, SP_TOKEN_EVAL_WHITELIST, &(SPCFG(eval).whitelist)}, + {parse_session, SP_TOKEN_SESSION_ENCRYPTION, &(SPCFG(session))}, + {parse_enable, SP_TOKEN_SLOPPY_COMPARISON, &(SPCFG(sloppy).enable)}, + {parse_wrapper_whitelist, SP_TOKEN_ALLOW_WRAPPERS, &(SPCFG(wrapper))}, + {parse_ini_protection, SP_TOKEN_INI_PROTECTION, &(SPCFG(ini))}, + {parse_ini_entry, SP_TOKEN_INI, NULL}, {NULL, NULL, NULL}}; return sp_process_rule(parsed_rule, sp_func); } diff --git a/src/sp_config.h b/src/sp_config.h index df36976..262050b 100644 --- a/src/sp_config.h +++ b/src/sp_config.h @@ -32,11 +32,6 @@ typedef struct { uint8_t mask; } sp_cidr; -typedef struct { - zend_string *encryption_key; - zend_string *cookies_env_var; -} sp_config_global; - typedef struct { bool enable; bool simulation; @@ -181,35 +176,6 @@ typedef struct { HashTable *entries; // ht of sp_ini_entry } sp_config_ini; -typedef struct { - sp_config_random *config_random; - sp_config_sloppy *config_sloppy; - sp_config_unserialize *config_unserialize; - sp_config_readonly_exec *config_readonly_exec; - sp_config_upload_validation *config_upload_validation; - sp_config_cookie *config_cookie; - sp_config_global *config_snuffleupagus; - sp_config_auto_cookie_secure *config_auto_cookie_secure; - sp_config_global_strict *config_global_strict; - sp_config_disable_xxe *config_disable_xxe; - sp_config_eval *config_eval; - sp_config_wrapper *config_wrapper; - sp_config_session *config_session; - sp_config_ini *config_ini; - bool hook_execute; - char log_media; - u_long max_execution_depth; - bool server_encode; - bool server_strip; - - HashTable *config_disabled_functions; - HashTable *config_disabled_functions_hooked; - HashTable *config_disabled_functions_ret; - HashTable *config_disabled_functions_ret_hooked; - sp_config_disabled_functions *config_disabled_functions_reg; - sp_config_disabled_functions *config_disabled_functions_reg_ret; -} sp_config; - #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) diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index bd8a9a1..f6af86b 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c @@ -49,12 +49,12 @@ SP_PARSE_FN(parse_session) { #endif if (cfg->encrypt) { - if (!SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var) { + if (!SPCFG(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) { + } else if (!SPCFG(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); @@ -127,12 +127,12 @@ SP_PARSE_FN(parse_readonly_exec) { 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)}, - {parse_ulong, SP_TOKEN_MAX_EXECUTION_DEPTH, &(SNUFFLEUPAGUS_G(config).max_execution_depth)}, - {parse_enable, SP_TOKEN_SERVER_ENCODE, &(SNUFFLEUPAGUS_G(config).server_encode)}, - {parse_enable, SP_TOKEN_SERVER_STRIP, &(SNUFFLEUPAGUS_G(config).server_strip)}, + {parse_str, SP_TOKEN_ENCRYPTION_KEY, &(SPCFG(encryption_key))}, + {parse_str, SP_TOKEN_ENV_VAR, &(SPCFG(cookies_env_var))}, + {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SPCFG(log_media))}, + {parse_ulong, SP_TOKEN_MAX_EXECUTION_DEPTH, &(SPCFG(max_execution_depth))}, + {parse_enable, SP_TOKEN_SERVER_ENCODE, &(SPCFG(server_encode))}, + {parse_enable, SP_TOKEN_SERVER_STRIP, &(SPCFG(server_strip))}, {0, 0, 0}}; SP_PROCESS_CONFIG_KEYWORDS_ERR(); @@ -140,7 +140,7 @@ SP_PARSE_FN(parse_global) { } SP_PARSE_FN(parse_eval_filter_conf) { - sp_config_eval *cfg = SNUFFLEUPAGUS_G(config).config_eval; + sp_config_eval *cfg = &(SPCFG(eval)); sp_config_keyword config_keywords[] = { {parse_list, SP_TOKEN_LIST, retval}, @@ -186,11 +186,11 @@ SP_PARSE_FN(parse_cookie) { SP_PROCESS_CONFIG_KEYWORDS(goto err); if (cookie->encrypt) { - if (!SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var) { + if (!SPCFG(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) { + } else if (!SPCFG(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); @@ -220,7 +220,7 @@ SP_PARSE_FN(parse_cookie) { } } - SNUFFLEUPAGUS_G(config).config_cookie->cookies = sp_list_insert(SNUFFLEUPAGUS_G(config).config_cookie->cookies, cookie); + SPCFG(cookie).cookies = sp_list_insert(SPCFG(cookie).cookies, cookie); return SP_PARSER_STOP; @@ -316,7 +316,7 @@ SP_PARSE_FN(parse_disabled_functions) { goto out; } if (df->filename && (*ZSTR_VAL(df->filename) != '/') && - (0 != strncmp(ZSTR_VAL(df->filename), "phar://", strlen("phar://")))) { + (0 != strncmp(ZSTR_VAL(df->filename), ZEND_STRL("phar://")))) { 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; } @@ -365,20 +365,20 @@ SP_PARSE_FN(parse_disabled_functions) { 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); + df->function = zend_string_init(ZEND_STRL("echo"), 1); } 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(SPCFG(disabled_functions_ret), df); } else { - add_df_to_hashtable(SNUFFLEUPAGUS_G(config).config_disabled_functions, df); + add_df_to_hashtable(SPCFG(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); + SPCFG(disabled_functions_reg_ret).disabled_functions = sp_list_insert(SPCFG(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); + SPCFG(disabled_functions_reg).disabled_functions = sp_list_insert(SPCFG(disabled_functions_reg).disabled_functions, df); } } return SP_PARSER_STOP; @@ -493,7 +493,7 @@ SP_PARSE_FN(parse_ini_entry) { } entry->access = ro - rw; - zend_hash_add_ptr(SNUFFLEUPAGUS_G(config).config_ini->entries, entry->key, entry); + zend_hash_add_ptr(SPCFG(ini).entries, entry->key, entry); return SP_PARSER_STOP; err: diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c index 7bcedd2..b2cff66 100644 --- a/src/sp_cookie_encryption.c +++ b/src/sp_cookie_encryption.c @@ -1,7 +1,7 @@ #include "php_snuffleupagus.h" static inline const sp_cookie *sp_lookup_cookie_config(const zend_string *key) { - const sp_list_node *it = SNUFFLEUPAGUS_G(config).config_cookie->cookies; + const sp_list_node *it = SPCFG(cookie).cookies; while (it) { const sp_cookie *config = it->data; @@ -133,11 +133,11 @@ PHP_FUNCTION(sp_setcookie) { } /* If the request was issued over HTTPS, the cookie should be "secure" */ - if (SNUFFLEUPAGUS_G(config).config_auto_cookie_secure) { + if (SPCFG(auto_cookie_secure).enable) { const zval server_vars = PG(http_globals)[TRACK_VARS_SERVER]; if (Z_TYPE(server_vars) == IS_ARRAY) { const zval *is_https = - zend_hash_str_find(Z_ARRVAL(server_vars), "HTTPS", strlen("HTTPS")); + zend_hash_str_find(Z_ARRVAL(server_vars), ZEND_STRL("HTTPS")); if (NULL != is_https) { secure = 1; } diff --git a/src/sp_crypt.c b/src/sp_crypt.c index ff8f65e..c1d9403 100644 --- a/src/sp_crypt.c +++ b/src/sp_crypt.c @@ -3,13 +3,10 @@ void generate_key(unsigned char *key) { PHP_SHA256_CTX ctx; const char *user_agent = getenv("HTTP_USER_AGENT"); - const zend_string *env_var_zend = - SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var; - const zend_string *encryption_key_zend = - SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key; + const zend_string *env_var_zend = SPCFG(cookies_env_var); + const zend_string *encryption_key_zend = SPCFG(encryption_key); const char *env_var = (env_var_zend ? getenv(ZSTR_VAL(env_var_zend)) : NULL); - const char *encryption_key = - (encryption_key_zend ? ZSTR_VAL(encryption_key_zend) : NULL); + const char *encryption_key = (encryption_key_zend ? ZSTR_VAL(encryption_key_zend) : NULL); assert(32 == crypto_secretbox_KEYBYTES); // 32 is the size of a SHA256. assert(encryption_key); // Encryption key can't be NULL diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 6ff3915..4ef72bf 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c @@ -479,21 +479,13 @@ ZEND_FUNCTION(check_disabled_function) { zif_handler orig_handler; const char* current_function_name = get_active_function_name(TSRMLS_C); - should_disable_ht( - execute_data, current_function_name, NULL, NULL, - SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions, - SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked); + should_disable_ht(execute_data, current_function_name, NULL, NULL, SPCFG(disabled_functions_reg).disabled_functions, SPCFG(disabled_functions_hooked)); orig_handler = zend_hash_str_find_ptr( - SNUFFLEUPAGUS_G(disabled_functions_hook), current_function_name, + SPG(disabled_functions_hook), current_function_name, strlen(current_function_name)); orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); - should_drop_on_ret_ht( - return_value, current_function_name, - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg_ret->disabled_functions, - SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, - execute_data); + should_drop_on_ret_ht(return_value, current_function_name, SPCFG(disabled_functions_reg_ret).disabled_functions, SPCFG(disabled_functions_ret_hooked), execute_data); } static int hook_functions_regexp(const sp_list_node* config) { @@ -547,10 +539,10 @@ ZEND_FUNCTION(eval_blacklist_callback) { } zend_string_release(tmp); - if (SNUFFLEUPAGUS_G(in_eval) > 0) { + if (SPG(in_eval) > 0) { // 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; + const sp_config_eval* config_eval = &(SPCFG(eval)); if (config_eval->dump) { sp_log_request(config_eval->dump, config_eval->textual_representation); @@ -565,7 +557,7 @@ ZEND_FUNCTION(eval_blacklist_callback) { whitelisted: orig_handler = zend_hash_str_find_ptr( - SNUFFLEUPAGUS_G(sp_eval_blacklist_functions_hook), current_function_name, + SPG(sp_eval_blacklist_functions_hook), current_function_name, strlen(current_function_name)); orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); } @@ -575,26 +567,19 @@ int hook_disabled_functions(void) { int ret = SUCCESS; - hook_functions(SNUFFLEUPAGUS_G(config).config_disabled_functions, - SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked); + hook_functions(SPCFG(disabled_functions), SPCFG(disabled_functions_hooked)); + hook_functions(SPCFG(disabled_functions_ret), SPCFG(disabled_functions_ret_hooked)); - hook_functions(SNUFFLEUPAGUS_G(config).config_disabled_functions_ret, - SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked); + ret |= hook_functions_regexp(SPCFG(disabled_functions_reg).disabled_functions); - ret |= hook_functions_regexp( - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg->disabled_functions); + ret |= hook_functions_regexp(SPCFG(disabled_functions_reg_ret).disabled_functions); - ret |= hook_functions_regexp( - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg_ret->disabled_functions); - - if (NULL != SNUFFLEUPAGUS_G(config).config_eval->blacklist) { - sp_list_node* it = SNUFFLEUPAGUS_G(config).config_eval->blacklist; + if (NULL != SPCFG(eval).blacklist) { + sp_list_node* it = SPCFG(eval).blacklist; while (it) { hook_function(ZSTR_VAL((zend_string*)it->data), - SNUFFLEUPAGUS_G(sp_eval_blacklist_functions_hook), + SPG(sp_eval_blacklist_functions_hook), PHP_FN(eval_blacklist_callback)); it = it->next; } @@ -611,10 +596,7 @@ int hook_echo(const char* str, size_t str_length) { #endif zend_string* zs = zend_string_init(str, str_length, 0); - should_disable_ht( - EG(current_execute_data), "echo", zs, NULL, - SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions, - SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked); + should_disable_ht(EG(current_execute_data), "echo", zs, NULL, SPCFG(disabled_functions_reg).disabled_functions, SPCFG(disabled_functions_hooked)); zend_string_release(zs); diff --git a/src/sp_execute.c b/src/sp_execute.c index 41257ad..ccb7508 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c @@ -8,8 +8,7 @@ static int (*orig_zend_stream_open)(const char *filename, // FIXME handle symlink ZEND_COLD static inline void terminate_if_writable(const char *filename) { - const sp_config_readonly_exec *config_ro_exec = - SNUFFLEUPAGUS_G(config).config_readonly_exec; + const sp_config_readonly_exec *config_ro_exec = &(SPCFG(readonly_exec)); if (0 == access(filename, W_OK)) { if (config_ro_exec->dump) { @@ -43,21 +42,18 @@ inline static void is_builtin_matching( return; } - should_disable_ht( - EG(current_execute_data), function_name, param_value, param_name, - SNUFFLEUPAGUS_G(config).config_disabled_functions_reg->disabled_functions, - ht); + should_disable_ht(EG(current_execute_data), function_name, param_value, param_name, SPCFG(disabled_functions_reg).disabled_functions, ht); } static void ZEND_HOT is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { - const sp_config_eval *config_eval = SNUFFLEUPAGUS_G(config).config_eval; + const sp_config_eval *config_eval = &(SPCFG(eval)); - if (EXPECTED(0 == SNUFFLEUPAGUS_G(in_eval))) { + if (EXPECTED(0 == SPG(in_eval))) { return; } - if (EXPECTED(NULL == SNUFFLEUPAGUS_G(config).config_eval->whitelist)) { + if (EXPECTED(NULL == config_eval->whitelist)) { return; } @@ -113,50 +109,45 @@ zend_string *get_eval_filename(const char *const filename) { } static inline void sp_orig_execute(zend_execute_data *execute_data) { - SNUFFLEUPAGUS_G(execution_depth)++; - if (SNUFFLEUPAGUS_G(execution_depth) > SNUFFLEUPAGUS_G(config).max_execution_depth && SNUFFLEUPAGUS_G(config).max_execution_depth > 0) { + SPG(execution_depth)++; + if (SPCFG(max_execution_depth) > 0 && SPG(execution_depth) > SPCFG(max_execution_depth)) { sp_log_drop("execute", "Maximum recursion limit reached. Script terminated."); } orig_execute_ex(execute_data); - SNUFFLEUPAGUS_G(execution_depth)--; + SPG(execution_depth)--; } static void sp_execute_ex(zend_execute_data *execute_data) { is_in_eval_and_whitelisted(execute_data); - const HashTable *config_disabled_functions = - SNUFFLEUPAGUS_G(config).config_disabled_functions; + const HashTable *config_disabled_functions = SPCFG(disabled_functions); if (!execute_data) { return; // LCOV_EXCL_LINE } if (UNEXPECTED(EX(func)->op_array.type == ZEND_EVAL_CODE)) { - const sp_list_node *config = zend_hash_str_find_ptr( - config_disabled_functions, "eval", sizeof("eval") - 1); + const sp_list_node *config = zend_hash_str_find_ptr(config_disabled_functions, ZEND_STRL("eval")); zend_string *filename = get_eval_filename(zend_get_executed_filename()); - is_builtin_matching(filename, "eval", NULL, config, - config_disabled_functions); + is_builtin_matching(filename, "eval", NULL, config, config_disabled_functions); zend_string_release(filename); - SNUFFLEUPAGUS_G(in_eval)++; + SPG(in_eval)++; sp_orig_execute(execute_data); - SNUFFLEUPAGUS_G(in_eval)--; + SPG(in_eval)--; return; } if (NULL != EX(func)->op_array.filename) { - if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { + if (SPCFG(readonly_exec).enable) { terminate_if_writable(ZSTR_VAL(EX(func)->op_array.filename)); } } - if (SNUFFLEUPAGUS_G(config).hook_execute) { + if (SPG(hook_execute)) { char *function_name = get_complete_function_path(execute_data); zval ret_val; - const sp_list_node *config_disabled_functions_reg = - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg->disabled_functions; + const sp_list_node *config_disabled_functions_reg = SPCFG(disabled_functions_reg).disabled_functions; if (!function_name) { sp_orig_execute(execute_data); @@ -195,11 +186,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) { sp_orig_execute(execute_data); - should_drop_on_ret_ht( - EX(return_value), function_name, - SNUFFLEUPAGUS_G(config) - .config_disabled_functions_reg_ret->disabled_functions, - SNUFFLEUPAGUS_G(config).config_disabled_functions_ret, execute_data); + should_drop_on_ret_ht(EX(return_value), function_name, SPCFG(disabled_functions_reg_ret).disabled_functions, SPCFG(disabled_functions_ret), execute_data); efree(function_name); if (EX(return_value) == &ret_val) { @@ -231,41 +218,36 @@ static int sp_stream_open(const char *filename, zend_file_handle *handle) { } zend_string *zend_filename = zend_string_init(filename, strlen(filename), 0); - const HashTable *disabled_functions_hooked = - SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked; + const HashTable *disabled_functions_hooked = SPCFG(disabled_functions_hooked); switch (data->opline->opcode) { case ZEND_INCLUDE_OR_EVAL: - if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { + if (SPCFG(readonly_exec).enable) { terminate_if_writable(filename); } switch (data->opline->extended_value) { case ZEND_INCLUDE: is_builtin_matching( zend_filename, "include", "inclusion path", - zend_hash_str_find_ptr(disabled_functions_hooked, "include", - sizeof("include") - 1), + zend_hash_str_find_ptr(disabled_functions_hooked, ZEND_STRL("include")), disabled_functions_hooked); break; case ZEND_REQUIRE: is_builtin_matching( zend_filename, "require", "inclusion path", - zend_hash_str_find_ptr(disabled_functions_hooked, "require", - sizeof("require") - 1), + zend_hash_str_find_ptr(disabled_functions_hooked, ZEND_STRL("require")), disabled_functions_hooked); break; case ZEND_REQUIRE_ONCE: is_builtin_matching( zend_filename, "require_once", "inclusion path", - zend_hash_str_find_ptr(disabled_functions_hooked, "require_once", - sizeof("require_once") - 1), + zend_hash_str_find_ptr(disabled_functions_hooked, ZEND_STRL("require_once")), disabled_functions_hooked); break; case ZEND_INCLUDE_ONCE: is_builtin_matching( zend_filename, "include_once", "inclusion path", - zend_hash_str_find_ptr(disabled_functions_hooked, "include_once", - sizeof("include_once") - 1), + zend_hash_str_find_ptr(disabled_functions_hooked, ZEND_STRL("include_once")), disabled_functions_hooked); break; EMPTY_SWITCH_DEFAULT_CASE(); // LCOV_EXCL_LINE diff --git a/src/sp_harden_rand.c b/src/sp_harden_rand.c index 43c2a5b..3e9bcb3 100644 --- a/src/sp_harden_rand.c +++ b/src/sp_harden_rand.c @@ -54,8 +54,7 @@ PHP_FUNCTION(sp_rand) { /* call the original `rand` function, * since we might no be the only ones to hook it*/ - orig_handler = zend_hash_str_find_ptr( - SNUFFLEUPAGUS_G(sp_internal_functions_hook), "rand", sizeof("rand") - 1); + orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("rand")); orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); random_int_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU); @@ -67,8 +66,7 @@ PHP_FUNCTION(sp_mt_rand) { /* call the original `mt_rand` function, * since we might no be the only ones to hook it*/ orig_handler = - zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), - "mt_rand", sizeof("mt_rand") - 1); + zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("mt_rand")); orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); random_int_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU); diff --git a/src/sp_ifilter.c b/src/sp_ifilter.c index a475c1e..8099882 100644 --- a/src/sp_ifilter.c +++ b/src/sp_ifilter.c @@ -77,12 +77,12 @@ static void sp_register_server_variables(zval *track_vars_array) { svars = Z_ARRVAL_P(track_vars_array); - if (SNUFFLEUPAGUS_G(config).server_encode) { + if (SPCFG(server_encode)) { sp_server_encode(svars, ZEND_STRL("REQUEST_URI")); sp_server_encode(svars, ZEND_STRL("QUERY_STRING")); } - if (SNUFFLEUPAGUS_G(config).server_strip) { + if (SPCFG(server_strip)) { sp_server_strip(svars, ZEND_STRL("PHP_SELF")); sp_server_strip(svars, ZEND_STRL("HTTP_HOST")); sp_server_strip(svars, ZEND_STRL("HTTP_USER_AGENT")); diff --git a/src/sp_ini.c b/src/sp_ini.c index 5777ca3..2238e3a 100644 --- a/src/sp_ini.c +++ b/src/sp_ini.c @@ -17,7 +17,7 @@ static bool /* success */ sp_ini_check(zend_string *varname, zend_string *new_va return false; } - sp_config_ini *cfg = SNUFFLEUPAGUS_G(config).config_ini; + sp_config_ini *cfg = &(SPCFG(ini)); sp_ini_entry *entry = zend_hash_find_ptr(cfg->entries, varname); if (sp_entry_p) { *sp_entry_p = entry; @@ -92,7 +92,7 @@ static PHP_INI_MH(sp_ini_onmodify) { } void sp_hook_ini() { - sp_config_ini *cfg = SNUFFLEUPAGUS_G(config).config_ini; + sp_config_ini *cfg = &(SPCFG(ini)); sp_ini_entry *sp_entry; zend_ini_entry *ini_entry; ZEND_HASH_FOREACH_PTR(cfg->entries, sp_entry) @@ -129,7 +129,7 @@ void sp_hook_ini() { void sp_unhook_ini() { sp_ini_entry *sp_entry; zend_ini_entry *ini_entry; - ZEND_HASH_FOREACH_PTR(SNUFFLEUPAGUS_G(config).config_ini->entries, sp_entry) + ZEND_HASH_FOREACH_PTR(SPCFG(ini).entries, sp_entry) if (!sp_entry->orig_onmodify) { // not hooked or no original onmodify continue; diff --git a/src/sp_session.c b/src/sp_session.c index 64233d1..b54849e 100644 --- a/src/sp_session.c +++ b/src/sp_session.c @@ -25,7 +25,7 @@ static int (*previous_sessionRINIT)(INIT_FUNC_ARGS) = NULL; static ZEND_INI_MH((*old_OnUpdateSaveHandler)) = NULL; static void check_sid_length(zend_string *sid) { - const sp_config_session *cfg = SNUFFLEUPAGUS_G(config).config_session; + const sp_config_session *cfg = &(SPCFG(session)); if (sid) { if (cfg->sid_min_length && ZSTR_LEN(sid) < cfg->sid_min_length) { @@ -38,7 +38,7 @@ static void check_sid_length(zend_string *sid) { } static int sp_hook_s_read(PS_READ_ARGS) { - const sp_config_session *cfg = SNUFFLEUPAGUS_G(config).config_session; + const sp_config_session *cfg = &(SPCFG(session)); check_sid_length(key); int r = old_s_read(mod_data, key, val, maxlifetime); @@ -65,7 +65,7 @@ static int sp_hook_s_read(PS_READ_ARGS) { } static int sp_hook_s_write(PS_WRITE_ARGS) { - const sp_config_session *cfg = SNUFFLEUPAGUS_G(config).config_session; + const sp_config_session *cfg = &(SPCFG(session)); check_sid_length(key); if (ZSTR_LEN(val) > 0 && cfg->encrypt) { diff --git a/src/sp_sloppy.c b/src/sp_sloppy.c index ff2d644..8afddc9 100644 --- a/src/sp_sloppy.c +++ b/src/sp_sloppy.c @@ -69,7 +69,7 @@ static void array_handler(INTERNAL_FUNCTION_PARAMETERS, const char* name, ZVAL_STRING(&func_name, name); - handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), + handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), name, size); zend_internal_function* func = zend_hash_str_find_ptr(CG(function_table), name, size); diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c index 82b2cef..1c9f731 100644 --- a/src/sp_unserialize.c +++ b/src/sp_unserialize.c @@ -4,10 +4,10 @@ PHP_FUNCTION(sp_serialize) { zif_handler orig_handler; /* Call the original `serialize` function. */ - orig_handler = - zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), - "serialize", sizeof("serialize") - 1); - orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("serialize")); + if (orig_handler) { + orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } /* Compute the HMAC of the textual representation of the serialized data*/ zval func_name; @@ -19,7 +19,7 @@ PHP_FUNCTION(sp_serialize) { params[1] = *return_value; ZVAL_STRING( ¶ms[2], - ZSTR_VAL(SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)); + ZSTR_VAL(SPCFG(encryption_key))); call_user_function(CG(function_table), NULL, &func_name, &hmac, 3, params); size_t len = Z_STRLEN_P(return_value) + Z_STRLEN(hmac); @@ -46,8 +46,7 @@ PHP_FUNCTION(sp_unserialize) { size_t buf_len = 0; zval *opts = NULL; - const sp_config_unserialize *config_unserialize = - SNUFFLEUPAGUS_G(config).config_unserialize; + const sp_config_unserialize *config_unserialize = &(SPCFG(unserialize)); if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &opts) == FAILURE) { @@ -71,7 +70,7 @@ PHP_FUNCTION(sp_unserialize) { ZVAL_STRING(¶ms[1], serialized_str); ZVAL_STRING( ¶ms[2], - ZSTR_VAL(SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)); + ZSTR_VAL(SPCFG(encryption_key))); call_user_function(CG(function_table), NULL, &func_name, &expected_hmac, 3, params); @@ -81,9 +80,7 @@ PHP_FUNCTION(sp_unserialize) { } if (0 == status) { - if ((orig_handler = zend_hash_str_find_ptr( - SNUFFLEUPAGUS_G(sp_internal_functions_hook), "unserialize", - sizeof("unserialize") - 1))) { + if ((orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("unserialize")))) { orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); } } else { @@ -93,9 +90,7 @@ PHP_FUNCTION(sp_unserialize) { } if (true == config_unserialize->simulation) { sp_log_simulation("unserialize", "Invalid HMAC for %s", serialized_str); - if ((orig_handler = zend_hash_str_find_ptr( - SNUFFLEUPAGUS_G(sp_internal_functions_hook), "unserialize", - sizeof("unserialize") - 1))) { + if ((orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("unserialize")))) { orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); } } else { diff --git a/src/sp_upload_validation.c b/src/sp_upload_validation.c index 4d44011..bff7e43 100644 --- a/src/sp_upload_validation.c +++ b/src/sp_upload_validation.c @@ -32,8 +32,7 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) { if (event == MULTIPART_EVENT_END) { zend_string *file_key __attribute__((unused)) = NULL; - const sp_config_upload_validation *config_upload = - SNUFFLEUPAGUS_G(config).config_upload_validation; + const sp_config_upload_validation *config_upload = &(SPCFG(upload_validation)); zval *file; pid_t pid; @@ -44,12 +43,9 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) { ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES]), file_key, file) { // for each uploaded file - char *filename = Z_STRVAL_P( - zend_hash_str_find(Z_ARRVAL_P(file), "name", sizeof("name") - 1)); - char *tmp_name = Z_STRVAL_P(zend_hash_str_find( - Z_ARRVAL_P(file), "tmp_name", sizeof("tmp_name") - 1)); - size_t filesize = Z_LVAL_P( - zend_hash_str_find(Z_ARRVAL_P(file), "size", sizeof("size") - 1)); + char *filename = Z_STRVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), ZEND_STRL("name"))); + char *tmp_name = Z_STRVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), ZEND_STRL("tmp_name"))); + size_t filesize = Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), ZEND_STRL("size"))); char *cmd[3] = {0}; char *env[5] = {0}; diff --git a/src/sp_utils.c b/src/sp_utils.c index de19321..ff85494 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c @@ -46,7 +46,7 @@ void sp_log_msgf(char const* restrict feature, int level, int type, break; } - switch (SNUFFLEUPAGUS_G(config).log_media) { + switch (SPCFG(log_media)) { case SP_SYSLOG: { const char* error_filename = zend_get_executed_filename(); int syslog_level = (level == E_ERROR) ? LOG_ERR : LOG_INFO; @@ -244,17 +244,17 @@ const zend_string* sp_zval_to_zend_string(const zval* zv) { return Z_STR_P(zv); } case IS_FALSE: - return zend_string_init("FALSE", sizeof("FALSE") - 1, 0); + return zend_string_init(ZEND_STRL("FALSE"), 0); case IS_TRUE: - return zend_string_init("TRUE", sizeof("TRUE") - 1, 0); + return zend_string_init(ZEND_STRL("TRUE"), 0); case IS_NULL: - return zend_string_init("NULL", sizeof("NULL") - 1, 0); + return zend_string_init(ZEND_STRL("NULL"), 0); case IS_OBJECT: - return zend_string_init("OBJECT", sizeof("OBJECT") - 1, 0); + return zend_string_init(ZEND_STRL("OBJECT"), 0); case IS_ARRAY: - return zend_string_init("ARRAY", sizeof("ARRAY") - 1, 0); + return zend_string_init(ZEND_STRL("ARRAY"), 0); case IS_RESOURCE: - return zend_string_init("RESOURCE", sizeof("RESOURCE") - 1, 0); + return zend_string_init(ZEND_STRL("RESOURCE"), 0); default: // LCOV_EXCL_LINE return zend_string_init("", 0, 0); // LCOV_EXCL_LINE } @@ -432,7 +432,7 @@ bool hook_function(const char* original_name, HashTable* hook_table, if (NULL == mb_name) { return FAILURE; } - memcpy(mb_name, "mb_", sizeof("mb_") - 1); + memcpy(mb_name, ZEND_STRL("mb_")); memcpy(mb_name + 3, VAR_AND_LEN(original_name)); _hook_function(mb_name, hook_table, new_function); efree(mb_name); @@ -471,7 +471,7 @@ 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; + const sp_list_node* it = SPCFG(eval).whitelist; if (!it) { return false; } diff --git a/src/sp_utils.h b/src/sp_utils.h index ef626a3..27c8bfa 100644 --- a/src/sp_utils.h +++ b/src/sp_utils.h @@ -23,10 +23,10 @@ #define SHA256_SIZE 32 #define HOOK_FUNCTION(original_name, hook_table, new_function) \ - hook_function(original_name, SNUFFLEUPAGUS_G(hook_table), new_function) + hook_function(original_name, SPG(hook_table), new_function) #define HOOK_FUNCTION_BY_REGEXP(regexp, hook_table, new_function) \ - hook_regexp(regexp, SNUFFLEUPAGUS_G(hook_table), new_function) + hook_regexp(regexp, SPG(hook_table), new_function) #define SP_TYPE_LOG (0) #define SP_TYPE_DROP (1) diff --git a/src/sp_wrapper.c b/src/sp_wrapper.c index 7610114..1538e33 100644 --- a/src/sp_wrapper.c +++ b/src/sp_wrapper.c @@ -1,7 +1,7 @@ #include "php_snuffleupagus.h" static bool wrapper_is_whitelisted(const zend_string *const zs) { - const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist; + const sp_list_node *list = SPCFG(wrapper).whitelist; if (!zs) { return false; // LCOV_EXCL_LINE @@ -38,8 +38,7 @@ void sp_disable_wrapper() { zend_hash_destroy(orig_complete); pefree(orig_complete, 1); - SNUFFLEUPAGUS_G(config).config_wrapper->num_wrapper = - zend_hash_num_elements(orig); + SPCFG(wrapper).num_wrapper = zend_hash_num_elements(orig); } PHP_FUNCTION(sp_stream_wrapper_register) { @@ -53,9 +52,7 @@ PHP_FUNCTION(sp_stream_wrapper_register) { // LCOV_EXCL_BR_END if (wrapper_is_whitelisted(protocol_name)) { - orig_handler = zend_hash_str_find_ptr( - SNUFFLEUPAGUS_G(sp_internal_functions_hook), "stream_wrapper_register", - sizeof("stream_wrapper_register") - 1); + orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("stream_wrapper_register")); orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); } } -- cgit v1.3