field in JSON) is the target of the attack. If target is set to dest_ip
then the target is the destination IP in the generated event.
+.. _keyword_requires:
+
requires
--------
expression. Rules that do not meet the requirements will by ignored,
and Suricata will not treat them as errors.
+Requirements that follow the valid format of ``<keyword>
+<expression>`` but are not known to Suricata are allowed for future
+compatiblity, however unknown requirement expressions will lead to the
+requirement not being met, skipping the rule.
+
When parsing rules, the parser attempts to process the ``requires``
keywords before others. This allows it to occur after keywords that
may only be present in specific versions of Suricata, as specified by
/// Passed in requirements not a valid UTF-8 string.
Utf8Error,
+
+ /// An unknown requirement was provided.
+ UnknownRequirement(String),
}
impl RequiresError {
Self::BadRequires => "Failed to parse requires expression\0",
Self::MultipleVersions => "Version may only be specified once\0",
Self::Utf8Error => "Requires expression is not valid UTF-8\0",
+ Self::UnknownRequirement(_) => "Unknown requirements\0",
};
msg.as_ptr() as *const c_char
}
/// - All of the inner most must evaluate to true.
/// - To pass, any of the outer must be true.
pub version: Vec<Vec<RuleRequireVersion>>,
+
+ /// Unknown parameters to requires.
+ pub unknown: Vec<String>,
}
fn parse_op(input: &str) -> IResult<&str, VersionCompareOp> {
// Unknown keyword, allow by warn in case we extend
// this in the future.
SCLogWarning!("Unknown requires keyword: {}", keyword);
+ requires.unknown.push(format!("{} {}", keyword, value));
}
}
fn check_requires(
requires: &Requires, suricata_version: &SuricataVersion,
) -> Result<(), RequiresError> {
+ if !requires.unknown.is_empty() {
+ return Err(RequiresError::UnknownRequirement(
+ requires.unknown.join(","),
+ ));
+ }
+
if !requires.version.is_empty() {
let mut errs = VecDeque::new();
let mut ok = 0;
patch: 0,
}
}]],
+ unknown: vec![],
}
);
patch: 0,
}
}]],
+ unknown: vec![],
}
);
patch: 2,
}
}]],
+ unknown: vec![],
}
);
}
}
]],
+ unknown: vec![],
}
);
}
assert!(check_requires(&requires, &SuricataVersion::new(9, 0, 0)).is_err());
// Unknown keyword.
- let requires = parse_requires("feature lua, foo bar, version >= 7.0.3").unwrap();
+ let requires = parse_requires("feature true_lua, foo bar, version >= 7.0.3").unwrap();
assert_eq!(
requires,
Requires {
- features: vec!["lua".to_string()],
+ features: vec!["true_lua".to_string()],
version: vec![vec![RuleRequireVersion {
op: VersionCompareOp::Gte,
version: SuricataVersion {
patch: 3,
}
}]],
+ unknown: vec!["foo bar".to_string()],
}
);
+
+ // This should not pass the requires check as it contains an
+ // unknown requires keyword.
+ //check_requires(&requires, &SuricataVersion::new(8, 0, 0)).unwrap();
+ assert!(check_requires(&requires, &SuricataVersion::new(8, 0, 0)).is_err());
}
#[test]
]
);
}
+
+ #[test]
+ fn test_requires_keyword() {
+ let requires = parse_requires("keyword true_bar").unwrap();
+ assert!(check_requires(&requires, &SuricataVersion::new(8, 0, 0)).is_err());
+ }
}