1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//! Types and definitions used in Endpoint Security but not declared in the ES headers
//!
//! The types here are not available in the [`libc`] crate either and only one of them is available
//! in the [`mach2`](https://docs.rs/mach2) crate.

use core::fmt;
use std::os::raw::c_int;
pub use std::os::raw::{c_uint, c_ushort};

use libc::{dev_t, gid_t, pid_t, uid_t};
pub use mach2::vm_types::user_addr_t;

pub type user_size_t = u64;

pub type attrgroup_t = u32;

pub type au_asid_t = pid_t;

/// Pointer to opaque type for Endpoint Security ACL.
///
/// The ACL provided cannot be directly used by functions within the `<sys/acl.h>` header. These
/// functions can mutate the struct passed into them, which is not compatible with the immutable
/// nature of `es_message_t`. Additionally, because this field is minimally constructed, you
/// must not use `acl_dup(3)` to get a mutable copy, as this can lead to out of bounds memory
/// access. To obtain a `acl_t` struct that is able to be used with all functions within `<sys/
/// acl.h>`, please use a combination of `acl_copy_ext(3)` followed by `acl_copy_int(3)`.
#[cfg(feature = "macos_10_15_1")]
pub type acl_t = *mut _acl;

/// Never use directly, use [`acl_t`] instead
#[repr(C)]
#[cfg(feature = "macos_10_15_1")]
pub struct _acl {
    _unused: [u8; 0],
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct au_tid_t {
    pub port: dev_t,
    pub machine: u32,
}

/// The audit token is an opaque token which identifies Mach tasks and senders of Mach messages
/// as subjects to the BSM audit system.  Only the appropriate BSM library routines should
/// be used to interpret the contents of the audit token as the representation of the subject
/// identity within the token may change over time.
///
/// Starting with macOS 11, almost all audit functions have been deprecated (see the system
/// header `bsm/libbsm.h`), do not use them if your program target more recent versions of
/// macOS.
#[repr(C)]
#[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
pub struct audit_token_t {
    /// Value of the token
    ///
    /// This is considered an opaque value, do not rely on its format
    pub val: [c_uint; 8],
}

// Make the debug representation an hex string to make it shorter and clearer when debugging
impl fmt::Debug for audit_token_t {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("audit_token_t")
            .field(&format!("0x{:08X}", self))
            .finish()
    }
}

impl fmt::LowerHex for audit_token_t {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for v in self.val {
            fmt::LowerHex::fmt(&v, f)?;
        }

        Ok(())
    }
}

impl fmt::UpperHex for audit_token_t {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for v in self.val {
            fmt::UpperHex::fmt(&v, f)?;
        }

        Ok(())
    }
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct attrlist {
    /// number of attr. bit sets in list (should be 5)
    pub bitmapcount: c_ushort,
    /// (to maintain 4-byte alignment)
    _reserved: u16,
    /// common attribute group
    pub commonattr: attrgroup_t,
    /// Volume attribute group
    pub volattr: attrgroup_t,
    /// directory attribute group
    pub dirattr: attrgroup_t,
    /// file attribute group
    pub fileattr: attrgroup_t,
    /// fork attribute group
    pub forkattr: attrgroup_t,
}

#[link(name = "bsm", kind = "dylib")]
extern "C" {
    /// Extract information from an [`audit_token_t`], used to identify Mach tasks and senders
    /// of Mach messages as subjects to the audit system. `audit_tokent_to_au32()` is the only
    /// method that should be used to parse an `audit_token_t`, since its internal representation
    /// may change over time. A pointer parameter may be `NULL` if that information is not needed.
    /// `audit_token_to_au32()` has been deprecated because the terminal ID information is no
    /// longer saved in this token. The last parameter is actually the process ID version. The
    /// API calls [`audit_token_to_auid()`], [`audit_token_to_euid()`], [`audit_token_to_ruid()`],
    /// [`audit_token_to_rgid()`], [`audit_token_to_pid()`], [`audit_token_to_asid()`], and/or
    /// [`audit_token_to_pidversion()`] should be used instead.
    ///
    /// Note: **this function has been deprecated by Apple in an unknown version**.
    ///
    /// - `atoken`: the audit token containing the desired information
    /// - `auidp`: Pointer to a `uid_t`; on return will be set to the task or sender's audit user ID
    /// - `euidp`: Pointer to a `uid_t`; on return will be set to the task or sender's effective
    ///  user ID
    /// - `egidp`: Pointer to a `gid_t`; on return will be set to the task or sender's effective
    ///  group ID
    /// - `ruidp`: Pointer to a `uid_t`; on return will be set to the task or sender's real user ID
    /// - `rgidp`: Pointer to a `gid_t`; on return will be set to the task or sender's real group ID
    /// - `pidp`: Pointer to a `pid_t`; on return will be set to the task or sender's process ID
    /// - `asidp`: Pointer to an `au_asid_t`; on return will be set to the task or sender's audit
    /// session ID
    /// - `tidp`: Pointer to an `au_tid_t`; on return will be set to the process ID version and NOT
    ///  THE SENDER'S TERMINAL ID.
    ///
    /// IMPORTANT: In Apple's `bsm-8`, these are marked `__APPLE_API_PRIVATE`.
    pub fn audit_token_to_au32(
        atoken: audit_token_t,
        auidp: *mut uid_t,
        euidp: *mut uid_t,
        egidp: *mut gid_t,
        ruidp: *mut uid_t,
        rgidp: *mut gid_t,
        pidp: *mut pid_t,
        asidp: *mut au_asid_t,
        tidp: *mut au_tid_t,
    );

    /// Extract the audit user ID from an `audit_token_t`, used to identify Mach tasks and
    /// senders of Mach messages as subjects of the audit system.
    ///
    /// - `atoken`: The Mach audit token.
    /// - Returns: The audit user ID extracted from the Mach audit token.
    pub fn audit_token_to_auid(atoken: audit_token_t) -> uid_t;

    /// Extract the effective user ID from an `audit_token_t`, used to identify Mach tasks and
    /// senders of Mach messages as subjects of the audit system.
    ///
    /// - `atoken`: The Mach audit token.
    /// - Returns: The effective user ID extracted from the Mach audit token.
    pub fn audit_token_to_euid(atoken: audit_token_t) -> uid_t;

    /// Extract the effective group ID from an `audit_token_t`, used to identify Mach tasks and
    /// senders of Mach messages as subjects of the audit system.
    ///
    /// - `atoken`: The Mach audit token.
    /// - Returns: The effective group ID extracted from the Mach audit token.
    pub fn audit_token_to_egid(atoken: audit_token_t) -> gid_t;

    /// Extract the real user ID from an `audit_token_t`, used to identify Mach tasks and
    /// senders of Mach messages as subjects of the audit system.
    ///
    /// - `atoken`: The Mach audit token.
    /// - Returns: The real user ID extracted from the Mach audit token.
    pub fn audit_token_to_ruid(atoken: audit_token_t) -> uid_t;

    /// Extract the real group ID from an `audit_token_t`, used to identify Mach tasks and
    /// senders of Mach messages as subjects of the audit system.
    ///
    /// - `atoken`: The Mach audit token.
    /// - Returns: The real group ID extracted from the Mach audit token.
    pub fn audit_token_to_rgid(atoken: audit_token_t) -> gid_t;

    /// Extract the process ID from an `audit_token_t`, used to identify Mach tasks and senders
    /// of Mach messages as subjects of the audit system.
    ///
    /// - `atoken`: The Mach audit token.
    /// - Returns: The process ID extracted from the Mach audit token.
    pub fn audit_token_to_pid(atoken: audit_token_t) -> pid_t;

    /// Extract the audit session ID from an `audit_token_t`, used to identify Mach tasks and
    /// senders of Mach messages as subjects of the audit system.
    ///
    /// - `atoken`: The Mach audit token.
    /// - Returns: The audit session ID extracted from the Mach audit token.
    pub fn audit_token_to_asid(atoken: audit_token_t) -> au_asid_t;

    /// Extract the process ID version from an `audit_token_t`, used to identify Mach tasks and
    /// senders of Mach messages as subjects of the audit system.
    ///
    /// - `atoken`: The Mach audit token.
    /// - Returns: The process ID version extracted from the Mach audit token.
    pub fn audit_token_to_pidversion(atoken: audit_token_t) -> c_int;
}