use waf_core::Severity;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Transform {
None,
Lowercase,
UrlDecode,
UrlDecodeUni,
HtmlEntityDecode,
CompressWhitespace,
RemoveWhitespace,
RemoveNulls,
NormalizePath,
Base64Decode,
Unsupported(String),
}
#[derive(Debug, Clone)]
pub enum Operator {
Rx(String),
Pm(Vec<String>),
PmFromFile(String),
Contains(String),
BeginsWith(String),
EndsWith(String),
Within(String),
StrEq(String),
Unsupported(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TargetKind {
Args,
ArgsNames,
ArgsGet,
ArgsPost,
RequestHeaders,
RequestHeadersNames,
RequestCookies,
RequestCookiesNames,
RequestUri,
RequestUriRaw,
RequestFilename,
QueryString,
RequestMethod,
RequestProtocol,
RequestLine,
RequestBody,
Unsupported(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Variable {
pub kind: TargetKind,
pub selector: Option<String>,
pub negated: bool,
pub count: bool,
pub regex_selector: bool,
}
#[derive(Debug, Clone)]
pub struct MatchUnit {
pub variables: Vec<Variable>,
pub operator: Operator,
pub negated: bool,
pub transforms: Vec<Transform>,
}
#[derive(Debug, Clone)]
pub struct CrsRule {
pub id: u64,
pub severity: Severity,
pub head: MatchUnit,
pub chain: Vec<MatchUnit>,
pub msg: Option<String>,
pub line_no: usize,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SkippedRule {
pub id: Option<u64>,
pub line_no: usize,
pub reason: String,
}
#[derive(Debug, Default)]
pub struct ParsedRuleset {
pub rules: Vec<CrsRule>,
pub skipped: Vec<SkippedRule>,
}
pub fn map_severity(word: &str) -> Option<Severity> {
match word.trim().to_ascii_uppercase().as_str() {
"EMERGENCY" | "ALERT" | "CRITICAL" | "0" | "1" | "2" => Some(Severity::Critical),
"ERROR" | "3" => Some(Severity::Error),
"WARNING" | "4" => Some(Severity::Warning),
"NOTICE" | "INFO" | "DEBUG" | "5" | "6" | "7" => Some(Severity::Notice),
_ => None,
}
}