Skip to main content

endpoint_sec/event/
event_su.rs

1//! [`EventSu`]
2
3use std::ffi::OsStr;
4
5use endpoint_sec_sys::{es_event_su_t, es_string_token_t};
6use libc::uid_t;
7
8/// A `su` policy decision event.
9#[doc(alias = "es_event_su_t")]
10pub struct EventSu<'a> {
11    /// The raw event.
12    pub(crate) raw: &'a es_event_su_t,
13}
14
15impl<'a> EventSu<'a> {
16    /// True iff su was successful.
17    #[inline(always)]
18    pub fn success(&self) -> bool {
19        self.raw.success
20    }
21
22    /// If `success` is `false`, a failure message is contained in this field.
23    #[inline(always)]
24    pub fn failure_message(&self) -> Option<&'a OsStr> {
25        match self.success() {
26            false => None,
27            // Safety: checked for `success` value, lifetime matches that of event
28            true => Some(unsafe { self.raw.failure_message.as_os_str() }),
29        }
30    }
31
32    /// The uid of the user who initiated the su.
33    #[inline(always)]
34    pub fn from_uid(&self) -> uid_t {
35        self.raw.from_uid
36    }
37
38    /// The name of the user who initiated the su.
39    #[inline(always)]
40    pub fn from_username(&self) -> &'a OsStr {
41        // Safety: lifetime matches that of message
42        unsafe { self.raw.from_username.as_os_str() }
43    }
44
45    /// True iff su was successful, Describes whether or not the to_uid is interpretable
46    #[inline(always)]
47    pub fn has_to_uid(&self) -> bool {
48        self.raw.has_to_uid
49    }
50
51    /// If success, the user ID that is going to be substituted
52    #[inline(always)]
53    pub fn to_uid(&self) -> Option<uid_t> {
54        // Safety: checked for success and `has_to_uid`
55        #[allow(clippy::unnecessary_lazy_evaluations)]
56        (self.success() && self.has_to_uid()).then(|| unsafe { self.raw.to_uid.uid })
57    }
58
59    /// If success, the user name that is going to be substituted
60    #[inline(always)]
61    pub fn to_username(&self) -> Option<&'a OsStr> {
62        match self.success() {
63            false => None,
64            // Safety: checked for success, lifetime matches that of event
65            true => unsafe { Some(self.raw.to_username.as_os_str()) },
66        }
67    }
68
69    /// If success, the shell that is going to be executed
70    #[inline(always)]
71    pub fn shell(&self) -> Option<&'a OsStr> {
72        match self.success() {
73            false => None,
74            // Safety: checked for success, lifetime matches that of event
75            true => unsafe { Some(self.raw.shell.as_os_str()) },
76        }
77    }
78
79    /// Argument count
80    #[inline(always)]
81    pub fn arg_count(&self) -> usize {
82        self.raw.argc
83    }
84
85    /// Environment count
86    #[inline(always)]
87    pub fn env_count(&self) -> usize {
88        self.raw.env_count
89    }
90
91    /// If success, the arguments are passed into to the shell
92    #[inline(always)]
93    pub fn args<'e>(&'e self) -> Option<SuArgs<'e, 'a>> {
94        match self.success() {
95            false => None,
96            true => Some(SuArgs::new(self)),
97        }
98    }
99
100    /// If success, list of environment variables that is going to be substituted
101    #[inline(always)]
102    pub fn envs<'e>(&'e self) -> Option<SuEnvs<'e, 'a>> {
103        match self.success() {
104            false => None,
105            true => Some(SuEnvs::new(self)),
106        }
107    }
108}
109
110// Safety: safe to send across threads: does not contain any interior mutability nor depend on current thread state
111unsafe impl Send for EventSu<'_> {}
112// Safety: safe to share across threads: does not contain any interior mutability nor depend on current thread state
113unsafe impl Sync for EventSu<'_> {}
114
115impl_debug_eq_hash_with_functions!(EventSu<'a>; success, failure_message, from_uid, from_username, to_uid, to_username, shell, arg_count, env_count);
116
117/// Read the `idx` arg of `raw`
118///
119/// # Safety
120///
121/// Must be called with a valid event for which `idx` is in range `0..raw.argc`
122unsafe fn read_nth_arg(raw: &es_event_su_t, idx: usize) -> es_string_token_t {
123    std::ptr::read(raw.argv.add(idx))
124}
125
126/// Read the `idx` env of `raw`
127///
128/// # Safety
129///
130/// Must be called with a valid event for which `idx` is in range `0..raw.env_count`
131unsafe fn read_nth_env(raw: &es_event_su_t, idx: usize) -> es_string_token_t {
132    std::ptr::read(raw.env.add(idx))
133}
134
135make_event_data_iterator!(
136    EventSu;
137    /// Iterator over the arguments of an [`EventSu`]
138    SuArgs with arg_count (usize);
139    &'raw OsStr;
140    read_nth_arg,
141    super::as_os_str,
142);
143
144make_event_data_iterator!(
145    EventSu;
146    /// Iterator over the environment of an [`EventSu`]
147    SuEnvs with env_count (usize);
148    &'raw OsStr;
149    read_nth_env,
150    super::as_os_str,
151);