Skip to main content

endpoint_sec/event/
event_sudo.rs

1//! [`EventSudo`]
2
3use std::ffi::OsStr;
4
5use endpoint_sec_sys::{es_event_sudo_t, es_sudo_plugin_type_t, es_sudo_reject_info_t};
6use libc::uid_t;
7
8/// A sudo event.
9#[doc(alias = "es_event_sudo_t")]
10pub struct EventSudo<'a> {
11    /// The raw reference.
12    pub(crate) raw: &'a es_event_sudo_t,
13}
14
15impl<'a> EventSudo<'a> {
16    /// True iff sudo was successful
17    #[inline(always)]
18    pub fn success(&self) -> bool {
19        self.raw.success
20    }
21
22    /// Optional. When success is false, describes why sudo was rejected
23    #[inline(always)]
24    pub fn reject_info(&self) -> Option<RejectInfo<'a>> {
25        match self.success() && (self.raw.reject_info.is_null() == false) {
26            false => None,
27            true => Some(RejectInfo {
28                // Safety: 'a tied to self, object obtained through ES
29                raw: unsafe { &*self.raw.reject_info },
30            }),
31        }
32    }
33    /// Describes whether or not the from_uid is interpretable
34    #[inline(always)]
35    pub fn has_from_uid(&self) -> bool {
36        self.raw.has_from_uid
37    }
38    /// Optional. The uid of the user who initiated the su
39    #[inline(always)]
40    pub fn from_uid(&self) -> Option<uid_t> {
41        // Safety: 'a tied to self, object obtained through ES
42        #[allow(clippy::unnecessary_lazy_evaluations)]
43        self.has_from_uid().then(|| unsafe { self.raw.from_uid.uid })
44    }
45    /// Optional. The name of the user who initiated the su
46    #[inline(always)]
47    pub fn from_username(&self) -> Option<&'a OsStr> {
48        // Safety: 'a tied to self, object obtained through ES
49        unsafe { self.raw.from_username.as_opt_os_str() }
50    }
51    /// Describes whether or not the to_uid is interpretable
52    #[inline(always)]
53    pub fn has_to_uid(&self) -> bool {
54        self.raw.has_to_uid
55    }
56    /// Optional. If success, the user ID that is going to be substituted
57    #[inline(always)]
58    pub fn to_uid(&self) -> Option<uid_t> {
59        if self.success() == false {
60            return None;
61        }
62        // Safety: 'a tied to self, object obtained through ES
63        #[allow(clippy::unnecessary_lazy_evaluations)]
64        self.has_to_uid().then(|| unsafe { self.raw.to_uid.uid })
65    }
66    /// Optional. If success, the user name that is going to be substituted
67    #[inline(always)]
68    pub fn to_username(&self) -> Option<&'a OsStr> {
69        if self.success() == false {
70            return None;
71        }
72        // Safety: 'a tied to self, object obtained through ES
73        unsafe { Some(self.raw.to_username.as_os_str()) }
74    }
75    /// Optional. The command to be run
76    #[inline(always)]
77    pub fn command(&self) -> Option<&'a OsStr> {
78        // Safety: 'a tied to self, object obtained through ES
79        unsafe { self.raw.command.as_opt_os_str() }
80    }
81}
82
83// Safety: safe to send across threads: does not contain any interior mutability nor depend on current thread state
84unsafe impl Send for EventSudo<'_> {}
85// Safety: safe to share across threads: does not contain any interior mutability nor depend on current thread state
86unsafe impl Sync for EventSudo<'_> {}
87
88impl_debug_eq_hash_with_functions!(EventSudo<'a>; success, reject_info, has_from_uid, from_uid, from_username, has_to_uid, to_uid, to_username, command);
89
90/// Provides context about failures in [`EventSudo`]
91#[doc(alias = "es_sudo_reject_info_t")]
92pub struct RejectInfo<'a> {
93    /// The raw reference.
94    raw: &'a es_sudo_reject_info_t,
95}
96
97impl<'a> RejectInfo<'a> {
98    /// The sudo plugin that initiated the reject
99    #[inline(always)]
100    pub fn plugin_name(&self) -> &'a OsStr {
101        // Safety: 'a tied to self, object obtained through ES
102        unsafe { self.raw.plugin_name.as_os_str() }
103    }
104    /// The sudo plugin type that initiated the reject
105    #[inline(always)]
106    pub fn plugin_type(&self) -> es_sudo_plugin_type_t {
107        self.raw.plugin_type
108    }
109    /// A reason represented by a string for the failure
110    #[inline(always)]
111    pub fn failure_message(&self) -> &'a OsStr {
112        // Safety: 'a tied to self, object obtained through ES
113        unsafe { self.raw.failure_message.as_os_str() }
114    }
115}
116
117// Safety: safe to send across threads: does not contain any interior mutability nor depend on current thread state
118unsafe impl Send for RejectInfo<'_> {}
119
120impl_debug_eq_hash_with_functions!(RejectInfo<'a>; plugin_name, plugin_type, failure_message);