linux_audit_parser/
key.rs

1use std::convert::Infallible;
2use std::fmt::{self, Debug, Display};
3use std::str::{self, FromStr};
4
5#[cfg(feature = "serde")]
6use serde_with::{DeserializeFromStr, SerializeDisplay};
7
8/// Common [`Key`]s found in SYSCALL records
9#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
10#[repr(usize)]
11pub enum Common {
12    Arch,
13    Argc,
14    CapFe,
15    CapFi,
16    CapFp,
17    CapFver,
18    Comm,
19    Cwd,
20    Dev,
21    Exe,
22    Exit,
23    Inode,
24    Item,
25    Items,
26    Key,
27    Mode,
28    Msg,
29    Name,
30    Nametype,
31    Pid,
32    PPid,
33    Ses,
34    Subj,
35    Success,
36    Syscall,
37    Tty,
38}
39
40const COMMON: &[(&str, Common)] = &[
41    ("arch", Common::Arch),
42    ("argc", Common::Argc),
43    ("cap_fe", Common::CapFe),
44    ("cap_fi", Common::CapFi),
45    ("cap_fp", Common::CapFp),
46    ("cap_fver", Common::CapFver),
47    ("comm", Common::Comm),
48    ("cwd", Common::Cwd),
49    ("dev", Common::Dev),
50    ("exe", Common::Exe),
51    ("exit", Common::Exit),
52    ("inode", Common::Inode),
53    ("item", Common::Item),
54    ("items", Common::Items),
55    ("key", Common::Key),
56    ("mode", Common::Mode),
57    ("msg", Common::Msg),
58    ("name", Common::Name),
59    ("nametype", Common::Nametype),
60    ("pid", Common::Pid),
61    ("ppid", Common::PPid),
62    ("ses", Common::Ses),
63    ("subj", Common::Subj),
64    ("success", Common::Success),
65    ("syscall", Common::Syscall),
66    ("tty", Common::Tty),
67];
68
69impl TryFrom<&[u8]> for Common {
70    type Error = &'static str;
71    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
72        let i = COMMON
73            .binary_search_by_key(&value, |(s, _)| s.as_bytes())
74            .map_err(|_| "unknown key")?;
75        Ok(COMMON[i].1)
76    }
77}
78
79impl From<Common> for &'static str {
80    fn from(value: Common) -> Self {
81        COMMON[value as usize].0
82    }
83}
84
85impl Display for Common {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        let c = COMMON[*self as usize].0;
88        write!(f, "{c}")
89    }
90}
91
92pub(crate) type NVec = tinyvec::TinyVec<[u8; 14]>;
93
94/// Representation of the key part of key/value pairs in [`Body`]
95///
96/// [`Body`]: crate::Body
97#[derive(PartialEq, Eq, Clone)]
98#[cfg_attr(feature = "serde", derive(SerializeDisplay, DeserializeFromStr))]
99pub enum Key {
100    /// regular ASCII-only name as returned by parser
101    Name(NVec),
102    /// ASCII-only name for UID fields
103    NameUID(NVec),
104    /// ASCII-only name for GID fields
105    NameGID(NVec),
106    /// special case for common values
107    Common(Common),
108    /// regular ASCII-only name, output/serialization in all-caps, for
109    /// translated / "enriched" values
110    NameTranslated(NVec),
111    /// special case for argument lists: `a0`, `a1`, (`SYSCALL` and
112    /// `EXECVE`); `a2[0]`, `a2[1]` (`EXECVE`)
113    Arg(u32, Option<u16>),
114    /// `a0_len` as found in `EXECVE` lines
115    ArgLen(u32),
116    /// Not returned by parser
117    Literal(&'static str),
118}
119
120impl Default for Key {
121    fn default() -> Self {
122        Key::Literal("no_key")
123    }
124}
125
126impl Debug for Key {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        f.write_str(&self.to_string())
129    }
130}
131
132impl Display for Key {
133    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134        match self {
135            Key::Arg(x, Some(y)) => write!(f, "a{x}[{y}]"),
136            Key::Arg(x, None) => write!(f, "a{x}"),
137            Key::ArgLen(x) => write!(f, "a{x}_len"),
138            Key::Name(r) | Key::NameUID(r) | Key::NameGID(r) => {
139                // safety: The parser guarantees an ASCII-only key.
140                let s = unsafe { str::from_utf8_unchecked(r) };
141                f.write_str(s)
142            }
143            Key::Common(c) => write!(f, "{c}"),
144            Key::NameTranslated(r) => {
145                // safety: The parser guarantees an ASCII-only key.
146                let s = unsafe { str::from_utf8_unchecked(r) };
147                f.write_str(&str::to_ascii_uppercase(s))
148            }
149            Key::Literal(s) => f.write_str(s),
150        }
151    }
152}
153
154fn try_parse_a(s: &str) -> Option<Key> {
155    match s.strip_prefix("a") {
156        Some(s) => {
157            if let Some(s) = s.strip_suffix("]") {
158                let (x, y) = s.split_once("[")?;
159                Some(Key::Arg(
160                    u32::from_str(x).ok()?,
161                    Some(u16::from_str(y).ok()?),
162                ))
163            } else if let Some(s) = s.strip_suffix("_len") {
164                Some(Key::ArgLen(u32::from_str(s).ok()?))
165            } else {
166                Some(Key::Arg(u32::from_str(s).ok()?, None))
167            }
168        }
169        _ => None,
170    }
171}
172
173impl FromStr for Key {
174    type Err = Infallible;
175
176    fn from_str(s: &str) -> Result<Self, Self::Err> {
177        if let Ok(c) = Common::try_from(s.as_bytes()) {
178            Ok(Key::Common(c))
179        } else if let Some(k) = try_parse_a(s) {
180            Ok(k)
181        } else if s.ends_with("uid") {
182            Ok(Key::NameUID(s.as_bytes().into()))
183        } else if s.ends_with("gid") {
184            Ok(Key::NameGID(s.as_bytes().into()))
185        } else {
186            Ok(Key::from(s.as_bytes()))
187        }
188    }
189}
190
191impl PartialEq<str> for Key {
192    fn eq(&self, other: &str) -> bool {
193        self == other.as_bytes()
194    }
195}
196
197impl PartialEq<[u8]> for Key {
198    fn eq(&self, other: &[u8]) -> bool {
199        match self {
200            Key::Name(r) | Key::NameUID(r) | Key::NameGID(r) => r.as_ref() == other,
201            _ => self.to_string().as_bytes() == other,
202        }
203    }
204}
205
206impl From<&'static str> for Key {
207    fn from(value: &'static str) -> Self {
208        Self::Literal(value)
209    }
210}
211
212impl From<&[u8]> for Key {
213    fn from(value: &[u8]) -> Self {
214        Self::Name(NVec::from(value))
215    }
216}