summaryrefslogtreecommitdiff
path: root/src/sp_disabled_functions.c
diff options
context:
space:
mode:
authorxXx-caillou-xXx2017-12-20 18:09:53 +0100
committerjvoisin2017-12-20 18:09:53 +0100
commite7f541396715ee2895abcf73044b91ae9b746201 (patch)
treeba0e9765e7f14f04b92585df1f3fcd1830ab4b00 /src/sp_disabled_functions.c
parent8d6cc4f2b63c3f0dc31fe6cecd34ac023ea1cccb (diff)
Better parsing of the rules
Thanks to this huge commit from @xXx-caillou-xXx, we can now write amazingly flexible rules.
Diffstat (limited to 'src/sp_disabled_functions.c')
-rw-r--r--src/sp_disabled_functions.c138
1 files changed, 70 insertions, 68 deletions
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c
index 6c180aa..c7974ff 100644
--- a/src/sp_disabled_functions.c
+++ b/src/sp_disabled_functions.c
@@ -64,43 +64,30 @@ end:
64static bool is_local_var_matching( 64static bool is_local_var_matching(
65 zend_execute_data* execute_data, 65 zend_execute_data* execute_data,
66 const sp_disabled_function* const config_node) { 66 const sp_disabled_function* const config_node) {
67 zend_execute_data* orig_execute_data = execute_data; 67 zval *var_value;
68 68
69 /*because execute_data points to hooked function data, 69 var_value = get_value(execute_data, config_node->var, false);
70 which we dont care about */ 70 if (var_value) {
71 zend_execute_data* current = execute_data->prev_execute_data; 71 char *var_value_str = sp_convert_to_string(var_value);
72 zval* value = NULL; 72 if (Z_TYPE_P(var_value) == IS_ARRAY) {
73 73 if (config_node->key || config_node->r_key) {
74 while (current) { 74 if (sp_match_array_key(var_value, config_node->key,
75 zend_string* key = NULL; 75 config_node->r_key)) {
76 EG(current_execute_data) = current; 76 efree(var_value_str);
77 zend_array* symtable = zend_rebuild_symbol_table(); 77 return true;
78 ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) { 78 }
79 if (0 == strcmp(config_node->var, key->val)) { // is the var name right? 79 } else if (sp_match_array_value(var_value, config_node->value,
80 if (Z_TYPE_P(value) == IS_INDIRECT) { 80 config_node->value_r)) {
81 value = Z_INDIRECT_P(value); 81 efree(var_value_str);
82 } 82 return true;
83 if (Z_TYPE_P(value) != IS_ARRAY) {
84 char* var_value_str = sp_convert_to_string(value);
85 if (true == sp_match_value(var_value_str, config_node->value,
86 config_node->value_r)) {
87 efree(var_value_str);
88 EG(current_execute_data) = orig_execute_data;
89 return true;
90 }
91 efree(var_value_str);
92 } else {
93 EG(current_execute_data) = orig_execute_data;
94 return sp_match_array_key_recurse(value, config_node->var_array_keys,
95 config_node->value, NULL);
96 }
97 } 83 }
84 } else if (sp_match_value(var_value_str, config_node->value,
85 config_node->value_r)) {
86 efree(var_value_str);
87 return true;
98 } 88 }
99 ZEND_HASH_FOREACH_END(); 89 efree(var_value_str);
100 current = current->prev_execute_data;
101 } 90 }
102
103 EG(current_execute_data) = orig_execute_data;
104 return false; 91 return false;
105} 92}
106 93
@@ -128,6 +115,7 @@ static bool is_param_matching(zend_execute_data* execute_data,
128 const char** arg_value_str) { 115 const char** arg_value_str) {
129 int nb_param = execute_data->func->common.num_args; 116 int nb_param = execute_data->func->common.num_args;
130 int i = 0; 117 int i = 0;
118 zval *arg_value;
131 119
132 if (config_node->pos != -1) { 120 if (config_node->pos != -1) {
133 if (config_node->pos <= nb_param) { 121 if (config_node->pos <= nb_param) {
@@ -154,7 +142,7 @@ static bool is_param_matching(zend_execute_data* execute_data,
154 *arg_value_str = builtin_param; 142 *arg_value_str = builtin_param;
155 return sp_match_value(builtin_param, config_node->value, 143 return sp_match_value(builtin_param, config_node->value,
156 config_node->value_r); 144 config_node->value_r);
157 } else { 145 } else if (config_node->r_param || config_node->pos != -1) {
158 // We're matching on a function (and not a language construct) 146 // We're matching on a function (and not a language construct)
159 for (; i < nb_param; i++) { 147 for (; i < nb_param; i++) {
160 if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency 148 if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency
@@ -162,49 +150,63 @@ static bool is_param_matching(zend_execute_data* execute_data,
162 } else { 150 } else {
163 *arg_name = execute_data->func->internal_function.arg_info[i].name; 151 *arg_name = execute_data->func->internal_function.arg_info[i].name;
164 } 152 }
165 153 const bool pcre_matching = config_node->r_param
166 const bool arg_matching = 154 && (true == is_regexp_matching(config_node->r_param, *arg_name));
167 config_node->param && (0 == strcmp(*arg_name, config_node->param));
168 const bool pcre_matching =
169 config_node->r_param &&
170 (true == is_regexp_matching(config_node->r_param, *arg_name));
171 155
172 /* This is the parameter name we're looking for. */ 156 /* This is the parameter name we're looking for. */
173 if (true == arg_matching || true == pcre_matching || 157 if (true == pcre_matching || config_node->pos != -1) {
174 (config_node->pos != -1)) { 158 arg_value = ZEND_CALL_VAR_NUM(execute_data, i);
175 zval* arg_value = ZEND_CALL_VAR_NUM(execute_data, i);
176 159
177 if (config_node->param_type) { // Are we matching on the `type`? 160 if (config_node->param_type) { // Are we matching on the `type`?
178 if (config_node->param_type == Z_TYPE_P(arg_value)) { 161 if (config_node->param_type == Z_TYPE_P(arg_value)) {
179 return true; 162 return true;
180 } 163 }
181 } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { 164 } else if (Z_TYPE_P(arg_value) == IS_ARRAY) {
182 *arg_value_str = estrdup("Array"); 165 *arg_value_str = sp_convert_to_string(arg_value);
183 // match on arr -> match on all key content, if a key is an array, 166 if (config_node->key || config_node->r_key) {
184 // ignore it 167 if (sp_match_array_key(arg_value, config_node->key,
185 // match on arr[foo] -> match only on key foo, if the key is an 168 config_node->r_key)) {
186 // array, match on all keys content 169 return true;
187 if (config_node->param_is_array == true) { 170 }
188 if (true == sp_match_array_key_recurse( 171 } else if (sp_match_array_value(arg_value, config_node->value,
189 arg_value, config_node->param_array_keys, 172 config_node->value_r)) {
190 config_node->value, config_node->value_r)) { 173 return true;
191 return true; 174 }
192 } 175 } else {
193 } else { // match on all keys, but don't go into subarray 176 *arg_value_str = sp_convert_to_string(arg_value);
194 if (true == sp_match_array_key(arg_value, config_node->value, 177 if (sp_match_value(*arg_value_str, config_node->value,
195 config_node->value_r)) { 178 config_node->value_r)) {
196 return true;
197 }
198 }
199 } else {
200 *arg_value_str = sp_convert_to_string(arg_value);
201 if (true == sp_match_value(*arg_value_str, config_node->value,
202 config_node->value_r)) {
203 return true; 179 return true;
204 } 180 }
205 } 181 }
206 } 182 }
207 } 183 }
184 } else if (config_node->param) {
185 *arg_name = config_node->param->value;
186 arg_value = get_value(execute_data, config_node->param, true);
187
188 if (arg_value) {
189 *arg_value_str = sp_convert_to_string(arg_value);
190 if (config_node->param_type) { // Are we matching on the `type`?
191 if (config_node->param_type
192 && config_node->param_type == Z_TYPE_P(arg_value)) {
193 return true;
194 }
195 } else if (Z_TYPE_P(arg_value) == IS_ARRAY) {
196 if (config_node->key || config_node->r_key) {
197 if (sp_match_array_key(arg_value, config_node->key,
198 config_node->r_key)) {
199 return true;
200 }
201 } else if (sp_match_array_value(arg_value, config_node->value,
202 config_node->value_r)) {
203 return true;
204 }
205 } else if (sp_match_value(*arg_value_str, config_node->value,
206 config_node->value_r)) {
207 return true;
208 }
209 }
208 } 210 }
209 return false; 211 return false;
210} 212}
@@ -214,7 +216,7 @@ bool should_disable(zend_execute_data* execute_data, const char* builtin_name,
214 char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; 216 char current_file_hash[SHA256_SIZE * 2 + 1] = {0};
215 const sp_node_t* config = get_config_node(builtin_name); 217 const sp_node_t* config = get_config_node(builtin_name);
216 char* complete_path_function = get_complete_function_path(execute_data); 218 char* complete_path_function = get_complete_function_path(execute_data);
217 char const* client_ip = sp_getenv("REMOTE_ADDR"); 219 char const* client_ip = getenv("REMOTE_ADDR");
218 const char* current_filename; 220 const char* current_filename;
219 221
220 if (!config || !config->data) { 222 if (!config || !config->data) {