/* ** handle flags that can be set/modified at runtime */ static char * ngx_http_naxsi_flags_loc_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_loc_conf_t *alcf = conf, **bar; ngx_http_dummy_main_conf_t *main_cf; ngx_str_t *value; if (!alcf || !cf) return (NGX_CONF_ERROR); value = cf->args->elts; main_cf = ngx_http_conf_get_module_main_conf(cf, ngx_http_naxsi_module); if (!alcf->pushed) { bar = ngx_array_push(main_cf->locations); if (!bar) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ *bar = alcf; alcf->pushed = 1; } /* it's a flagrule, just a hack to enable/disable mod */ if (!ngx_strcmp(value[0].data, TOP_ENABLED_FLAG_T) || !ngx_strcmp(value[0].data, TOP_ENABLED_FLAG_N)) { alcf->enabled = 1; return (NGX_CONF_OK); } else /* it's a flagrule, just a hack to enable/disable mod */ if (!ngx_strcmp(value[0].data, TOP_DISABLED_FLAG_T) || !ngx_strcmp(value[0].data, TOP_DISABLED_FLAG_N)) { alcf->force_disabled = 1; return (NGX_CONF_OK); } else /* it's a flagrule, currently just a hack to enable/disable learning mode */ if (!ngx_strcmp(value[0].data, TOP_LEARNING_FLAG_T) || !ngx_strcmp(value[0].data, TOP_LEARNING_FLAG_N)) { alcf->learning = 1; return (NGX_CONF_OK); } else if (!ngx_strcmp(value[0].data, TOP_LIBINJECTION_SQL_T) || !ngx_strcmp(value[0].data, TOP_LIBINJECTION_SQL_N)) { NX_LOG_DEBUG(_debug_loc_conf, NGX_LOG_EMERG, cf, 0, "LibInjectionSql enabled"); alcf->libinjection_sql_enabled = 1; return (NGX_CONF_OK); } else if (!ngx_strcmp(value[0].data, TOP_LIBINJECTION_XSS_T) || !ngx_strcmp(value[0].data, TOP_LIBINJECTION_XSS_N)) { alcf->libinjection_xss_enabled = 1; NX_LOG_DEBUG(_debug_loc_conf, NGX_LOG_EMERG, cf, 0, "LibInjectionXss enabled"); return (NGX_CONF_OK); } else return (NGX_CONF_ERROR); }
/* merge the two rules into father_wl, meaning ids. Not locations, as we are getting rid of it */ static ngx_int_t ngx_http_wlr_merge(ngx_conf_t *cf, ngx_http_whitelist_rule_t *father_wl, ngx_http_rule_t *curr) { uint i; ngx_int_t *tmp_ptr; NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "[naxsi] merging similar wl(s)"); if (!father_wl->ids) { father_wl->ids = ngx_array_create(cf->pool, 3, sizeof(ngx_int_t)); if (!father_wl->ids) return (NGX_ERROR); } for (i = 0; i < curr->wlid_array->nelts; i++) { tmp_ptr = ngx_array_push(father_wl->ids); if (!tmp_ptr) return (NGX_ERROR); *tmp_ptr = ((ngx_int_t *)curr->wlid_array->elts)[i]; //*tmp_ptr = curr->wlid_array->elts[i]; } return (NGX_OK); }
static char * ngx_http_dummy_read_main_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_main_conf_t *alcf = conf; ngx_str_t *value; ngx_http_rule_t rule, *rule_r; ngx_http_custom_rule_location_t *location; unsigned int i; if (!alcf || !cf) return (NGX_CONF_ERROR); /* alloc a new rule */ value = cf->args->elts; /* parse the line, fill rule struct */ NX_LOG_DEBUG(_debug_main_conf, NGX_LOG_EMERG, cf, 0, "XX-TOP READ CONF %s", value[0].data); if (ngx_strcmp(value[0].data, TOP_MAIN_BASIC_RULE_T) && ngx_strcmp(value[0].data, TOP_MAIN_BASIC_RULE_N)) { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } memset(&rule, 0, sizeof(ngx_http_rule_t)); if (ngx_http_dummy_cfg_parse_one_rule(cf/*, alcf*/, value, &rule, cf->args->nelts) != NGX_CONF_OK) { /* LCOV_EXCL_START */ ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); /* LCOV_EXCL_STOP */ } if (rule.br->headers) { NX_LOG_DEBUG(_debug_main_conf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in header rules", rule.rule_id); if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in body match rules (POST/PUT) */ if (rule.br->body || rule.br->body_var) { NX_LOG_DEBUG(_debug_main_conf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in body rules", rule.rule_id); if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in raw body match rules (POST/PUT) xx*/ if (rule.br->raw_body) { NX_LOG_DEBUG(_debug_main_conf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in raw (main) body rules", rule.rule_id); if (alcf->raw_body_rules == NULL) { alcf->raw_body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->raw_body_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->raw_body_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in generic rules, as it's matching the URI */ if (rule.br->url) { NX_LOG_DEBUG(_debug_main_conf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in generic rules", rule.rule_id); if (alcf->generic_rules == NULL) { alcf->generic_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->generic_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->generic_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in GET arg rules, but we should push in POST rules too */ if (rule.br->args_var || rule.br->args) { NX_LOG_DEBUG(_debug_main_conf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in GET rules", rule.rule_id); if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in custom locations. It's a rule matching a VAR_NAME or an EXACT_URI : - GET_VAR, POST_VAR, URI */ if (rule.br->custom_location) { NX_LOG_DEBUG(_debug_main_conf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in custom_location rules", rule.rule_id); location = rule.br->custom_locations->elts; for (i = 0; i < rule.br->custom_locations->nelts; i++) { if (location[i].args_var) { if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].body_var) { if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].headers_var) { if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } } } return (NGX_CONF_OK); }
static char * ngx_http_naxsi_cr_loc_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_loc_conf_t *alcf = conf, **bar; ngx_http_dummy_main_conf_t *main_cf; ngx_str_t *value; ngx_http_check_rule_t *rule_c; unsigned int i; u_char *var_end; if (!alcf || !cf) return (NGX_CONF_ERROR); value = cf->args->elts; main_cf = ngx_http_conf_get_module_main_conf(cf, ngx_http_naxsi_module); if (!alcf->pushed) { bar = ngx_array_push(main_cf->locations); if (!bar) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ *bar = alcf; alcf->pushed = 1; } if (ngx_strcmp(value[0].data, TOP_CHECK_RULE_T) && ngx_strcmp(value[0].data, TOP_CHECK_RULE_N)) return (NGX_CONF_ERROR); /* #ifdef _debug_readconf */ /* ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, */ /* "pushing rule %d in check rules", rule.rule_id); */ /* #endif */ i = 0; if (!alcf->check_rules) alcf->check_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_check_rule_t)); if (!alcf->check_rules) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ rule_c = ngx_array_push(alcf->check_rules); if (!rule_c) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memset(rule_c, 0, sizeof(ngx_http_check_rule_t)); /* process the first word : score rule */ if (value[1].data[i] == '$') { var_end = (u_char *) ngx_strchr((value[1].data)+i, ' '); if (!var_end) { /* LCOV_EXCL_START */ ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); /* LCOV_EXCL_STOP */ } rule_c->sc_tag.len = var_end - value[1].data; rule_c->sc_tag.data = ngx_pcalloc(cf->pool, rule_c->sc_tag.len + 1); if (!rule_c->sc_tag.data) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_c->sc_tag.data, value[1].data, rule_c->sc_tag.len); i += rule_c->sc_tag.len + 1; } else { /* LCOV_EXCL_START */ ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); /* LCOV_EXCL_STOP */ } // move to next word while (value[1].data[i] && value[1].data[i] == ' ') i++; // get the comparison type if (value[1].data[i] == '>' && value[1].data[i+1] == '=') rule_c->cmp = SUP_OR_EQUAL; else if (value[1].data[i] == '>' && value[1].data[i+1] != '=') rule_c->cmp = SUP; else if (value[1].data[i] == '<' && value[1].data[i+1] == '=') rule_c->cmp = INF_OR_EQUAL; else if (value[1].data[i] == '<' && value[1].data[i+1] != '=') rule_c->cmp = INF; else { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } // move to next word while (value[1].data[i] && !(value[1].data[i] >= '0' && value[1].data[i] <= '9') && (value[1].data[i] != '-')) i++; NX_LOG_DEBUG(_debug_readconf, NGX_LOG_EMERG, cf, 0, "XX-special score in checkrule:%s from (%d)", value[1].data, atoi((const char *)value[1].data+i)); // get the score rule_c->sc_score = atoi((const char *)(value[1].data+i)); /* process the second word : Action rule */ if (ngx_strstr(value[2].data, "BLOCK")) rule_c->block = 1; else if (ngx_strstr(value[2].data,"ALLOW")) rule_c->allow = 1; else if (ngx_strstr(value[2].data, "LOG")) rule_c->log = 1; else if (ngx_strstr(value[2].data, "DROP")) rule_c->drop = 1; else { /* LCOV_EXCL_START */ ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); /* LCOV_EXCL_STOP */ } return (NGX_CONF_OK); }
/* ** my hugly configuration parsing function. ** should be rewritten, cause code is hugly and not bof proof at all ** does : top level parsing config function, ** see foo_cfg_parse.c for stuff */ static char * ngx_http_dummy_read_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_loc_conf_t *alcf = conf, **bar; ngx_http_dummy_main_conf_t *main_cf; ngx_str_t *value; ngx_http_rule_t rule, *rule_r; ngx_http_custom_rule_location_t *location; unsigned int i; #ifdef _debug_readconf if (cf) { value = cf->args->elts; NX_LOG_DEBUG(_debug_readconf, NGX_LOG_EMERG, cf, 0, "TOP READ CONF %V %V", &(value[0]), &(value[1])); } #endif if (!alcf || !cf) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ value = cf->args->elts; main_cf = ngx_http_conf_get_module_main_conf(cf, ngx_http_naxsi_module); if (!alcf->pushed) { bar = ngx_array_push(main_cf->locations); if (!bar) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ *bar = alcf; alcf->pushed = 1; } /* ** if it's a basic rule */ if (!ngx_strcmp(value[0].data, TOP_BASIC_RULE_T) || !ngx_strcmp(value[0].data, TOP_BASIC_RULE_N)) { memset(&rule, 0, sizeof(ngx_http_rule_t)); if (ngx_http_dummy_cfg_parse_one_rule(cf, value, &rule, cf->args->nelts) != NGX_CONF_OK) { /* LCOV_EXCL_START */ ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); /* LCOV_EXCL_STOP */ } /* push in whitelist rules, as it have a whitelist ID array */ if (rule.wlid_array && rule.wlid_array->nelts > 0) { if (alcf->whitelist_rules == NULL) { alcf->whitelist_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->whitelist_rules == NULL) { return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } } rule_r = ngx_array_push(alcf->whitelist_rules); if (!rule_r) { return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ } memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* else push in appropriate ruleset : it's a normal rule */ else { if (rule.br->headers) { if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in body match rules (POST/PUT) */ if (rule.br->body || rule.br->body_var) { if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in raw body match rules (POST/PUT) */ if (rule.br->raw_body) { NX_LOG_DEBUG(_debug_readconf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in (read conf) raw_body rules", rule.rule_id); if (alcf->raw_body_rules == NULL) { alcf->raw_body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->raw_body_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->raw_body_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in generic rules, as it's matching the URI */ if (rule.br->url) { NX_LOG_DEBUG(_debug_readconf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in generic rules", rule.rule_id); if (alcf->generic_rules == NULL) { alcf->generic_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->generic_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->generic_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in GET arg rules, but we should push in POST rules too */ if (rule.br->args_var || rule.br->args) { NX_LOG_DEBUG(_debug_readconf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in GET rules", rule.rule_id); if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in custom locations. It's a rule matching a VAR_NAME or an EXACT_URI : - GET_VAR, POST_VAR, URI */ if (rule.br->custom_location) { NX_LOG_DEBUG(_debug_readconf, NGX_LOG_EMERG, cf, 0, "pushing rule %d in custom_location rules", rule.rule_id); location = rule.br->custom_locations->elts; for (i = 0; i < rule.br->custom_locations->nelts; i++) { if (location[i].args_var) { if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].body_var) { if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].headers_var) { if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; /* LCOV_EXCL_LINE */ } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); /* LCOV_EXCL_LINE */ memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } } } } return (NGX_CONF_OK); } ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); }
ngx_int_t ngx_http_dummy_create_hashtables_n(ngx_http_dummy_loc_conf_t *dlc, ngx_conf_t *cf) { int zone, uri_idx, name_idx, ret; ngx_http_rule_t *curr_r/*, *father_r*/; ngx_http_whitelist_rule_t *father_wlr; ngx_http_rule_t **rptr; ngx_regex_compile_t *rgc; char *fullname; uint i; if (!dlc->whitelist_rules || dlc->whitelist_rules->nelts < 1) { NX_LOG_DEBUG(_debug_whitelist_heavy , NGX_LOG_EMERG, cf, 0, "No whitelist registred, but it's your call."); return (NGX_OK); } NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "Building whitelist hashtables, %d items in list", dlc->whitelist_rules->nelts); dlc->tmp_wlr = ngx_array_create(cf->pool, dlc->whitelist_rules->nelts, sizeof(ngx_http_whitelist_rule_t)); /* iterate through each stored whitelist rule. */ for (i = 0; i < dlc->whitelist_rules->nelts; i++) { uri_idx = name_idx = zone = -1; /*a whitelist is in fact just another basic_rule_t */ curr_r = &(((ngx_http_rule_t*)(dlc->whitelist_rules->elts))[i]); NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "Processing wl %d/%p", i, curr_r); /*no custom location at all means that the rule is disabled */ if (!curr_r->br->custom_locations) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "WL %d is a disable rule.", i); if (ngx_http_wlr_push_disabled(cf, dlc, curr_r) == NGX_ERROR) return (NGX_ERROR); continue; } ret = ngx_http_wlr_identify(cf, dlc, curr_r, &zone, &uri_idx, &name_idx); if (ret != NGX_OK) /* LCOV_EXCL_START */ { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Following whitelist doesn't target any zone or is incorrect :"); if (name_idx != -1) ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist target name : %V", &(custloc_array(curr_r->br->custom_locations->elts)[name_idx].target)); else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist has no target name."); if (uri_idx != -1) ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist target uri : %V", &(custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target)); else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelists has no target uri."); return (NGX_ERROR); } /* LCOV_EXCL_STOP */ curr_r->br->zone = zone; /* ** Handle regular-expression-matchzone rules : ** Store them in a separate linked list, parsed ** at runtime. */ if (curr_r->br->rx_mz == 1) { if (!dlc->rxmz_wlr) { dlc->rxmz_wlr = ngx_array_create(cf->pool, 1, sizeof(ngx_http_rule_t *)); if (!dlc->rxmz_wlr) return (NGX_ERROR); /* LCOV_EXCL_LINE */ } if (name_idx != -1 && !custloc_array(curr_r->br->custom_locations->elts)[name_idx].target_rx) { custloc_array(curr_r->br->custom_locations->elts)[name_idx].target_rx = ngx_pcalloc(cf->pool, sizeof(ngx_regex_compile_t)); rgc = custloc_array(curr_r->br->custom_locations->elts)[name_idx].target_rx; rgc->options = PCRE_CASELESS|PCRE_MULTILINE; rgc->pattern = custloc_array(curr_r->br->custom_locations->elts)[name_idx].target; rgc->pool = cf->pool; rgc->err.len = 0; rgc->err.data = NULL; //custloc_array(curr_r->br->custom_locations->elts)[name_idx].target; if (ngx_regex_compile(rgc) != NGX_OK) return (NGX_ERROR); } if (uri_idx != -1 && !custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target_rx) { custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target_rx = ngx_pcalloc(cf->pool, sizeof(ngx_regex_compile_t)); rgc = custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target_rx; rgc->options = PCRE_CASELESS|PCRE_MULTILINE; rgc->pattern = custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target; rgc->pool = cf->pool; rgc->err.len = 0; rgc->err.data = NULL; //custloc_array(curr_r->br->custom_locations->elts)[name_idx].target; if (ngx_regex_compile(rgc) != NGX_OK) return (NGX_ERROR); } rptr = ngx_array_push(dlc->rxmz_wlr); if (!rptr) return (NGX_ERROR); *rptr = curr_r; continue; } /* ** Handle static match-zones for hashtables */ father_wlr = ngx_http_wlr_find(cf, dlc, curr_r, zone, uri_idx, name_idx, (char **) &fullname); if (!father_wlr) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "creating fresh WL [%s].", fullname); /* creates a new whitelist rule in the right place. setup name and zone, create a new (empty) whitelist_location, as well as a new (empty) id aray. */ father_wlr = ngx_array_push(dlc->tmp_wlr); if (!father_wlr) return (NGX_ERROR); memset(father_wlr, 0, sizeof(ngx_http_whitelist_rule_t)); father_wlr->name = ngx_pcalloc(cf->pool, sizeof(ngx_str_t)); if (!father_wlr->name) return (NGX_ERROR); father_wlr->name->len = strlen((const char *) fullname); father_wlr->name->data = (unsigned char *) fullname; father_wlr->zone = zone; /* If there is URI and no name idx, specify it, so that WL system won't get fooled by an argname like an URL */ if (uri_idx != -1 && name_idx == -1) father_wlr->uri_only = 1; /* If target_name is present in son, report it. */ if (curr_r->br->target_name) father_wlr->target_name = curr_r->br->target_name; } /*merges the two whitelist rules together, including custom_locations. */ if (ngx_http_wlr_merge(cf, father_wlr, curr_r) != NGX_OK) return (NGX_ERROR); } /* and finally, build the hashtables for various zones. */ if (ngx_http_wlr_finalize_hashtables(cf, dlc) != NGX_OK) return (NGX_ERROR); /* TODO : Free old whitelist_rules (dlc->whitelist_rules)*/ return (NGX_OK); }
static ngx_int_t ngx_http_wlr_finalize_hashtables(ngx_conf_t *cf, ngx_http_dummy_loc_conf_t *dlc) { int get_sz = 0, headers_sz = 0, body_sz = 0, uri_sz = 0; ngx_array_t *get_ar = NULL, *headers_ar = NULL, *body_ar = NULL, *uri_ar = NULL; ngx_hash_key_t *arr_node; ngx_hash_init_t hash_init; uint i; NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "finalizing hashtables"); for (i = 0; i < dlc->tmp_wlr->nelts; i++) { switch (((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].zone) { case FILE_EXT: case BODY: body_sz++; break; case HEADERS: headers_sz++; break; case URL: uri_sz++; break; case ARGS: get_sz++; break; case UNKNOWN: default: return (NGX_ERROR); } } NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "nb items : body:%d headers:%d uri:%d get:%d", body_sz, headers_sz, uri_sz, get_sz); if (get_sz) get_ar = ngx_array_create(cf->pool, get_sz, sizeof(ngx_hash_key_t)); if (headers_sz) headers_ar = ngx_array_create(cf->pool, headers_sz, sizeof(ngx_hash_key_t)); if (body_sz) body_ar = ngx_array_create(cf->pool, body_sz, sizeof(ngx_hash_key_t)); if (uri_sz) uri_ar = ngx_array_create(cf->pool, uri_sz, sizeof(ngx_hash_key_t)); for (i = 0; i < dlc->tmp_wlr->nelts; i++) { switch (((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].zone) { case FILE_EXT: case BODY: arr_node = (ngx_hash_key_t*) ngx_array_push(body_ar); break; case HEADERS: arr_node = (ngx_hash_key_t*) ngx_array_push(headers_ar); break; case URL: arr_node = (ngx_hash_key_t*) ngx_array_push(uri_ar); break; case ARGS: arr_node = (ngx_hash_key_t*) ngx_array_push(get_ar); break; default: return (NGX_ERROR); } if (!arr_node) return (NGX_ERROR); ngx_memset(arr_node, 0, sizeof(ngx_hash_key_t)); arr_node->key = *(((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name); arr_node->key_hash = ngx_hash_key_lc(((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name->data, ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name->len); arr_node->value = (void *) &(((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i]); #ifdef SPECIAL__debug_whitelist_heavy ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing new WL, zone:%d, target:%V, %d IDs", ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].zone , ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name, ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].ids->nelts); unsigned int z; for (z = 0; z < ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].ids->nelts; z++) ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "id:%d", ((int *)((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].ids->elts)[z]); #endif } hash_init.key = &ngx_hash_key_lc; hash_init.pool = cf->pool; hash_init.temp_pool = NULL; hash_init.max_size = 1024; hash_init.bucket_size = 512; if (body_ar) { dlc->wlr_body_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); hash_init.hash = dlc->wlr_body_hash; hash_init.name = "wlr_body_hash"; if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) body_ar->elts, body_ar->nelts) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$BODY hashtable init failed"); /* LCOV_EXCL_LINE */ return (NGX_ERROR); /* LCOV_EXCL_LINE */ } else NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "$BODY hashtable init successed !"); } if (uri_ar) { dlc->wlr_url_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); hash_init.hash = dlc->wlr_url_hash; hash_init.name = "wlr_url_hash"; if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) uri_ar->elts, uri_ar->nelts) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$URL hashtable init failed"); /* LCOV_EXCL_LINE */ return (NGX_ERROR); /* LCOV_EXCL_LINE */ } else NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "$URL hashtable init successed !"); } if (get_ar) { dlc->wlr_args_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); hash_init.hash = dlc->wlr_args_hash; hash_init.name = "wlr_args_hash"; if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) get_ar->elts, get_ar->nelts) != NGX_OK) { /* LCOV_EXCL_LINE */ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$ARGS hashtable init failed"); /* LCOV_EXCL_LINE */ return (NGX_ERROR); } else NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "$ARGS hashtable init successed %d !", dlc->wlr_args_hash->size); } if (headers_ar) { dlc->wlr_headers_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, sizeof(ngx_hash_t)); hash_init.hash = dlc->wlr_headers_hash; hash_init.name = "wlr_headers_hash"; if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) headers_ar->elts, headers_ar->nelts) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$HEADERS hashtable init failed"); /* LCOV_EXCL_LINE */ return (NGX_ERROR); /* LCOV_EXCL_LINE */ } else NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, "$HEADERS hashtable init successed %d !", dlc->wlr_headers_hash->size); } return (NGX_OK); }
ngx_http_whitelist_rule_t * ngx_http_wlr_find(ngx_conf_t *cf, ngx_http_dummy_loc_conf_t *dlc, ngx_http_rule_t *curr, int zone, int uri_idx, int name_idx, char **fullname) { uint i; /* Create unique string for rule, and try to find it in existing rules.*/ /*name AND uri*/ if (uri_idx != -1 && name_idx != -1) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist has uri + name"); /* allocate one extra byte in case curr->br->target_name is set. */ *fullname = ngx_pcalloc(cf->pool, custloc_array(curr->br->custom_locations->elts)[name_idx].target.len + custloc_array(curr->br->custom_locations->elts)[uri_idx].target.len + 3); /* if WL targets variable name instead of content, prefix hash with '#' */ if (curr->br->target_name) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist targets |NAME"); strncat(*fullname, (const char *) "#", 1); } strncat(*fullname, (const char *) custloc_array(curr->br->custom_locations->elts)[uri_idx].target.data, custloc_array(curr->br->custom_locations->elts)[uri_idx].target.len); strncat(*fullname, (const char *) "#", 1); strncat(*fullname, (const char *) custloc_array(curr->br->custom_locations->elts)[name_idx].target.data, custloc_array(curr->br->custom_locations->elts)[name_idx].target.len); } /* only uri */ else if (uri_idx != -1 && name_idx == -1) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist has uri"); //XXX set flag only_uri *fullname = ngx_pcalloc(cf->pool, custloc_array(curr->br->custom_locations->elts)[uri_idx].target.len + 3); if (curr->br->target_name) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist targets |NAME"); strncat(*fullname, (const char *) "#", 1); } strncat(*fullname, (const char *) custloc_array(curr->br->custom_locations->elts)[uri_idx].target.data, custloc_array(curr->br->custom_locations->elts)[uri_idx].target.len); } /* only name */ else if (name_idx != -1) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist has name"); *fullname = ngx_pcalloc(cf->pool, custloc_array(curr->br->custom_locations->elts)[name_idx].target.len + 2); if (curr->br->target_name) strncat(*fullname, (const char *) "#", 1); strncat(*fullname, (const char *) custloc_array(curr->br->custom_locations->elts)[name_idx].target.data, custloc_array(curr->br->custom_locations->elts)[name_idx].target.len); } /* problem houston */ else return (NULL); for (i = 0; i < dlc->tmp_wlr->nelts; i++) if (!strcmp((const char *)*fullname, (const char *)((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name->data) && ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].zone == (uint) zone) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "found existing 'same' WL : %V", ((ngx_http_whitelist_rule_t *) dlc->tmp_wlr->elts)[i].name); return (&((ngx_http_whitelist_rule_t *)dlc->tmp_wlr->elts)[i]); } return (NULL); }
static ngx_int_t ngx_http_wlr_identify(ngx_conf_t *cf, ngx_http_dummy_loc_conf_t *dlc, ngx_http_rule_t *curr, int *zone, int *uri_idx, int *name_idx) { uint i; /* identify global match zones (|ARGS|BODY|HEADERS|URL|FILE_EXT) */ if (curr->br->body || curr->br->body_var) *zone = BODY; else if (curr->br->headers || curr->br->headers_var) *zone = HEADERS; else if (curr->br->args || curr->br->args_var) *zone = ARGS; else if (curr->br->url) /*don't assume that named $URL means zone is URL.*/ *zone = URL; else if (curr->br->file_ext) *zone = FILE_EXT; /* if we're facing a WL in the style $URL:/bla|ARGS (or any other zone), push it to */ for (i = 0; i < curr->br->custom_locations->nelts; i++) { /* locate target URL if exists ($URL:/bla|ARGS) or ($URL:/bla|$ARGS_VAR:foo) */ if (custloc_array(curr->br->custom_locations->elts)[i].specific_url) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist has URI %V", &(custloc_array(curr->br->custom_locations->elts)[i].target)); *uri_idx = i; } /* identify named match zones ($ARGS_VAR:bla|$HEADERS_VAR:bla|$BODY_VAR:bla) */ if (custloc_array(curr->br->custom_locations->elts)[i].body_var) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist has body_var %V", &(custloc_array(curr->br->custom_locations->elts)[i].target)); /*#217 : scream on incorrect rules*/ if (*name_idx != -1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist can't target more than one BODY item."); return (NGX_ERROR); } *name_idx = i; *zone = BODY; } if (custloc_array(curr->br->custom_locations->elts)[i].headers_var) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist has header_var %V", &(custloc_array(curr->br->custom_locations->elts)[i].target)); /*#217 : scream on incorrect rules*/ if (*name_idx != -1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist can't target more than one HEADER item."); return (NGX_ERROR); } *name_idx = i; *zone = HEADERS; } if (custloc_array(curr->br->custom_locations->elts)[i].args_var) { NX_LOG_DEBUG(_debug_whitelist_heavy, NGX_LOG_EMERG, cf, 0, "whitelist has arg_var %V", &(custloc_array(curr->br->custom_locations->elts)[i].target)); /*#217 : scream on incorrect rules*/ if (*name_idx != -1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist can't target more than one ARGS item."); return (NGX_ERROR); } *name_idx = i; *zone = ARGS; } } if (*zone == -1) return (NGX_ERROR); return (NGX_OK); }