diff --git a/src/actions/phase.cc b/src/actions/phase.cc index 7c3f4858..da0605fc 100644 --- a/src/actions/phase.cc +++ b/src/actions/phase.cc @@ -20,6 +20,7 @@ #include "modsecurity/assay.h" #include "src/rule.h" +#include "src/utils.h" #include "modsecurity/modsecurity.h" namespace ModSecurity { @@ -30,7 +31,25 @@ Phase::Phase(std::string action) this->action_kind = ConfigurationKind; std::string a = action; a.erase(0, 6); - this->phase = std::stoi(a); + if (a.at(0) == '\'') { + a.erase(0, 1); + a.pop_back(); + } + + try { + this->phase = std::stoi(a); + } catch (...) { + this->phase = 0; + if (tolower(a) == "request") { + this->phase = this->phase + ModSecurity::Phases::RequestHeadersPhase; + } + if (tolower(a) == "response") { + this->phase = this->phase + ModSecurity::Phases::ResponseBodyPhase; + } + if (tolower(a) == "logging") { + this->phase = this->phase + ModSecurity::Phases::LoggingPhase; + } + } if (this->phase == 0) { /* Phase 0 is something new, we want to use as ConnectionPhase */ diff --git a/src/parser/driver.cc b/src/parser/driver.cc index ce59ce73..d85a2fc6 100644 --- a/src/parser/driver.cc +++ b/src/parser/driver.cc @@ -42,8 +42,9 @@ Driver::~Driver() { int Driver::addSecRule(Rule *rule) { if (rule->phase >= ModSecurity::Phases::NUMBER_OF_PHASES) { - /** TODO: return an error message */ - return -1; + parserError << "Unknown phase: " << std::to_string(rule->phase); + parserError << std::endl; + return false; } if (lastRule && lastRule->chained && lastRule->chainedRule == NULL) { diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 35801d13..ec0994ee 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -324,6 +324,7 @@ expression: /* variables */ $3, /* actions */ $8 ); + if (driver.addSecRule(rule) == false) { YYERROR; } diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index 7b960dcd..d8189c5f 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -23,7 +23,8 @@ using ModSecurity::split; %} %option noyywrap nounput batch debug noinput -ACTION (?i:accuracy|allow|append|block|capture|chain|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|maturity|multiMatch|noauditlog|nolog|pass|pause|phase:[0-9]+|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|skip|skipAfter|status:[0-9]+|ver|xmlns) +ACTION (?i:accuracy|allow|append|block|capture|chain|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|maturity|multiMatch|noauditlog|nolog|pass|pause|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|skip|skipAfter|status:[0-9]+|ver|xmlns) +ACTION_PHASE ((?i:phase:(?i:REQUEST|RESPONSE|LOGGING|[0-9]+))|(?i:phase:'(?i:REQUEST|RESPONSE|LOGGING|[0-9]+)')) ACTION_AUDIT_LOG (?i:auditlog) ACTION_SEVERITY (?i:severity) ACTION_SEVERITY_VALUE (?i:(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)|[0-9]+) @@ -248,6 +249,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile) } {ACTION} { return yy::seclang_parser::make_ACTION(yytext, *driver.loc.back()); } +{ACTION_PHASE} { return yy::seclang_parser::make_ACTION(yytext, *driver.loc.back()); } {ACTION_AUDIT_LOG} { return yy::seclang_parser::make_ACTION_AUDIT_LOG(yytext, *driver.loc.back()); } {ACTION_SEVERITY}:{ACTION_SEVERITY_VALUE} { return yy::seclang_parser::make_ACTION_SEVERITY(yytext + 9, *driver.loc.back()); } diff --git a/test/test-cases/regression/config-calling_phases_by_name.json b/test/test-cases/regression/config-calling_phases_by_name.json new file mode 100644 index 00000000..052392c0 --- /dev/null +++ b/test/test-cases/regression/config-calling_phases_by_name.json @@ -0,0 +1,89 @@ +[ + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: MATCHED_VAR (1/2)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*" + }, + "uri":"/?key=value&key=other_value", + "protocol":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "debug_log":"Target value: \"other_value\" \\(Variable: MATCHED_VAR\\)" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule ARGS:key \"@contains other_value\" \"id:1,phase:request,chain\"", + "SecRule MATCHED_VAR \"@eq asdf\" \"phase:request,pass\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: MATCHED_VAR (2/2)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*" + }, + "uri":"/?key=value&key=other_value", + "protocol":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "debug_log":"Target value: \"\" \\(Variable: MATCHED_VAR\\)" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule ARGS:key \"@contains other_value\" \"chain,phase:response,id:28\"", + "SecRule MATCHED_VAR \"@eq Aasdf\" \"pass\"", + "SecRule MATCHED_VAR \"@contains other_value\" \"id:29,phase:response,pass\"", + "SecRule MATCHED_VAR \"@contains other_value\" \"id:30,phase:response,pass\"" + ] + } +] +