From 096e7faa6a5e21e5416a7c8c484e27acd4636a66 Mon Sep 17 00:00:00 2001 From: xXx-caillou-xXx Date: Mon, 27 Aug 2018 13:56:44 +0200 Subject: Add whitelist support for php's wrappers --- src/sp_wrapper.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/sp_wrapper.c (limited to 'src/sp_wrapper.c') diff --git a/src/sp_wrapper.c b/src/sp_wrapper.c new file mode 100644 index 0000000..d9cd296 --- /dev/null +++ b/src/sp_wrapper.c @@ -0,0 +1,70 @@ +#include "php_snuffleupagus.h" +#include "sp_config.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) + +static bool wrapper_is_whitelisted(const zend_string *zs) { + const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist; + + if (!zs) { + return false; + } + + while (list) { + if (zend_string_equals_ci(zs, (const zend_string*)list->data)) { + return true; + } + list = list->next; + } + return false; +} + +void sp_disable_wrapper() { + HashTable *orig = php_stream_get_url_stream_wrappers_hash(); + HashTable *orig_complete = pemalloc(sizeof(*orig_complete), 1); + zval *zv; + zend_string *zs; + + // Copy the original hashtable into a temporary one, as I'm not sure about + // the behaviour of ZEND_HASH_FOREACH when element are removed from the + // hashtable used in the loop. + zend_hash_init(orig_complete, zend_hash_num_elements(orig), NULL, NULL, 1); + zend_hash_copy(orig_complete, orig, NULL); + zend_hash_clean(orig); + + ZEND_HASH_FOREACH_STR_KEY_VAL(orig_complete, zs, zv) { + if (wrapper_is_whitelisted(zs)) { + zend_hash_add(orig, zs, zv); + } + } + ZEND_HASH_FOREACH_END(); + + zend_hash_destroy(orig_complete); + pefree(orig_complete, 1); + SNUFFLEUPAGUS_G(config).config_wrapper->num_wrapper = zend_hash_num_elements(orig); +} + +PHP_FUNCTION(sp_stream_wrapper_register) { + void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); + zend_string *protocol_name = NULL; + + ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 2, EX_NUM_ARGS()); + Z_PARAM_STR(protocol_name); + ZEND_PARSE_PARAMETERS_END_EX((void)0); + + 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(INTERNAL_FUNCTION_PARAM_PASSTHRU); + } +} + +int hook_stream_wrappers() { + TSRMLS_FETCH(); + + HOOK_FUNCTION("stream_wrapper_register", sp_internal_functions_hook, + PHP_FN(sp_stream_wrapper_register)); + + return SUCCESS; +} -- cgit v1.3