diff options
| author | xXx-caillou-xXx | 2018-08-27 13:56:44 +0200 |
|---|---|---|
| committer | jvoisin | 2018-08-27 11:56:44 +0000 |
| commit | 096e7faa6a5e21e5416a7c8c484e27acd4636a66 (patch) | |
| tree | 3dd11a05c4406280238459be917b8f47d22400f7 /src/sp_wrapper.c | |
| parent | 6abdd9abca50c92390b94fbebb3e7065d5d532da (diff) | |
Add whitelist support for php's wrappers
Diffstat (limited to 'src/sp_wrapper.c')
| -rw-r--r-- | src/sp_wrapper.c | 70 |
1 files changed, 70 insertions, 0 deletions
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 @@ | |||
| 1 | #include "php_snuffleupagus.h" | ||
| 2 | #include "sp_config.h" | ||
| 3 | |||
| 4 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) | ||
| 5 | |||
| 6 | static bool wrapper_is_whitelisted(const zend_string *zs) { | ||
| 7 | const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist; | ||
| 8 | |||
| 9 | if (!zs) { | ||
| 10 | return false; | ||
| 11 | } | ||
| 12 | |||
| 13 | while (list) { | ||
| 14 | if (zend_string_equals_ci(zs, (const zend_string*)list->data)) { | ||
| 15 | return true; | ||
| 16 | } | ||
| 17 | list = list->next; | ||
| 18 | } | ||
| 19 | return false; | ||
| 20 | } | ||
| 21 | |||
| 22 | void sp_disable_wrapper() { | ||
| 23 | HashTable *orig = php_stream_get_url_stream_wrappers_hash(); | ||
| 24 | HashTable *orig_complete = pemalloc(sizeof(*orig_complete), 1); | ||
| 25 | zval *zv; | ||
| 26 | zend_string *zs; | ||
| 27 | |||
| 28 | // Copy the original hashtable into a temporary one, as I'm not sure about | ||
| 29 | // the behaviour of ZEND_HASH_FOREACH when element are removed from the | ||
| 30 | // hashtable used in the loop. | ||
| 31 | zend_hash_init(orig_complete, zend_hash_num_elements(orig), NULL, NULL, 1); | ||
| 32 | zend_hash_copy(orig_complete, orig, NULL); | ||
| 33 | zend_hash_clean(orig); | ||
| 34 | |||
| 35 | ZEND_HASH_FOREACH_STR_KEY_VAL(orig_complete, zs, zv) { | ||
| 36 | if (wrapper_is_whitelisted(zs)) { | ||
| 37 | zend_hash_add(orig, zs, zv); | ||
| 38 | } | ||
| 39 | } | ||
| 40 | ZEND_HASH_FOREACH_END(); | ||
| 41 | |||
| 42 | zend_hash_destroy(orig_complete); | ||
| 43 | pefree(orig_complete, 1); | ||
| 44 | SNUFFLEUPAGUS_G(config).config_wrapper->num_wrapper = zend_hash_num_elements(orig); | ||
| 45 | } | ||
| 46 | |||
| 47 | PHP_FUNCTION(sp_stream_wrapper_register) { | ||
| 48 | void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); | ||
| 49 | zend_string *protocol_name = NULL; | ||
| 50 | |||
| 51 | ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 2, EX_NUM_ARGS()); | ||
| 52 | Z_PARAM_STR(protocol_name); | ||
| 53 | ZEND_PARSE_PARAMETERS_END_EX((void)0); | ||
| 54 | |||
| 55 | if (wrapper_is_whitelisted(protocol_name)) { | ||
| 56 | orig_handler = zend_hash_str_find_ptr( | ||
| 57 | SNUFFLEUPAGUS_G(sp_internal_functions_hook), | ||
| 58 | "stream_wrapper_register", sizeof("stream_wrapper_register") - 1); | ||
| 59 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | int hook_stream_wrappers() { | ||
| 64 | TSRMLS_FETCH(); | ||
| 65 | |||
| 66 | HOOK_FUNCTION("stream_wrapper_register", sp_internal_functions_hook, | ||
| 67 | PHP_FN(sp_stream_wrapper_register)); | ||
| 68 | |||
| 69 | return SUCCESS; | ||
| 70 | } | ||
