17a0a89d2SRobert Watson /*- 27a0a89d2SRobert Watson * Copyright (c) 2004-2008 Apple Inc. 37a0a89d2SRobert Watson * All rights reserved. 47a0a89d2SRobert Watson * 57a0a89d2SRobert Watson * Redistribution and use in source and binary forms, with or without 67a0a89d2SRobert Watson * modification, are permitted provided that the following conditions 77a0a89d2SRobert Watson * are met: 87a0a89d2SRobert Watson * 97a0a89d2SRobert Watson * 1. Redistributions of source code must retain the above copyright 107a0a89d2SRobert Watson * notice, this list of conditions and the following disclaimer. 117a0a89d2SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 127a0a89d2SRobert Watson * notice, this list of conditions and the following disclaimer in the 137a0a89d2SRobert Watson * documentation and/or other materials provided with the distribution. 147a0a89d2SRobert Watson * 3. Neither the name of Apple Inc. ("Apple") nor the names of 157a0a89d2SRobert Watson * its contributors may be used to endorse or promote products derived 167a0a89d2SRobert Watson * from this software without specific prior written permission. 177a0a89d2SRobert Watson * 187a0a89d2SRobert Watson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 197a0a89d2SRobert Watson * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 207a0a89d2SRobert Watson * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 217a0a89d2SRobert Watson * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 227a0a89d2SRobert Watson * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 237a0a89d2SRobert Watson * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 247a0a89d2SRobert Watson * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 257a0a89d2SRobert Watson * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 267a0a89d2SRobert Watson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 277a0a89d2SRobert Watson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 287a0a89d2SRobert Watson * 29c74c7b73SRobert Watson * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd_darwin.c#3 $ 307a0a89d2SRobert Watson */ 317a0a89d2SRobert Watson 327a0a89d2SRobert Watson #include <sys/types.h> 337a0a89d2SRobert Watson 347a0a89d2SRobert Watson #include <config/config.h> 357a0a89d2SRobert Watson 367a0a89d2SRobert Watson #include <errno.h> 377a0a89d2SRobert Watson #include <stdarg.h> 387a0a89d2SRobert Watson #include <stdlib.h> 397a0a89d2SRobert Watson #include <unistd.h> 407a0a89d2SRobert Watson 417a0a89d2SRobert Watson #include <bsm/audit.h> 427a0a89d2SRobert Watson #include <bsm/audit_uevents.h> 437a0a89d2SRobert Watson #include <bsm/auditd_lib.h> 447a0a89d2SRobert Watson #include <bsm/libbsm.h> 457a0a89d2SRobert Watson 467a0a89d2SRobert Watson #include <asl.h> 477a0a89d2SRobert Watson #include <launch.h> 487a0a89d2SRobert Watson #include <notify.h> 497a0a89d2SRobert Watson #include <mach/port.h> 507a0a89d2SRobert Watson #include <mach/mach_error.h> 517a0a89d2SRobert Watson #include <mach/mach_traps.h> 527a0a89d2SRobert Watson #include <mach/mach.h> 537a0a89d2SRobert Watson #include <mach/host_special_ports.h> 547a0a89d2SRobert Watson 557a0a89d2SRobert Watson #include "auditd.h" 567a0a89d2SRobert Watson 577a0a89d2SRobert Watson #include "auditd_controlServer.h" 587a0a89d2SRobert Watson #include "audit_triggersServer.h" 597a0a89d2SRobert Watson 607a0a89d2SRobert Watson /* 617a0a89d2SRobert Watson * Apple System Logger Handles. 627a0a89d2SRobert Watson */ 637a0a89d2SRobert Watson static aslmsg au_aslmsg = NULL; 647a0a89d2SRobert Watson static aslclient au_aslclient = NULL; 657a0a89d2SRobert Watson 667a0a89d2SRobert Watson static mach_port_t control_port = MACH_PORT_NULL; 677a0a89d2SRobert Watson static mach_port_t signal_port = MACH_PORT_NULL; 687a0a89d2SRobert Watson static mach_port_t port_set = MACH_PORT_NULL; 697a0a89d2SRobert Watson 707a0a89d2SRobert Watson /* 717a0a89d2SRobert Watson * Current auditing state (cache). 727a0a89d2SRobert Watson */ 737a0a89d2SRobert Watson static int auditing_state = AUD_STATE_INIT; 747a0a89d2SRobert Watson 757a0a89d2SRobert Watson /* 767a0a89d2SRobert Watson * Maximum idle time before auditd terminates under launchd. 777a0a89d2SRobert Watson * If it is zero then auditd does not timeout while idle. 787a0a89d2SRobert Watson */ 797a0a89d2SRobert Watson static int max_idletime = 0; 807a0a89d2SRobert Watson 817a0a89d2SRobert Watson #ifndef __BSM_INTERNAL_NOTIFY_KEY 827a0a89d2SRobert Watson #define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" 837a0a89d2SRobert Watson #endif /* __BSM_INTERNAL_NOTIFY_KEY */ 847a0a89d2SRobert Watson 857a0a89d2SRobert Watson #ifndef __AUDIT_LAUNCHD_LABEL 86c74c7b73SRobert Watson #define __AUDIT_LAUNCHD_LABEL "com.apple.auditd" 877a0a89d2SRobert Watson #endif /* __AUDIT_LAUNCHD_LABEL */ 887a0a89d2SRobert Watson 897a0a89d2SRobert Watson #define MAX_MSG_SIZE 4096 907a0a89d2SRobert Watson 917a0a89d2SRobert Watson /* 927a0a89d2SRobert Watson * Open and set up system logging. 937a0a89d2SRobert Watson */ 947a0a89d2SRobert Watson void 957a0a89d2SRobert Watson auditd_openlog(int debug, gid_t gid) 967a0a89d2SRobert Watson { 977a0a89d2SRobert Watson uint32_t opt = 0; 987a0a89d2SRobert Watson char *cp = NULL; 997a0a89d2SRobert Watson 1007a0a89d2SRobert Watson if (debug) 1017a0a89d2SRobert Watson opt = ASL_OPT_STDERR; 1027a0a89d2SRobert Watson 103c74c7b73SRobert Watson au_aslclient = asl_open("auditd", "com.apple.auditd", opt); 1047a0a89d2SRobert Watson au_aslmsg = asl_new(ASL_TYPE_MSG); 1057a0a89d2SRobert Watson 1067a0a89d2SRobert Watson #ifdef ASL_KEY_READ_UID 1077a0a89d2SRobert Watson /* 1087a0a89d2SRobert Watson * Make it only so the audit administrator and members of the audit 1097a0a89d2SRobert Watson * review group (if used) have access to the auditd system log messages. 1107a0a89d2SRobert Watson */ 1117a0a89d2SRobert Watson asl_set(au_aslmsg, ASL_KEY_READ_UID, "0"); 1127a0a89d2SRobert Watson asprintf(&cp, "%u", gid); 1137a0a89d2SRobert Watson if (cp != NULL) { 1147a0a89d2SRobert Watson #ifdef ASL_KEY_READ_GID 1157a0a89d2SRobert Watson asl_set(au_aslmsg, ASL_KEY_READ_GID, cp); 1167a0a89d2SRobert Watson #endif 1177a0a89d2SRobert Watson free(cp); 1187a0a89d2SRobert Watson } 1197a0a89d2SRobert Watson #endif 1207a0a89d2SRobert Watson 1217a0a89d2SRobert Watson /* 1227a0a89d2SRobert Watson * Set the client-side system log filtering. 1237a0a89d2SRobert Watson */ 1247a0a89d2SRobert Watson if (debug) 1257a0a89d2SRobert Watson asl_set_filter(au_aslclient, 1267a0a89d2SRobert Watson ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); 1277a0a89d2SRobert Watson else 1287a0a89d2SRobert Watson asl_set_filter(au_aslclient, 1297a0a89d2SRobert Watson ASL_FILTER_MASK_UPTO(ASL_LEVEL_INFO)); 1307a0a89d2SRobert Watson } 1317a0a89d2SRobert Watson 1327a0a89d2SRobert Watson /* 1337a0a89d2SRobert Watson * Log messages at different priority levels. 1347a0a89d2SRobert Watson */ 1357a0a89d2SRobert Watson void 1367a0a89d2SRobert Watson auditd_log_err(const char *fmt, ...) 1377a0a89d2SRobert Watson { 1387a0a89d2SRobert Watson va_list ap; 1397a0a89d2SRobert Watson 1407a0a89d2SRobert Watson va_start(ap, fmt); 1417a0a89d2SRobert Watson asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_ERR, fmt, ap); 1427a0a89d2SRobert Watson va_end(ap); 1437a0a89d2SRobert Watson } 1447a0a89d2SRobert Watson 1457a0a89d2SRobert Watson void 1467a0a89d2SRobert Watson auditd_log_notice(const char *fmt, ...) 1477a0a89d2SRobert Watson { 1487a0a89d2SRobert Watson va_list ap; 1497a0a89d2SRobert Watson 1507a0a89d2SRobert Watson va_start(ap, fmt); 1517a0a89d2SRobert Watson asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_NOTICE, fmt, ap); 1527a0a89d2SRobert Watson va_end(ap); 1537a0a89d2SRobert Watson } 1547a0a89d2SRobert Watson 1557a0a89d2SRobert Watson void 1567a0a89d2SRobert Watson auditd_log_info(const char *fmt, ...) 1577a0a89d2SRobert Watson { 1587a0a89d2SRobert Watson va_list ap; 1597a0a89d2SRobert Watson 1607a0a89d2SRobert Watson va_start(ap, fmt); 1617a0a89d2SRobert Watson asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_INFO, fmt, ap); 1627a0a89d2SRobert Watson va_end(ap); 1637a0a89d2SRobert Watson } 1647a0a89d2SRobert Watson 1657a0a89d2SRobert Watson void 1667a0a89d2SRobert Watson auditd_log_debug(const char *fmt, ...) 1677a0a89d2SRobert Watson { 1687a0a89d2SRobert Watson va_list ap; 1697a0a89d2SRobert Watson 1707a0a89d2SRobert Watson va_start(ap, fmt); 1717a0a89d2SRobert Watson asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_DEBUG, fmt, ap); 1727a0a89d2SRobert Watson va_end(ap); 1737a0a89d2SRobert Watson } 1747a0a89d2SRobert Watson 1757a0a89d2SRobert Watson /* 1767a0a89d2SRobert Watson * Get the auditing state from the kernel and cache it. 1777a0a89d2SRobert Watson */ 1787a0a89d2SRobert Watson static void 1797a0a89d2SRobert Watson init_audit_state(void) 1807a0a89d2SRobert Watson { 1817a0a89d2SRobert Watson long au_cond; 1827a0a89d2SRobert Watson 1837a0a89d2SRobert Watson if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { 1847a0a89d2SRobert Watson if (errno != ENOSYS) { 1857a0a89d2SRobert Watson auditd_log_err("Audit status check failed (%s)", 1867a0a89d2SRobert Watson strerror(errno)); 1877a0a89d2SRobert Watson } 1887a0a89d2SRobert Watson auditing_state = AUD_STATE_DISABLED; 1897a0a89d2SRobert Watson } else 1907a0a89d2SRobert Watson if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED) 1917a0a89d2SRobert Watson auditing_state = AUD_STATE_DISABLED; 1927a0a89d2SRobert Watson else 1937a0a89d2SRobert Watson auditing_state = AUD_STATE_ENABLED; 1947a0a89d2SRobert Watson } 1957a0a89d2SRobert Watson 1967a0a89d2SRobert Watson /* 1977a0a89d2SRobert Watson * Update the cached auditing state. Let other tasks that may be caching it 1987a0a89d2SRobert Watson * as well to update their state via notify(3). 1997a0a89d2SRobert Watson */ 2007a0a89d2SRobert Watson void 2017a0a89d2SRobert Watson auditd_set_state(int state) 2027a0a89d2SRobert Watson { 2037a0a89d2SRobert Watson int old_auditing_state = auditing_state; 2047a0a89d2SRobert Watson 2057a0a89d2SRobert Watson if (state == AUD_STATE_INIT) 2067a0a89d2SRobert Watson init_audit_state(); 2077a0a89d2SRobert Watson else 2087a0a89d2SRobert Watson auditing_state = state; 2097a0a89d2SRobert Watson 2107a0a89d2SRobert Watson if (auditing_state != old_auditing_state) { 2117a0a89d2SRobert Watson notify_post(__BSM_INTERNAL_NOTIFY_KEY); 2127a0a89d2SRobert Watson 2137a0a89d2SRobert Watson if (auditing_state == AUD_STATE_ENABLED) 2147a0a89d2SRobert Watson auditd_log_notice("Auditing enabled"); 2157a0a89d2SRobert Watson if (auditing_state == AUD_STATE_DISABLED) 2167a0a89d2SRobert Watson auditd_log_notice("Auditing disabled"); 2177a0a89d2SRobert Watson } 2187a0a89d2SRobert Watson } 2197a0a89d2SRobert Watson 2207a0a89d2SRobert Watson /* 2217a0a89d2SRobert Watson * Get the cached auditing state. 2227a0a89d2SRobert Watson */ 2237a0a89d2SRobert Watson int 2247a0a89d2SRobert Watson auditd_get_state(void) 2257a0a89d2SRobert Watson { 2267a0a89d2SRobert Watson 2277a0a89d2SRobert Watson if (auditing_state == AUD_STATE_INIT) { 2287a0a89d2SRobert Watson init_audit_state(); 2297a0a89d2SRobert Watson notify_post(__BSM_INTERNAL_NOTIFY_KEY); 2307a0a89d2SRobert Watson } 2317a0a89d2SRobert Watson 2327a0a89d2SRobert Watson return (auditing_state); 2337a0a89d2SRobert Watson } 2347a0a89d2SRobert Watson 2357a0a89d2SRobert Watson /* 2367a0a89d2SRobert Watson * Lookup the audit mach port in the launchd dictionary. 2377a0a89d2SRobert Watson */ 2387a0a89d2SRobert Watson static mach_port_t 2397a0a89d2SRobert Watson lookup_machport(const char *label) 2407a0a89d2SRobert Watson { 2417a0a89d2SRobert Watson launch_data_t msg, msd, ld, cdict, to; 2427a0a89d2SRobert Watson mach_port_t mp = MACH_PORT_NULL; 2437a0a89d2SRobert Watson 2447a0a89d2SRobert Watson msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); 2457a0a89d2SRobert Watson 2467a0a89d2SRobert Watson cdict = launch_msg(msg); 2477a0a89d2SRobert Watson if (cdict == NULL) { 2487a0a89d2SRobert Watson auditd_log_err("launch_msg(\"" LAUNCH_KEY_CHECKIN 2497a0a89d2SRobert Watson "\") IPC failure: %m"); 2507a0a89d2SRobert Watson return (MACH_PORT_NULL); 2517a0a89d2SRobert Watson } 2527a0a89d2SRobert Watson 2537a0a89d2SRobert Watson if (launch_data_get_type(cdict) == LAUNCH_DATA_ERRNO) { 2547a0a89d2SRobert Watson errno = launch_data_get_errno(cdict); 2557a0a89d2SRobert Watson auditd_log_err("launch_data_get_type() can't get dict: %m"); 2567a0a89d2SRobert Watson return (MACH_PORT_NULL); 2577a0a89d2SRobert Watson } 2587a0a89d2SRobert Watson 2597a0a89d2SRobert Watson to = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_TIMEOUT); 2607a0a89d2SRobert Watson if (to) { 2617a0a89d2SRobert Watson max_idletime = launch_data_get_integer(to); 2627a0a89d2SRobert Watson auditd_log_debug("launchd timeout set to %d", max_idletime); 2637a0a89d2SRobert Watson } else { 2647a0a89d2SRobert Watson auditd_log_debug("launchd timeout not set, setting to 60"); 2657a0a89d2SRobert Watson max_idletime = 60; 2667a0a89d2SRobert Watson } 2677a0a89d2SRobert Watson 2687a0a89d2SRobert Watson msd = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_MACHSERVICES); 2697a0a89d2SRobert Watson if (msd == NULL) { 2707a0a89d2SRobert Watson auditd_log_err( 2717a0a89d2SRobert Watson "launch_data_dict_lookup() can't get mach services"); 2727a0a89d2SRobert Watson return (MACH_PORT_NULL); 2737a0a89d2SRobert Watson } 2747a0a89d2SRobert Watson 2757a0a89d2SRobert Watson ld = launch_data_dict_lookup(msd, label); 2767a0a89d2SRobert Watson if (ld == NULL) { 2777a0a89d2SRobert Watson auditd_log_err("launch_data_dict_lookup can't find %s", label); 2787a0a89d2SRobert Watson return (MACH_PORT_NULL); 2797a0a89d2SRobert Watson } 2807a0a89d2SRobert Watson 2817a0a89d2SRobert Watson mp = launch_data_get_machport(ld); 2827a0a89d2SRobert Watson 2837a0a89d2SRobert Watson return (mp); 2847a0a89d2SRobert Watson } 2857a0a89d2SRobert Watson 2867a0a89d2SRobert Watson static int 2877a0a89d2SRobert Watson mach_setup(int launchd_flag) 2887a0a89d2SRobert Watson { 2897a0a89d2SRobert Watson mach_msg_type_name_t poly; 2907a0a89d2SRobert Watson 2917a0a89d2SRobert Watson /* 2927a0a89d2SRobert Watson * Allocate a port set. 2937a0a89d2SRobert Watson */ 2947a0a89d2SRobert Watson if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, 2957a0a89d2SRobert Watson &port_set) != KERN_SUCCESS) { 2967a0a89d2SRobert Watson auditd_log_err("Allocation of port set failed"); 2977a0a89d2SRobert Watson return (-1); 2987a0a89d2SRobert Watson } 2997a0a89d2SRobert Watson 3007a0a89d2SRobert Watson 3017a0a89d2SRobert Watson /* 3027a0a89d2SRobert Watson * Allocate a signal reflection port. 3037a0a89d2SRobert Watson */ 3047a0a89d2SRobert Watson if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, 3057a0a89d2SRobert Watson &signal_port) != KERN_SUCCESS || 3067a0a89d2SRobert Watson mach_port_move_member(mach_task_self(), signal_port, port_set) != 3077a0a89d2SRobert Watson KERN_SUCCESS) { 3087a0a89d2SRobert Watson auditd_log_err("Allocation of signal port failed"); 3097a0a89d2SRobert Watson return (-1); 3107a0a89d2SRobert Watson } 3117a0a89d2SRobert Watson 3127a0a89d2SRobert Watson /* 3137a0a89d2SRobert Watson * Allocate a trigger port. 3147a0a89d2SRobert Watson */ 3157a0a89d2SRobert Watson if (launchd_flag) { 3167a0a89d2SRobert Watson /* 3177a0a89d2SRobert Watson * If started under launchd, lookup port in launchd dictionary. 3187a0a89d2SRobert Watson */ 3197a0a89d2SRobert Watson if ((control_port = lookup_machport(__AUDIT_LAUNCHD_LABEL)) == 3207a0a89d2SRobert Watson MACH_PORT_NULL || mach_port_move_member(mach_task_self(), 3217a0a89d2SRobert Watson control_port, port_set) != KERN_SUCCESS) { 3227a0a89d2SRobert Watson auditd_log_err("Cannot get Mach control port" 3237a0a89d2SRobert Watson " via launchd"); 3247a0a89d2SRobert Watson return (-1); 3257a0a89d2SRobert Watson } else 3267a0a89d2SRobert Watson auditd_log_debug("Mach control port registered" 3277a0a89d2SRobert Watson " via launchd"); 3287a0a89d2SRobert Watson } else { 3297a0a89d2SRobert Watson /* 3307a0a89d2SRobert Watson * If not started under launchd, allocate port and register. 3317a0a89d2SRobert Watson */ 3327a0a89d2SRobert Watson if (mach_port_allocate(mach_task_self(), 3337a0a89d2SRobert Watson MACH_PORT_RIGHT_RECEIVE, &control_port) != KERN_SUCCESS || 3347a0a89d2SRobert Watson mach_port_move_member(mach_task_self(), control_port, 3357a0a89d2SRobert Watson port_set) != KERN_SUCCESS) 3367a0a89d2SRobert Watson auditd_log_err("Allocation of trigger port failed"); 3377a0a89d2SRobert Watson 3387a0a89d2SRobert Watson /* 3397a0a89d2SRobert Watson * Create a send right on our trigger port. 3407a0a89d2SRobert Watson */ 3417a0a89d2SRobert Watson mach_port_extract_right(mach_task_self(), control_port, 3427a0a89d2SRobert Watson MACH_MSG_TYPE_MAKE_SEND, &control_port, &poly); 3437a0a89d2SRobert Watson 3447a0a89d2SRobert Watson /* 3457a0a89d2SRobert Watson * Register the trigger port with the kernel. 3467a0a89d2SRobert Watson */ 3477a0a89d2SRobert Watson if (host_set_audit_control_port(mach_host_self(), 3487a0a89d2SRobert Watson control_port) != KERN_SUCCESS) { 3497a0a89d2SRobert Watson auditd_log_err("Cannot set Mach control port"); 3507a0a89d2SRobert Watson return (-1); 3517a0a89d2SRobert Watson } else 3527a0a89d2SRobert Watson auditd_log_debug("Mach control port registered"); 3537a0a89d2SRobert Watson } 3547a0a89d2SRobert Watson 3557a0a89d2SRobert Watson return (0); 3567a0a89d2SRobert Watson } 3577a0a89d2SRobert Watson 3587a0a89d2SRobert Watson /* 3597a0a89d2SRobert Watson * Open the trigger messaging mechanism. 3607a0a89d2SRobert Watson */ 3617a0a89d2SRobert Watson int 3627a0a89d2SRobert Watson auditd_open_trigger(int launchd_flag) 3637a0a89d2SRobert Watson { 3647a0a89d2SRobert Watson 3657a0a89d2SRobert Watson return (mach_setup(launchd_flag)); 3667a0a89d2SRobert Watson } 3677a0a89d2SRobert Watson 3687a0a89d2SRobert Watson /* 3697a0a89d2SRobert Watson * Close the trigger messaging mechanism. 3707a0a89d2SRobert Watson */ 3717a0a89d2SRobert Watson int 3727a0a89d2SRobert Watson auditd_close_trigger(void) 3737a0a89d2SRobert Watson { 3747a0a89d2SRobert Watson 3757a0a89d2SRobert Watson return (0); 3767a0a89d2SRobert Watson } 3777a0a89d2SRobert Watson 3787a0a89d2SRobert Watson /* 3797a0a89d2SRobert Watson * Combined server handler. Called by the mach message loop when there is 3807a0a89d2SRobert Watson * a trigger or signal message. 3817a0a89d2SRobert Watson */ 3827a0a89d2SRobert Watson static boolean_t 3837a0a89d2SRobert Watson auditd_combined_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) 3847a0a89d2SRobert Watson { 3857a0a89d2SRobert Watson mach_port_t local_port = InHeadP->msgh_local_port; 3867a0a89d2SRobert Watson 3877a0a89d2SRobert Watson /* Reset the idle time alarm, if used. */ 3887a0a89d2SRobert Watson if (max_idletime) 3897a0a89d2SRobert Watson alarm(max_idletime); 3907a0a89d2SRobert Watson 3917a0a89d2SRobert Watson if (local_port == signal_port) { 3927a0a89d2SRobert Watson int signo = InHeadP->msgh_id; 3937a0a89d2SRobert Watson 3947a0a89d2SRobert Watson switch(signo) { 3957a0a89d2SRobert Watson case SIGTERM: 3967a0a89d2SRobert Watson case SIGALRM: 3977a0a89d2SRobert Watson auditd_terminate(); 3987a0a89d2SRobert Watson /* Not reached. */ 3997a0a89d2SRobert Watson 4007a0a89d2SRobert Watson case SIGCHLD: 4017a0a89d2SRobert Watson auditd_reap_children(); 4027a0a89d2SRobert Watson return (TRUE); 4037a0a89d2SRobert Watson 4047a0a89d2SRobert Watson case SIGHUP: 4057a0a89d2SRobert Watson auditd_config_controls(); 4067a0a89d2SRobert Watson return (TRUE); 4077a0a89d2SRobert Watson 4087a0a89d2SRobert Watson default: 4097a0a89d2SRobert Watson auditd_log_info("Received signal %d", signo); 4107a0a89d2SRobert Watson return (TRUE); 4117a0a89d2SRobert Watson } 4127a0a89d2SRobert Watson } else if (local_port == control_port) { 4137a0a89d2SRobert Watson boolean_t result; 4147a0a89d2SRobert Watson 4157a0a89d2SRobert Watson result = audit_triggers_server(InHeadP, OutHeadP); 4167a0a89d2SRobert Watson if (!result) 4177a0a89d2SRobert Watson result = auditd_control_server(InHeadP, OutHeadP); 4187a0a89d2SRobert Watson return (result); 4197a0a89d2SRobert Watson } 4207a0a89d2SRobert Watson auditd_log_info("Recevied msg on bad port 0x%x.", local_port); 4217a0a89d2SRobert Watson return (FALSE); 4227a0a89d2SRobert Watson } 4237a0a89d2SRobert Watson 4247a0a89d2SRobert Watson /* 4257a0a89d2SRobert Watson * The main event loop. Wait for trigger messages or signals and handle them. 4267a0a89d2SRobert Watson * It should not return unless there is a problem. 4277a0a89d2SRobert Watson */ 4287a0a89d2SRobert Watson void 4297a0a89d2SRobert Watson auditd_wait_for_events(void) 4307a0a89d2SRobert Watson { 4317a0a89d2SRobert Watson kern_return_t result; 4327a0a89d2SRobert Watson 4337a0a89d2SRobert Watson /* 4347a0a89d2SRobert Watson * Call the mach messaging server loop. 4357a0a89d2SRobert Watson */ 4367a0a89d2SRobert Watson result = mach_msg_server(auditd_combined_server, MAX_MSG_SIZE, 4377a0a89d2SRobert Watson port_set, MACH_MSG_OPTION_NONE); 4387a0a89d2SRobert Watson } 4397a0a89d2SRobert Watson 4407a0a89d2SRobert Watson /* 4417a0a89d2SRobert Watson * Implementation of the audit_triggers() MIG simpleroutine. Simply a 4427a0a89d2SRobert Watson * wrapper function. This handles input from the kernel on the host 4437a0a89d2SRobert Watson * special mach port. 4447a0a89d2SRobert Watson */ 4457a0a89d2SRobert Watson kern_return_t 4467a0a89d2SRobert Watson audit_triggers(mach_port_t __unused audit_port, int trigger) 4477a0a89d2SRobert Watson { 4487a0a89d2SRobert Watson 4497a0a89d2SRobert Watson auditd_handle_trigger(trigger); 4507a0a89d2SRobert Watson 4517a0a89d2SRobert Watson return (KERN_SUCCESS); 4527a0a89d2SRobert Watson } 4537a0a89d2SRobert Watson 4547a0a89d2SRobert Watson /* 4557a0a89d2SRobert Watson * Implementation of the auditd_control() MIG simpleroutine. Simply a 4567a0a89d2SRobert Watson * wrapper function. This handles input from the audit(1) tool. 4577a0a89d2SRobert Watson */ 4587a0a89d2SRobert Watson kern_return_t 4597a0a89d2SRobert Watson auditd_control(mach_port_t __unused auditd_port, int trigger) 4607a0a89d2SRobert Watson { 4617a0a89d2SRobert Watson 4627a0a89d2SRobert Watson auditd_handle_trigger(trigger); 4637a0a89d2SRobert Watson 4647a0a89d2SRobert Watson return (KERN_SUCCESS); 4657a0a89d2SRobert Watson } 4667a0a89d2SRobert Watson 4677a0a89d2SRobert Watson /* 4687a0a89d2SRobert Watson * When we get a signal, we are often not at a clean point. So, little can 4697a0a89d2SRobert Watson * be done in the signal handler itself. Instead, we send a message to the 4707a0a89d2SRobert Watson * main servicing loop to do proper handling from a non-signal-handler 4717a0a89d2SRobert Watson * context. 4727a0a89d2SRobert Watson */ 4737a0a89d2SRobert Watson void 4747a0a89d2SRobert Watson auditd_relay_signal(int signal) 4757a0a89d2SRobert Watson { 4767a0a89d2SRobert Watson mach_msg_empty_send_t msg; 4777a0a89d2SRobert Watson 4787a0a89d2SRobert Watson msg.header.msgh_id = signal; 4797a0a89d2SRobert Watson msg.header.msgh_remote_port = signal_port; 4807a0a89d2SRobert Watson msg.header.msgh_local_port = MACH_PORT_NULL; 4817a0a89d2SRobert Watson msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); 4827a0a89d2SRobert Watson mach_msg(&(msg.header), MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof(msg), 4837a0a89d2SRobert Watson 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 4847a0a89d2SRobert Watson } 485