Skip to main content

endpoint_sec/event/
event_gatekeeper_user_override.rs

1//! [`EventGatekeeperUserOverride`]
2
3use std::ffi::OsStr;
4
5use endpoint_sec_sys::{es_event_gatekeeper_user_override_t, es_gatekeeper_user_override_file_type_t, es_signed_file_info_t};
6
7use crate::File;
8
9/// Notification for a gatekeeper_user_override event.
10///
11/// This event type does not support caching (notify-only).
12///
13/// Hashes are calculated in usermode by Gatekeeper. There is no guarantee that
14/// any other program including the kernel will observe the same file at the
15/// reported path. Furthermore, there is no guarantee that the CDHash is valid
16/// or that it matches the containing binary.
17#[doc(alias = "es_event_gatekeeper_user_override_t")]
18pub struct EventGatekeeperUserOverride<'a> {
19    /// Raw event
20    pub(super) raw: &'a es_event_gatekeeper_user_override_t,
21}
22
23impl<'a> EventGatekeeperUserOverride<'a> {
24    /// Describes the target file that is being overridden by the user.
25    ///
26    /// If Endpoint security can't lookup the file at event submission it will
27    /// emit a path instead of a [`File`].
28    pub fn file(&self) -> Option<GatekeeperFile<'a>> {
29        match self.raw.file_type {
30            es_gatekeeper_user_override_file_type_t::ES_GATEKEEPER_USER_OVERRIDE_FILE_TYPE_PATH => {
31                // Safety: Union access (file_path) is allowed as file_type
32                // indicates this field was used to construct this event.
33                //
34                // 'a tied to self, object obtained through ES
35                let file_path = unsafe { self.raw.file.file_path.as_os_str() };
36                Some(GatekeeperFile::Path(file_path))
37            },
38            es_gatekeeper_user_override_file_type_t::ES_GATEKEEPER_USER_OVERRIDE_FILE_TYPE_FILE => {
39                // Safety: Union access (file) is allowed as file_type indicates
40                // this field was used to construct this event.
41                //
42                // 'a tied to self, object obtained through ES
43                let file = unsafe { self.raw.file.file.as_ref() };
44                Some(GatekeeperFile::File(File::new(file)))
45            },
46            _ => None,
47        }
48    }
49
50    /// SHA256 of the file.
51    ///
52    /// Provided if the filesize is less than 100MB.
53    #[inline(always)]
54    pub fn sha256(&self) -> &[u8; 32] {
55        // Safety: 'a tied to self, object obtained through ES
56        unsafe {
57            &*self.raw.sha256
58        }
59    }
60
61    /// Signing Information, available if the file has been signed.
62    #[inline(always)]
63    pub fn signing_info(&self) -> Option<SignedFileInfo<'_>> {
64        // Safety: 'a tied to self, object obtained through ES
65        let signing_info = unsafe { self.raw.signing_info()? };
66        Some(SignedFileInfo::new(signing_info))
67    }
68}
69
70// Safety: safe to send across threads: does not contain any interior mutability nor depend on current thread state
71unsafe impl Send for EventGatekeeperUserOverride<'_> {}
72// Safety: safe to share across threads: does not contain any interior mutability nor depend on current thread state
73unsafe impl Sync for EventGatekeeperUserOverride<'_> {}
74
75impl_debug_eq_hash_with_functions!(EventGatekeeperUserOverride<'a>; file, sha256, signing_info);
76
77/// The file being overridden by a user.
78#[derive(Debug, PartialEq, Hash)]
79pub enum GatekeeperFile<'a> {
80    /// Endpoint Security couldn't lookup the file, and emitted a path.
81    Path(&'a OsStr),
82    /// The full information of the file being overridden.
83    File(File<'a>),
84}
85
86
87/// Information from a signed file.
88///
89/// If the file is a multiarchitecture binary, only the signing information for
90/// the native host architecture is reported. I.e. the CDHash from the AArch64
91/// slice if the host is AArch64.
92pub struct SignedFileInfo<'a> {
93    /// Raw event
94    raw: &'a es_signed_file_info_t,
95}
96
97impl<'a> SignedFileInfo<'a> {
98    /// Create a new [`SignedFileInfo`] instance.
99    fn new(raw: &es_signed_file_info_t) -> SignedFileInfo<'_> {
100        SignedFileInfo { raw }
101    }
102
103    /// Code Directory Hash
104    #[inline(always)]
105    pub fn cdhash(&self) -> &'a [u8; 20] {
106        &self.raw.cdhash
107    }
108
109    /// Signing Identifier, if available in the signing information.
110    #[inline(always)]
111    pub fn signing_id(&self) -> &'a OsStr {
112        // Safety: 'a tied to self, object obtained through ES
113        unsafe {
114            self.raw.signing_id.as_os_str()
115        }
116    }
117
118    /// Team Identifier, if available in the signing information.
119    #[inline(always)]
120    pub fn team_id(&self) -> &'a OsStr {
121        // Safety: 'a tied to self, object obtained through ES
122        unsafe {
123            self.raw.team_id.as_os_str()
124        }
125    }
126}
127
128impl_debug_eq_hash_with_functions!(SignedFileInfo<'a>; cdhash, signing_id, team_id);