mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-09-29 19:24:29 +03:00
Adds support to SecRemoteRules and Include directives
This commit includes a refactoring on important pieces of the parser to allow it work in a stack fashion. Driver and Rules classes were simplified and the RulesProperties class was created.
This commit is contained in:
@@ -22,11 +22,12 @@ MAINTAINERCLEANFILES = \
|
||||
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
../headers/modsecurity/modsecurity.h \
|
||||
../headers/modsecurity/assay.h \
|
||||
../headers/modsecurity/rules.h \
|
||||
../headers/modsecurity/debug_log.h \
|
||||
../headers/modsecurity/intervention.h
|
||||
../headers/modsecurity/assay.h \
|
||||
../headers/modsecurity/debug_log.h \
|
||||
../headers/modsecurity/intervention.h \
|
||||
../headers/modsecurity/modsecurity.h \
|
||||
../headers/modsecurity/rules.h \
|
||||
../headers/modsecurity/rules_properties.h
|
||||
|
||||
|
||||
VARIABLES = \
|
||||
|
@@ -517,7 +517,9 @@ int Assay::processRequestBody() {
|
||||
|
||||
if (m_requestBodyType == WWWFormUrlEncoded) {
|
||||
std::string content = uri_decode(m_requestBody.str());
|
||||
content.erase(content.length()-1, 1);
|
||||
if (content.empty() == false) {
|
||||
content.pop_back();
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME:
|
||||
@@ -577,7 +579,7 @@ int Assay::processRequestBody() {
|
||||
store_variable("FULL_REQUEST", fullRequest);
|
||||
store_variable("FULL_REQUEST_LENGTH", std::to_string(fullRequest.size()));
|
||||
|
||||
if (m_requestBody.tellp() <= 0) {
|
||||
if (m_requestBody.tellp() > 0) {
|
||||
store_variable("REQUEST_BODY", m_requestBody.str());
|
||||
store_variable("REQUEST_BODY_LENGTH",
|
||||
std::to_string(m_requestBody.str().size()));
|
||||
|
@@ -64,14 +64,18 @@ int Driver::addSecRule(Rule *rule) {
|
||||
}
|
||||
}
|
||||
|
||||
this->rules[rule->phase].push_back(rule);
|
||||
|
||||
rules[rule->phase].push_back(rule);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int Driver::parse(const std::string &f, const std::string &ref) {
|
||||
this->ref = ref;
|
||||
if (ref.empty()) {
|
||||
this->ref = "<<reference missing or not informed>>";
|
||||
} else {
|
||||
this->ref = ref;
|
||||
}
|
||||
|
||||
buffer = f;
|
||||
scan_begin();
|
||||
yy::seclang_parser parser(*this);
|
||||
@@ -81,43 +85,48 @@ int Driver::parse(const std::string &f, const std::string &ref) {
|
||||
if (audit_log->init() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scan_end();
|
||||
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
|
||||
int Driver::parseFile(const std::string &f) {
|
||||
this->ref = f;
|
||||
file = f;
|
||||
scan_begin();
|
||||
yy::seclang_parser parser(*this);
|
||||
parser.set_debug_level(trace_parsing);
|
||||
int res = parser.parse();
|
||||
std::ifstream t(f);
|
||||
std::string str;
|
||||
|
||||
if (audit_log->init() == false) {
|
||||
if (t.is_open() == false) {
|
||||
parserError << "Failed to open the file: " << f << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
scan_end();
|
||||
return res == 0;
|
||||
t.seekg(0, std::ios::end);
|
||||
str.reserve(t.tellg());
|
||||
t.seekg(0, std::ios::beg);
|
||||
|
||||
str.assign((std::istreambuf_iterator<char>(t)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
return parse(str, f);
|
||||
}
|
||||
|
||||
|
||||
void Driver::error(const yy::location& l, const std::string& m) {
|
||||
error(l, m, "");
|
||||
}
|
||||
|
||||
|
||||
void Driver::error(const yy::location& l, const std::string& m,
|
||||
const std::string& c) {
|
||||
if (parserError.tellp() == 0) {
|
||||
parserError << "Parser error, ";
|
||||
parserError << "Configuration error, ";
|
||||
parserError << "File: " << ref << ". ";
|
||||
parserError << "Line: " << l.end.line << ". ";
|
||||
parserError << "Column: " << l.end.column << ". ";
|
||||
}
|
||||
parserError << c;
|
||||
}
|
||||
|
||||
|
||||
void Driver::parser_error(const yy::location& l, const std::string& m) {
|
||||
parserError << ". " << m << "." << std::endl;
|
||||
if (c.empty() == false) {
|
||||
parserError << c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "modsecurity/modsecurity.h"
|
||||
#include "src/rule.h"
|
||||
#include "modsecurity/rules.h"
|
||||
#include "modsecurity/rules_properties.h"
|
||||
#include "src/audit_log.h"
|
||||
|
||||
#include "parser/seclang-parser.hh"
|
||||
@@ -50,11 +51,7 @@ typedef struct Driver_t Driver;
|
||||
#endif
|
||||
|
||||
|
||||
class Driver : public Rules {
|
||||
/**
|
||||
* @todo Place driver and parser under the correct namespace.
|
||||
*
|
||||
*/
|
||||
class Driver : public RulesProperties {
|
||||
public:
|
||||
Driver();
|
||||
virtual ~Driver();
|
||||
@@ -63,30 +60,23 @@ class Driver : public Rules {
|
||||
|
||||
int result;
|
||||
|
||||
// Handling the scanner.
|
||||
void scan_begin();
|
||||
bool scan_begin();
|
||||
void scan_end();
|
||||
bool trace_scanning;
|
||||
|
||||
// Run the parser on file F.
|
||||
// Return 0 on success.
|
||||
int parseFile(const std::string& f);
|
||||
int parse(const std::string& f, const std::string &ref);
|
||||
|
||||
// The name of the file being parsed.
|
||||
// Used later to pass the file name to the location tracker.
|
||||
std::string file;
|
||||
|
||||
// Whether parser traces should be generated.
|
||||
bool trace_parsing;
|
||||
|
||||
|
||||
// Error handling.
|
||||
void error(const yy::location& l, const std::string& m);
|
||||
void parser_error(const yy::location& l, const std::string& m);
|
||||
void error(const yy::location& l, const std::string& m,
|
||||
const std::string& c);
|
||||
|
||||
yy::location loc;
|
||||
|
||||
std::string ref;
|
||||
std::string buffer;
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@
|
||||
%define parser_class_name {seclang_parser}
|
||||
%define api.token.constructor
|
||||
%define api.value.type variant
|
||||
//%define api.namespace {ModSecurity::yy}
|
||||
%define parse.assert
|
||||
%code requires
|
||||
{
|
||||
@@ -103,6 +104,8 @@ using ModSecurity::Variables::Variable;
|
||||
%token <std::string> CONFIG_VALUE_RELEVANT_ONLY
|
||||
%token <std::string> CONFIG_VALUE_PROCESS_PARTIAL
|
||||
%token <std::string> CONFIG_VALUE_REJECT
|
||||
%token <std::string> CONFIG_VALUE_ABORT
|
||||
%token <std::string> CONFIG_VALUE_WARN
|
||||
|
||||
%token <std::string> CONFIG_DIR_AUDIT_DIR
|
||||
%token <std::string> CONFIG_DIR_AUDIT_DIR_MOD
|
||||
@@ -135,6 +138,10 @@ using ModSecurity::Variables::Variable;
|
||||
%token <std::string> RUN_TIME_VAR_TIME_WDAY
|
||||
%token <std::string> RUN_TIME_VAR_TIME_YEAR
|
||||
|
||||
%token <std::string> CONFIG_INCLUDE
|
||||
%token <std::string> CONFIG_SEC_REMOTE_RULES
|
||||
%token <std::string> CONFIG_SEC_REMOTE_RULES_FAIL_ACTION
|
||||
|
||||
%token <std::string> CONFIG_DIR_GEO_DB
|
||||
|
||||
%token <std::string> OPERATOR
|
||||
@@ -316,6 +323,14 @@ expression:
|
||||
{
|
||||
driver.responseBodyLimitAction = ModSecurity::Rules::BodyLimitAction::RejectBodyLimitAction;
|
||||
}
|
||||
| CONFIG_SEC_REMOTE_RULES_FAIL_ACTION CONFIG_VALUE_ABORT
|
||||
{
|
||||
driver.remoteRulesActionOnFailed = Rules::OnFailedRemoteRulesAction::AbortOnFailedRemoteRulesAction;
|
||||
}
|
||||
| CONFIG_SEC_REMOTE_RULES_FAIL_ACTION CONFIG_VALUE_WARN
|
||||
{
|
||||
driver.remoteRulesActionOnFailed = Rules::OnFailedRemoteRulesAction::WarnOnFailedRemoteRulesAction;
|
||||
}
|
||||
|
||||
variables:
|
||||
variables PIPE VARIABLE
|
||||
@@ -572,5 +587,5 @@ void
|
||||
yy::seclang_parser::error (const location_type& l,
|
||||
const std::string& m)
|
||||
{
|
||||
driver.parser_error (l, m);
|
||||
driver.error (l, m);
|
||||
}
|
||||
|
@@ -1,12 +1,16 @@
|
||||
%{ /* -*- C++ -*- */
|
||||
# include <cerrno>
|
||||
# include <climits>
|
||||
# include <cstdlib>
|
||||
# include <string>
|
||||
# include "parser/driver.h"
|
||||
# include "seclang-parser.hh"
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include "parser/driver.h"
|
||||
#include "seclang-parser.hh"
|
||||
#include "utils/https_client.h"
|
||||
#include "utils.h"
|
||||
|
||||
using ModSecurity::Parser::Driver;
|
||||
using ModSecurity::Utils::HttpsClient;
|
||||
using ModSecurity::split;
|
||||
|
||||
// Work around an incompatibility in flex (at least versions
|
||||
// 2.5.31 through 2.5.33): it generates code that does
|
||||
@@ -16,9 +20,9 @@ using ModSecurity::Parser::Driver;
|
||||
# define yywrap() 1
|
||||
|
||||
// The location of the current token.
|
||||
static yy::location loc;
|
||||
%}
|
||||
%option noyywrap nounput batch debug noinput
|
||||
|
||||
ACTION (?i:accuracy|allow|append|auditlog|block|capture|chain|ctl|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|logdata|maturity|msg|multiMatch|noauditlog|nolog|pass|pause|phase:[0-9]+|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|rev|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|setvar|skip|skipAfter|status:[0-9]+|tag|ver|xmlns)
|
||||
ACTION_SEVERITY (?i:severity:[0-9]+|severity:'[0-9]+'|severity:(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)|severity:'(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)')
|
||||
DIRECTIVE SecRule
|
||||
@@ -53,7 +57,11 @@ CONFIG_DIR_DEBUG_LVL SecDebugLogLevel
|
||||
|
||||
CONFIG_COMPONENT_SIG (?i:SecComponentSignature)
|
||||
|
||||
CONFIG_INCLUDE Include
|
||||
CONFIG_INCLUDE (?i:Include)
|
||||
CONFIG_SEC_REMOTE_RULES (?i:SecRemoteRules)
|
||||
CONFIG_SEC_REMOTE_RULES_FAIL_ACTION (?i:SecRemoteRulesFailAction)
|
||||
|
||||
|
||||
DICT_ELEMENT [A-Za-z_]+
|
||||
|
||||
|
||||
@@ -92,8 +100,10 @@ CONFIG_VALUE_RELEVANT_ONLY RelevantOnly
|
||||
CONFIG_VALUE_PROCESS_PARTIAL (?i:ProcessPartial)
|
||||
CONFIG_VALUE_REJECT (?i:Reject)
|
||||
|
||||
CONFIG_VALUE_ABORT (?i:Abort)
|
||||
CONFIG_VALUE_WARN (?i:Warn)
|
||||
|
||||
CONFIG_VALUE_PATH [A-Za-z_/\.]+
|
||||
CONFIG_VALUE_PATH [0-9A-Za-z_/\.\-]+
|
||||
AUDIT_PARTS [ABCDEFHJKZ]+
|
||||
CONFIG_VALUE_NUMBER [0-9]+
|
||||
|
||||
@@ -102,112 +112,155 @@ FREE_TEXT_NEW_LINE [^\"|\n]+
|
||||
|
||||
%{
|
||||
// Code run each time a pattern is matched.
|
||||
# define YY_USER_ACTION loc.columns (yyleng);
|
||||
# define YY_USER_ACTION driver.loc.columns (yyleng);
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
%{
|
||||
// Code run each time yylex is called.
|
||||
loc.step();
|
||||
driver.loc.step();
|
||||
%}
|
||||
|
||||
{DIRECTIVE} { return yy::seclang_parser::make_DIRECTIVE(yytext, loc); }
|
||||
{TRANSFORMATION} { return yy::seclang_parser::make_TRANSFORMATION(yytext, loc); }
|
||||
{CONFIG_DIR_RULE_ENG} { return yy::seclang_parser::make_CONFIG_DIR_RULE_ENG(yytext, loc); }
|
||||
{CONFIG_DIR_RES_BODY} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY(yytext, loc); }
|
||||
{CONFIG_DIR_REQ_BODY} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY(yytext, loc); }
|
||||
{DIRECTIVE} { return yy::seclang_parser::make_DIRECTIVE(yytext, driver.loc); }
|
||||
{TRANSFORMATION} { return yy::seclang_parser::make_TRANSFORMATION(yytext, driver.loc); }
|
||||
{CONFIG_DIR_RULE_ENG} { return yy::seclang_parser::make_CONFIG_DIR_RULE_ENG(yytext, driver.loc); }
|
||||
{CONFIG_DIR_RES_BODY} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY(yytext, driver.loc); }
|
||||
{CONFIG_DIR_REQ_BODY} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY(yytext, driver.loc); }
|
||||
|
||||
%{ /* Audit log entries */ %}
|
||||
{CONFIG_DIR_AUDIT_DIR}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_DIR(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_AUDIT_DIR_MOD}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_DIR_MOD(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_AUDIT_ENG} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_ENG(yytext, loc); }
|
||||
{CONFIG_DIR_AUDIT_FLE_MOD}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_FLE_MOD(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_AUDIT_LOG2}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG2(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_AUDIT_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_AUDIT_LOG_P}[ ]{AUDIT_PARTS} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG_P(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_AUDIT_STS}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_STS(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_AUDIT_TPE} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_TPE(yytext, loc); }
|
||||
{CONFIG_DIR_AUDIT_DIR}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_DIR(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_AUDIT_DIR_MOD}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_DIR_MOD(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_AUDIT_ENG} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_ENG(yytext, driver.loc); }
|
||||
{CONFIG_DIR_AUDIT_FLE_MOD}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_FLE_MOD(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_AUDIT_LOG2}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG2(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_AUDIT_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_AUDIT_LOG_P}[ ]{AUDIT_PARTS} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG_P(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_AUDIT_STS}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_STS(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_AUDIT_TPE} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_TPE(yytext, driver.loc); }
|
||||
|
||||
%{ /* Debug log entries */ %}
|
||||
{CONFIG_DIR_DEBUG_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LOG(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_DEBUG_LVL}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LVL(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_DEBUG_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LOG(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_DEBUG_LVL}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LVL(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
|
||||
%{ /* Variables */ %}
|
||||
{VARIABLE}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_VARIABLE(yytext, loc); }
|
||||
{RUN_TIME_VAR_DUR} { return yy::seclang_parser::make_RUN_TIME_VAR_DUR(yytext, loc); }
|
||||
{RUN_TIME_VAR_ENV}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_RUN_TIME_VAR_ENV(yytext, loc); }
|
||||
{RUN_TIME_VAR_BLD} { return yy::seclang_parser::make_RUN_TIME_VAR_BLD(yytext, loc); }
|
||||
{RUN_TIME_VAR_HSV} { return yy::seclang_parser::make_RUN_TIME_VAR_HSV(yytext, loc); }
|
||||
{VARIABLE}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_VARIABLE(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_DUR} { return yy::seclang_parser::make_RUN_TIME_VAR_DUR(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_ENV}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_RUN_TIME_VAR_ENV(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_BLD} { return yy::seclang_parser::make_RUN_TIME_VAR_BLD(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_HSV} { return yy::seclang_parser::make_RUN_TIME_VAR_HSV(yytext, driver.loc); }
|
||||
|
||||
%{ /* Variables: TIME */ %}
|
||||
{RUN_TIME_VAR_TIME} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME_DAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_DAY(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME_EPOCH} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_EPOCH(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME_HOUR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_HOUR(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME_MIN} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MIN(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME_MON} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MON(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME_SEC} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_SEC(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME_WDAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_WDAY(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME_YEAR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_YEAR(yytext, loc); }
|
||||
{RUN_TIME_VAR_TIME} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_TIME_DAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_DAY(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_TIME_EPOCH} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_EPOCH(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_TIME_HOUR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_HOUR(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_TIME_MIN} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MIN(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_TIME_MON} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MON(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_TIME_SEC} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_SEC(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_TIME_WDAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_WDAY(yytext, driver.loc); }
|
||||
{RUN_TIME_VAR_TIME_YEAR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_YEAR(yytext, driver.loc); }
|
||||
|
||||
%{ /* Geo DB loopkup */ %}
|
||||
{CONFIG_DIR_GEO_DB}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONFIG_DIR_GEO_DB(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_GEO_DB}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONFIG_DIR_GEO_DB(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
|
||||
%{ /* Request body limit */ %}
|
||||
{CONFIG_DIR_REQ_BODY_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_REQ_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT_ACTION(yytext, loc); }
|
||||
{CONFIG_DIR_REQ_BODY_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_REQ_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT_ACTION(yytext, driver.loc); }
|
||||
%{ /* Reponse body limit */ %}
|
||||
{CONFIG_DIR_RES_BODY_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT(strchr(yytext, ' ') + 1, loc); }
|
||||
{CONFIG_DIR_RES_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT_ACTION(yytext, loc); }
|
||||
{CONFIG_DIR_RES_BODY_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT(strchr(yytext, ' ') + 1, driver.loc); }
|
||||
{CONFIG_DIR_RES_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT_ACTION(yytext, driver.loc); }
|
||||
|
||||
{CONFIG_COMPONENT_SIG}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_COMPONENT_SIG(strchr(yytext, ' ') + 2, loc); }
|
||||
{CONFIG_COMPONENT_SIG}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_COMPONENT_SIG(strchr(yytext, ' ') + 2, driver.loc); }
|
||||
|
||||
{CONFIG_VALUE_ON} { return yy::seclang_parser::make_CONFIG_VALUE_ON(yytext, loc); }
|
||||
{CONFIG_VALUE_OFF} { return yy::seclang_parser::make_CONFIG_VALUE_OFF(yytext, loc); }
|
||||
{CONFIG_VALUE_SERIAL} { return yy::seclang_parser::make_CONFIG_VALUE_SERIAL(yytext, loc); }
|
||||
{CONFIG_VALUE_PARALLEL} { return yy::seclang_parser::make_CONFIG_VALUE_PARALLEL(yytext, loc); }
|
||||
{CONFIG_VALUE_DETC} { return yy::seclang_parser::make_CONFIG_VALUE_DETC(yytext, loc); }
|
||||
{CONFIG_VALUE_RELEVANT_ONLY} { return yy::seclang_parser::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, loc); }
|
||||
{CONFIG_VALUE_PROCESS_PARTIAL} { return yy::seclang_parser::make_CONFIG_VALUE_PROCESS_PARTIAL(yytext, loc); }
|
||||
{CONFIG_VALUE_REJECT} { return yy::seclang_parser::make_CONFIG_VALUE_REJECT(yytext, loc); }
|
||||
{CONFIG_VALUE_WARN} { return yy::seclang_parser::make_CONFIG_VALUE_WARN(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_ABORT} { return yy::seclang_parser::make_CONFIG_VALUE_ABORT(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_ON} { return yy::seclang_parser::make_CONFIG_VALUE_ON(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_OFF} { return yy::seclang_parser::make_CONFIG_VALUE_OFF(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_SERIAL} { return yy::seclang_parser::make_CONFIG_VALUE_SERIAL(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_PARALLEL} { return yy::seclang_parser::make_CONFIG_VALUE_PARALLEL(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_DETC} { return yy::seclang_parser::make_CONFIG_VALUE_DETC(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_RELEVANT_ONLY} { return yy::seclang_parser::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_PROCESS_PARTIAL} { return yy::seclang_parser::make_CONFIG_VALUE_PROCESS_PARTIAL(yytext, driver.loc); }
|
||||
{CONFIG_VALUE_REJECT} { return yy::seclang_parser::make_CONFIG_VALUE_REJECT(yytext, driver.loc); }
|
||||
|
||||
["]{OPERATOR}[ ]{FREE_TEXT}["] { return yy::seclang_parser::make_OPERATOR(yytext, driver.loc); }
|
||||
["]{OPERATORNOARG}["] { return yy::seclang_parser::make_OPERATOR(yytext, driver.loc); }
|
||||
{ACTION} { return yy::seclang_parser::make_ACTION(yytext, driver.loc); }
|
||||
{ACTION_SEVERITY} { return yy::seclang_parser::make_ACTION_SEVERITY(yytext, driver.loc); }
|
||||
["] { return yy::seclang_parser::make_QUOTATION_MARK(driver.loc); }
|
||||
[,] { return yy::seclang_parser::make_COMMA(driver.loc); }
|
||||
[|] { return yy::seclang_parser::make_PIPE(driver.loc); }
|
||||
{VARIABLENOCOLON} { return yy::seclang_parser::make_VARIABLE(yytext, driver.loc); }
|
||||
[ \t]+ { return yy::seclang_parser::make_SPACE(driver.loc); }
|
||||
[\n]+ { driver.loc.lines(yyleng); driver.loc.step(); }
|
||||
. { driver.error (driver.loc, "invalid character", yytext); }
|
||||
<<EOF>> {
|
||||
if (yyin) {
|
||||
fclose(yyin);
|
||||
}
|
||||
|
||||
yypop_buffer_state();
|
||||
if (!YY_CURRENT_BUFFER)
|
||||
{
|
||||
return yy::seclang_parser::make_END(driver.loc);
|
||||
}
|
||||
}
|
||||
|
||||
%{ /* Include external configurations */ %}
|
||||
{CONFIG_INCLUDE}[ ]{CONFIG_VALUE_PATH} {
|
||||
const char *file = strchr(yytext, ' ') + 1;
|
||||
yyin = fopen(file, "r" );
|
||||
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
||||
}
|
||||
|
||||
{CONFIG_SEC_REMOTE_RULES}[ ][^ ]+[ ][^\n\r ]+ {
|
||||
HttpsClient c;
|
||||
std::string key;
|
||||
std::string url;
|
||||
|
||||
std::vector<std::string> conf = split(yytext, ' ');
|
||||
key = conf[1];
|
||||
url = conf[2];
|
||||
|
||||
YY_BUFFER_STATE temp = YY_CURRENT_BUFFER;
|
||||
yypush_buffer_state(temp);
|
||||
|
||||
bool ret = c.download(url);
|
||||
|
||||
if (ret == false) {
|
||||
/**
|
||||
* TODO: Implement the fail action.
|
||||
*
|
||||
*/
|
||||
if (driver.remoteRulesActionOnFailed == Rules::OnFailedRemoteRulesAction::WarnOnFailedRemoteRulesAction) {
|
||||
}
|
||||
if (driver.remoteRulesActionOnFailed == Rules::OnFailedRemoteRulesAction::AbortOnFailedRemoteRulesAction) {
|
||||
}
|
||||
}
|
||||
|
||||
yy_scan_string(c.content.c_str());
|
||||
}
|
||||
|
||||
{CONFIG_SEC_REMOTE_RULES_FAIL_ACTION} { return yy::seclang_parser::make_CONFIG_SEC_REMOTE_RULES_FAIL_ACTION(yytext, driver.loc); }
|
||||
|
||||
["]{OPERATOR}[ ]{FREE_TEXT}["] { return yy::seclang_parser::make_OPERATOR(yytext, loc); }
|
||||
["]{OPERATORNOARG}["] { return yy::seclang_parser::make_OPERATOR(yytext, loc); }
|
||||
{ACTION} { return yy::seclang_parser::make_ACTION(yytext, loc); }
|
||||
{ACTION_SEVERITY} { return yy::seclang_parser::make_ACTION_SEVERITY(yytext, loc); }
|
||||
["] { return yy::seclang_parser::make_QUOTATION_MARK(loc); }
|
||||
[,] { return yy::seclang_parser::make_COMMA(loc); }
|
||||
[|] { return yy::seclang_parser::make_PIPE(loc); }
|
||||
{VARIABLENOCOLON} { return yy::seclang_parser::make_VARIABLE(yytext, loc); }
|
||||
[ \t]+ { return yy::seclang_parser::make_SPACE(loc); }
|
||||
[\n]+ { loc.lines(yyleng); loc.step(); }
|
||||
. { driver.error (loc, "invalid character", yytext); }
|
||||
<<EOF>> { return yy::seclang_parser::make_END(loc); }
|
||||
|
||||
%%
|
||||
|
||||
namespace ModSecurity {
|
||||
|
||||
void Driver::scan_begin () {
|
||||
bool Driver::scan_begin () {
|
||||
yy_flex_debug = trace_scanning;
|
||||
|
||||
if (buffer.empty() == false) {
|
||||
yy_scan_string(buffer.c_str());
|
||||
} else if (file.empty() == false) {
|
||||
if (!(yyin = fopen (file.c_str (), "r"))) {
|
||||
// FIXME: we should return a decent error.
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Driver::scan_end () {
|
||||
if (buffer.empty() == false) {
|
||||
yy_scan_string(buffer.c_str());
|
||||
} else if (file.empty() == false) {
|
||||
fclose(yyin);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
65
src/rules.cc
65
src/rules.cc
@@ -97,11 +97,11 @@ Rules::~Rules() {
|
||||
* @retval false Problem loading the rules.
|
||||
*
|
||||
*/
|
||||
bool Rules::loadFromUri(char *uri) {
|
||||
bool Rules::loadFromUri(const char *uri) {
|
||||
Driver *driver = new Driver();
|
||||
|
||||
if (driver->parseFile(uri) == false) {
|
||||
parserError << driver->parserError.rdbuf();
|
||||
parserError << driver->parserError.str();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,19 @@ bool Rules::loadFromUri(char *uri) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Rules::load(const char *file, const std::string &ref) {
|
||||
Driver *driver = new Driver();
|
||||
|
||||
if (driver->parse(file, ref) == false) {
|
||||
parserError << driver->parserError.str();
|
||||
return false;
|
||||
}
|
||||
this->merge(driver);
|
||||
delete driver;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Rules::loadRemote(char *key, char *uri) {
|
||||
HttpsClient client;
|
||||
@@ -124,22 +137,8 @@ bool Rules::loadRemote(char *key, char *uri) {
|
||||
}
|
||||
|
||||
|
||||
bool Rules::load(const char *plain_rules) {
|
||||
return this->load(plain_rules, "");
|
||||
}
|
||||
|
||||
|
||||
bool Rules::load(const char *plain_rules, const std::string &ref) {
|
||||
Driver *driver = new Driver();
|
||||
|
||||
if (driver->parse(plain_rules, ref) == false) {
|
||||
parserError << driver->parserError.str();
|
||||
return false;
|
||||
}
|
||||
this->merge(driver);
|
||||
delete driver;
|
||||
|
||||
return true;
|
||||
bool Rules::load(const char *plainRules) {
|
||||
return this->load(plainRules, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -188,23 +187,20 @@ int Rules::merge(Driver *from) {
|
||||
this->requestBodyLimitAction = from->requestBodyLimitAction;
|
||||
this->responseBodyLimitAction = from->responseBodyLimitAction;
|
||||
|
||||
if (m_custom_debug_log) {
|
||||
this->debug_log = m_custom_debug_log->new_instance();
|
||||
if (customDebugLog) {
|
||||
this->debugLog = customDebugLog->new_instance();
|
||||
} else {
|
||||
this->debug_log = new DebugLog();
|
||||
this->debugLog = new DebugLog();
|
||||
}
|
||||
|
||||
this->audit_log = from->audit_log;
|
||||
|
||||
this->debug_log->setDebugLevel(this->debug_level);
|
||||
this->debug_log->setOutputFile(this->debug_log_path);
|
||||
this->debugLog->setDebugLevel(this->debug_level);
|
||||
this->debugLog->setOutputFile(this->debug_log_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Rules::debug(int level, std::string message) {
|
||||
this->debug_log->write_log(level, message);
|
||||
}
|
||||
|
||||
int Rules::merge(Rules *from) {
|
||||
for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
|
||||
@@ -226,21 +222,28 @@ int Rules::merge(Rules *from) {
|
||||
this->requestBodyLimitAction = from->requestBodyLimitAction;
|
||||
this->responseBodyLimitAction = from->responseBodyLimitAction;
|
||||
|
||||
if (m_custom_debug_log) {
|
||||
this->debug_log = m_custom_debug_log->new_instance();
|
||||
if (customDebugLog) {
|
||||
this->debugLog = customDebugLog->new_instance();
|
||||
} else {
|
||||
this->debug_log = new DebugLog();
|
||||
this->debugLog = new DebugLog();
|
||||
}
|
||||
|
||||
this->audit_log = from->audit_log;
|
||||
|
||||
this->debug_log->setDebugLevel(this->debug_level);
|
||||
this->debug_log->setOutputFile(this->debug_log_path);
|
||||
this->debugLog->setDebugLevel(this->debug_level);
|
||||
this->debugLog->setOutputFile(this->debug_log_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Rules::debug(int level, std::string message) {
|
||||
if (debugLog != NULL) {
|
||||
debugLog->write_log(level, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Rules::dump() {
|
||||
std::cout << "Rules: " << std::endl;
|
||||
for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
|
||||
|
Reference in New Issue
Block a user