1use std::ffi::{CStr, CString};
2use std::ptr::null_mut;
3
4#[derive(Clone)]
6pub struct Config {
7 pub(crate) raw: libddwaf_sys::ddwaf_config,
8 _obfuscator: Obfuscator, }
10impl Config {
11 #[must_use]
13 pub fn new(limits: Limits, obfuscator: Obfuscator) -> Self {
14 Self {
15 raw: libddwaf_sys::ddwaf_config {
16 limits,
17 obfuscator: obfuscator.raw,
18 free_fn: None,
19 },
20 _obfuscator: obfuscator,
21 }
22 }
23}
24impl Default for Config {
25 fn default() -> Self {
26 Self::new(Limits::default(), Obfuscator::default())
27 }
28}
29
30pub type Limits = libddwaf_sys::_ddwaf_config__ddwaf_config_limits;
32
33#[repr(transparent)]
39pub struct Obfuscator {
40 raw: libddwaf_sys::_ddwaf_config__ddwaf_config_obfuscator,
41}
42impl Obfuscator {
43 pub fn new<T: Into<Vec<u8>>, U: Into<Vec<u8>>>(
49 key_regex: Option<T>,
50 value_regex: Option<U>,
51 ) -> Self {
52 let key_regex = key_regex.map_or(null_mut(), |s| {
53 CString::new(s).expect("Invalid key regex").into_raw()
54 });
55 let value_regex = value_regex.map_or(null_mut(), |s| {
56 CString::new(s).expect("Invalid value regex").into_raw()
57 });
58 Self {
59 #[allow(clippy::used_underscore_items)]
60 raw: libddwaf_sys::_ddwaf_config__ddwaf_config_obfuscator {
61 key_regex,
62 value_regex,
63 },
64 }
65 }
66
67 #[must_use]
70 pub const fn key_regex(&self) -> Option<&CStr> {
71 if self.raw.key_regex.is_null() {
72 None
73 } else {
74 Some(unsafe { CStr::from_ptr(self.raw.key_regex) })
75 }
76 }
77
78 #[must_use]
81 pub const fn value_regex(&self) -> Option<&CStr> {
82 if self.raw.value_regex.is_null() {
83 None
84 } else {
85 Some(unsafe { CStr::from_ptr(self.raw.value_regex) })
86 }
87 }
88}
89impl Clone for Obfuscator {
90 fn clone(&self) -> Self {
91 Self::new(
92 self.key_regex().map(CStr::to_bytes),
93 self.value_regex().map(CStr::to_bytes),
94 )
95 }
96}
97pub const OBFUSCATOR_DEFAULT_KEY_REGEX: &str = r"(?i)pass|pw(?:or)?d|secret|(?:api|private|public|access)[_-]?key|token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization|jsessionid|phpsessid|asp\.net[_-]sessionid|sid|jwt";
99pub const OBFUSCATOR_DEFAULT_VAL_REGEX: &str = r#"(?i)(?:p(?:ass)?w(?:or)?d|pass(?:[_-]?phrase)?|secret(?:[_-]?key)?|(?:(?:api|private|public|access)[_-]?)key(?:[_-]?id)?|(?:(?:auth|access|id|refresh)[_-]?)?token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|jsessionid|phpsessid|asp\.net(?:[_-]|-)sessionid|sid|jwt)(?:\s*=([^;&]+)|"\s*:\s*("[^"]+"|\d+))|bearer\s+([a-z0-9\._\-]+)|token\s*:\s*([a-z0-9]{13})|gh[opsu]_([0-9a-zA-Z]{36})|ey[I-L][\w=-]+\.(ey[I-L][\w=-]+(?:\.[\w.+\/=-]+)?)|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY[\-]{5}([^\-]+)[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*([a-z0-9\/\.+]{100,})"#;
101impl Default for Obfuscator {
102 fn default() -> Self {
103 Obfuscator::new(
104 Some(OBFUSCATOR_DEFAULT_KEY_REGEX),
105 Some(OBFUSCATOR_DEFAULT_VAL_REGEX),
106 )
107 }
108}
109impl Drop for Obfuscator {
110 fn drop(&mut self) {
111 if !self.raw.key_regex.is_null() {
112 unsafe {
113 drop(CString::from_raw(self.raw.key_regex.cast_mut()));
114 }
115 }
116 if !self.raw.value_regex.is_null() {
117 unsafe {
118 drop(CString::from_raw(self.raw.value_regex.cast_mut()));
119 }
120 }
121 }
122}