/* * ModSecurity for Apache 2.x, http://www.modsecurity.org/ * Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/) * * You may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * If any of the files related to licensing are missing or if you have any * other questions related to licensing please contact Trustwave Holdings, Inc. * directly using the email address security@modsecurity.org. */ #include "http_core.h" #include "modsecurity.h" #include "apache2.h" #include "re.h" #include "msc_util.h" #include "libxml/xpathInternals.h" /** * Generates a variable from a string and a length. */ static int var_simple_generate_ex(msre_var *var, apr_table_t *vartab, apr_pool_t *mptmp, const char *value, int value_len) { msre_var *rvar = NULL; if (value == NULL) return 0; rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = value; rvar->value_len = value_len; apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /** * Generates a variable from a NULL-terminated string. */ static int var_simple_generate(msre_var *var, apr_table_t *vartab, apr_pool_t *mptmp, const char *value) { if (value == NULL) return 0; return var_simple_generate_ex(var, vartab, mptmp, value, strlen(value)); } /** * Validate that a target parameter is valid. We only need to take * care of the case when the parameter is a regular expression. */ static char *var_generic_list_validate(msre_ruleset *ruleset, msre_var *var) { /* It's OK if there's no parameter. */ if (var->param == NULL) return NULL; /* Is it a regular expression? */ if ((strlen(var->param) > 2)&&(var->param[0] == '/') &&(var->param[strlen(var->param) - 1] == '/')) { /* Regex. */ msc_regex_t *regex = NULL; const char *errptr = NULL; const char *pattern = NULL; int erroffset; pattern = apr_pstrmemdup(ruleset->mp, var->param + 1, strlen(var->param + 1) - 1); if (pattern == NULL) return FATAL_ERROR; regex = msc_pregcomp(ruleset->mp, pattern, PCRE_DOTALL | PCRE_CASELESS | PCRE_DOLLAR_ENDONLY, &errptr, &erroffset); if (regex == NULL) { return apr_psprintf(ruleset->mp, "Error compiling pattern (offset %d): %s", erroffset, errptr); } /* Store the compiled regex for later. */ var->param_data = regex; } /* Simple string */ return NULL; } /* Custom parameter validation functions */ /* ARGS */ static int var_args_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; /* Loop through the arguments. */ arr = apr_table_elts(msr->arguments); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_arg *arg = (msc_arg *)te[i].val; int match = 0; /* Figure out if we want to include this argument. */ if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; /* Run the regex against the argument name. */ if (!(msc_regexec((msc_regex_t *)var->param_data, arg->name, arg->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(arg->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = arg->value; rvar->value_len = arg->value_len; rvar->name = apr_psprintf(mptmp, "ARGS:%s", log_escape_nq_ex(mptmp, arg->name, arg->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* ARGS_COMBINED_SIZE */ static int var_args_combined_size_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; unsigned int combined_size = 0; int i; msre_var *rvar = NULL; arr = apr_table_elts(msr->arguments); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_arg *arg = (msc_arg *)te[i].val; combined_size += arg->name_len; combined_size += arg->value_len; } rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%u", combined_size); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* ARGS_NAMES */ static int var_args_names_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->arguments); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_arg *arg = (msc_arg *)te[i].val; int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, arg->name, arg->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(arg->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = arg->name; rvar->value_len = arg->name_len; rvar->name = apr_psprintf(mptmp, "ARGS_NAMES:%s", log_escape_nq_ex(mptmp, arg->name, arg->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* ARGS_GET */ static int var_args_get_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; /* Loop through the arguments. */ arr = apr_table_elts(msr->arguments); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_arg *arg = (msc_arg *)te[i].val; int match = 0; /* Only QUERY_STRING arguments */ if (strcmp("QUERY_STRING", arg->origin) != 0) continue; /* Figure out if we want to include this argument. */ if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; /* Run the regex against the argument name. */ if (!(msc_regexec((msc_regex_t *)var->param_data, arg->name, arg->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(arg->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = arg->value; rvar->value_len = arg->value_len; rvar->name = apr_psprintf(mptmp, "ARGS_GET:%s", log_escape_nq_ex(mptmp, arg->name, arg->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* ARGS_GET_NAMES */ static int var_args_get_names_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->arguments); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_arg *arg = (msc_arg *)te[i].val; int match = 0; /* Only QUERY_STRING arguments */ if (strcmp("QUERY_STRING", arg->origin) != 0) continue; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, arg->name, arg->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(arg->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = arg->name; rvar->value_len = arg->name_len; rvar->name = apr_psprintf(mptmp, "ARGS_GET_NAMES:%s", log_escape_nq_ex(mptmp, arg->name, arg->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* ARGS_POST */ static int var_args_post_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; /* Loop through the arguments. */ arr = apr_table_elts(msr->arguments); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_arg *arg = (msc_arg *)te[i].val; int match = 0; /* Only BODY arguments */ if (strcmp("BODY", arg->origin) != 0) continue; /* Figure out if we want to include this argument. */ if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; /* Run the regex against the argument name. */ if (!(msc_regexec((msc_regex_t *)var->param_data, arg->name, arg->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(arg->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = arg->value; rvar->value_len = arg->value_len; rvar->name = apr_psprintf(mptmp, "ARGS_POST:%s", log_escape_nq_ex(mptmp, arg->name, arg->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* ARGS_POST_NAMES */ static int var_args_post_names_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->arguments); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_arg *arg = (msc_arg *)te[i].val; int match = 0; /* Only BODY arguments */ if (strcmp("BODY", arg->origin) != 0) continue; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, arg->name, arg->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(arg->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = arg->name; rvar->value_len = arg->name_len; rvar->name = apr_psprintf(mptmp, "ARGS_POST_NAMES:%s", log_escape_nq_ex(mptmp, arg->name, arg->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* RULE */ static int var_rule_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_actionset *actionset = NULL; if (rule == NULL) return 0; actionset = rule->actionset; if (rule->chain_starter != NULL) actionset = rule->chain_starter->actionset; if ((strcasecmp(var->param, "id") == 0)&&(actionset->id != NULL)) { return var_simple_generate(var, vartab, mptmp, actionset->id); } else if ((strcasecmp(var->param, "rev") == 0)&&(actionset->rev != NULL)) { return var_simple_generate(var, vartab, mptmp, actionset->rev); } else if ((strcasecmp(var->param, "severity") == 0)&&(actionset->severity != -1)) { char *value = apr_psprintf(mptmp, "%d", actionset->severity); return var_simple_generate(var, vartab, mptmp, value); } else if ((strcasecmp(var->param, "msg") == 0)&&(actionset->msg != NULL)) { return var_simple_generate(var, vartab, mptmp, actionset->msg); } else if ((strcasecmp(var->param, "logdata") == 0)&&(actionset->logdata != NULL)) { return var_simple_generate(var, vartab, mptmp, actionset->logdata); } else if ((strcasecmp(var->param, "ver") == 0)&&(actionset->version != NULL)) { return var_simple_generate(var, vartab, mptmp, actionset->version); } else if ((strcasecmp(var->param, "maturity") == 0)&&(actionset->maturity != -1)) { char *value = apr_psprintf(mptmp, "%d", actionset->maturity); return var_simple_generate(var, vartab, mptmp, value); } else if ((strcasecmp(var->param, "accuracy") == 0)&&(actionset->accuracy != -1)) { char *value = apr_psprintf(mptmp, "%d", actionset->accuracy); return var_simple_generate(var, vartab, mptmp, value); } return 0; } /* ENV */ static char *var_env_validate(msre_ruleset *ruleset, msre_var *var) { if (var->param == NULL) { return apr_psprintf(ruleset->mp, "Parameter required for ENV."); } if ((strlen(var->param) > 2)&&(var->param[0] == '/') &&(var->param[strlen(var->param) - 1] == '/')) { return apr_psprintf(ruleset->mp, "Regular expressions not supported in ENV."); } return NULL; } static int var_env_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = get_env_var(msr->r, (char *)var->param); if (value != NULL) { return var_simple_generate(var, vartab, mptmp, value); } return 0; } /* REQUEST_URI_RAW */ static int var_request_uri_raw_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->r->unparsed_uri); } /* UNIQUE_ID */ static int var_uniqueid_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = get_env_var(msr->r, "UNIQUE_ID"); if (value != NULL) { return var_simple_generate(var, vartab, mptmp, value); } return 0; } /* REQUEST_URI */ static int var_request_uri_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) /* dynamic */ { char *value = NULL; if (msr->r->parsed_uri.query == NULL) value = msr->r->parsed_uri.path; else value = apr_pstrcat(mptmp, msr->r->parsed_uri.path, "?", msr->r->parsed_uri.query, NULL); return var_simple_generate(var, vartab, mptmp, value); } /* REQBODY_PROCESSOR */ static int var_reqbody_processor_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); if (msr->msc_reqbody_processor == NULL) { rvar->value = apr_pstrdup(mptmp, ""); rvar->value_len = 0; } else { rvar->value = apr_pstrdup(mptmp, msr->msc_reqbody_processor); rvar->value_len = strlen(rvar->value); } apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* SDBM_DELETE_ERROR */ static int var_sdbm_delete_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%d", msr->msc_sdbm_delete_error); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* REQBODY_ERROR */ static int var_reqbody_processor_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%d", msr->msc_reqbody_error); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* REQBODY_ERROR_MSG */ static int var_reqbody_processor_error_msg_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); if (msr->msc_reqbody_error_msg == NULL) { rvar->value = apr_pstrdup(mptmp, ""); rvar->value_len = 0; } else { rvar->value = apr_psprintf(mptmp, "%s", msr->msc_reqbody_error_msg); rvar->value_len = strlen(rvar->value); } apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* XML */ static char *var_xml_validate(msre_ruleset *ruleset, msre_var *var) { /* It's OK if there's no parameter. */ if (var->param == NULL) return NULL; /* ENH validate XPath expression in advance. */ return NULL; } static int var_xml_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *tarr; const apr_table_entry_t *telts; xmlXPathContextPtr xpathCtx; xmlXPathObjectPtr xpathObj; xmlNodeSetPtr nodes; const xmlChar* xpathExpr = NULL; int i, count; /* Is there an XML document tree at all? */ if ((msr->xml == NULL)||(msr->xml->doc == NULL)) { /* Sorry, we've got nothing to give! */ return 0; } if (var->param == NULL) { /* Invocation without an XPath expression makes sense * with functions that manipulate the document tree. */ msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_pstrdup(mptmp, "[XML document tree]"); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* Process the XPath expression. */ count = 0; xpathExpr = (const xmlChar*)var->param; xpathCtx = xmlXPathNewContext(msr->xml->doc); if (xpathCtx == NULL) { msr_log(msr, 1, "XML: Unable to create new XPath context."); return -1; } /* Look through the actionset of the associated rule * for the namespace information. Register them if any are found. */ tarr = apr_table_elts(rule->actionset->actions); telts = (const apr_table_entry_t*)tarr->elts; for (i = 0; i < tarr->nelts; i++) { msre_action *action = (msre_action *)telts[i].val; if (strcasecmp(action->metadata->name, "xmlns") == 0) { char *prefix, *href; if (parse_name_eq_value(mptmp, action->param, &prefix, &href) < 0) return -1; if ((prefix == NULL)||(href == NULL)) return -1; if(xmlXPathRegisterNs(xpathCtx, (const xmlChar*)prefix, (const xmlChar*)href) != 0) { msr_log(msr, 1, "Failed to register XML namespace href \"%s\" prefix \"%s\".", log_escape(mptmp, prefix), log_escape(mptmp, href)); return -1; } msr_log(msr, 4, "Registered XML namespace href \"%s\" prefix \"%s\".", log_escape(mptmp, prefix), log_escape(mptmp, href)); } } /* Initialise XPath expression. */ xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); if (xpathObj == NULL) { msr_log(msr, 1, "XML: Unable to evaluate xpath expression."); xmlXPathFreeContext(xpathCtx); return -1; } /* Evaluate XPath expression. */ nodes = xpathObj->nodesetval; if (nodes == NULL) { xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); return 0; } /* Create one variable for each node in the result. */ for(i = 0; i < nodes->nodeNr; i++) { msre_var *rvar = NULL; char *content = NULL; content = (char *)xmlNodeGetContent(nodes->nodeTab[i]); if (content != NULL) { rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_pstrdup(mptmp, content); xmlFree(content); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); return count; } /* WEBSERVER_ERROR_LOG */ static int var_webserver_error_log_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; int i, count = 0; for(i = 0; i < msr->error_messages->nelts; i++) { error_message_t *em = (((error_message_t **)msr->error_messages->elts)[i]); char *fem = NULL; fem = format_error_log_message(mptmp, em); if (fem != NULL) { rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_pstrdup(mptmp, fem); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } #if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2 static int var_useragent_ip_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->useragent_ip ? msr->useragent_ip : "0.0.0.0"); } #endif /* REMOTE_ADDR */ static int var_remote_addr_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { #if !defined(MSC_TEST) #if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 3 if (ap_find_linked_module("mod_remoteip.c") != NULL) { if(msr->r->useragent_ip != NULL) msr->remote_addr = apr_pstrdup(msr->mp, msr->r->useragent_ip); return var_simple_generate(var, vartab, mptmp, msr->remote_addr); } #endif #endif return var_simple_generate(var, vartab, mptmp, msr->remote_addr); } /* REMOTE_HOST */ static int var_remote_host_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value1 = ap_get_remote_host(msr->r->connection, msr->r->per_dir_config, REMOTE_NAME, NULL); return var_simple_generate(var, vartab, mptmp, value1); } /* REMOTE_PORT */ static int var_remote_port_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = apr_psprintf(mptmp, "%u", msr->remote_port); return var_simple_generate(var, vartab, mptmp, value); } /* REMOTE_USER */ static int var_remote_user_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->remote_user); } /* TX */ static int var_tx_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->tx_vars); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_string *str = (msc_string *)te[i].val; int match; /* Figure out if we want to include this variable. */ match = 0; if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, str->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = str->value; rvar->value_len = str->value_len; rvar->name = apr_psprintf(mptmp, "TX:%s", log_escape_nq_ex(mptmp, str->name, str->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* GEO */ static int var_geo_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->geo_vars); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_string *str = (msc_string *)te[i].val; int match; /* Figure out if we want to include this variable. */ match = 0; if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, str->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = str->value; rvar->value_len = str->value_len; rvar->name = apr_psprintf(mptmp, "GEO:%s", log_escape_nq_ex(mptmp, str->name, str->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* HIGHEST_SEVERITY */ static int var_highest_severity_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, apr_psprintf(mptmp, "%d", msr->highest_severity)); } /* IP */ static int var_ip_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; apr_table_t *target_col = NULL; target_col = (apr_table_t *)apr_table_get(msr->collections, "ip"); if (target_col == NULL) return 0; arr = apr_table_elts(target_col); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_string *str = (msc_string *)te[i].val; int match; /* Figure out if we want to include this variable. */ match = 0; if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, str->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = str->value; rvar->value_len = str->value_len; rvar->name = apr_psprintf(mptmp, "IP:%s", log_escape_nq_ex(mptmp, str->name, str->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* MATCHED_VAR */ static int var_matched_var_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate_ex(var, vartab, mptmp, apr_pmemdup(mptmp, msr->matched_var->value, msr->matched_var->value_len), msr->matched_var->value_len); } /* MATCHED_VAR_NAME */ static int var_matched_var_name_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate_ex(var, vartab, mptmp, apr_pmemdup(mptmp, msr->matched_var->name, msr->matched_var->name_len), msr->matched_var->name_len); } /* SESSION */ static int var_session_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; apr_table_t *target_col = NULL; target_col = (apr_table_t *)apr_table_get(msr->collections, "session"); if (target_col == NULL) return 0; arr = apr_table_elts(target_col); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_string *str = (msc_string *)te[i].val; int match; /* Figure out if we want to include this variable. */ match = 0; if (var->param == NULL) match = 1; /* Unconditional inclusion. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, str->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = str->value; rvar->value_len = str->value_len; rvar->name = apr_psprintf(mptmp, "SESSION:%s", log_escape_nq_ex(mptmp, str->name, str->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* USER */ static int var_user_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; apr_table_t *target_col = NULL; target_col = (apr_table_t *)apr_table_get(msr->collections, "user"); if (target_col == NULL) return 0; arr = apr_table_elts(target_col); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_string *str = (msc_string *)te[i].val; int match; /* Figure out if we want to include this variable. */ match = 0; if (var->param == NULL) match = 1; /* Unconditional match. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, str->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = str->value; rvar->value_len = str->value_len; rvar->name = apr_psprintf(mptmp, "USER:%s", log_escape_nq_ex(mptmp, str->name, str->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* GLOBAL */ static int var_global_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; apr_table_t *target_col = NULL; target_col = (apr_table_t *)apr_table_get(msr->collections, "global"); if (target_col == NULL) return 0; arr = apr_table_elts(target_col); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_string *str = (msc_string *)te[i].val; int match; /* Figure out if we want to include this variable. */ match = 0; if (var->param == NULL) match = 1; /* Unconditional match. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, str->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = str->value; rvar->value_len = str->value_len; rvar->name = apr_psprintf(mptmp, "GLOBAL:%s", log_escape_nq_ex(mptmp, str->name, str->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* RESOURCE */ static int var_resource_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; apr_table_t *target_col = NULL; target_col = (apr_table_t *)apr_table_get(msr->collections, "resource"); if (target_col == NULL) return 0; arr = apr_table_elts(target_col); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { msc_string *str = (msc_string *)te[i].val; int match; /* Figure out if we want to include this variable. */ match = 0; if (var->param == NULL) match = 1; /* Unconditional match. */ else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, str->name_len, &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = str->value; rvar->value_len = str->value_len; rvar->name = apr_psprintf(mptmp, "RESOURCE:%s", log_escape_nq_ex(mptmp, str->name, str->name_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* FILES_TMP_CONTENT */ static int var_files_tmp_contents_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { multipart_part **parts = NULL; int i, count = 0; if (msr->mpd == NULL) return 0; parts = (multipart_part **)msr->mpd->parts->elts; for (i = 0; i < msr->mpd->parts->nelts; i++) { if ((parts[i]->type == MULTIPART_FILE) && (parts[i]->tmp_file_name != NULL)) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) { match = 1; } else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, parts[i]->name, strlen(parts[i]->name), &my_error_msg) == PCRE_ERROR_NOMATCH)) { match = 1; } } else { /* Simple comparison. */ if (strcasecmp(parts[i]->name, var->param) == 0) { match = 1; } } } /* If we had a match add this argument to the collection. */ if (match) { char buf[1024]; FILE *file; size_t nread; char *full_content = NULL; size_t total_lenght = 0; msre_var *rvar = NULL; file = fopen(parts[i]->tmp_file_name, "r"); if (file == NULL) { continue; } while ((nread = fread(buf, 1, 1023, file)) > 0) { total_lenght += nread; buf[nread] = '\0'; if (full_content == NULL) { full_content = apr_psprintf(mptmp, "%s", buf); } else { full_content = apr_psprintf(mptmp, "%s%s", full_content, buf); } } fclose(file); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = full_content; rvar->value_len = total_lenght; rvar->name = apr_psprintf(mptmp, "FILES_TMP_CONTENT:%s", log_escape_nq(mptmp, parts[i]->name)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } } return count; } /* FILES_TMPNAMES */ static int var_files_tmpnames_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { multipart_part **parts = NULL; int i, count = 0; if (msr->mpd == NULL) return 0; parts = (multipart_part **)msr->mpd->parts->elts; for(i = 0; i < msr->mpd->parts->nelts; i++) { if ((parts[i]->type == MULTIPART_FILE)&&(parts[i]->tmp_file_name != NULL)) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, parts[i]->name, strlen(parts[i]->name), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(parts[i]->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = parts[i]->tmp_file_name; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "FILES_TMPNAMES:%s", log_escape_nq(mptmp, parts[i]->name)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } } return count; } /* FILES */ static int var_files_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { multipart_part **parts = NULL; int i, count = 0; if (msr->mpd == NULL) return 0; parts = (multipart_part **)msr->mpd->parts->elts; for(i = 0; i < msr->mpd->parts->nelts; i++) { if (parts[i]->type == MULTIPART_FILE) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, parts[i]->name, strlen(parts[i]->name), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(parts[i]->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = parts[i]->filename; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "FILES:%s", log_escape_nq(mptmp, parts[i]->name)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } } return count; } /* FILES_SIZES */ static int var_files_sizes_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { multipart_part **parts = NULL; int i, count = 0; if (msr->mpd == NULL) return 0; parts = (multipart_part **)msr->mpd->parts->elts; for(i = 0; i < msr->mpd->parts->nelts; i++) { if (parts[i]->type == MULTIPART_FILE) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, parts[i]->name, strlen(parts[i]->name), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(parts[i]->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%u", parts[i]->tmp_file_size); rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "FILES_SIZES:%s", log_escape_nq(mptmp, parts[i]->name)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } } return count; } /* FILES_NAMES */ static int var_files_names_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { multipart_part **parts = NULL; int i, count = 0; if (msr->mpd == NULL) return 0; parts = (multipart_part **)msr->mpd->parts->elts; for(i = 0; i < msr->mpd->parts->nelts; i++) { if (parts[i]->type == MULTIPART_FILE) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = parts[i]->name; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "FILES_NAMES:%s", log_escape_nq_ex(mptmp, parts[i]->name, rvar->value_len)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* FILES_COMBINED_SIZE */ static int var_files_combined_size_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { multipart_part **parts = NULL; msre_var *rvar = NULL; unsigned int combined_size = 0; int i; if (msr->mpd != NULL) { parts = (multipart_part **)msr->mpd->parts->elts; for(i = 0; i < msr->mpd->parts->nelts; i++) { if (parts[i]->type == MULTIPART_FILE) { combined_size += parts[i]->tmp_file_size; } } } rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%u", combined_size); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* MODSEC_BUILD */ static int var_modsec_build_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, modsec_build(mptmp)); } /* MULTIPART_FILENAME */ static int var_multipart_filename_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->multipart_filename); } /* MULTIPART_NAME */ static int var_multipart_name_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->multipart_name); } /* MULTIPART_BOUNDARY_QUOTED */ static int var_multipart_boundary_quoted_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_boundary_quoted != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_BOUNDARY_WHITESPACE */ static int var_multipart_boundary_whitespace_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_boundary_whitespace != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_DATA_AFTER */ static int var_multipart_data_after_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_data_after != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_DATA_BEFORE */ static int var_multipart_data_before_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_data_before != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_HEADER_FOLDING */ static int var_multipart_header_folding_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_header_folding != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_CRLF_LINE */ static int var_multipart_crlf_line_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_crlf_line != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_CRLF_LF_LINES */ static int var_multipart_crlf_lf_lines_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_lf_line != 0)&&(msr->mpd->flag_crlf_line != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_LF_LINE */ static int var_multipart_lf_line_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_lf_line != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_MISSING_SEMICOLON */ static int var_multipart_missing_semicolon_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_missing_semicolon != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_INVALID_PART */ static int var_multipart_invalid_part_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_invalid_part != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_INVALID_QUOTING */ static int var_multipart_invalid_quoting_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_invalid_quoting != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_INVALID_HEADER_FOLDING */ static int var_multipart_invalid_header_folding_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_invalid_header_folding != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_FILE_LIMIT_EXCEEDED */ static int var_multipart_file_limit_exceeded_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_file_limit_exceeded != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* MULTIPART_STRICT_ERROR */ static int var_multipart_strict_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if (msr->mpd != NULL) { /* Respond positive if at least one of the multipart flags is raised. */ if ( (msr->mpd->flag_error) ||(msr->mpd->flag_boundary_quoted != 0) ||(msr->mpd->flag_boundary_whitespace != 0) ||(msr->mpd->flag_data_before != 0) ||(msr->mpd->flag_data_after != 0) ||(msr->mpd->flag_header_folding != 0) ||(msr->mpd->flag_lf_line != 0) ||(msr->mpd->flag_missing_semicolon != 0) ||(msr->mpd->flag_invalid_quoting != 0) ||(msr->mpd->flag_invalid_part != 0) ||(msr->mpd->flag_invalid_header_folding != 0) ||(msr->mpd->flag_file_limit_exceeded != 0) ) { return var_simple_generate(var, vartab, mptmp, "1"); } } return var_simple_generate(var, vartab, mptmp, "0"); } /* MULTIPART_UNMATCHED_BOUNDARY */ static int var_multipart_unmatched_boundary_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if ((msr->mpd != NULL)&&(msr->mpd->flag_unmatched_boundary != 0)) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* URLENCODED_ERROR */ static int var_urlencoded_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if (msr->urlencoded_error) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* INBOUND_DATA_ERROR */ static int var_inbound_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if (msr->inbound_error) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } /* OUTBOUND_DATA_ERROR */ static int var_outbound_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if (msr->outbound_error) { return var_simple_generate(var, vartab, mptmp, "1"); } else { return var_simple_generate(var, vartab, mptmp, "0"); } } static apr_time_t calculate_perf_combined(modsec_rec *msr) { return msr->time_phase1 + msr->time_phase2 + msr->time_phase3 + msr->time_phase4 + msr->time_phase5 + msr->time_storage_write /* time_storage_read is already included in phases */ + msr->time_logging + msr->time_gc; } char *format_all_performance_variables(modsec_rec *msr, apr_pool_t *mp) { return apr_psprintf(mp, "combined=%" APR_TIME_T_FMT ", p1=%" APR_TIME_T_FMT ", p2=%" APR_TIME_T_FMT ", p3=%" APR_TIME_T_FMT ", p4=%" APR_TIME_T_FMT ", p5=%" APR_TIME_T_FMT ", sr=%" APR_TIME_T_FMT ", sw=%" APR_TIME_T_FMT ", l=%" APR_TIME_T_FMT ", gc=%" APR_TIME_T_FMT, calculate_perf_combined(msr), msr->time_phase1, msr->time_phase2, msr->time_phase3, msr->time_phase4, msr->time_phase5, msr->time_storage_read, msr->time_storage_write, msr->time_logging, msr->time_gc); } static int generate_performance_variable(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp, apr_time_t value) { msre_var *rvar = NULL; rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%" APR_TIME_T_FMT, value); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* PERF_ALL */ static int var_perf_all_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = format_all_performance_variables(msr, mptmp); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* PERF_COMBINED */ static int var_perf_combined_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, calculate_perf_combined(msr)); } /* PERF_GC */ static int var_perf_gc_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_gc); } /* PERF_PHASE1 */ static int var_perf_phase1_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_phase1); } /* PERF_PHASE2 */ static int var_perf_phase2_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_phase2); } /* PERF_PHASE3 */ static int var_perf_phase3_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_phase3); } /* PERF_PHASE4 */ static int var_perf_phase4_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_phase4); } /* PERF_PHASE5 */ static int var_perf_phase5_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_phase5); } /* PERF_SREAD */ static int var_perf_sread_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_storage_read); } /* PERF_SWRITE */ static int var_perf_swrite_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_storage_write); } /* PERF_LOGGING */ static int var_perf_logging_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_logging); } /* PERF_RULES */ static int var_perf_rules_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->perf_rules); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, te[i].key, strlen(te[i].key), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(te[i].key, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = te[i].val; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "PERF_RULES:%s", log_escape_nq(mptmp, te[i].key)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* DURATION */ static int var_duration_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%" APR_TIME_T_FMT, (apr_time_now() - msr->r->request_time)); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME */ static int var_time_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; struct tm *tm; time_t tc; tc = time(NULL); tm = localtime(&tc); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%02d%02d%02d%02d%02d%02d%02d", (tm->tm_year / 100) + 19, (tm->tm_year % 100), tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME_YEAR */ static int var_time_year_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; struct tm *tm; time_t tc; tc = time(NULL); tm = localtime(&tc); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%02d%02d", (tm->tm_year / 100) + 19, tm->tm_year % 100); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME_WDAY */ static int var_time_wday_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; struct tm *tm; time_t tc; tc = time(NULL); tm = localtime(&tc); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%d", tm->tm_wday); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME_SEC */ static int var_time_sec_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; struct tm *tm; time_t tc; tc = time(NULL); tm = localtime(&tc); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%02d", tm->tm_sec); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME_MIN */ static int var_time_min_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; struct tm *tm; time_t tc; tc = time(NULL); tm = localtime(&tc); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%02d", tm->tm_min); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME_HOUR */ static int var_time_hour_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; struct tm *tm; time_t tc; tc = time(NULL); tm = localtime(&tc); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%02d", tm->tm_hour); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME_MON */ static int var_time_mon_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; struct tm *tm; time_t tc; tc = time(NULL); tm = localtime(&tc); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%02d", tm->tm_mon + 1); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME_DAY */ static int var_time_day_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; struct tm *tm; time_t tc; tc = time(NULL); tm = localtime(&tc); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%02d", tm->tm_mday); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* TIME_EPOCH */ static int var_time_epoch_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { msre_var *rvar = NULL; time_t tc; tc = time(NULL); rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = apr_psprintf(mptmp, "%ld", (long)tc); rvar->value_len = strlen(rvar->value); apr_table_addn(vartab, rvar->name, (void *)rvar); return 1; } /* QUERY_STRING */ static int var_query_string_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->query_string); } /* REQUEST_BASENAME */ static int var_request_basename_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = file_basename(mptmp, msr->r->parsed_uri.path); return var_simple_generate(var, vartab, mptmp, value); } /* FULL_REQUEST */ static int var_full_request_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; char *full_request = NULL; int full_request_length = 0; int headers_length = 0; int request_line_length = 0; arr = apr_table_elts(msr->request_headers); headers_length = msc_headers_to_buffer(arr, NULL, 0); if (headers_length < 0) { msr_log(msr, 9, "Variable FULL_REQUEST failed. Problems to measure " \ "headers length."); goto failed_measure_buffer; } request_line_length = strlen(msr->request_line) + /* \n\n: */ 2; full_request_length = request_line_length + headers_length + msr->msc_reqbody_length + /* \0: */1; full_request = malloc(sizeof(char)*full_request_length); if (full_request == NULL) { if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 8, "Variable FULL_REQUEST will not be created, not " \ "enough memory available."); } goto failed_not_enough_mem; } memset(full_request, '\0', sizeof(char)*msr->msc_full_request_length); msr->msc_full_request_buffer = full_request; msr->msc_full_request_length = full_request_length; apr_snprintf(full_request, request_line_length + 1, /* +1 here because sprintf will place \0 in the end of the string.*/ "%s\n\n", msr->request_line); headers_length = msc_headers_to_buffer(arr, full_request + request_line_length, headers_length); if (headers_length < 0) { msr_log(msr, 9, "Variable FULL_REQUEST will not be created, failed " \ "to fill headers buffer."); goto failed_fill_buffer; } if (msr->msc_reqbody_length > 0 && msr->msc_reqbody_buffer != NULL) { memcpy(full_request + (headers_length + request_line_length), msr->msc_reqbody_buffer, msr->msc_reqbody_length); } full_request[msr->msc_full_request_length-1] = '\0'; return var_simple_generate_ex(var, vartab, mptmp, full_request, msr->msc_full_request_length); failed_fill_buffer: failed_not_enough_mem: failed_measure_buffer: return 0; } /* FULL_REQUEST_LENGTH */ static int var_full_request_length_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; char *value = NULL; int headers_length = 0; arr = apr_table_elts(msr->request_headers); headers_length = msc_headers_to_buffer(arr, NULL, 0); msr->msc_full_request_length = headers_length + msr->msc_reqbody_length + /* \0: */1; value = apr_psprintf(mptmp, "%d", msr->msc_full_request_length); return var_simple_generate(var, vartab, mptmp, value); } /* REQUEST_BODY */ static int var_request_body_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if (msr->msc_reqbody_buffer != NULL) { return var_simple_generate_ex(var, vartab, mptmp, msr->msc_reqbody_buffer, msr->msc_reqbody_length); } return 0; } /* REQUEST_BODY_LENGTH */ static int var_request_body_length_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = apr_psprintf(mptmp, "%d", msr->msc_reqbody_length); return var_simple_generate(var, vartab, mptmp, value); } /* MATCHED_VARS_NAMES */ static int var_matched_vars_names_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->matched_vars); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; msc_string *str = (msc_string *)te[i].val; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, strlen(str->name), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match && (strncmp(str->name,"MATCHED_VARS:",13) != 0) && (strncmp(str->name,"MATCHED_VARS_NAMES:",19))) { msre_var *rvar = apr_palloc(mptmp, sizeof(msre_var)); rvar->param = NULL; rvar->param_data = NULL; rvar->metadata = NULL; rvar->param_regex = NULL; rvar->value = apr_pstrndup(mptmp, str->name, strlen(str->name)); rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "%s", log_escape_nq(mptmp, str->name)); if(var->is_counting == 0) rvar->is_counting = 0; else rvar->is_counting = 1; if(var->is_negated == 0) rvar->is_negated = 0; else rvar->is_negated = 1; apr_table_addn(vartab, rvar->name, (void *)rvar); if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "Set variable \"%s\" size %d to collection.", rvar->name,rvar->value_len); } count++; } } return count; } /* MATCHED_VARS */ static int var_matched_vars_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->matched_vars); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; msc_string *str = (msc_string *)te[i].val; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, str->name, strlen(str->name), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(str->name, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match && (strncmp(str->name,"MATCHED_VARS:",13) != 0) && (strncmp(str->name,"MATCHED_VARS_NAMES:",19))) { msre_var *rvar = apr_palloc(mptmp, sizeof(msre_var)); rvar->param = NULL; rvar->param_data = NULL; rvar->metadata = NULL; rvar->param_regex = NULL; rvar->value = apr_pstrndup(mptmp, str->value, str->value_len); rvar->value_len = str->value_len; rvar->name = apr_psprintf(mptmp, "%s", log_escape_nq(mptmp, str->name)); if(var->is_counting == 0) rvar->is_counting = 0; else rvar->is_counting = 1; if(var->is_negated == 0) rvar->is_negated = 0; else rvar->is_negated = 1; apr_table_addn(vartab, rvar->name, (void *)rvar); if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "Set variable \"%s\" value \"%s\" size %d to collection.", rvar->name, rvar->value, rvar->value_len); } count++; } } return count; } /* REQUEST_COOKIES */ static int var_request_cookies_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->request_cookies); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, te[i].key, strlen(te[i].key), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(te[i].key, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = te[i].val; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "REQUEST_COOKIES:%s", log_escape_nq(mptmp, te[i].key)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* REQUEST_COOKIES_NAMES */ static int var_request_cookies_names_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->request_cookies); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, te[i].key, strlen(te[i].key), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(te[i].key, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = te[i].key; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "REQUEST_COOKIES_NAMES:%s", log_escape_nq(mptmp, te[i].key)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* REQUEST_HEADERS */ static int var_request_headers_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->request_headers); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, te[i].key, strlen(te[i].key), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(te[i].key, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = te[i].val; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "REQUEST_HEADERS:%s", log_escape_nq(mptmp, te[i].key)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* REQUEST_HEADERS_NAMES */ static int var_request_headers_names_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->request_headers); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, te[i].key, strlen(te[i].key), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(te[i].key, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = te[i].key; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "REQUEST_HEADERS_NAMES:%s", log_escape_nq(mptmp, te[i].key)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* REQUEST_FILENAME */ static int var_request_filename_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->r->parsed_uri.path); } /* REQUEST_LINE */ static int var_request_line_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->request_line); } /* REQUEST_METHOD */ static int var_request_method_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->request_method); } /* REQUEST_PROTOCOL */ static int var_request_protocol_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->request_protocol); } /* SERVER_ADDR */ static int var_server_addr_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->local_addr); } /* SERVER_NAME */ static int var_server_name_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->hostname); } /* SERVER_PORT */ static int var_server_port_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = apr_psprintf(mptmp, "%u", msr->local_port); return var_simple_generate(var, vartab, mptmp, value); } /* SCRIPT_BASENAME */ static int var_script_basename_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = file_basename(mptmp, msr->r->filename); return var_simple_generate(var, vartab, mptmp, value); } /* SCRIPT_FILENAME */ static int var_script_filename_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = msr->r->filename; return var_simple_generate(var, vartab, mptmp, value); } /* SCRIPT_GID */ static int var_script_gid_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = apr_psprintf(mptmp, "%ld", (long)msr->r->finfo.group); return var_simple_generate(var, vartab, mptmp, value); } /* SCRIPT_GROUPNAME */ static int var_script_groupname_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = NULL; if (apr_gid_name_get(&value, msr->r->finfo.group, mptmp) == APR_SUCCESS) { return var_simple_generate(var, vartab, mptmp, value); } return 0; } /* SCRIPT_MODE */ static int var_script_mode_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = apr_psprintf(mptmp, "%04x", msr->r->finfo.protection); return var_simple_generate(var, vartab, mptmp, value); } /* SCRIPT_UID */ static int var_script_uid_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = apr_psprintf(mptmp, "%ld", (long)msr->r->finfo.user); return var_simple_generate(var, vartab, mptmp, value); } /* SCRIPT_USERNAME */ static int var_script_username_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = NULL; if (apr_uid_name_get(&value, msr->r->finfo.user, mptmp) == APR_SUCCESS) { return var_simple_generate(var, vartab, mptmp, value); } return 0; } /* AUTH_TYPE */ static int var_auth_type_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { char *value = msr->r->ap_auth_type; return var_simple_generate(var, vartab, mptmp, value); } /* PATH_INFO */ static int var_path_info_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value = msr->r->path_info; return var_simple_generate(var, vartab, mptmp, value); } /* STREAM_OUTPUT_BODY */ static int var_stream_output_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if (msr->stream_output_data != NULL) { return var_simple_generate_ex(var, vartab, mptmp, msr->stream_output_data, msr->stream_output_length); } return 0; } /* STREAM_INPUT_BODY */ static int var_stream_input_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if (msr->stream_input_data != NULL) { return var_simple_generate_ex(var, vartab, mptmp, msr->stream_input_data, msr->stream_input_length); } return 0; } /* RESPONSE_BODY */ static int var_response_body_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { if (msr->resbody_data != NULL) { return var_simple_generate_ex(var, vartab, mptmp, msr->resbody_data, msr->resbody_length); } return 0; } /* RESPONSE_HEADERS */ static int var_response_headers_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; if (msr->response_headers == NULL) return 0; arr = apr_table_elts(msr->response_headers); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, te[i].key, strlen(te[i].key), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(te[i].key, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = te[i].val; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "RESPONSE_HEADERS:%s", log_escape_nq(mptmp, te[i].key)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* RESPONSE_HEADERS_NAMES */ static int var_response_headers_names_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const apr_array_header_t *arr = NULL; const apr_table_entry_t *te = NULL; int i, count = 0; arr = apr_table_elts(msr->response_headers); te = (apr_table_entry_t *)arr->elts; for (i = 0; i < arr->nelts; i++) { int match = 0; /* Figure out if we want to include this variable. */ if (var->param == NULL) match = 1; else { if (var->param_data != NULL) { /* Regex. */ char *my_error_msg = NULL; if (!(msc_regexec((msc_regex_t *)var->param_data, te[i].key, strlen(te[i].key), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1; } else { /* Simple comparison. */ if (strcasecmp(te[i].key, var->param) == 0) match = 1; } } /* If we had a match add this argument to the collection. */ if (match) { msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var)); rvar->value = te[i].key; rvar->value_len = strlen(rvar->value); rvar->name = apr_psprintf(mptmp, "RESPONSE_HEADERS_NAMES:%s", log_escape_nq(mptmp, te[i].key)); apr_table_addn(vartab, rvar->name, (void *)rvar); count++; } } return count; } /* STATUS_LINE */ static int var_status_line_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value = msr->status_line; return var_simple_generate(var, vartab, mptmp, value); } /* RESPONSE_PROTOCOL */ static int var_response_protocol_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value = msr->response_protocol; return var_simple_generate(var, vartab, mptmp, value); } /* RESPONSE_STATUS */ static int var_response_status_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value = apr_psprintf(mptmp, "%u", msr->response_status); return var_simple_generate(var, vartab, mptmp, value); } /* RESPONSE_CONTENT_TYPE */ static int var_response_content_type(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { return var_simple_generate(var, vartab, mptmp, msr->r->content_type); } /* RESPONSE_CONTENT_LENGTH */ static int var_response_content_length(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value = apr_psprintf(mptmp, "%" APR_OFF_T_FMT, msr->r->clength); return var_simple_generate(var, vartab, mptmp, value); } /* USERID */ static int var_userid_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value = msr->userid; return var_simple_generate(var, vartab, mptmp, value); } /* SESSIONID */ static int var_sessionid_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value = msr->sessionid; return var_simple_generate(var, vartab, mptmp, value); } /* WEBAPPID */ static int var_webappid_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, apr_table_t *vartab, apr_pool_t *mptmp) { const char *value = msr->txcfg->webappid; return var_simple_generate(var, vartab, mptmp, value); } /* ---------------------------------------------- */ /** * */ void msre_engine_variable_register(msre_engine *engine, const char *name, unsigned int type, unsigned int argc_min, unsigned int argc_max, fn_var_validate_t validate, fn_var_generate_t generate, unsigned int is_cacheable, unsigned int availability) { msre_var_metadata *metadata = (msre_var_metadata *)apr_pcalloc(engine->mp, sizeof(msre_var_metadata)); if (metadata == NULL) return; metadata->name = name; metadata->type = type; metadata->argc_min = argc_min; metadata->argc_max = argc_max; metadata->validate = validate; metadata->generate = generate; metadata->is_cacheable = is_cacheable; metadata->availability = availability; apr_table_setn(engine->variables, name, (void *)metadata); } /** * */ void msre_engine_register_default_variables(msre_engine *engine) { /* ARGS */ msre_engine_variable_register(engine, "ARGS", VAR_LIST, 0, 1, var_generic_list_validate, var_args_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* ARGS_COMBINED_SIZE */ msre_engine_variable_register(engine, "ARGS_COMBINED_SIZE", VAR_LIST, 0, 0, NULL, var_args_combined_size_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* ARGS_GET */ msre_engine_variable_register(engine, "ARGS_GET", VAR_LIST, 0, 1, var_generic_list_validate, var_args_get_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* ARGS_GET_NAMES */ msre_engine_variable_register(engine, "ARGS_GET_NAMES", VAR_LIST, 0, 1, var_generic_list_validate, var_args_get_names_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* ARGS_NAMES */ msre_engine_variable_register(engine, "ARGS_NAMES", VAR_LIST, 0, 1, var_generic_list_validate, var_args_names_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* ARGS_POST */ msre_engine_variable_register(engine, "ARGS_POST", VAR_LIST, 0, 1, var_generic_list_validate, var_args_post_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* ARGS_POST_NAMES */ msre_engine_variable_register(engine, "ARGS_POST_NAMES", VAR_LIST, 0, 1, var_generic_list_validate, var_args_post_names_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* AUTH_TYPE */ msre_engine_variable_register(engine, "AUTH_TYPE", VAR_SIMPLE, 0, 0, NULL, var_auth_type_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* ENV */ msre_engine_variable_register(engine, "ENV", VAR_LIST, 0, 1, var_env_validate, var_env_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* FILES */ msre_engine_variable_register(engine, "FILES", VAR_LIST, 0, 1, var_generic_list_validate, var_files_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* FILES_COMBINED_SIZE */ msre_engine_variable_register(engine, "FILES_COMBINED_SIZE", VAR_LIST, 0, 0, NULL, var_files_combined_size_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* FILES_NAMES */ msre_engine_variable_register(engine, "FILES_NAMES", VAR_LIST, 0, 0, NULL, var_files_names_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* FILES_SIZES */ msre_engine_variable_register(engine, "FILES_SIZES", VAR_LIST, 0, 1, var_generic_list_validate, var_files_sizes_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* FILES_TMPNAMES */ msre_engine_variable_register(engine, "FILES_TMPNAMES", VAR_LIST, 0, 1, var_generic_list_validate, var_files_tmpnames_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* FILES_TMP_CONTENT */ msre_engine_variable_register(engine, "FILES_TMP_CONTENT", VAR_LIST, 0, 1, var_generic_list_validate, var_files_tmp_contents_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* GEO */ msre_engine_variable_register(engine, "GEO", VAR_LIST, 0, 1, var_generic_list_validate, var_geo_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* GLOBAL */ msre_engine_variable_register(engine, "GLOBAL", VAR_LIST, 1, 1, var_generic_list_validate, var_global_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* HIGHEST_SEVERITY */ msre_engine_variable_register(engine, "HIGHEST_SEVERITY", VAR_SIMPLE, 0, 0, NULL, var_highest_severity_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* IP */ msre_engine_variable_register(engine, "IP", VAR_LIST, 1, 1, var_generic_list_validate, var_ip_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* MATCHED_VAR */ msre_engine_variable_register(engine, "MATCHED_VAR", VAR_SIMPLE, 0, 0, NULL, var_matched_var_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* MATCHED_VAR_NAME */ msre_engine_variable_register(engine, "MATCHED_VAR_NAME", VAR_SIMPLE, 0, 0, NULL, var_matched_var_name_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* MODSEC_BUILD */ msre_engine_variable_register(engine, "MODSEC_BUILD", VAR_SIMPLE, 0, 0, NULL, var_modsec_build_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* MULTIPART_FILENAME */ msre_engine_variable_register(engine, "MULTIPART_FILENAME", VAR_SIMPLE, 0, 0, NULL, var_multipart_filename_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* MULTIPART_NAME */ msre_engine_variable_register(engine, "MULTIPART_NAME", VAR_SIMPLE, 0, 0, NULL, var_multipart_name_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* MULTIPART_BOUNDARY_QUOTED */ msre_engine_variable_register(engine, "MULTIPART_BOUNDARY_QUOTED", VAR_SIMPLE, 0, 0, NULL, var_multipart_boundary_quoted_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_BOUNDARY_WHITESPACE */ msre_engine_variable_register(engine, "MULTIPART_BOUNDARY_WHITESPACE", VAR_SIMPLE, 0, 0, NULL, var_multipart_boundary_whitespace_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_DATA_AFTER */ msre_engine_variable_register(engine, "MULTIPART_DATA_AFTER", VAR_SIMPLE, 0, 0, NULL, var_multipart_data_after_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_DATA_BEFORE */ msre_engine_variable_register(engine, "MULTIPART_DATA_BEFORE", VAR_SIMPLE, 0, 0, NULL, var_multipart_data_before_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_HEADER_FOLDING */ msre_engine_variable_register(engine, "MULTIPART_HEADER_FOLDING", VAR_SIMPLE, 0, 0, NULL, var_multipart_header_folding_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_CRLF_LINE */ msre_engine_variable_register(engine, "MULTIPART_CRLF_LINE", VAR_SIMPLE, 0, 0, NULL, var_multipart_crlf_line_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_CRLF_LF_LINES */ msre_engine_variable_register(engine, "MULTIPART_CRLF_LF_LINES", VAR_SIMPLE, 0, 0, NULL, var_multipart_crlf_lf_lines_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_LF_LINE */ msre_engine_variable_register(engine, "MULTIPART_LF_LINE", VAR_SIMPLE, 0, 0, NULL, var_multipart_lf_line_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_MISSING_SEMICOLON */ msre_engine_variable_register(engine, "MULTIPART_MISSING_SEMICOLON", VAR_SIMPLE, 0, 0, NULL, var_multipart_missing_semicolon_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_INVALID_PART */ msre_engine_variable_register(engine, "MULTIPART_INVALID_PART", VAR_SIMPLE, 0, 0, NULL, var_multipart_invalid_part_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_INVALID_QUOTING */ msre_engine_variable_register(engine, "MULTIPART_INVALID_QUOTING", VAR_SIMPLE, 0, 0, NULL, var_multipart_invalid_quoting_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_INVALID_HEADER_FOLDING */ msre_engine_variable_register(engine, "MULTIPART_INVALID_HEADER_FOLDING", VAR_SIMPLE, 0, 0, NULL, var_multipart_invalid_header_folding_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_FILE_LIMIT_EXCEEDED */ msre_engine_variable_register(engine, "MULTIPART_FILE_LIMIT_EXCEEDED", VAR_SIMPLE, 0, 0, NULL, var_multipart_file_limit_exceeded_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_STRICT_ERROR */ msre_engine_variable_register(engine, "MULTIPART_STRICT_ERROR", VAR_SIMPLE, 0, 0, NULL, var_multipart_strict_error_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* MULTIPART_UNMATCHED_BOUNDARY */ msre_engine_variable_register(engine, "MULTIPART_UNMATCHED_BOUNDARY", VAR_SIMPLE, 0, 0, NULL, var_multipart_unmatched_boundary_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* PATH_INFO */ msre_engine_variable_register(engine, "PATH_INFO", VAR_SIMPLE, 0, 0, NULL, var_path_info_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* QUERY_STRING */ msre_engine_variable_register(engine, "QUERY_STRING", VAR_SIMPLE, 0, 0, NULL, var_query_string_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); #if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2 /* USERAGENT_IP */ msre_engine_variable_register(engine, "USERAGENT_IP", VAR_SIMPLE, 0, 0, NULL, var_useragent_ip_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); #endif /* REMOTE_ADDR */ msre_engine_variable_register(engine, "REMOTE_ADDR", VAR_SIMPLE, 0, 0, NULL, var_remote_addr_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REMOTE_HOST */ msre_engine_variable_register(engine, "REMOTE_HOST", VAR_SIMPLE, 0, 0, NULL, var_remote_host_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* REMOTE_PORT */ msre_engine_variable_register(engine, "REMOTE_PORT", VAR_SIMPLE, 0, 0, NULL, var_remote_port_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* REMOTE_USER */ msre_engine_variable_register(engine, "REMOTE_USER", VAR_SIMPLE, 0, 0, NULL, var_remote_user_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* RESOURCE */ msre_engine_variable_register(engine, "RESOURCE", VAR_LIST, 1, 1, var_generic_list_validate, var_resource_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* REQBODY_PROCESSOR */ msre_engine_variable_register(engine, "REQBODY_PROCESSOR", VAR_SIMPLE, 0, 0, NULL, var_reqbody_processor_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_HEADERS ); msre_engine_variable_register(engine, "SDBM_DELETE_ERROR", VAR_SIMPLE, 0, 0, NULL, var_sdbm_delete_error_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); /* REQBODY_PROCESSOR_ERROR - Deprecated */ msre_engine_variable_register(engine, "REQBODY_PROCESSOR_ERROR", VAR_SIMPLE, 0, 0, NULL, var_reqbody_processor_error_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); /* REQBODY_PROCESSOR_ERROR_MSG - Deprecated */ msre_engine_variable_register(engine, "REQBODY_PROCESSOR_ERROR_MSG", VAR_SIMPLE, 0, 0, NULL, var_reqbody_processor_error_msg_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); /* REQBODY_ERROR */ msre_engine_variable_register(engine, "REQBODY_ERROR", VAR_SIMPLE, 0, 0, NULL, var_reqbody_processor_error_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); /* REQBODY_ERROR_MSG */ msre_engine_variable_register(engine, "REQBODY_ERROR_MSG", VAR_SIMPLE, 0, 0, NULL, var_reqbody_processor_error_msg_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); /* REQUEST_BASENAME */ msre_engine_variable_register(engine, "REQUEST_BASENAME", VAR_SIMPLE, 0, 0, NULL, var_request_basename_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_HEADERS ); /* FULL_REQUEST */ msre_engine_variable_register(engine, "FULL_REQUEST", VAR_SIMPLE, 0, 0, NULL, var_full_request_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* FULL_REQUEST_LENGTH */ msre_engine_variable_register(engine, "FULL_REQUEST_LENGTH", VAR_SIMPLE, 0, 0, NULL, var_full_request_length_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* REQUEST_BODY */ msre_engine_variable_register(engine, "REQUEST_BODY", VAR_LIST, 0, 1, var_generic_list_validate, var_request_body_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* REQUEST_BODY_LENGTH */ msre_engine_variable_register(engine, "REQUEST_BODY_LENGTH", VAR_SIMPLE, 0, 0, NULL, var_request_body_length_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* MATCHED_VARS_NAMES */ msre_engine_variable_register(engine, "MATCHED_VARS_NAMES", VAR_LIST, 0, 1, var_generic_list_validate, var_matched_vars_names_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* MATCHED_VARS */ msre_engine_variable_register(engine, "MATCHED_VARS", VAR_LIST, 0, 1, var_generic_list_validate, var_matched_vars_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_COOKIES */ msre_engine_variable_register(engine, "REQUEST_COOKIES", VAR_LIST, 0, 1, var_generic_list_validate, var_request_cookies_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_COOKIES_NAMES */ msre_engine_variable_register(engine, "REQUEST_COOKIES_NAMES", VAR_LIST, 0, 1, var_generic_list_validate, var_request_cookies_names_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_FILENAME */ msre_engine_variable_register(engine, "REQUEST_FILENAME", VAR_SIMPLE, 0, 0, NULL, var_request_filename_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_HEADERS */ msre_engine_variable_register(engine, "REQUEST_HEADERS", VAR_LIST, 0, 1, var_generic_list_validate, var_request_headers_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_HEADERS_NAMES */ msre_engine_variable_register(engine, "REQUEST_HEADERS_NAMES", VAR_LIST, 0, 1, var_generic_list_validate, var_request_headers_names_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_LINE */ msre_engine_variable_register(engine, "REQUEST_LINE", VAR_SIMPLE, 0, 0, NULL, var_request_line_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_METHOD */ msre_engine_variable_register(engine, "REQUEST_METHOD", VAR_SIMPLE, 0, 0, NULL, var_request_method_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_PROTOCOL */ msre_engine_variable_register(engine, "REQUEST_PROTOCOL", VAR_SIMPLE, 0, 0, NULL, var_request_protocol_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* REQUEST_URI */ msre_engine_variable_register(engine, "REQUEST_URI", VAR_SIMPLE, 0, 0, NULL, var_request_uri_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_HEADERS ); /* REQUEST_URI_RAW */ msre_engine_variable_register(engine, "REQUEST_URI_RAW", VAR_SIMPLE, 0, 0, NULL, var_request_uri_raw_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* UNIQUE_ID */ msre_engine_variable_register(engine, "UNIQUE_ID", VAR_SIMPLE, 0, 0, NULL, var_uniqueid_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* STREAM_OUTPUT_BODY */ msre_engine_variable_register(engine, "STREAM_OUTPUT_BODY", VAR_SIMPLE, 0, 0, NULL, var_stream_output_generate, VAR_CACHE, PHASE_RESPONSE_BODY ); /* STREAM_INPUT_BODY */ msre_engine_variable_register(engine, "STREAM_INPUT_BODY", VAR_SIMPLE, 0, 0, NULL, var_stream_input_generate, VAR_CACHE, PHASE_FIRST ); /* RESPONSE_BODY */ msre_engine_variable_register(engine, "RESPONSE_BODY", VAR_SIMPLE, 0, 0, NULL, var_response_body_generate, VAR_CACHE, PHASE_RESPONSE_BODY ); /* RESPONSE_CONTENT_LENGTH */ msre_engine_variable_register(engine, "RESPONSE_CONTENT_LENGTH", VAR_SIMPLE, 0, 0, NULL, var_response_content_length, VAR_DONT_CACHE, /* temp copy */ PHASE_RESPONSE_HEADERS ); /* RESPONSE_CONTENT_TYPE */ msre_engine_variable_register(engine, "RESPONSE_CONTENT_TYPE", VAR_SIMPLE, 0, 0, NULL, var_response_content_type, VAR_CACHE, PHASE_RESPONSE_HEADERS ); /* RESPONSE_HEADERS */ msre_engine_variable_register(engine, "RESPONSE_HEADERS", VAR_LIST, 0, 1, var_generic_list_validate, var_response_headers_generate, VAR_CACHE, PHASE_RESPONSE_HEADERS ); /* RESPONSE_HEADERS_NAMES */ msre_engine_variable_register(engine, "RESPONSE_HEADERS_NAMES", VAR_LIST, 0, 1, var_generic_list_validate, var_response_headers_names_generate, VAR_CACHE, PHASE_RESPONSE_HEADERS ); /* RESPONSE_PROTOCOL */ msre_engine_variable_register(engine, "RESPONSE_PROTOCOL", VAR_SIMPLE, 0, 0, NULL, var_response_protocol_generate, VAR_CACHE, PHASE_RESPONSE_HEADERS ); /* RESPONSE_STATUS */ msre_engine_variable_register(engine, "RESPONSE_STATUS", VAR_SIMPLE, 0, 0, NULL, var_response_status_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_RESPONSE_HEADERS ); /* RULE */ msre_engine_variable_register(engine, "RULE", VAR_LIST, 1, 1, NULL, var_rule_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_RESPONSE_HEADERS ); /* SCRIPT_GID */ msre_engine_variable_register(engine, "SCRIPT_GID", VAR_SIMPLE, 0, 0, NULL, var_script_gid_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* SCRIPT_BASENAME */ msre_engine_variable_register(engine, "SCRIPT_BASENAME", VAR_SIMPLE, 0, 0, NULL, var_script_basename_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* SCRIPT_FILENAME */ msre_engine_variable_register(engine, "SCRIPT_FILENAME", VAR_SIMPLE, 0, 0, NULL, var_script_filename_generate, VAR_CACHE, PHASE_REQUEST_BODY ); /* SCRIPT_GROUPNAME */ msre_engine_variable_register(engine, "SCRIPT_GROUPNAME", VAR_SIMPLE, 0, 0, NULL, var_script_groupname_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* SCRIPT_MODE */ msre_engine_variable_register(engine, "SCRIPT_MODE", VAR_SIMPLE, 0, 0, NULL, var_script_mode_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* SCRIPT_UID */ msre_engine_variable_register(engine, "SCRIPT_UID", VAR_SIMPLE, 0, 0, NULL, var_script_uid_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* SCRIPT_USERNAME */ msre_engine_variable_register(engine, "SCRIPT_USERNAME", VAR_SIMPLE, 0, 0, NULL, var_script_username_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_BODY ); /* SERVER_ADDR */ msre_engine_variable_register(engine, "SERVER_ADDR", VAR_SIMPLE, 0, 0, NULL, var_server_addr_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* SERVER_NAME */ msre_engine_variable_register(engine, "SERVER_NAME", VAR_SIMPLE, 0, 0, NULL, var_server_name_generate, VAR_CACHE, PHASE_REQUEST_HEADERS ); /* SERVER_PORT */ msre_engine_variable_register(engine, "SERVER_PORT", VAR_SIMPLE, 0, 0, NULL, var_server_port_generate, VAR_DONT_CACHE, /* temp copy */ PHASE_REQUEST_HEADERS ); /* SESSION */ msre_engine_variable_register(engine, "SESSION", VAR_LIST, 1, 1, var_generic_list_validate, var_session_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* SESSIONID */ msre_engine_variable_register(engine, "SESSIONID", VAR_SIMPLE, 0, 0, NULL, var_sessionid_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_RESPONSE_HEADERS ); /* STATUS_LINE */ msre_engine_variable_register(engine, "STATUS_LINE", VAR_SIMPLE, 0, 0, NULL, var_status_line_generate, VAR_CACHE, PHASE_RESPONSE_HEADERS ); /* URLENCODED_ERROR */ msre_engine_variable_register(engine, "URLENCODED_ERROR", VAR_SIMPLE, 0, 0, NULL, var_urlencoded_error_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_HEADERS ); /* INBOUND_DATA_ERROR */ msre_engine_variable_register(engine, "INBOUND_DATA_ERROR", VAR_SIMPLE, 0, 0, NULL, var_inbound_error_generate, VAR_DONT_CACHE, /* flag */ PHASE_REQUEST_BODY ); /* OUTBOUND_DATA_ERROR */ msre_engine_variable_register(engine, "OUTBOUND_DATA_ERROR", VAR_SIMPLE, 0, 0, NULL, var_outbound_error_generate, VAR_DONT_CACHE, /* flag */ PHASE_RESPONSE_BODY ); /* USER */ msre_engine_variable_register(engine, "USER", VAR_LIST, 1, 1, var_generic_list_validate, var_user_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* USERID */ msre_engine_variable_register(engine, "USERID", VAR_SIMPLE, 0, 0, NULL, var_userid_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_RESPONSE_HEADERS ); /* PERF_RULES */ msre_engine_variable_register(engine, "PERF_RULES", VAR_LIST, 0, 1, var_generic_list_validate, var_perf_rules_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_ALL */ msre_engine_variable_register(engine, "PERF_ALL", VAR_SIMPLE, 0, 0, NULL, var_perf_all_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_COMBINED */ msre_engine_variable_register(engine, "PERF_COMBINED", VAR_SIMPLE, 0, 0, NULL, var_perf_combined_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_GC */ msre_engine_variable_register(engine, "PERF_GC", VAR_SIMPLE, 0, 0, NULL, var_perf_gc_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_LOGGING */ msre_engine_variable_register(engine, "PERF_LOGGING", VAR_SIMPLE, 0, 0, NULL, var_perf_logging_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_PHASE1 */ msre_engine_variable_register(engine, "PERF_PHASE1", VAR_SIMPLE, 0, 0, NULL, var_perf_phase1_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_PHASE2 */ msre_engine_variable_register(engine, "PERF_PHASE2", VAR_SIMPLE, 0, 0, NULL, var_perf_phase2_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_PHASE3 */ msre_engine_variable_register(engine, "PERF_PHASE3", VAR_SIMPLE, 0, 0, NULL, var_perf_phase3_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_PHASE4 */ msre_engine_variable_register(engine, "PERF_PHASE4", VAR_SIMPLE, 0, 0, NULL, var_perf_phase4_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_PHASE5 */ msre_engine_variable_register(engine, "PERF_PHASE5", VAR_SIMPLE, 0, 0, NULL, var_perf_phase5_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_SREAD */ msre_engine_variable_register(engine, "PERF_SREAD", VAR_SIMPLE, 0, 0, NULL, var_perf_sread_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* PERF_SWRITE */ msre_engine_variable_register(engine, "PERF_SWRITE", VAR_SIMPLE, 0, 0, NULL, var_perf_swrite_generate, VAR_DONT_CACHE, PHASE_REQUEST_HEADERS ); /* DURATION */ msre_engine_variable_register(engine, "DURATION", VAR_SIMPLE, 0, 0, NULL, var_duration_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME */ msre_engine_variable_register(engine, "TIME", VAR_SIMPLE, 0, 0, NULL, var_time_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME_DAY */ msre_engine_variable_register(engine, "TIME_DAY", VAR_SIMPLE, 0, 0, NULL, var_time_day_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME_EPOCH */ msre_engine_variable_register(engine, "TIME_EPOCH", VAR_SIMPLE, 0, 0, NULL, var_time_epoch_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME_HOUR */ msre_engine_variable_register(engine, "TIME_HOUR", VAR_SIMPLE, 0, 0, NULL, var_time_hour_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME_MIN */ msre_engine_variable_register(engine, "TIME_MIN", VAR_SIMPLE, 0, 0, NULL, var_time_min_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME_MON */ msre_engine_variable_register(engine, "TIME_MON", VAR_SIMPLE, 0, 0, NULL, var_time_mon_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME_SEC */ msre_engine_variable_register(engine, "TIME_SEC", VAR_SIMPLE, 0, 0, NULL, var_time_sec_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME_WDAY */ msre_engine_variable_register(engine, "TIME_WDAY", VAR_SIMPLE, 0, 0, NULL, var_time_wday_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TIME_YEAR */ msre_engine_variable_register(engine, "TIME_YEAR", VAR_SIMPLE, 0, 0, NULL, var_time_year_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* TX */ msre_engine_variable_register(engine, "TX", VAR_LIST, 1, 1, var_generic_list_validate, var_tx_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* WEBAPPID */ msre_engine_variable_register(engine, "WEBAPPID", VAR_SIMPLE, 0, 0, NULL, var_webappid_generate, VAR_DONT_CACHE, PHASE_RESPONSE_HEADERS ); /* WEBSERVER_ERROR_LOG */ msre_engine_variable_register(engine, "WEBSERVER_ERROR_LOG", VAR_LIST, 0, 0, NULL, var_webserver_error_log_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_HEADERS ); /* XML */ msre_engine_variable_register(engine, "XML", VAR_LIST, 0, 1, var_xml_validate, var_xml_generate, VAR_DONT_CACHE, /* dynamic */ PHASE_REQUEST_BODY ); }