%skeleton "lalr1.cc" /* -*- C++ -*- */ %require "3.0.2" %defines %define parser_class_name {seclang_parser} %define api.token.constructor %define api.value.type variant %define parse.assert %code requires { # include class Driver; #include "actions/action.h" #include "actions/transformations/transformation.h" #include "operators/operator.h" #include "rule.h" #include "utils/geo_lookup.h" #include "audit_log.h" #include "variables/duration.h" #include "variables/env.h" #include "variables/highest_severity.h" #include "variables/modsec_build.h" #include "variables/time_day.h" #include "variables/time_epoch.h" #include "variables/time.h" #include "variables/time_hour.h" #include "variables/time_min.h" #include "variables/time_mon.h" #include "variables/time_sec.h" #include "variables/time_wday.h" #include "variables/time_year.h" using ModSecurity::actions::Action; using ModSecurity::actions::transformations::Transformation; using ModSecurity::operators::Operator; using ModSecurity::Rule; using ModSecurity::Utils::GeoLookup; using ModSecurity::Variables::Duration; using ModSecurity::Variables::Env; using ModSecurity::Variables::HighestSeverity; using ModSecurity::Variables::ModsecBuild; using ModSecurity::Variables::Time; using ModSecurity::Variables::TimeDay; using ModSecurity::Variables::TimeEpoch; using ModSecurity::Variables::TimeHour; using ModSecurity::Variables::TimeMin; using ModSecurity::Variables::TimeMon; using ModSecurity::Variables::TimeSec; using ModSecurity::Variables::TimeWDay; using ModSecurity::Variables::TimeYear; using ModSecurity::Variables::Variable; } // The parsing context. %param { Driver& driver } %locations %initial-action { // Initialize the initial location. @$.begin.filename = @$.end.filename = &driver.file; }; %define parse.trace %define parse.error verbose %code { #include "parser/driver.h" } %define api.token.prefix {TOK_} %token END 0 "end of file" CONFIG_DIR_VAL "+" COMMA "*" QUOTATION_MARK ")" SPACE PIPE UNKNOWN FREE_TEXT ; %left ARGS CONFIG_VALUE_RELEVANT_ONLY CONFIG_VALUE_ON CONFIG_VALUE_OFF CONFIG_VALUE %token DIRECTIVE %token CONFIG_DIRECTIVE %token CONFIG_DIR_REQ_BODY_LIMIT %token CONFIG_DIR_RES_BODY_LIMIT %token CONFIG_DIR_REQ_BODY_LIMIT_ACTION %token CONFIG_DIR_RES_BODY_LIMIT_ACTION %token CONFIG_DIR_RULE_ENG %token CONFIG_DIR_REQ_BODY %token CONFIG_DIR_RES_BODY %token CONFIG_VALUE %token CONFIG_VALUE_ON %token CONFIG_VALUE_OFF %token CONFIG_VALUE_DETC %token CONFIG_VALUE_SERIAL %token CONFIG_VALUE_PARALLEL %token CONFIG_VALUE_RELEVANT_ONLY %token CONFIG_VALUE_PROCESS_PARTIAL %token CONFIG_VALUE_REJECT %token CONFIG_DIR_AUDIT_DIR %token CONFIG_DIR_AUDIT_DIR_MOD %token CONFIG_DIR_AUDIT_ENG %token CONFIG_DIR_AUDIT_FLE_MOD %token CONFIG_DIR_AUDIT_LOG %token CONFIG_DIR_AUDIT_LOG2 %token CONFIG_DIR_AUDIT_LOG_P %token CONFIG_DIR_AUDIT_STS %token CONFIG_DIR_AUDIT_TPE %token CONFIG_COMPONENT_SIG %token CONFIG_DIR_DEBUG_LOG %token CONFIG_DIR_DEBUG_LVL %token VARIABLE %token RUN_TIME_VAR_DUR %token RUN_TIME_VAR_ENV %token RUN_TIME_VAR_BLD %token RUN_TIME_VAR_HSV %token RUN_TIME_VAR_TIME %token RUN_TIME_VAR_TIME_DAY %token RUN_TIME_VAR_TIME_EPOCH %token RUN_TIME_VAR_TIME_HOUR %token RUN_TIME_VAR_TIME_MIN %token RUN_TIME_VAR_TIME_MON %token RUN_TIME_VAR_TIME_SEC %token RUN_TIME_VAR_TIME_WDAY %token RUN_TIME_VAR_TIME_YEAR %token CONFIG_DIR_GEO_DB %token OPERATOR %token ACTION %token ACTION_SEVERITY %token TRANSFORMATION %token CONFIG_VALUE_NUMBER %type *> actions %type *> variables %printer { yyoutput << $$; } <*>; %% %start secrule; secrule: | secrule line line: expression | SPACE expression | SPACE { } audit_log: /* SecAuditLogDirMode */ CONFIG_DIR_AUDIT_DIR_MOD { driver.audit_log->setStorageDirMode(strtol($1.c_str(), NULL, 8)); } /* SecAuditLogStorageDir */ | CONFIG_DIR_AUDIT_DIR { driver.audit_log->setStorageDir($1); } /* SecAuditEngine */ | CONFIG_DIR_AUDIT_ENG SPACE CONFIG_VALUE_RELEVANT_ONLY { driver.audit_log->setStatus(ModSecurity::AuditLog::RelevantOnlyAuditLogStatus); } | CONFIG_DIR_AUDIT_ENG SPACE CONFIG_VALUE_OFF { driver.audit_log->setStatus(ModSecurity::AuditLog::OffAuditLogStatus); } | CONFIG_DIR_AUDIT_ENG SPACE CONFIG_VALUE_ON { driver.audit_log->setStatus(ModSecurity::AuditLog::OnAuditLogStatus); } /* SecAuditLogFileMode */ | CONFIG_DIR_AUDIT_FLE_MOD { driver.audit_log->setFileMode(strtol($1.c_str(), NULL, 8)); } /* SecAuditLog2 */ | CONFIG_DIR_AUDIT_LOG2 { driver.audit_log->setFilePath2($1); } /* SecAuditLogParts */ | CONFIG_DIR_AUDIT_LOG_P { driver.audit_log->setParts($1); } /* SecAuditLog */ | CONFIG_DIR_AUDIT_LOG { driver.audit_log->setFilePath1($1); } /* SecAuditLogRelevantStatus */ | CONFIG_DIR_AUDIT_STS { std::string relevant_status($1); relevant_status.pop_back(); relevant_status.erase(0, 1); driver.audit_log->setRelevantStatus(relevant_status); } /* SecAuditLogType */ | CONFIG_DIR_AUDIT_TPE SPACE CONFIG_VALUE_SERIAL { driver.audit_log->setType(ModSecurity::AuditLog::SerialAuditLogType); } | CONFIG_DIR_AUDIT_TPE SPACE CONFIG_VALUE_PARALLEL { driver.audit_log->setType(ModSecurity::AuditLog::ParallelAuditLogType); } expression: audit_log | DIRECTIVE SPACE variables SPACE OPERATOR SPACE QUOTATION_MARK actions QUOTATION_MARK { Rule *rule = new Rule( /* op */ Operator::instantiate($5), /* variables */ $3, /* actions */ $8 ); driver.addSecRule(rule); } | CONFIG_DIR_RULE_ENG SPACE CONFIG_VALUE_OFF { driver.secRuleEngine = ModSecurity::Rules::DisabledRuleEngine; } | CONFIG_DIR_RULE_ENG SPACE CONFIG_VALUE_ON { driver.secRuleEngine = ModSecurity::Rules::EnabledRuleEngine; } | CONFIG_DIR_RULE_ENG SPACE CONFIG_VALUE_DETC { driver.secRuleEngine = ModSecurity::Rules::DetectionOnlyRuleEngine; } | CONFIG_DIR_REQ_BODY SPACE CONFIG_VALUE_ON { driver.sec_request_body_access = true; } | CONFIG_DIR_REQ_BODY SPACE CONFIG_VALUE_OFF { driver.sec_request_body_access = false; } | CONFIG_DIR_RES_BODY SPACE CONFIG_VALUE_ON { driver.sec_request_body_access = true; } | CONFIG_DIR_RES_BODY SPACE CONFIG_VALUE_OFF { driver.sec_request_body_access = false; } | CONFIG_COMPONENT_SIG { driver.components.push_back($1); } /* Debug log: start */ | CONFIG_DIR_DEBUG_LVL { driver.debug_level = atoi($1.c_str()); } | CONFIG_DIR_DEBUG_LOG { driver.debug_log_path = $1; } /* Debug log: end */ | CONFIG_DIR_GEO_DB { GeoLookup::getInstance().setDataBase($1); } /* Body limits */ | CONFIG_DIR_REQ_BODY_LIMIT { driver.requestBodyLimit = atoi($1.c_str()); } | CONFIG_DIR_RES_BODY_LIMIT { driver.responseBodyLimit = atoi($1.c_str()); } | CONFIG_DIR_REQ_BODY_LIMIT_ACTION SPACE CONFIG_VALUE_PROCESS_PARTIAL { driver.requestBodyLimitAction = ModSecurity::Rules::BodyLimitAction::ProcessPartialBodyLimitAction; } | CONFIG_DIR_REQ_BODY_LIMIT_ACTION SPACE CONFIG_VALUE_REJECT { driver.requestBodyLimitAction = ModSecurity::Rules::BodyLimitAction::RejectBodyLimitAction; } | CONFIG_DIR_RES_BODY_LIMIT_ACTION SPACE CONFIG_VALUE_PROCESS_PARTIAL { driver.responseBodyLimitAction = ModSecurity::Rules::BodyLimitAction::ProcessPartialBodyLimitAction; } | CONFIG_DIR_RES_BODY_LIMIT_ACTION SPACE CONFIG_VALUE_REJECT { driver.responseBodyLimitAction = ModSecurity::Rules::BodyLimitAction::RejectBodyLimitAction; } variables: variables PIPE VARIABLE { std::vector *v = $1; v->push_back(new Variable($3)); $$ = $1; } | VARIABLE { std::vector *variables = new std::vector; variables->push_back(new Variable($1)); $$ = variables; } | variables PIPE RUN_TIME_VAR_DUR { std::vector *v = $1; v->push_back(new Duration($3)); $$ = $1; } | RUN_TIME_VAR_DUR { std::vector *variables = new std::vector; variables->push_back(new Duration($1)); $$ = variables; } | variables PIPE RUN_TIME_VAR_ENV { std::vector *v = $1; v->push_back(new Env($3)); $$ = $1; } | RUN_TIME_VAR_ENV { std::vector *variables = new std::vector; variables->push_back(new Env($1)); $$ = variables; } | variables PIPE RUN_TIME_VAR_BLD { std::vector *v = $1; v->push_back(new ModsecBuild($3)); $$ = $1; } | RUN_TIME_VAR_BLD { std::vector *variables = new std::vector; variables->push_back(new ModsecBuild($1)); $$ = variables; } | variables PIPE RUN_TIME_VAR_HSV { std::vector *v = $1; v->push_back(new HighestSeverity($3)); $$ = $1; } | RUN_TIME_VAR_HSV { std::vector *variables = new std::vector; variables->push_back(new HighestSeverity($1)); $$ = variables; } | RUN_TIME_VAR_TIME { std::vector *variables = new std::vector; variables->push_back(new Time($1)); $$ = variables; } | RUN_TIME_VAR_TIME_DAY { std::vector *variables = new std::vector; variables->push_back(new TimeDay($1)); $$ = variables; } | RUN_TIME_VAR_TIME_EPOCH { std::vector *variables = new std::vector; variables->push_back(new ModSecurity::Variables::TimeEpoch($1)); $$ = variables; } | RUN_TIME_VAR_TIME_HOUR { std::vector *variables = new std::vector; variables->push_back(new ModSecurity::Variables::TimeHour($1)); $$ = variables; } | RUN_TIME_VAR_TIME_MIN { std::vector *variables = new std::vector; variables->push_back(new ModSecurity::Variables::TimeMin($1)); $$ = variables; } | RUN_TIME_VAR_TIME_MON { std::vector *variables = new std::vector; variables->push_back(new ModSecurity::Variables::TimeMon($1)); $$ = variables; } | RUN_TIME_VAR_TIME_SEC { std::vector *variables = new std::vector; variables->push_back(new ModSecurity::Variables::TimeSec($1)); $$ = variables; } | RUN_TIME_VAR_TIME_WDAY { std::vector *variables = new std::vector; variables->push_back(new ModSecurity::Variables::TimeWDay($1)); $$ = variables; } | RUN_TIME_VAR_TIME_YEAR { std::vector *variables = new std::vector; variables->push_back(new ModSecurity::Variables::TimeYear($1)); $$ = variables; } | variables PIPE RUN_TIME_VAR_TIME { std::vector *v = $1; v->push_back(new ModSecurity::Variables::Time($3)); $$ = $1; } | variables PIPE RUN_TIME_VAR_TIME_DAY { std::vector *v = $1; v->push_back(new ModSecurity::Variables::TimeDay($3)); $$ = $1; } | variables PIPE RUN_TIME_VAR_TIME_EPOCH { std::vector *v = $1; v->push_back(new ModSecurity::Variables::TimeEpoch($3)); $$ = $1; } | variables PIPE RUN_TIME_VAR_TIME_HOUR { std::vector *v = $1; v->push_back(new ModSecurity::Variables::TimeHour($3)); $$ = $1; } | variables PIPE RUN_TIME_VAR_TIME_MIN { std::vector *v = $1; v->push_back(new ModSecurity::Variables::TimeMin($3)); $$ = $1; } | variables PIPE RUN_TIME_VAR_TIME_MON { std::vector *v = $1; v->push_back(new ModSecurity::Variables::TimeMon($3)); $$ = $1; } | variables PIPE RUN_TIME_VAR_TIME_SEC { std::vector *v = $1; v->push_back(new ModSecurity::Variables::TimeSec($3)); $$ = $1; } | variables PIPE RUN_TIME_VAR_TIME_WDAY { std::vector *v = $1; v->push_back(new ModSecurity::Variables::TimeWDay($3)); $$ = $1; } | variables PIPE RUN_TIME_VAR_TIME_YEAR { std::vector *v = $1; v->push_back(new ModSecurity::Variables::TimeYear($3)); $$ = $1; } actions: actions COMMA SPACE ACTION { std::vector *a = $1; a->push_back(Action::instantiate($4)); $$ = $1; } | actions COMMA ACTION { std::vector *a = $1; a->push_back(Action::instantiate($3)); $$ = $1; } | SPACE ACTION { std::vector *actions = new std::vector; actions->push_back(Action::instantiate($2)); $$ = actions; } | ACTION { std::vector *actions = new std::vector; actions->push_back(Action::instantiate($1)); $$ = actions; } | actions COMMA SPACE TRANSFORMATION { std::vector *a = $1; a->push_back(Transformation::instantiate($4)); $$ = $1; } | actions COMMA TRANSFORMATION { std::vector *a = $1; a->push_back(Transformation::instantiate($3)); $$ = $1; } | SPACE TRANSFORMATION { std::vector *actions = new std::vector; actions->push_back(Transformation::instantiate($2)); $$ = actions; } | TRANSFORMATION { std::vector *actions = new std::vector; actions->push_back(Transformation::instantiate($1)); $$ = actions; } | actions COMMA SPACE ACTION_SEVERITY { std::vector *a = $1; a->push_back(Action::instantiate($4)); $$ = $1; } | actions COMMA ACTION_SEVERITY { std::vector *a = $1; a->push_back(Action::instantiate($3)); $$ = $1; } | SPACE ACTION_SEVERITY { std::vector *actions = new std::vector; actions->push_back(Action::instantiate($2)); $$ = actions; } | ACTION_SEVERITY { std::vector *actions = new std::vector; actions->push_back(Action::instantiate($1)); $$ = actions; } %% void yy::seclang_parser::error (const location_type& l, const std::string& m) { driver.parser_error (l, m); }