diff options
| author | jvoisin | 2017-11-29 15:33:53 +0100 |
|---|---|---|
| committer | blotus | 2017-11-29 15:33:53 +0100 |
| commit | 24d414503e9831ae9a7a7871e93fdd8430911466 (patch) | |
| tree | a5842ecf07b63910892a8bfe48828f5065e3393d /src | |
| parent | 5aabc746bd4588a437e37a442e557c3bc7fe6f35 (diff) | |
Refactoring (#79)
Refactoring of should_disable().
Diffstat (limited to 'src')
| -rw-r--r-- | src/sp_disabled_functions.c | 301 |
1 files changed, 156 insertions, 145 deletions
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index ca1f6a9..4e52431 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c | |||
| @@ -5,9 +5,8 @@ | |||
| 5 | 5 | ||
| 6 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) | 6 | ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) |
| 7 | 7 | ||
| 8 | static zend_always_inline char* get_complete_function_path( | 8 | static char* get_complete_function_path( |
| 9 | zend_execute_data const* const execute_data) { | 9 | zend_execute_data const* const execute_data) { |
| 10 | |||
| 11 | if (!(execute_data->func->common.function_name)) { | 10 | if (!(execute_data->func->common.function_name)) { |
| 12 | return NULL; | 11 | return NULL; |
| 13 | } | 12 | } |
| @@ -28,20 +27,21 @@ static zend_always_inline char* get_complete_function_path( | |||
| 28 | return complete_path_function; | 27 | return complete_path_function; |
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | static bool is_functions_list_matching(zend_execute_data *execute_data, sp_node_t *functions_list) { | 30 | static bool is_functions_list_matching(zend_execute_data* execute_data, |
| 31 | sp_node_t* functions_list) { | ||
| 32 | zend_execute_data *orig_execute_data, *current; | 32 | zend_execute_data *orig_execute_data, *current; |
| 33 | orig_execute_data = current = execute_data; | 33 | orig_execute_data = current = execute_data; |
| 34 | sp_node_t *it = functions_list; | 34 | sp_node_t* it = functions_list; |
| 35 | 35 | ||
| 36 | while (current) { | 36 | while (current) { |
| 37 | if (it == NULL) { // every function in the list matched, we've got a match! | 37 | if (it == NULL) { // every function in the list matched, we've got a match! |
| 38 | EG(current_execute_data) = orig_execute_data; | 38 | EG(current_execute_data) = orig_execute_data; |
| 39 | return true; | 39 | return true; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | EG(current_execute_data) = current; | 42 | EG(current_execute_data) = current; |
| 43 | 43 | ||
| 44 | char *complete_path_function = get_complete_function_path(current); | 44 | char* complete_path_function = get_complete_function_path(current); |
| 45 | if (!complete_path_function) { | 45 | if (!complete_path_function) { |
| 46 | goto end; | 46 | goto end; |
| 47 | } | 47 | } |
| @@ -61,36 +61,39 @@ end: | |||
| 61 | return false; | 61 | return false; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static bool is_local_var_matching(zend_execute_data *execute_data, const sp_disabled_function *const config_node) { | 64 | static bool is_local_var_matching( |
| 65 | zend_execute_data *orig_execute_data = execute_data; | 65 | zend_execute_data* execute_data, |
| 66 | const sp_disabled_function* const config_node) { | ||
| 67 | zend_execute_data* orig_execute_data = execute_data; | ||
| 66 | 68 | ||
| 67 | /*because execute_data points to hooked function data, | 69 | /*because execute_data points to hooked function data, |
| 68 | which we dont care about */ | 70 | which we dont care about */ |
| 69 | zend_execute_data *current = execute_data->prev_execute_data; | 71 | zend_execute_data* current = execute_data->prev_execute_data; |
| 70 | zval *value = NULL; | 72 | zval* value = NULL; |
| 71 | 73 | ||
| 72 | while (current) { | 74 | while (current) { |
| 73 | zend_string *key = NULL; | 75 | zend_string* key = NULL; |
| 74 | EG(current_execute_data) = current; | 76 | EG(current_execute_data) = current; |
| 75 | zend_array *symtable = zend_rebuild_symbol_table(); | 77 | zend_array* symtable = zend_rebuild_symbol_table(); |
| 76 | ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) { | 78 | ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) { |
| 77 | if (0 == strcmp(config_node->var, key->val)) { // is the var name right? | 79 | if (0 == strcmp(config_node->var, key->val)) { // is the var name right? |
| 78 | if (Z_TYPE_P(value) == IS_INDIRECT) { | 80 | if (Z_TYPE_P(value) == IS_INDIRECT) { |
| 79 | value = Z_INDIRECT_P(value); | 81 | value = Z_INDIRECT_P(value); |
| 80 | } | 82 | } |
| 81 | if (Z_TYPE_P(value) != IS_ARRAY) { | 83 | if (Z_TYPE_P(value) != IS_ARRAY) { |
| 82 | char *var_value_str = sp_convert_to_string(value); | 84 | char* var_value_str = sp_convert_to_string(value); |
| 83 | if (true == sp_match_value(var_value_str, config_node->value, config_node->value_r)) { | 85 | if (true == sp_match_value(var_value_str, config_node->value, |
| 84 | efree(var_value_str); | 86 | config_node->value_r)) { |
| 85 | EG(current_execute_data) = orig_execute_data; | 87 | efree(var_value_str); |
| 86 | return true; | 88 | EG(current_execute_data) = orig_execute_data; |
| 87 | } | 89 | return true; |
| 88 | efree(var_value_str); | 90 | } |
| 89 | } | 91 | efree(var_value_str); |
| 90 | else { | 92 | } else { |
| 91 | EG(current_execute_data) = orig_execute_data; | 93 | EG(current_execute_data) = orig_execute_data; |
| 92 | return sp_match_array_key_recurse(value, config_node->var_array_keys, config_node->value, NULL); | 94 | return sp_match_array_key_recurse(value, config_node->var_array_keys, |
| 93 | } | 95 | config_node->value, NULL); |
| 96 | } | ||
| 94 | } | 97 | } |
| 95 | } | 98 | } |
| 96 | ZEND_HASH_FOREACH_END(); | 99 | ZEND_HASH_FOREACH_END(); |
| @@ -101,51 +104,135 @@ static bool is_local_var_matching(zend_execute_data *execute_data, const sp_disa | |||
| 101 | return false; | 104 | return false; |
| 102 | } | 105 | } |
| 103 | 106 | ||
| 104 | static sp_node_t *get_config(const char *builtin_name) { | 107 | static const sp_node_t* get_config_node(const char* builtin_name) { |
| 105 | if (!builtin_name) { | 108 | if (!builtin_name) { |
| 106 | return SNUFFLEUPAGUS_G(config).config_disabled_functions->disabled_functions; | 109 | return SNUFFLEUPAGUS_G(config) |
| 107 | } | 110 | .config_disabled_functions->disabled_functions; |
| 108 | if (!strcmp(builtin_name, "eval")) { | 111 | } else if (!strcmp(builtin_name, "eval")) { |
| 109 | return SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_eval; | 112 | return SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_eval; |
| 113 | } else if (!strcmp(builtin_name, "include") || | ||
| 114 | !strcmp(builtin_name, "include_once") || | ||
| 115 | !strcmp(builtin_name, "require") || | ||
| 116 | !strcmp(builtin_name, "require_once")) { | ||
| 117 | return SNUFFLEUPAGUS_G(config) | ||
| 118 | .config_disabled_constructs->construct_include; | ||
| 110 | } | 119 | } |
| 111 | if (!strcmp(builtin_name, "include") || | 120 | return NULL; // This should never happen. |
| 112 | !strcmp(builtin_name, "include_once") || | 121 | } |
| 113 | !strcmp(builtin_name, "require") || | 122 | |
| 114 | !strcmp(builtin_name, "require_once")) { | 123 | static bool is_param_matching(zend_execute_data* execute_data, |
| 115 | return SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include; | 124 | sp_disabled_function const* const config_node, |
| 125 | const char* builtin_name, | ||
| 126 | const char* builtin_param, const char** arg_name, | ||
| 127 | const char* builtin_param_name, | ||
| 128 | const char** arg_value_str) { | ||
| 129 | int nb_param = execute_data->func->common.num_args; | ||
| 130 | int i = 0; | ||
| 131 | |||
| 132 | if (config_node->pos != -1) { | ||
| 133 | if (config_node->pos <= nb_param) { | ||
| 134 | char* complete_function_path = get_complete_function_path(execute_data); | ||
| 135 | sp_log_err("config", | ||
| 136 | "It seems that you wrote a rule filtering on the " | ||
| 137 | "%d%s argument of the function '%s', but it takes only %d " | ||
| 138 | "arguments. " | ||
| 139 | "Matching on _all_ arguments instead.", | ||
| 140 | config_node->pos, GET_SUFFIX(config_node->pos), | ||
| 141 | complete_function_path, nb_param); | ||
| 142 | efree(complete_function_path); | ||
| 143 | } else { | ||
| 144 | i = config_node->pos; | ||
| 145 | nb_param = (config_node->pos) + 1; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | if (builtin_name) { | ||
| 150 | // we are matching on a builtin param, but for PHP, it's not the same a | ||
| 151 | // function param | ||
| 152 | *arg_name = builtin_param_name; | ||
| 153 | *arg_value_str = builtin_param; | ||
| 154 | return sp_match_value(builtin_param, config_node->value, | ||
| 155 | config_node->value_r); | ||
| 156 | } else { | ||
| 157 | for (; i < nb_param; i++) { | ||
| 158 | if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency | ||
| 159 | *arg_name = ZSTR_VAL(execute_data->func->common.arg_info[i].name); | ||
| 160 | } else { | ||
| 161 | *arg_name = execute_data->func->internal_function.arg_info[i].name; | ||
| 162 | } | ||
| 163 | |||
| 164 | const bool arg_matching = | ||
| 165 | config_node->param && (0 == strcmp(*arg_name, config_node->param)); | ||
| 166 | const bool pcre_matching = | ||
| 167 | config_node->r_param && | ||
| 168 | (true == is_regexp_matching(config_node->r_param, *arg_name)); | ||
| 169 | |||
| 170 | /* This is the parameter name we're looking for. */ | ||
| 171 | if (true == arg_matching || true == pcre_matching || | ||
| 172 | (config_node->pos != -1)) { | ||
| 173 | zval* arg_value = ZEND_CALL_VAR_NUM(execute_data, i); | ||
| 174 | |||
| 175 | if (config_node->param_type) { // Are we matching on the `type`? | ||
| 176 | if (config_node->param_type == Z_TYPE_P(arg_value)) { | ||
| 177 | return true; | ||
| 178 | } | ||
| 179 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { | ||
| 180 | *arg_value_str = estrdup("Array"); | ||
| 181 | // match on arr -> match on all key content, if a key is an array, | ||
| 182 | // ignore it | ||
| 183 | // match on arr[foo] -> match only on key foo, if the key is an | ||
| 184 | // array, match on all keys content | ||
| 185 | if (config_node->param_is_array == true) { | ||
| 186 | if (true == sp_match_array_key_recurse( | ||
| 187 | arg_value, config_node->param_array_keys, | ||
| 188 | config_node->value, config_node->value_r)) { | ||
| 189 | return true; | ||
| 190 | } | ||
| 191 | } else { // match on all keys, but don't go into subarray | ||
| 192 | if (true == sp_match_array_key(arg_value, config_node->value, | ||
| 193 | config_node->value_r)) { | ||
| 194 | return true; | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } else { | ||
| 198 | *arg_value_str = sp_convert_to_string(arg_value); | ||
| 199 | if (true == sp_match_value(*arg_value_str, config_node->value, | ||
| 200 | config_node->value_r)) { | ||
| 201 | return true; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | } | ||
| 205 | } | ||
| 116 | } | 206 | } |
| 117 | return NULL; | 207 | return false; |
| 118 | } | 208 | } |
| 119 | 209 | ||
| 120 | bool should_disable(zend_execute_data* execute_data, const char *builtin_name, const char *builtin_param, | 210 | bool should_disable(zend_execute_data* execute_data, const char* builtin_name, |
| 121 | const char *builtin_param_name) { | 211 | const char* builtin_param, const char* builtin_param_name) { |
| 122 | char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; | 212 | char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; |
| 123 | const sp_node_t* config = get_config(builtin_name); | 213 | const sp_node_t* config = get_config_node(builtin_name); |
| 124 | char* complete_path_function = get_complete_function_path(execute_data); | 214 | char* complete_path_function = get_complete_function_path(execute_data); |
| 125 | char const* client_ip = sp_getenv("REMOTE_ADDR"); | 215 | char const* client_ip = sp_getenv("REMOTE_ADDR"); |
| 126 | const char* current_filename; | 216 | const char* current_filename; |
| 127 | 217 | ||
| 218 | if (!config || !config->data) { | ||
| 219 | return false; | ||
| 220 | } | ||
| 221 | |||
| 128 | if (builtin_name && !strcmp(builtin_name, "eval")) { | 222 | if (builtin_name && !strcmp(builtin_name, "eval")) { |
| 129 | current_filename = get_eval_filename(zend_get_executed_filename()); | 223 | current_filename = get_eval_filename(zend_get_executed_filename()); |
| 130 | } | 224 | } else { |
| 131 | else { | ||
| 132 | current_filename = zend_get_executed_filename(); | 225 | current_filename = zend_get_executed_filename(); |
| 133 | } | 226 | } |
| 134 | 227 | ||
| 135 | if (!complete_path_function) { | 228 | if (!complete_path_function) { |
| 136 | if (builtin_name) { | 229 | if (builtin_name) { |
| 137 | complete_path_function = (char *)builtin_name; | 230 | complete_path_function = (char*)builtin_name; |
| 138 | } | 231 | } else { |
| 139 | else { | ||
| 140 | return false; | 232 | return false; |
| 141 | } | 233 | } |
| 142 | } | 234 | } |
| 143 | 235 | ||
| 144 | if (!config || !config->data) { | ||
| 145 | return false; | ||
| 146 | } | ||
| 147 | |||
| 148 | |||
| 149 | while (config) { | 236 | while (config) { |
| 150 | sp_disabled_function const* const config_node = | 237 | sp_disabled_function const* const config_node = |
| 151 | (sp_disabled_function*)(config->data); | 238 | (sp_disabled_function*)(config->data); |
| @@ -155,13 +242,14 @@ bool should_disable(zend_execute_data* execute_data, const char *builtin_name, c | |||
| 155 | /* The order matters, since when we have `config_node->functions_list`, | 242 | /* The order matters, since when we have `config_node->functions_list`, |
| 156 | we also do have `config_node->function` */ | 243 | we also do have `config_node->function` */ |
| 157 | if (config_node->functions_list) { | 244 | if (config_node->functions_list) { |
| 158 | if (false == | 245 | if (false == is_functions_list_matching(execute_data, |
| 159 | is_functions_list_matching(execute_data, config_node->functions_list)) { | 246 | config_node->functions_list)) { |
| 160 | goto next; | 247 | goto next; |
| 161 | } | 248 | } |
| 162 | } else if (config_node->function) { /* Litteral match against the function name. */ | 249 | } else if (config_node |
| 250 | ->function) { /* Litteral match against the function name. */ | ||
| 163 | if (0 != strcmp(config_node->function, complete_path_function)) { | 251 | if (0 != strcmp(config_node->function, complete_path_function)) { |
| 164 | goto next; | 252 | goto next; |
| 165 | } | 253 | } |
| 166 | } else if (config_node->r_function) { | 254 | } else if (config_node->r_function) { |
| 167 | if (false == | 255 | if (false == |
| @@ -177,7 +265,6 @@ bool should_disable(zend_execute_data* execute_data, const char *builtin_name, c | |||
| 177 | } | 265 | } |
| 178 | 266 | ||
| 179 | if (config_node->filename) { /* Check the current file name. */ | 267 | if (config_node->filename) { /* Check the current file name. */ |
| 180 | |||
| 181 | if (0 != strcmp(current_filename, config_node->filename)) { | 268 | if (0 != strcmp(current_filename, config_node->filename)) { |
| 182 | goto next; | 269 | goto next; |
| 183 | } | 270 | } |
| @@ -199,7 +286,7 @@ bool should_disable(zend_execute_data* execute_data, const char *builtin_name, c | |||
| 199 | 286 | ||
| 200 | if (config_node->line) { | 287 | if (config_node->line) { |
| 201 | if (config_node->line != zend_get_executed_lineno()) { | 288 | if (config_node->line != zend_get_executed_lineno()) { |
| 202 | goto next; | 289 | goto next; |
| 203 | } | 290 | } |
| 204 | } | 291 | } |
| 205 | 292 | ||
| @@ -209,87 +296,11 @@ bool should_disable(zend_execute_data* execute_data, const char *builtin_name, c | |||
| 209 | } | 296 | } |
| 210 | 297 | ||
| 211 | /* Check if we filter on parameter value*/ | 298 | /* Check if we filter on parameter value*/ |
| 212 | if (config_node->param || config_node->r_param || (config_node->pos != -1)) { | 299 | if (config_node->param || config_node->r_param || |
| 213 | int nb_param = execute_data->func->common.num_args; | 300 | (config_node->pos != -1)) { |
| 214 | bool arg_matched = false; | 301 | if (false == is_param_matching(execute_data, config_node, builtin_name, |
| 215 | int i = 0; | 302 | builtin_param, &arg_name, |
| 216 | 303 | builtin_param_name, &arg_value_str)) { | |
| 217 | if (config_node->pos != -1) { | ||
| 218 | if (config_node->pos <= nb_param) { | ||
| 219 | sp_log_err("config", "It seems that you wrote a rule filtering on the " | ||
| 220 | "%d%s argument of the function '%s', but it takes only %d arguments. " | ||
| 221 | "Matching on _all_ arguments instead.", | ||
| 222 | config_node->pos, | ||
| 223 | GET_SUFFIX(config_node->pos), | ||
| 224 | complete_path_function, nb_param); | ||
| 225 | } else { | ||
| 226 | i = config_node->pos; | ||
| 227 | nb_param = (config_node->pos) + 1; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | if (builtin_name) { | ||
| 232 | // we are matching on a builtin param, but for PHP, it's not the same a function param | ||
| 233 | arg_matched = sp_match_value(builtin_param, config_node->value, config_node->value_r); | ||
| 234 | arg_name = builtin_param_name; | ||
| 235 | arg_value_str = builtin_param; | ||
| 236 | } | ||
| 237 | else { | ||
| 238 | for (; i < nb_param; i++) { | ||
| 239 | arg_matched = false; | ||
| 240 | if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency | ||
| 241 | arg_name = ZSTR_VAL(execute_data->func->common.arg_info[i].name); | ||
| 242 | } else { | ||
| 243 | arg_name = execute_data->func->internal_function.arg_info[i].name; | ||
| 244 | } | ||
| 245 | |||
| 246 | const bool arg_matching = | ||
| 247 | config_node->param && (0 == strcmp(arg_name, config_node->param)); | ||
| 248 | const bool pcre_matching = | ||
| 249 | config_node->r_param && | ||
| 250 | (true == is_regexp_matching(config_node->r_param, arg_name)); | ||
| 251 | |||
| 252 | /* This is the parameter name we're looking for. */ | ||
| 253 | if (true == arg_matching || true == pcre_matching || (config_node->pos != -1)) { | ||
| 254 | zval* arg_value = ZEND_CALL_VAR_NUM(execute_data, i); | ||
| 255 | |||
| 256 | if (config_node->param_type) { // Are we matching on the `type`? | ||
| 257 | if (config_node->param_type == Z_TYPE_P(arg_value)) { | ||
| 258 | arg_matched = true; | ||
| 259 | break; | ||
| 260 | } | ||
| 261 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { | ||
| 262 | arg_value_str = estrdup("Array"); | ||
| 263 | // match on arr -> match on all key content, if a key is an array, | ||
| 264 | // ignore it | ||
| 265 | // match on arr[foo] -> match only on key foo, if the key is an | ||
| 266 | // array, match on all keys content | ||
| 267 | if (config_node->param_is_array == true) { | ||
| 268 | if (true == sp_match_array_key_recurse( | ||
| 269 | arg_value, config_node->param_array_keys, | ||
| 270 | config_node->value, config_node->value_r)) { | ||
| 271 | arg_matched = true; | ||
| 272 | break; | ||
| 273 | } | ||
| 274 | } else { // match on all keys, but don't go into subarray | ||
| 275 | if (true == sp_match_array_key(arg_value, config_node->value, | ||
| 276 | config_node->value_r)) { | ||
| 277 | arg_matched = true; | ||
| 278 | break; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | } else { | ||
| 282 | arg_value_str = sp_convert_to_string(arg_value); | ||
| 283 | if (true == sp_match_value(arg_value_str, config_node->value, | ||
| 284 | config_node->value_r)) { | ||
| 285 | arg_matched = true; | ||
| 286 | break; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | } | ||
| 290 | } | ||
| 291 | } | ||
| 292 | if (false == arg_matched) { | ||
| 293 | goto next; | 304 | goto next; |
| 294 | } | 305 | } |
| 295 | } | 306 | } |
| @@ -302,21 +313,21 @@ bool should_disable(zend_execute_data* execute_data, const char *builtin_name, c | |||
| 302 | 313 | ||
| 303 | if (config_node->functions_list) { | 314 | if (config_node->functions_list) { |
| 304 | sp_log_disable(config_node->function, arg_name, arg_value_str, | 315 | sp_log_disable(config_node->function, arg_name, arg_value_str, |
| 305 | config_node); | 316 | config_node); |
| 306 | } else { | 317 | } else { |
| 307 | sp_log_disable(complete_path_function, arg_name, arg_value_str, | 318 | sp_log_disable(complete_path_function, arg_name, arg_value_str, |
| 308 | config_node); | 319 | config_node); |
| 309 | } | 320 | } |
| 310 | if (true == config_node->simulation) { | 321 | if (true == config_node->simulation) { |
| 311 | goto next; | 322 | goto next; |
| 312 | } else { // We've got a match, the function won't be executed | 323 | } else { // We've got a match, the function won't be executed |
| 313 | if (builtin_name == NULL) { | 324 | if (builtin_name == NULL) { |
| 314 | efree(complete_path_function); | 325 | efree(complete_path_function); |
| 315 | } | 326 | } |
| 316 | return true; | 327 | return true; |
| 317 | } | 328 | } |
| 318 | next: | 329 | next: |
| 319 | config = config->next; | 330 | config = config->next; |
| 320 | } | 331 | } |
| 321 | allow: | 332 | allow: |
| 322 | if (builtin_name == NULL) { | 333 | if (builtin_name == NULL) { |
| @@ -381,10 +392,10 @@ static bool should_drop_on_ret(zval* return_value, | |||
| 381 | ret_value_str = sp_convert_to_string(return_value); | 392 | ret_value_str = sp_convert_to_string(return_value); |
| 382 | 393 | ||
| 383 | match_type = (config_node->ret_type) && | 394 | match_type = (config_node->ret_type) && |
| 384 | (config_node->ret_type == Z_TYPE_P(return_value)); | 395 | (config_node->ret_type == Z_TYPE_P(return_value)); |
| 385 | match_value = (config_node->ret || config_node->r_ret) && | 396 | match_value = (config_node->ret || config_node->r_ret) && |
| 386 | (true == sp_match_value(ret_value_str, config_node->ret, | 397 | (true == sp_match_value(ret_value_str, config_node->ret, |
| 387 | config_node->r_ret)); | 398 | config_node->r_ret)); |
| 388 | 399 | ||
| 389 | if (true == match_type || true == match_value) { | 400 | if (true == match_type || true == match_value) { |
| 390 | if (true == config_node->allow) { | 401 | if (true == config_node->allow) { |
