summaryrefslogtreecommitdiff
path: root/src/sp_unserialize.c
diff options
context:
space:
mode:
authorSebastien Blot2017-09-20 10:11:01 +0200
committerSebastien Blot2017-09-20 10:11:01 +0200
commit868f96c759b6650d88ff9f4fbc5c048302134248 (patch)
treec0de0af318bf77a8959164ef11aeeeb2b7bab294 /src/sp_unserialize.c
Initial import
Diffstat (limited to 'src/sp_unserialize.c')
-rw-r--r--src/sp_unserialize.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c
new file mode 100644
index 0000000..b5b67b4
--- /dev/null
+++ b/src/sp_unserialize.c
@@ -0,0 +1,111 @@
1#include "php_snuffleupagus.h"
2
3ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)
4
5PHP_FUNCTION(sp_serialize) {
6 void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS);
7
8 /* Call the original `serialize` function. */
9 if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook),
10 "serialize", 9))) {
11 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
12 } else {
13 sp_log_err("disabled_functions",
14 "Unable to find the pointer to the original function 'serialize' in "
15 "the hashtable.\n");
16 }
17
18 /* Compute the HMAC of the textual representation of the serialized data*/
19 zval func_name;
20 zval hmac;
21 zval params[3];
22
23 ZVAL_STRING(&func_name, "hash_hmac");
24 ZVAL_STRING(&params[0], "sha256");
25 params[1] = *return_value;
26 ZVAL_STRING(&params[2],
27 SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key);
28 call_user_function(CG(function_table), NULL, &func_name, &hmac, 3, params);
29
30 size_t len = Z_STRLEN_P(return_value) + Z_STRLEN(hmac);
31 zend_string *res = zend_string_alloc(len, 0);
32
33 memcpy(ZSTR_VAL(res), Z_STRVAL_P(return_value), Z_STRLEN_P(return_value));
34 memcpy(ZSTR_VAL(res) + Z_STRLEN_P(return_value), Z_STRVAL(hmac),
35 Z_STRLEN(hmac));
36 ZSTR_VAL(res)[len] = '\0';
37
38 /* Append the computed HMAC to the serialized data. */
39 return_value->value.str = res;
40 return;
41}
42
43PHP_FUNCTION(sp_unserialize) {
44 void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS);
45
46 char *buf = NULL;
47 char *serialized_str = NULL;
48 char *hmac = NULL;
49 zval expected_hmac;
50 size_t buf_len = 0;
51 zval *opts = NULL;
52
53 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &opts) ==
54 FAILURE) {
55 RETURN_FALSE;
56 }
57
58 /* 64 is the length of HMAC-256 */
59 if (buf_len < 64) {
60 sp_log_msg("unserialize", LOG_DROP, "The serialized object is too small.");
61 RETURN_FALSE;
62 }
63
64 hmac = buf + buf_len - 64;
65 serialized_str = ecalloc(sizeof(*serialized_str) * (buf_len - 64 + 1), 1);
66 memcpy(serialized_str, buf, buf_len - 64);
67
68 zval func_name;
69 ZVAL_STRING(&func_name, "hash_hmac");
70
71 zval params[3];
72 ZVAL_STRING(&params[0], "sha256");
73 ZVAL_STRING(&params[1], serialized_str);
74 ZVAL_STRING(&params[2],
75 SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key);
76 call_user_function(CG(function_table), NULL, &func_name, &expected_hmac, 3,
77 params);
78
79 unsigned int status = 0;
80 for (uint8_t i = 0; i < 64; i++) {
81 status |= (hmac[i] ^ (Z_STRVAL(expected_hmac))[i]);
82 }
83
84 if (0 == status) {
85 if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook),
86 "unserialize", 11))) {
87 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
88 }
89 } else {
90 if ( true == SNUFFLEUPAGUS_G(config).config_unserialize->simulation) {
91 sp_log_msg("unserialize", LOG_NOTICE, "Invalid HMAC for %s", serialized_str);
92 if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook),
93 "unserialize", 11))) {
94 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
95 }
96 } else {
97 sp_log_msg("unserialize", LOG_DROP, "Invalid HMAC for %s", serialized_str);
98 }
99 }
100 efree(serialized_str);
101 return;
102}
103
104int hook_serialize(void) {
105 TSRMLS_FETCH();
106
107 HOOK_FUNCTION("serialize", sp_internal_functions_hook, PHP_FN(sp_serialize), false);
108 HOOK_FUNCTION("unserialize", sp_internal_functions_hook, PHP_FN(sp_unserialize), false);
109
110 return SUCCESS;
111}