diff options
| author | xXx-caillou-xXx | 2017-12-20 18:09:53 +0100 |
|---|---|---|
| committer | jvoisin | 2017-12-20 18:09:53 +0100 |
| commit | e7f541396715ee2895abcf73044b91ae9b746201 (patch) | |
| tree | ba0e9765e7f14f04b92585df1f3fcd1830ab4b00 /src/sp_disabled_functions.c | |
| parent | 8d6cc4f2b63c3f0dc31fe6cecd34ac023ea1cccb (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.c | 138 |
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: | |||
| 64 | static bool is_local_var_matching( | 64 | static 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) { |
