From 7832438b7abedf567ce6376f99949f419abcdff1 Mon Sep 17 00:00:00 2001 From: kkadosh Date: Tue, 29 May 2018 19:34:16 +0000 Subject: Support session encryption Implement session encryption.--- src/sp_session.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/sp_session.c (limited to 'src/sp_session.c') diff --git a/src/sp_session.c b/src/sp_session.c new file mode 100644 index 0000000..4085007 --- /dev/null +++ b/src/sp_session.c @@ -0,0 +1,159 @@ +#include "php_snuffleupagus.h" +#include "ext/session/php_session.h" + +ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus); + +#ifdef ZTS +static ts_rsrc_id session_globals_id = 0; +#define SESSION_G(v) ZEND_TSRMG(session_globals_id, php_ps_globals *, v) +#ifdef COMPILE_DL_SESSION +ZEND_TSRMLS_CACHE_EXTERN(); +#endif +#else +#define SESSION_G(v) (ps_globals.v) +#endif + +static php_ps_globals *session_globals = NULL; +static ps_module *s_module; +static ps_module *s_original_mod; +static int (*old_s_read)(PS_READ_ARGS); +static int (*old_s_write)(PS_WRITE_ARGS); +static int (*previous_sessionRINIT)(INIT_FUNC_ARGS) = NULL; +static ZEND_INI_MH((*old_OnUpdateSaveHandler)) = NULL; + + +static int sp_hook_s_read(PS_READ_ARGS) { + int r = old_s_read(mod_data, key, val, maxlifetime); + if (r == SUCCESS && SNUFFLEUPAGUS_G(config).config_session->encrypt && + val != NULL && *val != NULL && ZSTR_LEN(*val)) { + zend_string *orig_val = *val; + zval val_zval; + ZVAL_PSTRINGL(&val_zval, ZSTR_VAL(*val), ZSTR_LEN(*val)); + + int ret = decrypt_zval( + &val_zval, SNUFFLEUPAGUS_G(config).config_session->simulation, + NULL); + if (0 != ret) { + if (SNUFFLEUPAGUS_G(config).config_session->simulation) { + return ret; + } else { + sp_terminate(); + } + } + + *val = zend_string_dup(val_zval.value.str, 0); + if (*val == NULL) { + *val = ZSTR_EMPTY_ALLOC(); + } + zend_string_release(orig_val); + } + + return r; +} + + +static int sp_hook_s_write(PS_WRITE_ARGS) { + if (ZSTR_LEN(val) > 0 && + SNUFFLEUPAGUS_G(config).config_session->encrypt) { + zend_string *new_val = encrypt_zval(ZSTR_VAL(val), ZSTR_LEN(val)); + return old_s_write(mod_data, key, new_val, maxlifetime); + } + return old_s_write(mod_data, key, val, maxlifetime); +} + +static void sp_hook_session_module() { + ps_module *old_mod = SESSION_G(mod); + ps_module *mod; + + if (old_mod == NULL || s_module == old_mod) { + return; + } + + if (s_module == NULL) { + s_module = mod = malloc(sizeof(ps_module)); + if (mod == NULL) { + return; + } + } + + s_original_mod = old_mod; + + mod = s_module; + memcpy(mod, old_mod, sizeof(ps_module)); + + old_s_read = mod->s_read; + mod->s_read = sp_hook_s_read; + + old_s_write = mod->s_write; + mod->s_write = sp_hook_s_write; + + SESSION_G(mod) = mod; +} + +static PHP_INI_MH(sp_OnUpdateSaveHandler) { + if (stage == PHP_INI_STAGE_RUNTIME && + SESSION_G(session_status) == php_session_none && + s_original_mod && + zend_string_equals_literal(new_value, "user") == 0 && + strcmp(((ps_module *)s_original_mod)->s_name, "user") == + 0) { + return SUCCESS; + } + + SESSION_G(mod) = s_original_mod; + + int r = old_OnUpdateSaveHandler(entry, new_value, mh_arg1, mh_arg2, mh_arg3, + stage); + + sp_hook_session_module(); + + return r; +} + +static int sp_hook_session_RINIT(INIT_FUNC_ARGS) { + if (SESSION_G(mod) == NULL) { + zend_ini_entry *ini_entry; + if ((ini_entry = zend_hash_str_find_ptr( + EG(ini_directives), ZEND_STRL("session.save_handler")))) { + if (ini_entry->value) { + sp_OnUpdateSaveHandler(NULL, ini_entry->value, NULL, NULL, NULL, 0); + } + } + } + return previous_sessionRINIT(INIT_FUNC_ARGS_PASSTHRU); +} + +void hook_session() { + zend_module_entry *module; + + if ((module = zend_hash_str_find_ptr(&module_registry, + ZEND_STRL("session"))) == NULL) { + return; + } + +#ifdef ZTS + if (session_globals_id == 0) { + session_globals_id = *module->globals_id_ptr; + } +#else + if (session_globals == NULL) { + session_globals = module->globals_ptr; + } +#endif + if (old_OnUpdateSaveHandler != NULL) { + return; + } + + previous_sessionRINIT = module->request_startup_func; + module->request_startup_func = sp_hook_session_RINIT; + + zend_ini_entry *ini_entry; + if ((ini_entry = zend_hash_str_find_ptr( + EG(ini_directives), ZEND_STRL("session.save_handler"))) != NULL) { + old_OnUpdateSaveHandler = ini_entry->on_modify; + ini_entry->on_modify = sp_OnUpdateSaveHandler; + } + s_module = NULL; + + sp_hook_session_module(); +} \ No newline at end of file -- cgit v1.3