diff --git a/apache2/apache2_config.c b/apache2/apache2_config.c index 1fa8669b..30ba91fe 100644 --- a/apache2/apache2_config.c +++ b/apache2/apache2_config.c @@ -912,11 +912,6 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type, } } - /* Optimisation */ - if ((rule->op_name != NULL)&&(strcasecmp(rule->op_name, "inspectFile") == 0)) { - dcfg->upload_validates_files = 1; - } - /* Create skip table if one does not already exist. */ if (dcfg->tmp_rule_placeholders == NULL) { dcfg->tmp_rule_placeholders = apr_table_make(cmd->pool, 10); @@ -2449,6 +2444,30 @@ static const char *cmd_upload_keep_files(cmd_parms *cmd, void *_dcfg, return NULL; } +static const char *cmd_upload_save_tmp_files(cmd_parms *cmd, void *_dcfg, + const char *p1) +{ + directory_config *dcfg = (directory_config *)_dcfg; + + if (dcfg == NULL) return NULL; + + if (strcasecmp(p1, "on") == 0) + { + dcfg->upload_validates_files = 1; + } + else if (strcasecmp(p1, "off") == 0) + { + dcfg->upload_validates_files = 0; + } + else + { + return apr_psprintf(cmd->pool, "ModSecurity: Invalid setting for SecTmpSaveUploadedFiles: %s", + p1); + } + + return NULL; +} + static const char *cmd_web_app_id(cmd_parms *cmd, void *_dcfg, const char *p1) { directory_config *dcfg = (directory_config *)_dcfg; @@ -3685,6 +3704,14 @@ const command_rec module_directives[] = { "On or Off" ), + AP_INIT_TAKE1 ( + "SecTmpSaveUploadedFiles", + cmd_upload_save_tmp_files, + NULL, + CMD_SCOPE_ANY, + "On or Off" + ), + AP_INIT_TAKE1 ( "SecWebAppId", cmd_web_app_id, diff --git a/apache2/re_variables.c b/apache2/re_variables.c index ebccf9eb..d728f5f4 100644 --- a/apache2/re_variables.c +++ b/apache2/re_variables.c @@ -1113,6 +1113,97 @@ static int var_resource_generate(modsec_rec *msr, msre_var *var, msre_rule *rule 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) { + static int buf_size = 1024; + char buf[buf_size]; + FILE *file; + size_t nread; + char *full_content = NULL; + size_t total_lenght = 0; + + file = fopen(parts[i]->tmp_file_name, "r"); + if (file == NULL) + { + continue; + } + + while ((nread = fread(buf, 1, buf_size-1, 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); + + msre_var *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, @@ -2854,6 +2945,17 @@ void msre_engine_register_default_variables(msre_engine *engine) { 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",