#ifndef __ENDPOINT_SECURITY_MESSAGE_H #define __ENDPOINT_SECURITY_MESSAGE_H #ifndef __ENDPOINT_SECURITY_INDIRECT__ #error "Please #include instead of this file directly." #endif /* __ENDPOINT_SECURITY_INDIRECT__ */ #include #include #include #include #include #include #include #include #include #include #if !__DARWIN_64_BIT_INO_T #error This header requires __DARWIN_64_BIT_INO_T #endif /* !__DARWIN_64_BIT_INO_T */ /** * The EndpointSecurity subsystem is responsible for creating, populating and * delivering these data structures to ES clients. */ /** * A note on userspace events: * * Before macOS 13.0 almost all ES events were created by `xnu` (the macOS kernel). * Such events are *mandatory*. * If no `es_event_setuid_t` event is emitted then no `setuid` took place. This is a secuirty guarantee. * Most events added in macOS 13 and 14 are emitted by userspace binaries and frameworks. * ES still guarantees that if an event was not emitted *by that binary or framework* then it did not happen, but this is not * quite the same guarantee. * * Consider `es_event_su_t`. * This event is created by the `su` binary first shipped in macOS 14.0, but it's entirely possible for a user to install (or * compile) a different `su`! ES only guarantees that the platform binary shipped with macOS emits `es_event_su_t` events. As such * `es_event_su_t` does not provide the same security guarantee that `es_event_setuid_t` does. * * When a user invokes the platform `su` binary ES will emit both `es_event_su_t` and `es_event_setuid_t` events. * When a user compiles their own `su` binary from source and executes it: * ES will emit an `es_event_setuid_t` event. * ES will NOT emit an `es_event_su_t`. * * Userspace events are inherntly discretionary. * It is the at the users discrtion as to wether the use the builtin binaries/frameworks or not. * Kernel events are mandatory. There is no `setuid` syscall that ES does not interdict. * * The following events are created by userspace binaries or frameworks: * ES_EVENT_TYPE_AUTH_FILE_PROVIDER_MATERIALIZE * ES_EVENT_TYPE_NOTIFY_FILE_PROVIDER_MATERIALIZE * ES_EVENT_TYPE_AUTH_FILE_PROVIDER_UPDATE * ES_EVENT_TYPE_NOTIFY_FILE_PROVIDER_UPDATE * ES_EVENT_TYPE_NOTIFY_AUTHENTICATION * ES_EVENT_TYPE_NOTIFY_XP_MALWARE_DETECTED * ES_EVENT_TYPE_NOTIFY_XP_MALWARE_REMEDIATED * ES_EVENT_TYPE_NOTIFY_LW_SESSION_LOGIN * ES_EVENT_TYPE_NOTIFY_LW_SESSION_LOGOUT * ES_EVENT_TYPE_NOTIFY_LW_SESSION_LOCK * ES_EVENT_TYPE_NOTIFY_LW_SESSION_UNLOCK * ES_EVENT_TYPE_NOTIFY_SCREENSHARING_ATTACH * ES_EVENT_TYPE_NOTIFY_SCREENSHARING_DETACH * ES_EVENT_TYPE_NOTIFY_OPENSSH_LOGIN * ES_EVENT_TYPE_NOTIFY_OPENSSH_LOGOUT * ES_EVENT_TYPE_NOTIFY_LOGIN_LOGIN * ES_EVENT_TYPE_NOTIFY_LOGIN_LOGOUT * ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_ADD * ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_REMOVE * ES_EVENT_TYPE_NOTIFY_PROFILE_ADD * ES_EVENT_TYPE_NOTIFY_PROFILE_REMOVE * ES_EVENT_TYPE_NOTIFY_SU * ES_EVENT_TYPE_NOTIFY_AUTHORIZATION_PETITION * ES_EVENT_TYPE_NOTIFY_AUTHORIZATION_JUDGEMENT * ES_EVENT_TYPE_NOTIFY_SUDO * ES_EVENT_TYPE_NOTIFY_OD_GROUP_ADD * ES_EVENT_TYPE_NOTIFY_OD_GROUP_REMOVE * ES_EVENT_TYPE_NOTIFY_OD_GROUP_SET * ES_EVENT_TYPE_NOTIFY_OD_MODIFY_PASSWORD * ES_EVENT_TYPE_NOTIFY_OD_DISABLE_USER * ES_EVENT_TYPE_NOTIFY_OD_ENABLE_USER * ES_EVENT_TYPE_NOTIFY_OD_ATTRIBUTE_VALUE_ADD * ES_EVENT_TYPE_NOTIFY_OD_ATTRIBUTE_VALUE_REMOVE * ES_EVENT_TYPE_NOTIFY_OD_ATTRIBUTE_SET * ES_EVENT_TYPE_NOTIFY_OD_CREATE_USER * ES_EVENT_TYPE_NOTIFY_OD_CREATE_GROUP * ES_EVENT_TYPE_NOTIFY_OD_DELETE_USER * ES_EVENT_TYPE_NOTIFY_OD_DELETE_GROUP * ES_EVENT_TYPE_NOTIFY_GATEKEEPER_USER_OVERRIDE * ES_EVENT_TYPE_NOTIFY_TCC_MODIFY */ /** * @brief es_file_t provides the stat information and path to a file that relates to a security * event. The path may be truncated, which is indicated by the path_truncated flag. * * @field path Absolute path of the file * @field path_truncated Indicates if the path field was truncated * @field stat stat of file. See `man 2 stat` for details * * @note For the FAT family of filesystems the `stat.st_ino` field is set to 999999999 for empty files * * @discussion For files with a link count greater than 1, the absolute path given may not be the only absolute path that exists, * and which hard link the emitted path points to is undefined. * * Overlong paths are truncated at a maximum length that currently is 16K, though that number is not considered API and may change * at any time. * */ typedef struct { es_string_token_t path; bool path_truncated; struct stat stat; } es_file_t; /** * @brief Information related to a thread. * * @field thread_id The unique thread ID of the thread. */ typedef struct { uint64_t thread_id; } es_thread_t; /** * @brief Information related to a process. This is used both for describing processes that * performed an action (e.g. in the case of the `es_message_t` `process` field, or are targets * of an action (e.g. for exec events this describes the new process being executed, for signal * events this describes the process that will receive the signal). * * @field audit_token Audit token of the process. * @field ppid Parent pid of the process. It is recommended to instead use the parent_audit_token field. * @see parent_audit_token * @field original_ppid Original ppid of the process. This field stays constant even in the event * this process is reparented. * @field group_id Process group id the process belongs to. * @field session_id Session id the process belongs to. * @field codesigning_flags Code signing flags of the process. The values for these flags can be * found in the include file `cs_blobs.h` (`#include `). * @field is_es_client Indicates this process has the Endpoint Security entitlement. * @field cdhash The code directory hash of the code signature associated with this process. * @field signing_id The signing id of the code signature associated with this process. * @field team_id The team id of the code signature associated with this process. * @field executable The executable file that is executing in this process. * @field tty The TTY this process is associated with, or NULL if the process does not have an * associated TTY. The TTY is a property of the POSIX session the process belongs to. * A process' session may be associated with a TTY independently from whether its stdin * or any other file descriptors point to a TTY device (as per isatty(3), tty(1)). * Field available only if message version >= 2. * @field start_time Process start time, i.e. time of fork creating this process. * Field available only if message version >= 3. * @field responsible_audit_token audit token of the process responsible for this process, which * may be the process itself in case there is no responsible process or the responsible * process has already exited. * Field available only if message version >= 4. * @field parent_audit_token The audit token of the parent process * Field available only if message version >= 4. * * @discussion * - Values such as pid, pidversion, uid, gid, etc. can be extracted from audit tokens using API * provided in libbsm. * - The tuple (pid, pidversion) identifies a specific process execution, and should be used to link * events to the process that emitted them. Executing an executable image in a process using the * exec or posix_spawn family of syscalls increments the pidversion. However, (pid, pidversion) * is not meant to be unique across reboots or across multiple systems. * - Clients should take caution when processing events where `is_es_client` is true. If multiple ES * clients exist, actions taken by one client could trigger additional actions by the other client, * causing a potentially infinite cycle. * - Fields related to code signing in the target `es_process_t` reflect the state of the process * at the time the message is generated. In the specific case of exec, this is after the exec * completed in the kernel, but before any code in the process has started executing. At that * point, XNU has validated the signature itself and has verified that the CDHash is correct in * that the hash of all the individual page hashes in the Code Directory matches the signed CDHash, * essentially verifying the signature was not tampered with. However, individual page hashes are * not verified by XNU until the corresponding pages are paged in once they are accessed while the * binary executes. It is not until the individual pages are paged in that XNU determines if a * binary has been tampered with and will update the code signing flags accordingly. * EndpointSecurity provides clients the current state of the CS flags in the `codesigning_flags` * member of the `es_process_t` struct. The CS_VALID bit in the `codesigning_flags` means that * everything the kernel has validated up to that point in time was valid, but not that there has * been a full validation of all the pages in the executable file. If page content has been * tampered with in the executable, we won't know until that page is paged in. At that time, the * process will have its CS_VALID bit cleared and, if CS_KILL is set, the process will be killed, * preventing any tampered code from being executed. CS_KILL is generally set for platform * binaries and for binaries having opted into the hardened runtime. An ES client wishing to * detect tampered code before it is paged in, for example at exec time, can use the Security * framework to do so, but should be cautious of the potentially significant performance cost. The * EndpointSecurity subsystem itself has no role in verifying the validity of code signatures. */ typedef struct { audit_token_t audit_token; pid_t ppid; pid_t original_ppid; pid_t group_id; pid_t session_id; uint32_t codesigning_flags; bool is_platform_binary; bool is_es_client; es_cdhash_t cdhash; es_string_token_t signing_id; es_string_token_t team_id; es_file_t *_Nonnull executable; es_file_t *_Nullable tty; /* field available only if message version >= 2 */ struct timeval start_time; /* field available only if message version >= 3 */ audit_token_t responsible_audit_token; /* field available only if message version >= 4 */ audit_token_t parent_audit_token; /* field available only if message version >= 4 */ } es_process_t; /** * @brief Describes machine-specific thread state as used by `thread_create_running` and other * Mach API functions. * * @field flavor Indicates the representation of the machine-specific thread state. * @field state The machine-specific thread state, equivalent to thread_state_t in Mach APIs. * * @note The size subfield of the state field is in bytes, NOT natural_t units. Definitions * for working with thread state can be found in the include file `mach/thread_status.h` and * corresponding machine-dependent headers. */ typedef struct { int flavor; es_token_t state; } es_thread_state_t; /** * @brief Structure for describing an open file descriptor * * @field fd File descriptor number * @field fdtype File descriptor type, as libproc fdtype * * Fields available only if fdtype == PROX_FDTYPE_PIPE: * @field extra.pipe.pipe_id Unique id of the pipe for correlation with other * file descriptors pointing to the same or other end of the same pipe. */ typedef struct { int32_t fd; uint32_t fdtype; union { struct { uint64_t pipe_id; } pipe; }; } es_fd_t; typedef enum { ES_BTM_ITEM_TYPE_USER_ITEM, ES_BTM_ITEM_TYPE_APP, ES_BTM_ITEM_TYPE_LOGIN_ITEM, ES_BTM_ITEM_TYPE_AGENT, ES_BTM_ITEM_TYPE_DAEMON } es_btm_item_type_t; /** * @brief Structure describing a BTM launch item * * @field item_type Type of launch item. * @field legacy True iff item is a legacy plist. * @field managed True iff item is managed by MDM. * @field uid User ID for the item (may be user nobody (-2)). * @field item_url URL for item. * If file URL describing a relative path, it is relative * to app_url. * @field app_url Optional. URL for app the item is attributed to. */ typedef struct { es_btm_item_type_t item_type; bool legacy; bool managed; uid_t uid; es_string_token_t item_url; es_string_token_t app_url; } es_btm_launch_item_t; typedef enum { ES_PROFILE_SOURCE_MANAGED, ES_PROFILE_SOURCE_INSTALL, } es_profile_source_t; /** * @brief Structure describing a Profile event * * @field identifier Profile identifier. * @field uuid Profile UUID. * @field install_source Source of Profile installation (MDM/Manual Install) * @field organization Profile organization name. * @field display_name Profile display name. * @field scope Profile scope. */ typedef struct { es_string_token_t identifier; es_string_token_t uuid; es_profile_source_t install_source; es_string_token_t organization; es_string_token_t display_name; es_string_token_t scope; } es_profile_t; /** * @brief Execute a new process * * @field target The new process that is being executed * @field dyld_exec_path The exec path passed up to dyld, before symlink resolution. * This is the path argument to execve(2) or posix_spawn(2), or the interpreter * from the shebang line for scripts run through the shell script image activator. * Field available only if message version >= 7. * @field script Script being executed by interpreter. This field is only valid if a script was * executed directly and not as an argument to the interpreter (e.g. `./foo.sh` not `/bin/sh ./foo.sh`) * Field available only if message version >= 2. * @field cwd Current working directory at exec time. * Field available only if message version >= 3. * @field last_fd Highest open file descriptor after the exec completed. * This number is equal to or larger than the highest number of file descriptors available * via `es_exec_fd_count` and `es_exec_fd`, in which case EndpointSecurity has capped the * number of file descriptors available in the message. File descriptors for open files are * not necessarily contiguous. The exact number of open file descriptors is not available. * Field available only if message version >= 4. * @field image_cputype The CPU type of the executable image which is being executed. * In case of translation, this may be a different architecture than the one of the system. * Field available only if message version >= 6. * @field image_cpusubtype The CPU subtype of the executable image. * Field available only if message version >= 6. * * @note Process arguments, environment variables and file descriptors are packed, use API functions * to access them: `es_exec_arg`, `es_exec_arg_count`, `es_exec_env`, `es_exec_env_count`, * `es_exec_fd` and `es_exec_fd_count`. * * @note The API may only return descriptions for a subset of open file descriptors; how many and * which file descriptors are available as part of exec events is not considered API and can change * in future releases. * * @note The CPU type and subtype correspond to CPU_TYPE_* and CPU_SUBTYPE_* macros defined in * ``. * * @note Fields related to code signing in `target` represent kernel state for the process at the * point in time the exec has completed, but the binary has not started running yet. Because code * pages are not validated until they are paged in, this means that modifications to code pages * would not have been detected yet at this point. For a more thorough explanation, please see the * documentation for `es_process_t`. * * @note There are two `es_process_t` fields that are represented in an `es_message_t` that contains * an `es_event_exec_t`. The `es_process_t` within the `es_message_t` struct (named "process") * contains information about the program that calls execve(2) (or posix_spawn(2)). This information * is gathered prior to the program being replaced. The other `es_process_t`, within the * `es_event_exec_t` struct (named "target"), contains information about the program after the image * has been replaced by execve(2) (or posix_spawn(2)). This means that both `es_process_t` structs * refer to the same process (as identified by pid), but not necessarily the same program, and * definitely not the same program execution (as identified by pid, pidversion tuple). The * `audit_token_t` structs contained in the two different `es_process_t` structs will not be * identical: the pidversion field will be updated, and the uid/gid values may be different if the * new program had setuid/setgid permission bits set. * * @note Cache key for this event type: (process executable file, target executable file) */ typedef struct { es_process_t *_Nonnull target; es_string_token_t dyld_exec_path; /* field available only if message version >= 7 */ union { uint8_t reserved[64]; struct { es_file_t *_Nullable script; /* field available only if message version >= 2 */ es_file_t *_Nonnull cwd; /* field available only if message version >= 3 */ int last_fd; /* field available only if message version >= 4 */ cpu_type_t image_cputype; /* field available only if message version >= 6 */ cpu_subtype_t image_cpusubtype; /* field available only if message version >= 6 */ }; }; } es_event_exec_t; /** * @brief TCC Modification Event. Occurs when a TCC permission is granted * or revoked. * * @field service The TCC service for which permissions are being modified. * @field identity The identity of the application that is the subject of the permission. * @field identity_type The identity type of the application string (Bundle ID, path, etc). * @field update_type The type of TCC modification event (Grant/Revoke etc) * @field instigator_token Audit token of the instigator of the modification. * @field instigator (Optional) The process information for the instigator. * @field responsible_token (Optional) Audit token of the responsible process for the modification. * @field responsible (Optional) The process information for the responsible process. * @field right The resulting TCC permission of the operation/modification. * @field reason The reason the TCC permissions were updated. * * @note This event type does not support caching. */ typedef struct { es_string_token_t service; es_string_token_t identity; es_tcc_identity_type_t identity_type; es_tcc_event_type_t update_type; audit_token_t instigator_token; es_process_t *_Nullable instigator; audit_token_t *_Nullable responsible_token; es_process_t *_Nullable responsible; es_tcc_authorization_right_t right; es_tcc_authorization_reason_t reason; } es_event_tcc_modify_t; /** * @brief Open a file system object * * @field fflag The desired flags to be used when opening `file` (see note) * @field file The file that will be opened * * @note: The `fflag` field represents the mask as applied by the kernel, not as represented by typical * open(2) `oflag` values. When responding to `ES_EVENT_TYPE_AUTH_OPEN` events using * es_respond_flags_result(), ensure that the same FFLAG values are used (e.g. FREAD, FWRITE instead * of O_RDONLY, O_RDWR, etc...). * * @note Cache key for this event type: (process executable file, file that will be opened) * * @see fcntl.h */ typedef struct { int32_t fflag; es_file_t *_Nonnull file; uint8_t reserved[64]; } es_event_open_t; /** * @brief Load a kernel extension * * @field identifier The signing identifier of the kext being loaded * * @note This event type does not support caching. * @note Not all AUTH_KEXTLOAD events can be delivered. * In rare circumstances when kextloading is blocking all userspace execution it will be automatically allowed. * NOTIFY_KEXTLOAD will still be (eventually) delivered. */ typedef struct { es_string_token_t identifier; uint8_t reserved[64]; } es_event_kextload_t; /** * @brief Unload a kernel extension * * @field identifier The signing identifier of the kext being unloaded * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t identifier; uint8_t reserved[64]; } es_event_kextunload_t; /** * @brief Unlink a file system object * * @field target The object that will be removed * @field parent_dir The parent directory of the `target` file system object * * @note This event can fire multiple times for a single syscall, for example when the syscall * has to be retried due to racing VFS operations. * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull target; es_file_t *_Nonnull parent_dir; uint8_t reserved[64]; } es_event_unlink_t; /** * @brief Memory map a file * * @field protection The protection (region accessibility) value * @field max_protection The maximum allowed protection value the operating system will respect * @field flags The type and attributes of the mapped file * @field file_pos The offset into `source` that will be mapped * @field source The file system object being mapped * * @note Cache key for this event type: (process executable file, source file) */ typedef struct { int32_t protection; int32_t max_protection; int32_t flags; uint64_t file_pos; es_file_t *_Nonnull source; uint8_t reserved[64]; } es_event_mmap_t; /** * @brief Link to a file * * @field source The existing object to which a hard link will be created * @field target_dir The directory in which the link will be created * @field target_filename The name of the new object linked to `source` * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull source; es_file_t *_Nonnull target_dir; es_string_token_t target_filename; uint8_t reserved[64]; } es_event_link_t; // The following types are used in mount events typedef enum { ES_MOUNT_DISPOSITION_EXTERNAL, // device is external storage ES_MOUNT_DISPOSITION_INTERNAL, // device is internal storage ES_MOUNT_DISPOSITION_NETWORK, // device is a network share ES_MOUNT_DISPOSITION_VIRTUAL, // device is virtual (dmg or file) ES_MOUNT_DISPOSITION_NULLFS, // mount uses nullfs, commonly for app translocation ES_MOUNT_DISPOSITION_UNKNOWN // unable to determine disposition } es_mount_disposition_t; /** * @brief Mount a file system * * @field statfs The file system stats for the file system being mounted * @field disposition The device disposition of the f_mntfromname * * @note Cache key for this event type: (process executable file, mount point) */ typedef struct { struct statfs *_Nonnull statfs; es_mount_disposition_t disposition; /* field available only if message version >= 8 */ uint8_t reserved[60]; } es_event_mount_t; /** * @brief Unmount a file system * * @field statfs The file system stats for the file system being unmounted * * @note This event type does not support caching (notify-only). */ typedef struct { struct statfs *_Nonnull statfs; uint8_t reserved[64]; } es_event_unmount_t; /** * @brief Remount a file system * * @field statfs The file system stats for the file system being remounted * @field remount_flags The provided remount flags * @field disposition The device disposition of the f_mntfromname * @note This event type does not support caching (notify-only). */ typedef struct { struct statfs *_Nonnull statfs; uint64_t remount_flags; /* field available only if message version >= 8 */ es_mount_disposition_t disposition; /* field available only if message version >= 8 */ uint8_t reserved[52]; } es_event_remount_t; /** * @brief Fork a new process * * @field child The child process that was created * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nonnull child; uint8_t reserved[64]; } es_event_fork_t; /** * @brief Control protection of pages * * @field protection The desired new protection value * @field address The base address to which the protection value will apply * @field size The size of the memory region the protection value will apply * * @note This event type does not support caching. */ typedef struct { int32_t protection; user_addr_t address; user_size_t size; uint8_t reserved[64]; } es_event_mprotect_t; /** * @brief Send a signal to a process * * Signals may be sent on behalf of another process or directly. Notably launchd often sends signals * on behalf of another process for service start/stop operations. If this is the case an * instigator will be provided. The relationship between each process is illustrated below: * * Delegated Signal: * * Instigator Process -> IPC to Sender Process (launchd) -> Target Process * * Direct Signal: * * Sender Process -> Target Process * * Clients may wish to block delegated signals from launchd for non-authorized instigators, while still * allowing direct signals initiated by launchd for shutdown/reboot/restart. * * @field sig The signal number to be delivered * @field target The process that will receive the signal * @field instigator Process information for the instigator (if applicable). * * @note This event will not fire if a process sends a signal to itself. * @note This event type does not support caching. * @note Be aware of the nullablity of some of the fields. The instigator may not be * applicable. */ typedef struct { int sig; es_process_t *_Nonnull target; es_process_t *_Nullable instigator; uint8_t reserved[56]; } es_event_signal_t; typedef enum { ES_DESTINATION_TYPE_EXISTING_FILE, ES_DESTINATION_TYPE_NEW_PATH, } es_destination_type_t; /** * @brief Rename a file system object * * @field source The source file that is being renamed * @field destination_type Whether or not the destination refers to an existing or new file * @field destination Information about the destination of the renamed file (see note) * @field existing_file The destination file that will be overwritten * @field new_path Information regarding the destination of a newly created file * @field dir The directory into which the file will be renamed * @field filename The name of the new file that will be created * * @note The `destination_type` field describes which member in the `destination` union should * accessed. `ES_DESTINATION_TYPE_EXISTING_FILE` means that `existing_file` should be used, * `ES_DESTINATION_TYPE_NEW_PATH` means that the `new_path` struct should be used. * * @note This event can fire multiple times for a single syscall, for example when the syscall * has to be retried due to racing VFS operations. * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull source; es_destination_type_t destination_type; union { es_file_t *_Nonnull existing_file; struct { es_file_t *_Nonnull dir; es_string_token_t filename; } new_path; } destination; uint8_t reserved[64]; } es_event_rename_t; /** * @brief Set an extended attribute * * @field target The file for which the extended attribute will be set * @field extattr The extended attribute which will be set * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull target; es_string_token_t extattr; uint8_t reserved[64]; } es_event_setextattr_t; /** * @brief Retrieve an extended attribute * * @field target The file for which the extended attribute will be retrieved * @field extattr The extended attribute which will be retrieved * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { es_file_t *_Nonnull target; es_string_token_t extattr; uint8_t reserved[64]; } es_event_getextattr_t; /** * @brief Delete an extended attribute * * @field target The file for which the extended attribute will be deleted * @field extattr The extended attribute which will be deleted * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull target; es_string_token_t extattr; uint8_t reserved[64]; } es_event_deleteextattr_t; /** * @brief Modify file mode * * @field mode The desired new mode * @field target The file for which mode information will be modified * * @note The `mode` member is the desired new mode. The `target` * member's `stat` information contains the current mode. * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { mode_t mode; es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_setmode_t; /** * @brief Modify file flags information * * @field flags The desired new flags * @field target The file for which flags information will be modified * * @note The `flags` member is the desired set of new flags. The `target` * member's `stat` information contains the current set of flags. * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { uint32_t flags; es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_setflags_t; /** * @brief Modify file owner information * * @field uid The desired new UID * @field gid The desired new GID * @field target The file for which owner information will be modified * * @note The `uid` and `gid` members are the desired new values. The `target` * member's `stat` information contains the current uid and gid values. * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { uid_t uid; gid_t gid; es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_setowner_t; /** * @brief Close a file descriptor * * @field modified Set to TRUE if the target file being closed has been modified * @field target The file that is being closed * @field was_mapped_writable Indicates that at some point in the lifetime of the * target file vnode it was mapped into a process as writable. * Field available only if message version >= 6. * * @note This event type does not support caching (notify-only). * * `was_mapped_writable` only indicates whether the target file was mapped into writable memory or not for the lifetime of the * vnode. It does not indicate whether the file has actually been written to by way of writing to mapped memory, and it does not * indicate whether the file is currently still mapped writable. Correct interpretation requires consideration of vnode lifetimes * in the kernel. * * The `modified` flag only reflects that a file was or was not modified by filesystem syscall. * If a file was only modifed though a memory mapping this flag will be false, but was_mapped_writable will be true. */ typedef struct { bool modified; es_file_t *_Nonnull target; union { uint8_t reserved[64]; struct { bool was_mapped_writable; /* Field available only if message version >= 6. */ }; }; } es_event_close_t; /** * @brief Create a file system object * * @field destination_type Whether or not the destination refers to an existing file (see note) * @field destination Information about the destination of the new file (see note) * @field existing_file The file system object that was created * @field dir The directory in which the new file system object will be created * @field filename The name of the new file system object to create * @field acl The ACL that the new file system object got or gets created with. * May be NULL if the file system object gets created without ACL. * @note The acl provided cannot be directly used by functions within * the 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 , please use a combination of * `acl_copy_ext(3)` followed by `acl_copy_int(3)`. * Field available only if message version >= 2. * * @note If an object is being created but has not yet been created, the * `destination_type` will be `ES_DESTINATION_TYPE_NEW_PATH`. * * @note Typically `ES_EVENT_TYPE_NOTIFY_CREATE` events are fired after the * object has been created and the `destination_type` will be * `ES_DESTINATION_TYPE_EXISTING_FILE`. The exception to this is for * notifications that occur if an ES client responds to an * `ES_EVENT_TYPE_AUTH_CREATE` event with `ES_AUTH_RESULT_DENY`. * * @note This event can fire multiple times for a single syscall, for example when the syscall * has to be retried due to racing VFS operations. * * @note This event type does not support caching. */ typedef struct { es_destination_type_t destination_type; union { es_file_t *_Nonnull existing_file; struct { es_file_t *_Nonnull dir; es_string_token_t filename; mode_t mode; } new_path; } destination; uint8_t reserved2[16]; union { uint8_t reserved[48]; struct { acl_t _Nullable acl; /* field available only if message version >= 2 */ }; }; } es_event_create_t; /** * @brief Terminate a process * * @field stat The exit status of a process (same format as wait(2)) * * @note This event type does not support caching (notify-only). */ typedef struct { int stat; uint8_t reserved[64]; } es_event_exit_t; /** * @brief Exchange data atomically between two files * * @field file1 The first file to be exchanged * @field file2 The second file to be exchanged * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull file1; es_file_t *_Nonnull file2; uint8_t reserved[64]; } es_event_exchangedata_t; /** * @brief Write to a file * * @field target The file being written to * * @note This event type does not support caching (notify-only). */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_write_t; /** * @brief Truncate a file * * @field target The file that is being truncated * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_truncate_t; /** * @brief Change directories * * @field target The desired new current working directory * * @note Cache key for this event type: (process executable file, target directory) */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_chdir_t; /** * @brief View stat information of a file * * @field target The file for which stat information will be retrieved * * @note This event type does not support caching (notify-only). */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_stat_t; /** * @brief Change the root directory for a process * * @field target The directory which will be the new root * * @note Cache key for this event type: (process executable file, target directory) */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_chroot_t; /** * @brief List extended attributes of a file * * @field target The file for which extended attributes are being retrieved * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_listextattr_t; /** * @brief Open a connection to an I/O Kit IOService * * @field user_client_type A constant specifying the type of connection to be * created, interpreted only by the IOService's family. * This field corresponds to the type argument to IOServiceOpen(). * @field user_client_class Meta class name of the user client instance. * * This event is fired when a process calls IOServiceOpen() in order to open * a communications channel with an I/O Kit driver. The event does not * correspond to driver <-> device communication and is neither providing * visibility nor access control into devices being attached. * * @note This event type does not support caching. */ typedef struct { uint32_t user_client_type; es_string_token_t user_client_class; uint8_t reserved[64]; } es_event_iokit_open_t; typedef enum { // Task port obtained by calling e.g. task_for_pid(), where the caller // obtains a task port for a process identified by pid. ES_GET_TASK_TYPE_TASK_FOR_PID, // Task port obtained by calling e.g. processor_set_tasks(), where the // caller obtains a set of task ports. ES_GET_TASK_TYPE_EXPOSE_TASK, // Task port obtained by calling e.g. task_identity_token_get_task_port(), // where the caller obtains a task port for a process identified by an // identity token. Task identity tokens generally have to be given up // by the target process voluntarily prior to the conversion into task // ports. ES_GET_TASK_TYPE_IDENTITY_TOKEN, } es_get_task_type_t; /** * @brief Get a process's task control port * * @field target The process for which the task control port will be retrieved. * @field type Type indicating how the process is obtaining the task port for * the target process. * Field available only if message version >= 5. * * This event is fired when a process obtains a send right to a task control * port (e.g. task_for_pid(), task_identity_token_get_task_port(), * processor_set_tasks() and other means). * * @note Task control ports were formerly known as simply "task ports". * * @note There are many legitimate reasons why a process might need to obtain * a send right to a task control port of another process, not limited to intending * to debug or suspend the target process. For instance, frameworks and their * daemons may need to obtain a task control port to fulfill requests made by the * target process. Obtaining a task control port is in itself not indicative of * malicious activity. Denying system processes acquiring task control ports may * result in breaking system functionality in potentially fatal ways. * * @note Cache key for this event type: * (process executable file, target executable file) */ typedef struct { es_process_t *_Nonnull target; es_get_task_type_t type; /* field available only if message version >= 5 */ uint8_t reserved[60]; } es_event_get_task_t; /** * @brief Get a process's task read port * * @field target The process for which the task read port will be retrieved. * @field type Type indicating how the process is obtaining the task port for * the target process. * Field available only if message version >= 5. * * This event is fired when a process obtains a send right to a task read * port (e.g. task_read_for_pid(), task_identity_token_get_task_port()). * * @note Cache key for this event type: * (process executable file, target executable file) */ typedef struct { es_process_t *_Nonnull target; es_get_task_type_t type; /* field available only if message version >= 5 */ uint8_t reserved[60]; } es_event_get_task_read_t; /** * @brief Get a process's task inspect port * * @field target The process for which the task inspect port will be retrieved. * @field type Type indicating how the process is obtaining the task port for * the target process. * Field available only if message version >= 5. * * This event is fired when a process obtains a send right to a task inspect * port (e.g. task_inspect_for_pid(), task_identity_token_get_task_port()). * * @note This event type does not support caching. */ typedef struct { es_process_t *_Nonnull target; es_get_task_type_t type; /* field available only if message version >= 5 */ uint8_t reserved[60]; } es_event_get_task_inspect_t; /** * @brief Get a process's task name port * * @field target The process for which the task name port will be retrieved. * @field type Type indicating how the process is obtaining the task port for * the target process. * Field available only if message version >= 5. * * This event is fired when a process obtains a send right to a task name * port (e.g. task_name_for_pid(), task_identity_token_get_task_port()). * * @note This event type does not support caching. */ typedef struct { es_process_t *_Nonnull target; es_get_task_type_t type; /* field available only if message version >= 5 */ uint8_t reserved[60]; } es_event_get_task_name_t; /** * @brief Retrieve file system attributes * * @field attrlist The attributes that will be retrieved * @field target The file for which attributes will be retrieved * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { struct attrlist attrlist; es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_getattrlist_t; /** * @brief Set file system attributes * * @field attrlist The attributes that will be modified * @field target The file for which attributes will be modified * * @note This event type does not support caching. */ typedef struct { struct attrlist attrlist; es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_setattrlist_t; /** * @brief Update file contents via the FileProvider framework * * @field source The staged file that has had its contents updated * @field target_path The destination that the staged `source` file will be moved to * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull source; es_string_token_t target_path; uint8_t reserved[64]; } es_event_file_provider_update_t; /** * @brief Materialize a file via the FileProvider framework * * @field instigator The process that instigated the materialize operation. * @field source The staged file that has been materialized * @field target The destination of the staged `source` file * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching. */ typedef struct { es_process_t *_Nullable instigator; es_file_t *_Nonnull source; es_file_t *_Nonnull target; audit_token_t instigator_token; // Available in msg versions >= 8. uint8_t reserved[32]; } es_event_file_provider_materialize_t; /** * @brief Resolve a symbolic link * * @field source The symbolic link that is attempting to be resolved * * @note This is not limited only to readlink(2). Other operations such as path lookups * can also cause this event to be fired. */ typedef struct { es_file_t *_Nonnull source; uint8_t reserved[64]; } es_event_readlink_t; /** * @brief Lookup a file system object * * @field source_dir The current directory * @field relative_target The path to lookup relative to the `source_dir` * * @note The `relative_target` data may contain untrusted user input. * * @note This event type does not support caching (notify-only). */ typedef struct { es_file_t *_Nonnull source_dir; es_string_token_t relative_target; uint8_t reserved[64]; } es_event_lookup_t; /** * @brief Test file access * * @field mode Access permission to check * @field target The file to check for access * * @note This event type does not support caching (notify-only). */ typedef struct { int32_t mode; es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_access_t; /** * @brief Change file access and modification times (e.g. via utimes(2)) * * @field target The path which will have its times modified * @field atime The desired new access time * @field mtime The desired new modification time * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { es_file_t *_Nonnull target; struct timespec atime; struct timespec mtime; uint8_t reserved[64]; } es_event_utimes_t; /** * @brief Clone a file * * @field source The file that will be cloned * @field target_dir The directory into which the `source` file will be cloned * @field target_name The name of the new file to which `source` will be cloned * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull source; es_file_t *_Nonnull target_dir; es_string_token_t target_name; uint8_t reserved[64]; } es_event_clone_t; /** * @brief Copy a file using the copyfile syscall * * @field source The file that will be cloned * @field target_file The file existing at the target path that will be overwritten * by the copyfile operation. NULL if no such file exists. * @field target_dir The directory into which the `source` file will be copied * @field target_name The name of the new file to which `source` will be copied * @field mode Corresponds to mode argument of the copyfile syscall * @field flags Corresponds to flags argument of the copyfile syscall * * @note Not to be confused with copyfile(3). * @note Prior to macOS 12.0, the copyfile syscall fired open, unlink and auth * create events, but no notify create, nor write or close events. * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull source; es_file_t *_Nullable target_file; es_file_t *_Nonnull target_dir; es_string_token_t target_name; mode_t mode; int32_t flags; uint8_t reserved[56]; } es_event_copyfile_t; /** * @brief File control * * @field target The target file on which the file control command will be performed * @field cmd The `cmd` argument given to fcntl(2) * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull target; int32_t cmd; uint8_t reserved[64]; } es_event_fcntl_t; /** * @brief Read directory entries * * @field target The directory whose contents will be read * * @note Cache key for this event type: (process executable file, target directory) */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_readdir_t; /** * @brief Retrieve file system path based on FSID * * @field target Describes the file system path that will be retrieved * * @note This event can fire multiple times for a single syscall, for example when the syscall * has to be retried due to racing VFS operations. * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_fsgetpath_t; /** * @brief Modify the system time * * @note This event is not fired if the program contains the entitlement * com.apple.private.settime. Additionally, even if an ES client responds to * ES_EVENT_TYPE_AUTH_SETTIME events with ES_AUTH_RESULT_ALLOW, the operation * may still fail for other reasons (e.g. unprivileged user). * * @note This event type does not support caching. */ typedef struct { uint8_t reserved[64]; } es_event_settime_t; /** * @brief Duplicate a file descriptor * * @field target Describes the file the duplicated file descriptor points to * * @note This event type does not support caching (notify-only). */ typedef struct { es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_dup_t; /** * @brief Fired when a UNIX-domain socket is about to be bound to a path. * * @field dir Describes the directory the socket file is created in. * @field filename The filename of the socket file. * @field mode The mode of the socket file. * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull dir; es_string_token_t filename; mode_t mode; uint8_t reserved[64]; } es_event_uipc_bind_t; /** * @brief Fired when a UNIX-domain socket is about to be connected. * * @field file Describes the socket file that the socket is bound to. * @field domain The communications domain of the socket (see socket(2)). * @field type The type of the socket (see socket(2)). * @field protocol The protocol of the socket (see socket(2)). * * @note Cache key for this event type: (process executable file, socket file) */ typedef struct { es_file_t *_Nonnull file; int domain; int type; int protocol; uint8_t reserved[64]; } es_event_uipc_connect_t; /** * @brief Set a file ACL. * * @field set_or_clear Describes whether or not the ACL on the `target` is being set or cleared * @field acl Union that is valid when `set_or_clear` is set to `ES_SET` * @field set The acl_t structure to be used by various acl(3) functions * @note The acl provided cannot be directly used by functions within * the 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 , please use a combination of * `acl_copy_ext(3)` followed by `acl_copy_int(3)`. * @field target Describes the file whose ACL is being set. * * @note This event type does not support caching. */ typedef struct { es_file_t *_Nonnull target; es_set_or_clear_t set_or_clear; union { acl_t _Nonnull set; } acl; uint8_t reserved[64]; } es_event_setacl_t; /** * @brief Fired when a pseudoterminal control device is granted * * @field dev Major and minor numbers of device * * @note This event type does not support caching (notify-only). */ typedef struct { dev_t dev; uint8_t reserved[64]; } es_event_pty_grant_t; /** * @brief Fired when a pseudoterminal control device is closed * * @field dev Major and minor numbers of device * * @note This event type does not support caching (notify-only). */ typedef struct { dev_t dev; uint8_t reserved[64]; } es_event_pty_close_t; /** * @brief Access control check for retrieving process information. * * @field target The process for which the access will be checked * @field type The type of call number used to check the access on the target process * @field flavor The flavor used to check the access on the target process * * @note Cache key for this event type: (process executable file, target process executable file, type) */ typedef struct { es_process_t *_Nullable target; es_proc_check_type_t type; int flavor; uint8_t reserved[64]; } es_event_proc_check_t; /** * @brief Access control check for searching a volume or a mounted file system * * @field attrlist The attributes that will be used to do the search * @field target The volume whose contents will be searched * * @note Cache key for this event type: (process executable file, target file) */ typedef struct { struct attrlist attrlist; es_file_t *_Nonnull target; uint8_t reserved[64]; } es_event_searchfs_t; /** * @brief This enum describes the type of suspend/resume operations that are currently used. */ typedef enum { ES_PROC_SUSPEND_RESUME_TYPE_SUSPEND = 0, ES_PROC_SUSPEND_RESUME_TYPE_RESUME = 1, ES_PROC_SUSPEND_RESUME_TYPE_SHUTDOWN_SOCKETS = 3, } es_proc_suspend_resume_type_t; /** * @brief Fired when one of pid_suspend, pid_resume or pid_shutdown_sockets * is called on a process. * * @field target The process that is being suspended, resumed, or is the object * of a pid_shutdown_sockets call. * @field type The type of operation that was called on the target process. * * @note This event type does not support caching. */ typedef struct { es_process_t *_Nullable target; es_proc_suspend_resume_type_t type; uint8_t reserved[64]; } es_event_proc_suspend_resume_t; /** * @brief Code signing status for process was invalidated. * * @note This event fires when the CS_VALID bit is removed from a * process' CS flags, that is, when the first invalid page is paged in * for a process with an otherwise valid code signature, or when a * process is explicitly invalidated by a csops(CS_OPS_MARKINVALID) * syscall. This event does not fire if CS_HARD was set, since CS_HARD * by design prevents the process from going invalid. * * @note This event type does not support caching (notify-only). */ typedef struct { uint8_t reserved[64]; } es_event_cs_invalidated_t; /** * @brief Fired when one process attempts to attach to another process * * @field target The process that will be attached to by the process * that instigated the event * * @note This event can fire multiple times for a single trace attempt, for example * when the processes to which is being attached is reparented during the operation * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nonnull target; uint8_t reserved[64]; } es_event_trace_t; /** * @brief Notification that a process has attempted to create a thread in * another process by calling one of the thread_create or thread_create_running * MIG routines. * * @field target The process in which a new thread was created * @field thread_state The new thread state in case of thread_create_running, * NULL in case of thread_create. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nonnull target; es_thread_state_t *_Nullable thread_state; uint8_t reserved[64]; } es_event_remote_thread_create_t; /** * @brief Notification that a process has called setuid(). * * @field uid The uid argument to the setuid() syscall. * * @note This event type does not support caching (notify-only). */ typedef struct { uid_t uid; uint8_t reserved[64]; } es_event_setuid_t; /** * @brief Notification that a process has called setgid(). * * @field gid The gid argument to the setgid() syscall. * * @note This event type does not support caching (notify-only). */ typedef struct { uid_t gid; uint8_t reserved[64]; } es_event_setgid_t; /** * @brief Notification that a process has called seteuid(). * * @field euid The euid argument to the seteuid() syscall. * * @note This event type does not support caching (notify-only). */ typedef struct { uid_t euid; uint8_t reserved[64]; } es_event_seteuid_t; /** * @brief Notification that a process has called setegid(). * * @field egid The egid argument to the setegid() syscall. * * @note This event type does not support caching (notify-only). */ typedef struct { uid_t egid; uint8_t reserved[64]; } es_event_setegid_t; /** * @brief Notification that a process has called setreuid(). * * @field ruid The ruid argument to the setreuid() syscall. * @field euid The euid argument to the setreuid() syscall. * * @note This event type does not support caching (notify-only). */ typedef struct { uid_t ruid; uid_t euid; uint8_t reserved[64]; } es_event_setreuid_t; /** * @brief Notification that a process has called setregid(). * * @field rgid The rgid argument to the setregid() syscall. * @field egid The egid argument to the setregid() syscall. * * @note This event type does not support caching (notify-only). */ typedef struct { uid_t rgid; uid_t egid; uint8_t reserved[64]; } es_event_setregid_t; /** * @brief OpenDirectory authentication data for type ES_AUTHENTICATION_TYPE_OD. * * @field instigator Process that instigated the authentication * (XPC caller that asked for authentication). * @field record_type OD record type against which OD is authenticating. * Typically "Users", but other record types can auth too. * @field record_name OD record name against which OD is authenticating. * For record type "Users", this is the username. * @field node_name OD node against which OD is authenticating. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. */ typedef struct { es_process_t *_Nullable instigator; es_string_token_t record_type; es_string_token_t record_name; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_authentication_od_t; typedef enum { ES_TOUCHID_MODE_VERIFICATION, ES_TOUCHID_MODE_IDENTIFICATION } es_touchid_mode_t; /** * @brief TouchID authentication data for type ES_AUTHENTICATION_TYPE_TOUCHID. * * @field instigator Process that instigated the authentication * (XPC caller that asked for authentication). * @field touchid_mode TouchID authentication type * @field has_uid Describes whether or not the uid of the user authenticated is available * @field uid Union that is valid when `has_uid` is set to `true` * @field uid.uid uid of user that was authenticated. * This will be set when `success` is true and `touchid_mode` is of * verification type i.e. ES_TOUCHID_MODE_VERIFICATION * @field instigator_token Audit token of the process that instigated this event. */ typedef struct { es_process_t *_Nullable instigator; es_touchid_mode_t touchid_mode; bool has_uid; union { uid_t uid; } uid; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_authentication_touchid_t; /** * @brief Token authentication data for type ES_AUTHENTICATION_TYPE_TOKEN. * * @field instigator Process that instigated the authentication * (XPC caller that asked for authentication). * @field pubkey_hash Hash of the public key which CryptoTokenKit is authenticating. * @field token_id Token identifier of the event which CryptoTokenKit is authenticating. * @field kerberos_principal Optional. This will be available if token is used for GSS PKINIT * authentication for obtaining a kerberos TGT. NULL in all other cases. * @field instigator_token Audit token of the process that instigated this event. * */ typedef struct { es_process_t *_Nullable instigator; es_string_token_t pubkey_hash; es_string_token_t token_id; es_string_token_t kerberos_principal; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_authentication_token_t; typedef enum { /// Unlock the machine using Apple Watch. ES_AUTO_UNLOCK_MACHINE_UNLOCK = 1, /// Approve an authorization prompt using Apple Watch. ES_AUTO_UNLOCK_AUTH_PROMPT = 2 } es_auto_unlock_type_t; /** * @brief Auto Unlock authentication data for type ES_AUTHENTICATION_TYPE_TOKEN. * * @field username Username for which the authentication was attempted. * @field type Purpose of the authentication. * * @note This kind of authentication is performed when authenticating to the local * Mac using an Apple Watch for the purpose of unlocking the machine or confirming * an authorization prompt. Auto Unlock is part of Continuity. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t username; es_auto_unlock_type_t type; } es_event_authentication_auto_unlock_t; /** * @brief Notification that an authentication was performed. * * @field success True iff authentication was successful. * @field type The type of authentication. * @field data Type-specific data describing the authentication. * * @note This event type does not support caching (notify-only). */ typedef struct { bool success; es_authentication_type_t type; union { es_event_authentication_od_t *_Nonnull od; es_event_authentication_touchid_t *_Nonnull touchid; es_event_authentication_token_t *_Nonnull token; es_event_authentication_auto_unlock_t *_Nonnull auto_unlock; } data; } es_event_authentication_t; /** * @brief Notification that XProtect detected malware. * * @field signature_version Version of the signatures used for detection. * Currently corresponds to XProtect version. * @field malware_identifier String identifying the malware that was detected. * @field incident_identifier String identifying the incident, intended for linking * multiple malware detected and remediated events. * @field detected_path Path where malware was detected. This path is not * necessarily a malicious binary, it can also be a * legitimate file containing a malicious portion. * * @note For any given malware incident, XProtect may emit zero or more * xp_malware_detected events, and zero or more xp_malware_remediated events. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t signature_version; es_string_token_t malware_identifier; es_string_token_t incident_identifier; es_string_token_t detected_path; } es_event_xp_malware_detected_t; /** * @brief Notification that XProtect remediated malware. * * @field signature_version Version of the signatures used for remediation. * Currently corresponds to XProtect version. * @field malware_identifier String identifying the malware that was detected. * @field incident_identifier String identifying the incident, intended for linking * multiple malware detected and remediated events. * @field action_type String indicating the type of action that was taken, * e.g. "path_delete". * @field success True iff remediation was successful. * @field result_description String describing specific reasons for failure or success. * @field remediated_path Optional. Path that was subject to remediation, if any. * This path is not necessarily a malicious binary, it can * also be a legitimate file containing a malicious portion. * Specifically, the file at this path may still exist after * successful remediation. * @field remediated_process_audit_token Audit token of process that was subject to * remediation, if any. * * @note For any given malware incident, XProtect may emit zero or more * xp_malware_detected events, and zero or more xp_malware_remediated events. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t signature_version; es_string_token_t malware_identifier; es_string_token_t incident_identifier; es_string_token_t action_type; bool success; es_string_token_t result_description; es_string_token_t remediated_path; audit_token_t *_Nullable remediated_process_audit_token; } es_event_xp_malware_remediated_t; /** * @brief es_graphical_session_id_t is a session identifier identifying a on-console or off-console graphical session. * A graphical session exists and can potentially be attached to via Screen Sharing before a user is logged in. * EndpointSecurity clients should treat the `graphical_session_id` as an opaque identifier and not assign * special meaning to it beyond correlating events pertaining to the same graphical session. Not to be confused with the audit * session ID. */ typedef uint32_t es_graphical_session_id_t; /** * @brief Notification that LoginWindow has logged in a user. * * @field username Short username of the user. * @field graphical_session_id Graphical session id of the session. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t username; es_graphical_session_id_t graphical_session_id; } es_event_lw_session_login_t; /** * @brief Notification that LoginWindow has logged out a user. * * @field username Short username of the user. * @field graphical_session_id Graphical session id of the session. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t username; es_graphical_session_id_t graphical_session_id; } es_event_lw_session_logout_t; /** * @brief Notification that LoginWindow locked the screen of a session. * * @field username Short username of the user. * @field graphical_session_id Graphical session id of the session. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t username; es_graphical_session_id_t graphical_session_id; } es_event_lw_session_lock_t; /** * @brief Notification that LoginWindow unlocked the screen of a session. * * @field username Short username of the user. * @field graphical_session_id Graphical session id of the session. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t username; es_graphical_session_id_t graphical_session_id; } es_event_lw_session_unlock_t; /** * @brief Notification that Screen Sharing has attached to a graphical session. * * @field success True iff Screen Sharing successfully attached. * @field source_address_type Type of source address. * @field source_address Optional. Source address of connection, or NULL. * Depending on the transport used, the source * address may or may not be available. * @field viewer_appleid Optional. For screen sharing initiated using an * Apple ID (e.g., from Messages or FaceTime), this * is the viewer's (client's) Apple ID. It is not * necessarily the Apple ID that invited the screen * sharing. NULL if unavailable. * @field authentication_type Type of authentication. * @field authentication_username Optional. Username used for authentication to * Screen Sharing. NULL if authentication type doesn't * use an username (e.g. simple VNC password). * @field session_username Optional. Username of the loginwindow session if * available, NULL otherwise. * @field existing_session True iff there was an existing user session. * @field graphical_session_id Graphical session id of the screen shared. * * @note This event type does not support caching (notify-only). * @discussion This event is not emitted when a screensharing session has the same source and destination address. * For example if device A is acting as a NAT gateway for device B, then a screensharing session from B -> A would not emit an * event. */ typedef struct { bool success; es_address_type_t source_address_type; es_string_token_t source_address; es_string_token_t viewer_appleid; es_string_token_t authentication_type; es_string_token_t authentication_username; es_string_token_t session_username; bool existing_session; es_graphical_session_id_t graphical_session_id; } es_event_screensharing_attach_t; /** * @brief Notification that Screen Sharing has detached from a graphical session. * * @field source_address_type Type of source address. * @field source_address Optional. Source address of connection, or NULL. * Depending on the transport used, the source * address may or may not be available. * @field viewer_appleid Optional. For screen sharing initiated using an * Apple ID (e.g., from Messages or FaceTime), this * is the viewer's (client's) Apple ID. It is not * necessarily the Apple ID that invited the screen * sharing. NULL if unavailable. * @field graphical_session_id Graphical session id of the screen shared. * * @note This event type does not support caching (notify-only). * @discussion This event is not emitted when a screensharing session has the same source and destination address. */ typedef struct { es_address_type_t source_address_type; es_string_token_t source_address; es_string_token_t viewer_appleid; es_graphical_session_id_t graphical_session_id; } es_event_screensharing_detach_t; typedef enum { ES_OPENSSH_LOGIN_EXCEED_MAXTRIES = 0, ES_OPENSSH_LOGIN_ROOT_DENIED = 1, ES_OPENSSH_AUTH_SUCCESS = 2, ES_OPENSSH_AUTH_FAIL_NONE = 3, ES_OPENSSH_AUTH_FAIL_PASSWD = 4, ES_OPENSSH_AUTH_FAIL_KBDINT = 5, ES_OPENSSH_AUTH_FAIL_PUBKEY = 6, ES_OPENSSH_AUTH_FAIL_HOSTBASED = 7, ES_OPENSSH_AUTH_FAIL_GSSAPI = 8, ES_OPENSSH_INVALID_USER = 9, } es_openssh_login_result_type_t; /** * @brief Notification for OpenSSH login event. * * @field success True iff login was successful. * @field result_type Result type for the login attempt. * @field source_address_type Type of source address. * @field source_address Source address of connection. * @field username Username used for login. * @field has_uid Describes whether or not the uid of the user logged in is available * @field uid Union that is valid when `has_uid` is set to `true` * @field uid.uid uid of user that was logged in. * * @note This is a connection-level event. An SSH connection that is used * for multiple interactive sessions and/or non-interactive commands will * emit only a single successful login event. * * @note This event type does not support caching (notify-only). */ typedef struct { bool success; es_openssh_login_result_type_t result_type; es_address_type_t source_address_type; es_string_token_t source_address; es_string_token_t username; bool has_uid; union { uid_t uid; } uid; } es_event_openssh_login_t; /** * @brief Notification for OpenSSH logout event. * * @field source_address_type Type of address used in the connection. * @field source_address Source address of the connection. * @field username Username which got logged out. * @field uid uid of user that was logged out. * * @note This is a connection-level event. An SSH connection that is used * for multiple interactive sessions and/or non-interactive commands will * emit only a single logout event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_address_type_t source_address_type; es_string_token_t source_address; es_string_token_t username; uid_t uid; } es_event_openssh_logout_t; /** * @brief Notification for authenticated login event from /usr/bin/login. * * @field success True iff login was successful. * @field failure_message Optional. Failure message generated. * @field username Username used for login. * @field has_uid Describes whether or not the uid of the user logged in is available or not. * @field uid Union that is valid when `has_uid` is set to `true` * @field uid.uid uid of user that was logged in. * * @note This event type does not support caching (notify-only). */ typedef struct { bool success; es_string_token_t failure_message; es_string_token_t username; bool has_uid; union { uid_t uid; } uid; } es_event_login_login_t; /** * @brief Notification for authenticated logout event from /usr/bin/login. * * @field username Username used for login. * @field uid uid of user that was logged in. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t username; uid_t uid; } es_event_login_logout_t; /** * @brief Notification for launch item being made known to background * task management. This includes launch agents and daemons as * well as login items added by the user, via MDM or by an app. * * @field instigator Optional. Process that instigated the BTM operation * (XPC caller that asked for the item to be added). * @field app Optional. App process that registered the item. * @field item BTM launch item. * @field executable_path Optional. If available and applicable, the POSIX executable * path from the launchd plist. * If the path is relative, it is relative to item->app_url. * @field instigator_token Audit token of the process that instigated this event. * @field app_token Audit token of the app process that registered the item. * * @note May be emitted for items where an add was already seen previously, * with or without the item having changed. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; es_process_t *_Nullable app; es_btm_launch_item_t *_Nonnull item; es_string_token_t executable_path; audit_token_t *_Nullable instigator_token; // Available in msg versions >= 8. audit_token_t *_Nullable app_token; // Available in msg versions >= 8. } es_event_btm_launch_item_add_t; /** * @brief Notification for launch item being removed from background * task management. This includes launch agents and daemons as * well as login items added by the user, via MDM or by an app. * * @field instigator Optional. Process that instigated the BTM operation * (XPC caller that asked for the item to be removed). * @field app Optional. App process that registered the item. * @field item BTM launch item. * @field instigator_token Audit token of the process that instigated this event. * @field app_token Audit token of the app process that removed the item. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; es_process_t *_Nullable app; es_btm_launch_item_t *_Nonnull item; audit_token_t *_Nullable instigator_token; // Available in msg versions >= 8. audit_token_t *_Nullable app_token; // Available in msg versions >= 8. } es_event_btm_launch_item_remove_t; /** * @brief Notification for a su policy decisions events. * * @field success True iff su was successful. * @field failure_message Optional. If success is false, a failure message is contained in this field * @field from_uid The uid of the user who initiated the su * @field from_username The username of the user who initiated the su * @field has_to_uid True iff su was successful, Describes whether or not the to_uid is interpretable * @field to_uid Optional. If success, the user ID that is going to be substituted * @field to_username Optional. If success, the user name that is going to be substituted * @field shell Optional. If success, the shell is going to execute * @field argc The length of argv * @field argv If success, the arguments are passed into to the shell * @field env_count The length of env * @field env If success, list of environment variables that is going to be substituted * * @note This event type does not support caching (notify-only). Should always * emit on success but will only emit on security relevant failures. For example, * Endpoint Security clients will not get an event for su being passed invalid * command line arguments. * */ typedef struct { bool success; es_string_token_t failure_message; uid_t from_uid; es_string_token_t from_username; bool has_to_uid; union { uid_t uid; } to_uid; es_string_token_t to_username; es_string_token_t shell; size_t argc; es_string_token_t *_Nullable argv; size_t env_count; es_string_token_t *_Nullable env; } es_event_su_t; /** * @brief Provides context about failures in es_event_sudo_t. * * @field plugin_name The sudo plugin that initiated the reject * @field plugin_type The sudo plugin type that initiated the reject * @field failure_message A reason represented by a string for the failure * */ typedef struct { es_string_token_t plugin_name; es_sudo_plugin_type_t plugin_type; es_string_token_t failure_message; } es_sudo_reject_info_t; /** * @brief Notification for a sudo event. * * @field success True iff sudo was successful * @field reject_info Optional. When success is false, describes why sudo was rejected * @field has_from_uid Describes whether or not the from_uid is interpretable * @field from_uid Optional. The uid of the user who initiated the sudo * @field from_username Optional. The username of the user who initiated the sudo * @field has_to_uid Describes whether or not the to_uid is interpretable * @field to_uid Optional. If success, the user ID that is going to be substituted * @field to_username Optional. If success, the user name that is going to be substituted * @field command Optional. The command to be run * * @note This event type does not support caching (notify-only). * */ typedef struct { bool success; es_sudo_reject_info_t *_Nullable reject_info; bool has_from_uid; union { uid_t uid; } from_uid; es_string_token_t from_username; bool has_to_uid; union { uid_t uid; } to_uid; es_string_token_t to_username; es_string_token_t command; } es_event_sudo_t; /** * @brief Notification for Profiles installed on the system. * * @field instigator Process that instigated the Profile install or update. * @field is_update Indicates if the profile is an update to an already installed * profile. * @field profile Profile install item. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; bool is_update; es_profile_t *_Nonnull profile; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_profile_add_t; /** * @brief Notification for Profiles removed on the system. * @field instigator Process that instigated the Profile removal. * @field profile Profile being removed. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; es_profile_t *_Nonnull profile; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_profile_remove_t; /** * @brief Notification that a process peititioned for certain authorization rights * * @field instigator Process that submitted the petition (XPC caller) * @field petitioner Process that created the petition * @field flags Flags associated with the petition. Defined Security framework "Authorization/Authorizatioh.h" * @field right_count The number of elements in `rights` * @field rights Array of string tokens, each token is the name of a right being requested * @field instigator_token Audit token of the process that submitted the petition. * @field petitioner_token Audit token of the process that created the petition. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; es_process_t *_Nullable petitioner; uint32_t flags; size_t right_count; es_string_token_t *_Nullable rights; audit_token_t instigator_token; // Available in msg versions >= 8. audit_token_t petitioner_token; // Available in msg versions >= 8. } es_event_authorization_petition_t; /** * @brief Describes, for a single right, the class of that right and if it was granted * * @field right_name The name of the right being considered * @field rule_class The class of the right being considered * The rule class determines how the operating system determines * if it should be granted or not * @field granted Indicates if the right was granted or not */ typedef struct { es_string_token_t right_name; es_authorization_rule_class_t rule_class; bool granted; } es_authorization_result_t; /** * @brief Notification that a process had it's right petition judged * * @field instigator Process that submitted the petition (XPC caller) * @field petitioner Process that created the petition * @field return_code The overall result of the petition. 0 indicates success. * Possible return codes are defined Security framework "Authorization/Authorizatioh.h" * @field result_count The number of elements in `results` * @field results Array of results. One for each right that was peititioned * @field instigator_token Audit token of the process that submitted the petition. * @field petitioner_token Audit token of the process that created the petition. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; es_process_t *_Nullable petitioner; int return_code; size_t result_count; es_authorization_result_t *_Nullable results; audit_token_t instigator_token; // Available in msg versions >= 8. audit_token_t petitioner_token; // Available in msg versions >= 8. } es_event_authorization_judgement_t; /** * @brief The identity of a group member * * @field member_type Indicates the type of the member, and how it is identified. * Note that member_type indicates which field of member_value is initialised. * @field member_value The member identity. */ typedef struct { es_od_member_type_t member_type; union { uuid_t uuid; es_string_token_t name; } member_value; } es_od_member_id_t; /** * @brief Notification that a member was added to a group. * * @field instigator Process that instigated operation (XPC caller). * @field group_name The group to which the member was added. * @field member The identity of the member added. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). * @note This event does not indicate that a member was actually added. * For example when adding a user to a group they are already a member of. */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t group_name; es_od_member_id_t *_Nonnull member; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_group_add_t; /** * @brief Notification that a member was removed from a group. * * @field instigator Process that instigated operation (XPC caller). * @field group_name The group from which the member was removed. * @field member The identity of the member removed. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). * @note This event does not indicate that a member was actually removed. * For example when removing a user from a group they are not a member of. */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t group_name; es_od_member_id_t *_Nonnull member; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_group_remove_t; /** * @brief An array of group member identities. * * @field member_type Indicates the type of the members, and how they are identified. * Note that member_type indicates which field of member_array is initialised. * @field member_count The number of elements in member_array. * @field member_array A union of pointers. * The initialised member points to the first element of an array of member values. */ typedef struct { es_od_member_type_t member_type; size_t member_count; union { uuid_t *_Nonnull uuids; es_string_token_t *_Nonnull names; } member_array; } es_od_member_id_array_t; /** * @brief Notification that a group had it's members initialised or replaced. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field group_name The group for which members were set. * @field members Array of new members. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). * @note This event does not indicate that a member was actually removed. * For example when removing a user from a group they are not a member of. */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t group_name; es_od_member_id_array_t *_Nonnull members; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_group_set_t; /** * @brief Notification that an account had its password modified. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field account_type The type of the account for which the password was modified. * @field account_name The name of the account for which the password was modified. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_od_account_type_t account_type; es_string_token_t account_name; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_modify_password_t; /** * @brief Notification that a user account was disabled. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field user_name The name of the user account that was disabled. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t user_name; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_disable_user_t; /** * @brief Notification that a user account was enabled. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field user_name The name of the user account that was enabled. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t user_name; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_enable_user_t; /** * @brief Notification that an attribute value was added to a record. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field record_type The type of the record to which the attribute value was added. * @field record_name The name of the record to which the attribute value was added. * @field attribute_name The name of the attribute to which the value was added. * @field attribute_value The value that was added. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * * @note This event type does not support caching (notify-only). * @note Attributes conceptually have the type `Map String (Set String)`. * Each OD record has a Map of attribute name to Set of attribute value. * When an attribute value is added, it is inserted into the set of values for that name. */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_od_record_type_t record_type; es_string_token_t record_name; es_string_token_t attribute_name; es_string_token_t attribute_value; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_attribute_value_add_t; /** * @brief Notification that an attribute value was removed from a record. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field record_type The type of the record from which the attribute value was removed. * @field record_name The name of the record from which the attribute value was removed. * @field attribute_name The name of the attribute from which the value was removed. * @field attribute_value The value that was removed. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). * @note Attributes conceptually have the type `Map String (Set String)`. * Each OD record has a Map of attribute name to Set of attribute value. * When an attribute value is removed, it is subtraced from the set of values for that name. * @note Removing a value that was never added is a no-op. */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_od_record_type_t record_type; es_string_token_t record_name; es_string_token_t attribute_name; es_string_token_t attribute_value; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_attribute_value_remove_t; /** * @brief Notification that an attribute is being set. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field record_type The type of the record for which the attribute is being set. * @field record_name The name of the record for which the attribute is being set. * @field attribute_name The name of the attribute that was set. * @field attribute_value_count The size of attribute_value_array. * @field attribute_values Array of attribute values that were set. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). * @note Attributes conceptually have the type `Map String (Set String)`. * Each OD record has a Map of attribute name to Set of attribute value. * An attribute set operation indicates the entire set of attribute values was replaced. * @note The new set of attribute values may be empty. */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_od_record_type_t record_type; es_string_token_t record_name; es_string_token_t attribute_name; size_t attribute_value_count; es_string_token_t *_Nullable attribute_values; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_attribute_set_t; /** * @brief Notification that a user account was created. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field user_name The name of the user account that was created. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t user_name; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_create_user_t; /** * @brief Notification that a group was created. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field group_name The name of the group that was created. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t group_name; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_create_group_t; /** * @brief Notification that a user account was deleted. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field user_name The name of the user account that was deleted. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t user_name; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_delete_user_t; /** * @brief Notification that a group was deleted. * * @field instigator Process that instigated operation (XPC caller). * @field error_code 0 indicates the operation succeeded. * Values inidicating specific failure reasons are defined in odconstants.h. * @field group_name The name of the group that was deleted. * @field node_name OD node being mutated. * Typically one of "/Local/Default", "/LDAPv3/" or * "/Active Directory/". * @field db_path Optional. If node_name is "/Local/Default", this is * the path of the database against which OD is * authenticating. * @field instigator_token Audit token of the process that instigated this event. * * * @note This event type does not support caching (notify-only). */ typedef struct { es_process_t *_Nullable instigator; int error_code; es_string_token_t group_name; es_string_token_t node_name; es_string_token_t db_path; audit_token_t instigator_token; // Available in msg versions >= 8. } es_event_od_delete_group_t; /** * @brief Notification for an XPC connection being established to a named service. * * @field service_name Service name of the named service. * @field service_domain_type The type of XPC domain in which the service resides in. * * @note This event type does not support caching (notify-only). */ typedef struct { es_string_token_t service_name; es_xpc_domain_type_t service_domain_type; } es_event_xpc_connect_t; /** * @brief Notification for a gatekeeper_user_override events. * * @field file_type The type of the file field. If Endpoint security can't lookup the file at event * submission it will emit a path instead of an es_file_t * @field file Describes the target file that is being overridden by the user * @field sha256 SHA256 of the file. Provided if the filesize is less than 100MB. * @field signing_info Signing Information, available if the file has been signed. * * @note This event type does not support caching (notify-only). * @note Hashes are calculated in usermode by Gatekeeper. There is no guarantee that any other program including the * kernel will observe the same file at the reported path. Furthermore there is no guarantee that the CDHash * is valid or that it matches the containing binary. */ typedef struct { es_gatekeeper_user_override_file_type_t file_type; union { es_string_token_t file_path; es_file_t *_Nonnull file; } file; es_sha256_t *_Nullable sha256; es_signed_file_info_t *_Nullable signing_info; } es_event_gatekeeper_user_override_t; /** * Union of all possible events that can appear in an es_message_t */ typedef union { /** * Events added before macOS 13.0 use structs directly. */ es_event_access_t access; es_event_chdir_t chdir; es_event_chroot_t chroot; es_event_clone_t clone; es_event_close_t close; es_event_copyfile_t copyfile; es_event_create_t create; es_event_cs_invalidated_t cs_invalidated; es_event_deleteextattr_t deleteextattr; es_event_dup_t dup; es_event_exchangedata_t exchangedata; es_event_exec_t exec; es_event_exit_t exit; es_event_file_provider_materialize_t file_provider_materialize; es_event_file_provider_update_t file_provider_update; es_event_fcntl_t fcntl; es_event_fork_t fork; es_event_fsgetpath_t fsgetpath; es_event_get_task_t get_task; es_event_get_task_read_t get_task_read; es_event_get_task_inspect_t get_task_inspect; es_event_get_task_name_t get_task_name; es_event_getattrlist_t getattrlist; es_event_getextattr_t getextattr; es_event_iokit_open_t iokit_open; es_event_kextload_t kextload; es_event_kextunload_t kextunload; es_event_link_t link; es_event_listextattr_t listextattr; es_event_lookup_t lookup; es_event_mmap_t mmap; es_event_mount_t mount; es_event_mprotect_t mprotect; es_event_open_t open; es_event_proc_check_t proc_check; es_event_proc_suspend_resume_t proc_suspend_resume; es_event_pty_close_t pty_close; es_event_pty_grant_t pty_grant; es_event_readdir_t readdir; es_event_readlink_t readlink; es_event_remote_thread_create_t remote_thread_create; es_event_remount_t remount; es_event_rename_t rename; es_event_searchfs_t searchfs; es_event_setacl_t setacl; es_event_setattrlist_t setattrlist; es_event_setextattr_t setextattr; es_event_setflags_t setflags; es_event_setmode_t setmode; es_event_setowner_t setowner; es_event_settime_t settime; es_event_setuid_t setuid; es_event_setgid_t setgid; es_event_seteuid_t seteuid; es_event_setegid_t setegid; es_event_setreuid_t setreuid; es_event_setregid_t setregid; es_event_signal_t signal; es_event_stat_t stat; es_event_trace_t trace; es_event_truncate_t truncate; es_event_uipc_bind_t uipc_bind; es_event_uipc_connect_t uipc_connect; es_event_unlink_t unlink; es_event_unmount_t unmount; es_event_utimes_t utimes; es_event_write_t write; /** * Events added in macOS 13.0 or later use nonnull pointers. */ es_event_authentication_t *_Nonnull authentication; es_event_xp_malware_detected_t *_Nonnull xp_malware_detected; es_event_xp_malware_remediated_t *_Nonnull xp_malware_remediated; es_event_lw_session_login_t *_Nonnull lw_session_login; es_event_lw_session_logout_t *_Nonnull lw_session_logout; es_event_lw_session_lock_t *_Nonnull lw_session_lock; es_event_lw_session_unlock_t *_Nonnull lw_session_unlock; es_event_screensharing_attach_t *_Nonnull screensharing_attach; es_event_screensharing_detach_t *_Nonnull screensharing_detach; es_event_openssh_login_t *_Nonnull openssh_login; es_event_openssh_logout_t *_Nonnull openssh_logout; es_event_login_login_t *_Nonnull login_login; es_event_login_logout_t *_Nonnull login_logout; es_event_btm_launch_item_add_t *_Nonnull btm_launch_item_add; es_event_btm_launch_item_remove_t *_Nonnull btm_launch_item_remove; es_event_profile_add_t *_Nonnull profile_add; es_event_profile_remove_t *_Nonnull profile_remove; es_event_su_t *_Nonnull su; es_event_authorization_petition_t *_Nonnull authorization_petition; es_event_authorization_judgement_t *_Nonnull authorization_judgement; es_event_sudo_t *_Nonnull sudo; es_event_od_group_add_t *_Nonnull od_group_add; es_event_od_group_remove_t *_Nonnull od_group_remove; es_event_od_group_set_t *_Nonnull od_group_set; es_event_od_modify_password_t *_Nonnull od_modify_password; es_event_od_disable_user_t *_Nonnull od_disable_user; es_event_od_enable_user_t *_Nonnull od_enable_user; es_event_od_attribute_value_add_t *_Nonnull od_attribute_value_add; es_event_od_attribute_value_remove_t *_Nonnull od_attribute_value_remove; es_event_od_attribute_set_t *_Nonnull od_attribute_set; es_event_od_create_user_t *_Nonnull od_create_user; es_event_od_create_group_t *_Nonnull od_create_group; es_event_od_delete_user_t *_Nonnull od_delete_user; es_event_od_delete_group_t *_Nonnull od_delete_group; es_event_xpc_connect_t *_Nonnull xpc_connect; es_event_gatekeeper_user_override_t *_Nonnull gatekeeper_user_override; es_event_tcc_modify_t *_Nonnull tcc_modify; } es_events_t; /** * es_result_t indicates the result of the ES subsystem authorization process * The result_type field indicates if the result is an es_auth_result_t or a uint32_t (flags) */ typedef struct { es_result_type_t result_type; union { es_auth_result_t auth; uint32_t flags; uint8_t reserved[32]; } result; } es_result_t; /** * @brief es_message_t is the top level datatype that encodes information sent * from the ES subsystem to its clients. Each security event being processed * by the ES subsystem will be encoded in an es_message_t. A message can be an * authorization request or a notification of an event that has already taken * place. * * @field version Indicates the message version; some fields are not available * and must not be accessed unless the message version is equal to or * higher than the message version at which the field was introduced. * @field time The time at which the event was generated. * @field mach_time The Mach absolute time at which the event was generated. * @field deadline The Mach absolute time before which an auth event must * be responded to. If a client fails to respond to auth events prior to the `deadline`, * the client will be killed. * Each message can contain its own unique deadline, and some deadlines * can vary substantially. Clients must take care to inspect the deadline * value of each message to know how much time is allotted for processing. * @field process Describes the process that took the action. * @field seq_num Per-client, per-event-type sequence number that can be * inspected to detect whether the kernel had to drop events for this * client. When no events are dropped for this client, seq_num * increments by 1 for every message of that event type. When events * have been dropped, the difference between the last seen sequence * number of that event type plus 1 and seq_num of the received message * indicates the number of events that had to be dropped. * Dropped events generally indicate that more events were generated in * the kernel than the client was able to handle. * Field available only if message version >= 2. * @see global_seq_num * @field action_type Indicates if the action field is an auth or notify action. * @field action For auth events, contains the opaque auth ID that must be * supplied when responding to the event. For notify events, describes * the result of the action. * @field event_type Indicates which event struct is defined in the event union. * @field event Contains data specific to the event type. * @field thread Describes the thread that took the action. May be NULL when * thread is not applicable, for example for trace events that describe * the traced process calling ptrace(PT_TRACE_ME) or for cs invalidated * events that are a result of another process calling * csops(CS_OPS_MARKINVALID). * Field available only if message version >= 4. * @field global_seq_num Per-client sequence number that can be inspected to * detect whether the kernel had to drop events for this client. When no * events are dropped for this client, global_seq_num increments by 1 for * every message. When events have been dropped, the difference between * the last seen global sequence number and the global_seq_num of the * received message indicates the number of events that had to be dropped. * Dropped events generally indicate that more events were generated in * the kernel than the client was able to handle. * Field available only if message version >= 4. * @see seq_num * @field opaque Opaque data that must not be accessed directly. * * @note For events that can be authorized there are unique NOTIFY and AUTH * event types for the same event data, eg: event.exec is the correct union * label for both ES_EVENT_TYPE_AUTH_EXEC and ES_EVENT_TYPE_NOTIFY_EXEC event * types. * * @note For fields marked only available in specific message versions, all * access must be guarded at runtime by checking the value of the message * version field, e.g. * ``` * if (msg->version >= 2) { * acl = msg->event.create.acl; * } * ``` * * @note Fields using Mach time are in the resolution matching the ES client's * architecture. This means they can be compared to mach_absolute_time() and * converted to nanoseconds with the help of mach_timebase_info(). Further * note that on Apple silicon, x86_64 clients running under Rosetta 2 will see * Mach times in a different resolution than native arm64 clients. For more * information on differences regarding Mach time on Apple silicon and Intel-based * Mac computers, see "Addressing Architectural Differences in Your macOS Code": * https://developer.apple.com/documentation/apple_silicon/addressing_architectural_differences_in_your_macos_code */ typedef struct { uint32_t version; struct timespec time; uint64_t mach_time; uint64_t deadline; es_process_t *_Nonnull process; uint64_t seq_num; /* field available only if message version >= 2 */ es_action_type_t action_type; union { es_event_id_t auth; es_result_t notify; } action; es_event_type_t event_type; es_events_t event; es_thread_t *_Nullable thread; /* field available only if message version >= 4 */ uint64_t global_seq_num; /* field available only if message version >= 4 */ uint64_t opaque[]; /* Opaque data that must not be accessed directly */ } es_message_t; __BEGIN_DECLS /** * Calculate the size of an es_message_t. * * @warning This function MUST NOT be used in conjunction with attempting to copy an es_message_t (e.g. * by using the reported size in order to `malloc(3)` a buffer, and `memcpy(3)` an existing es_message_t * into that buffer). Doing so will result in use-after-free bugs. * * @deprecated Please use `es_retain_message` to retain an es_message_t. * * @param msg The message for which the size will be calculated * @return Size of the message */ OS_EXPORT API_DEPRECATED( "Please use es_retain_message to retain a message. Do not use this in conjunction with attempting to copy a message, doing " "so will result in use-after-free bugs.", macos(10.15, 11.0), ios(18.0, 18.0) ) API_UNAVAILABLE(tvos, watchos) size_t es_message_size(const es_message_t *_Nonnull msg); /** * Retains an es_message_t, returning a non-const pointer to the given es_message_t for compatibility with * existing code. * * @warning It is invalid to attempt to write to the returned es_message_t, despite being non-const, and * doing so will result in a crash. * * @deprecated Use es_retain_message to retain a message. * * @param msg The message to be retained * @return non-const pointer to the retained es_message_t. * * @brief The caller must release the memory with `es_free_message` */ OS_EXPORT API_DEPRECATED("Use es_retain_message to retain a message.", macos(10.15, 11.0)) API_UNAVAILABLE(ios, tvos, watchos) es_message_t *_Nullable es_copy_message(const es_message_t *_Nonnull msg); /** * Releases the memory associated with the given es_message_t that was retained via `es_copy_message` * * @deprecated Use `es_release_message` to release a message. * * @param msg The message to be released */ OS_EXPORT API_DEPRECATED("Use es_release_message to release a message.", macos(10.15, 11.0)) API_UNAVAILABLE(ios, tvos, watchos) void es_free_message(es_message_t *_Nonnull msg); /** * Retains the given es_message_t, extending its lifetime until released with `es_release_message`. * * @param msg The message to be retained * * @note It is necessary to retain a message when the es_message_t provided in the event handler block of * `es_new_client` will be processed asynchronously. */ OS_EXPORT API_AVAILABLE(macos(11.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(tvos, watchos) void es_retain_message(const es_message_t *_Nonnull msg); /** * Releases the given es_message_t that was previously retained with `es_retain_message` * * @param msg The message to be released */ OS_EXPORT API_AVAILABLE(macos(11.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(tvos, watchos) void es_release_message(const es_message_t *_Nonnull msg); /** * Get the number of arguments in a message containing an es_event_exec_t * @param event The es_event_exec_t being inspected * @return The number of arguments */ OS_EXPORT API_AVAILABLE(macos(10.15)) API_UNAVAILABLE(ios) API_UNAVAILABLE(tvos, watchos) uint32_t es_exec_arg_count(const es_event_exec_t *_Nonnull event); /** * Get the number of environment variables in a message containing an es_event_exec_t * @param event The es_event_exec_t being inspected * @return The number of environment variables */ OS_EXPORT API_AVAILABLE(macos(10.15)) API_UNAVAILABLE(ios) API_UNAVAILABLE(tvos, watchos) uint32_t es_exec_env_count(const es_event_exec_t *_Nonnull event); /** * Get the number of file descriptors in a message containing an es_event_exec_t * @param event The es_event_exec_t being inspected * @return The number of file descriptors */ OS_EXPORT API_AVAILABLE(macos(11.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(tvos, watchos) uint32_t es_exec_fd_count(const es_event_exec_t *_Nonnull event); /** * Get the argument at the specified position in the message containing an es_event_exec_t * @param event The es_event_exec_t being inspected * @param index Index of the argument to retrieve (starts from 0) * @return es_string_token_t containing a pointer to the argument and its length. * This is a zero-allocation operation. The returned pointer must not outlive exec_event. * @brief Reading an an argument where `index` >= `es_exec_arg_count()` is undefined */ OS_EXPORT API_AVAILABLE(macos(10.15)) API_UNAVAILABLE(ios) API_UNAVAILABLE(tvos, watchos) es_string_token_t es_exec_arg(const es_event_exec_t *_Nonnull event, uint32_t index); /** * Get the environment variable at the specified position in the message containing an es_event_exec_t * @param event The es_event_exec_t being inspected * @param index Index of the environment variable to retrieve (starts from 0) * @return es_string_token_t containing a pointer to the environment variable and its length. * This is zero-allocation operation. The returned pointer must not outlive exec_event. * @brief Reading an an env where `index` >= `es_exec_env_count()` is undefined */ OS_EXPORT API_AVAILABLE(macos(10.15)) API_UNAVAILABLE(ios) API_UNAVAILABLE(tvos, watchos) es_string_token_t es_exec_env(const es_event_exec_t *_Nonnull event, uint32_t index); /** * Get the file descriptor at the specified position in the message containing an es_event_exec_t * @param event The es_event_exec_t being inspected * @param index Index of the file descriptor to retrieve (starts from 0) * @return Pointer to es_fd_t describing the file descriptor. * This is zero-allocation operation. The returned pointer must not outlive exec_event. * @note Reading an fd where `index` >= `es_exec_fd_count()` is undefined */ OS_EXPORT API_AVAILABLE(macos(11.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(tvos, watchos) const es_fd_t *_Nonnull es_exec_fd(const es_event_exec_t *_Nonnull event, uint32_t index); /** * This typedef is no longer used, but exists for API backwards compatibility. */ typedef struct statfs es_statfs_t; __END_DECLS #endif /* __ENDPOINT_SECURITY_MESSAGE_H */