152267f74SRobert Watson /*- 206edd2f1SRobert Watson * Copyright (c) 2004-2009 Apple Inc. 3ca0716f5SRobert Watson * All rights reserved. 4ca0716f5SRobert Watson * 5ca0716f5SRobert Watson * Redistribution and use in source and binary forms, with or without 6ca0716f5SRobert Watson * modification, are permitted provided that the following conditions 7ca0716f5SRobert Watson * are met: 8ca0716f5SRobert Watson * 9ca0716f5SRobert Watson * 1. Redistributions of source code must retain the above copyright 10ca0716f5SRobert Watson * notice, this list of conditions and the following disclaimer. 11ca0716f5SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 12ca0716f5SRobert Watson * notice, this list of conditions and the following disclaimer in the 13ca0716f5SRobert Watson * documentation and/or other materials provided with the distribution. 1452267f74SRobert Watson * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15ca0716f5SRobert Watson * its contributors may be used to endorse or promote products derived 16ca0716f5SRobert Watson * from this software without specific prior written permission. 17ca0716f5SRobert Watson * 18ca0716f5SRobert Watson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19ca0716f5SRobert Watson * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20ca0716f5SRobert Watson * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21ca0716f5SRobert Watson * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22ca0716f5SRobert Watson * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23ca0716f5SRobert Watson * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24ca0716f5SRobert Watson * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25ca0716f5SRobert Watson * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26ca0716f5SRobert Watson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27ca0716f5SRobert Watson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28ca0716f5SRobert Watson */ 29ca0716f5SRobert Watson 307a0a89d2SRobert Watson #include <sys/types.h> 3152267f74SRobert Watson 3252267f74SRobert Watson #include <config/config.h> 3352267f74SRobert Watson 34ca0716f5SRobert Watson #include <sys/dirent.h> 3552267f74SRobert Watson #ifdef HAVE_FULL_QUEUE_H 36ca0716f5SRobert Watson #include <sys/queue.h> 3752267f74SRobert Watson #else /* !HAVE_FULL_QUEUE_H */ 3852267f74SRobert Watson #include <compat/queue.h> 3952267f74SRobert Watson #endif /* !HAVE_FULL_QUEUE_H */ 407a0a89d2SRobert Watson #include <sys/mman.h> 417a0a89d2SRobert Watson #include <sys/param.h> 42ca0716f5SRobert Watson #include <sys/stat.h> 43ca0716f5SRobert Watson #include <sys/wait.h> 44ca0716f5SRobert Watson 45ca0716f5SRobert Watson #include <bsm/audit.h> 46ca0716f5SRobert Watson #include <bsm/audit_uevents.h> 477a0a89d2SRobert Watson #include <bsm/auditd_lib.h> 48ca0716f5SRobert Watson #include <bsm/libbsm.h> 49ca0716f5SRobert Watson 50506764c6SRobert Watson #include <err.h> 51ca0716f5SRobert Watson #include <errno.h> 52ca0716f5SRobert Watson #include <fcntl.h> 5323bf6e20SRobert Watson #include <grp.h> 54ca0716f5SRobert Watson #include <stdio.h> 55ca0716f5SRobert Watson #include <stdlib.h> 56ca0716f5SRobert Watson #include <time.h> 57ca0716f5SRobert Watson #include <unistd.h> 58ca0716f5SRobert Watson #include <signal.h> 59ca0716f5SRobert Watson #include <string.h> 60ca0716f5SRobert Watson 61ca0716f5SRobert Watson #include "auditd.h" 6252267f74SRobert Watson 6352267f74SRobert Watson #ifndef HAVE_STRLCPY 6452267f74SRobert Watson #include <compat/strlcpy.h> 6552267f74SRobert Watson #endif 66ca0716f5SRobert Watson 677a0a89d2SRobert Watson /* 6806edd2f1SRobert Watson * XXX The following are temporary until these can be added to the kernel 697a0a89d2SRobert Watson * audit.h header. 707a0a89d2SRobert Watson */ 717a0a89d2SRobert Watson #ifndef AUDIT_TRIGGER_INITIALIZE 727a0a89d2SRobert Watson #define AUDIT_TRIGGER_INITIALIZE 7 737a0a89d2SRobert Watson #endif 7406edd2f1SRobert Watson #ifndef AUDIT_TRIGGER_EXPIRE_TRAILS 7506edd2f1SRobert Watson #define AUDIT_TRIGGER_EXPIRE_TRAILS 8 7606edd2f1SRobert Watson #endif 7706edd2f1SRobert Watson 78ca0716f5SRobert Watson 79ca0716f5SRobert Watson /* 807a0a89d2SRobert Watson * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and 817a0a89d2SRobert Watson * http://wiki.freebsd.org/launchd for more information. 827a0a89d2SRobert Watson * 837a0a89d2SRobert Watson * In order for auditd to work "on demand" with launchd(8) it can't: 847a0a89d2SRobert Watson * call daemon(3) 857a0a89d2SRobert Watson * call fork and having the parent process exit 867a0a89d2SRobert Watson * change uids or gids. 877a0a89d2SRobert Watson * set up the current working directory or chroot. 887a0a89d2SRobert Watson * set the session id 897a0a89d2SRobert Watson * change stdio to /dev/null. 907a0a89d2SRobert Watson * call setrusage(2) 917a0a89d2SRobert Watson * call setpriority(2) 927a0a89d2SRobert Watson * Ignore SIGTERM. 937a0a89d2SRobert Watson * auditd (in 'launchd mode') is launched on demand so it must catch 947a0a89d2SRobert Watson * SIGTERM to exit cleanly. 957a0a89d2SRobert Watson */ 967a0a89d2SRobert Watson static int launchd_flag = 0; 977a0a89d2SRobert Watson 987a0a89d2SRobert Watson /* 997a0a89d2SRobert Watson * The GID of the audit review group (if used). The audit trail files and 1007a0a89d2SRobert Watson * system logs (Mac OS X only) can only be reviewed by members of this group 1017a0a89d2SRobert Watson * or the audit administrator (aka. "root"). 1027a0a89d2SRobert Watson */ 1037a0a89d2SRobert Watson static gid_t audit_review_gid = -1; 1047a0a89d2SRobert Watson 1057a0a89d2SRobert Watson /* 1067a0a89d2SRobert Watson * The path and file name of the last audit trail file. 1077a0a89d2SRobert Watson */ 1087a0a89d2SRobert Watson static char *lastfile = NULL; 1097a0a89d2SRobert Watson 1107a0a89d2SRobert Watson /* 1117a0a89d2SRobert Watson * Error starting auditd. Run warn script and exit. 112ca0716f5SRobert Watson */ 113ca0716f5SRobert Watson static void 114ca0716f5SRobert Watson fail_exit(void) 115ca0716f5SRobert Watson { 116ca0716f5SRobert Watson 117ca0716f5SRobert Watson audit_warn_nostart(); 118ca0716f5SRobert Watson exit(1); 119ca0716f5SRobert Watson } 120ca0716f5SRobert Watson 121ca0716f5SRobert Watson /* 1227a0a89d2SRobert Watson * Follow the 'current' symlink to get the active trail file name. 123ca0716f5SRobert Watson */ 124ca0716f5SRobert Watson static char * 1257a0a89d2SRobert Watson get_curfile(void) 126ca0716f5SRobert Watson { 1277a0a89d2SRobert Watson char *cf; 1287a0a89d2SRobert Watson int len; 129ca0716f5SRobert Watson 1307a0a89d2SRobert Watson cf = malloc(MAXPATHLEN); 1317a0a89d2SRobert Watson if (cf == NULL) { 1327a0a89d2SRobert Watson auditd_log_err("malloc failed: %m"); 133ca0716f5SRobert Watson return (NULL); 13452267f74SRobert Watson } 1357a0a89d2SRobert Watson 1367a0a89d2SRobert Watson len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1); 1377a0a89d2SRobert Watson if (len < 0) { 1387a0a89d2SRobert Watson free(cf); 1397a0a89d2SRobert Watson return (NULL); 1407a0a89d2SRobert Watson } 1417a0a89d2SRobert Watson 1427a0a89d2SRobert Watson /* readlink() doesn't terminate string. */ 1437a0a89d2SRobert Watson cf[len] = '\0'; 1447a0a89d2SRobert Watson 1457a0a89d2SRobert Watson return (cf); 146ca0716f5SRobert Watson } 147ca0716f5SRobert Watson 148ca0716f5SRobert Watson /* 149ca0716f5SRobert Watson * Close the previous audit trail file. 150ca0716f5SRobert Watson */ 151ca0716f5SRobert Watson static int 152ca0716f5SRobert Watson close_lastfile(char *TS) 153ca0716f5SRobert Watson { 154ca0716f5SRobert Watson char *ptr; 155ca0716f5SRobert Watson char *oldname; 156ca0716f5SRobert Watson 1577a0a89d2SRobert Watson /* If lastfile is NULL try to get it from the 'current' link. */ 1587a0a89d2SRobert Watson if (lastfile == NULL) 1597a0a89d2SRobert Watson lastfile = get_curfile(); 1607a0a89d2SRobert Watson 161ca0716f5SRobert Watson if (lastfile != NULL) { 162aa772005SRobert Watson oldname = strdup(lastfile); 163ca0716f5SRobert Watson if (oldname == NULL) 164ca0716f5SRobert Watson return (-1); 165ca0716f5SRobert Watson 166ca0716f5SRobert Watson /* Rename the last file -- append timestamp. */ 167ca0716f5SRobert Watson if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { 16806edd2f1SRobert Watson memcpy(ptr, TS, POSTFIX_LEN); 169aa772005SRobert Watson if (auditd_rename(oldname, lastfile) != 0) 1707a0a89d2SRobert Watson auditd_log_err( 171bb97b418SRobert Watson "Could not rename %s to %s: %m", oldname, 172bb97b418SRobert Watson lastfile); 1734bd0c025SRobert Watson else { 1747a0a89d2SRobert Watson /* 1757a0a89d2SRobert Watson * Remove the 'current' symlink since the link 1767a0a89d2SRobert Watson * is now invalid. 1777a0a89d2SRobert Watson */ 1787a0a89d2SRobert Watson (void) unlink(AUDIT_CURRENT_LINK); 1797a0a89d2SRobert Watson auditd_log_notice("renamed %s to %s", 180ca0716f5SRobert Watson oldname, lastfile); 1814bd0c025SRobert Watson audit_warn_closefile(lastfile); 1824bd0c025SRobert Watson } 18352267f74SRobert Watson } else 1847a0a89d2SRobert Watson auditd_log_err("Could not rename %s to %s", oldname, 18552267f74SRobert Watson lastfile); 186ca0716f5SRobert Watson free(lastfile); 187ca0716f5SRobert Watson free(oldname); 188ca0716f5SRobert Watson lastfile = NULL; 189ca0716f5SRobert Watson } 190ca0716f5SRobert Watson return (0); 191ca0716f5SRobert Watson } 192ca0716f5SRobert Watson 193ca0716f5SRobert Watson /* 194ca0716f5SRobert Watson * Create the new file name, swap with existing audit file. 195ca0716f5SRobert Watson */ 196ca0716f5SRobert Watson static int 197ca0716f5SRobert Watson swap_audit_file(void) 198ca0716f5SRobert Watson { 1997a0a89d2SRobert Watson int err; 200aa772005SRobert Watson char *newfile, *name; 201aa772005SRobert Watson char TS[TIMESTAMP_LEN + 1]; 2027a0a89d2SRobert Watson time_t tt; 203ca0716f5SRobert Watson 204aa772005SRobert Watson if (getTSstr(tt, TS, sizeof(TS)) != 0) 205ca0716f5SRobert Watson return (-1); 206aa772005SRobert Watson /* 207aa772005SRobert Watson * If prefix and suffix are the same, it means that records are 208aa772005SRobert Watson * being produced too fast. We don't want to rename now, because 209aa772005SRobert Watson * next trail file can get the same name and once that one is 210aa772005SRobert Watson * terminated also within one second it will overwrite the current 211aa772005SRobert Watson * one. Just keep writing to the same trail and wait for the next 212aa772005SRobert Watson * trigger from the kernel. 213aa772005SRobert Watson * FREEBSD KERNEL WAS UPDATED TO KEEP SENDING TRIGGERS, WHICH MIGHT 214aa772005SRobert Watson * NOT BE THE CASE FOR OTHER OSES. 215aa772005SRobert Watson * If the kernel will not keep sending triggers, trail file will not 216aa772005SRobert Watson * be terminated. 217aa772005SRobert Watson */ 218aa772005SRobert Watson if (lastfile == NULL) { 219aa772005SRobert Watson name = NULL; 220aa772005SRobert Watson } else { 221aa772005SRobert Watson name = strrchr(lastfile, '/'); 222aa772005SRobert Watson if (name != NULL) 223aa772005SRobert Watson name++; 224aa772005SRobert Watson } 225aa772005SRobert Watson if (name != NULL && strncmp(name, TS, TIMESTAMP_LEN) == 0) { 226aa772005SRobert Watson auditd_log_debug("Not ready to terminate trail file yet."); 227aa772005SRobert Watson return (0); 228aa772005SRobert Watson } 2297a0a89d2SRobert Watson err = auditd_swap_trail(TS, &newfile, audit_review_gid, 2307a0a89d2SRobert Watson audit_warn_getacdir); 2317a0a89d2SRobert Watson if (err != ADE_NOERR) { 2327a0a89d2SRobert Watson auditd_log_err("%s: %m", auditd_strerror(err)); 2337a0a89d2SRobert Watson if (err != ADE_ACTL) 234ca0716f5SRobert Watson return (-1); 235ca0716f5SRobert Watson } 236ca0716f5SRobert Watson 237ca0716f5SRobert Watson /* 2387a0a89d2SRobert Watson * Only close the last file if were in an auditing state before 2397a0a89d2SRobert Watson * calling swap_audit_file(). We may need to recover from a crash. 240ca0716f5SRobert Watson */ 2417a0a89d2SRobert Watson if (auditd_get_state() == AUD_STATE_ENABLED) 242ca0716f5SRobert Watson close_lastfile(TS); 2437a0a89d2SRobert Watson 2447a0a89d2SRobert Watson 2457a0a89d2SRobert Watson /* 2467a0a89d2SRobert Watson * auditd_swap_trail() potentially enables auditing (if not already 2477a0a89d2SRobert Watson * enabled) so updated the cached state as well. 2487a0a89d2SRobert Watson */ 2497a0a89d2SRobert Watson auditd_set_state(AUD_STATE_ENABLED); 2507a0a89d2SRobert Watson 2517a0a89d2SRobert Watson /* 2527a0a89d2SRobert Watson * Create 'current' symlink. Recover from crash, if needed. 2537a0a89d2SRobert Watson */ 2547a0a89d2SRobert Watson if (auditd_new_curlink(newfile) != 0) 2557a0a89d2SRobert Watson auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m", 2567a0a89d2SRobert Watson newfile, auditd_strerror(err)); 2577a0a89d2SRobert Watson 2587a0a89d2SRobert Watson lastfile = newfile; 2597a0a89d2SRobert Watson auditd_log_notice("New audit file is %s", newfile); 2607a0a89d2SRobert Watson 261ca0716f5SRobert Watson return (0); 262ca0716f5SRobert Watson } 263ca0716f5SRobert Watson 264ca0716f5SRobert Watson /* 2657a0a89d2SRobert Watson * Create a new audit log trail file and swap with the current one, if any. 266ca0716f5SRobert Watson */ 267ca0716f5SRobert Watson static int 2687a0a89d2SRobert Watson do_trail_file(void) 269ca0716f5SRobert Watson { 2707a0a89d2SRobert Watson int err; 271ca0716f5SRobert Watson 272ca0716f5SRobert Watson /* 2737a0a89d2SRobert Watson * First, refresh the list of audit log directories. 274ca0716f5SRobert Watson */ 2757a0a89d2SRobert Watson err = auditd_read_dirs(audit_warn_soft, audit_warn_hard); 2767a0a89d2SRobert Watson if (err) { 277c74c7b73SRobert Watson auditd_log_err("auditd_read_dirs(): %s", 2787a0a89d2SRobert Watson auditd_strerror(err)); 2797a0a89d2SRobert Watson if (err == ADE_HARDLIM) 2807a0a89d2SRobert Watson audit_warn_allhard(); 2817a0a89d2SRobert Watson if (err != ADE_SOFTLIM) 2827a0a89d2SRobert Watson return (-1); 2837a0a89d2SRobert Watson else 2847a0a89d2SRobert Watson audit_warn_allsoft(); 2857a0a89d2SRobert Watson /* continue on with soft limit error */ 2867a0a89d2SRobert Watson } 287ca0716f5SRobert Watson 288ca0716f5SRobert Watson /* 2897a0a89d2SRobert Watson * Create a new file and swap with the one being used in kernel. 290ca0716f5SRobert Watson */ 291ca0716f5SRobert Watson if (swap_audit_file() == -1) { 292ca0716f5SRobert Watson /* 293ca0716f5SRobert Watson * XXX Faulty directory listing? - user should be given 294ca0716f5SRobert Watson * XXX an opportunity to change the audit_control file 295ca0716f5SRobert Watson * XXX switch to a reduced mode of auditing? 296ca0716f5SRobert Watson */ 297ca0716f5SRobert Watson return (-1); 298ca0716f5SRobert Watson } 299ca0716f5SRobert Watson 30006edd2f1SRobert Watson /* 30106edd2f1SRobert Watson * Finally, see if there are any trail files to expire. 30206edd2f1SRobert Watson */ 30306edd2f1SRobert Watson err = auditd_expire_trails(audit_warn_expired); 30406edd2f1SRobert Watson if (err) 30506edd2f1SRobert Watson auditd_log_err("auditd_expire_trails(): %s", 30606edd2f1SRobert Watson auditd_strerror(err)); 30706edd2f1SRobert Watson 3087a0a89d2SRobert Watson return (0); 309ca0716f5SRobert Watson } 310ca0716f5SRobert Watson 3117a0a89d2SRobert Watson /* 3127a0a89d2SRobert Watson * Start up auditing. 3137a0a89d2SRobert Watson */ 3147a0a89d2SRobert Watson static void 3157a0a89d2SRobert Watson audit_setup(void) 3167a0a89d2SRobert Watson { 3177a0a89d2SRobert Watson int err; 3187a0a89d2SRobert Watson 319aa772005SRobert Watson /* Configure trail files distribution. */ 320aa772005SRobert Watson err = auditd_set_dist(); 321aa772005SRobert Watson if (err) { 322aa772005SRobert Watson auditd_log_err("auditd_set_dist() %s: %m", 323aa772005SRobert Watson auditd_strerror(err)); 324aa772005SRobert Watson } else 325aa772005SRobert Watson auditd_log_debug("Configured trail files distribution."); 326aa772005SRobert Watson 3277a0a89d2SRobert Watson if (do_trail_file() == -1) { 3287a0a89d2SRobert Watson auditd_log_err("Error creating audit trail file"); 3297a0a89d2SRobert Watson fail_exit(); 3307a0a89d2SRobert Watson } 3317a0a89d2SRobert Watson 3327a0a89d2SRobert Watson /* Generate an audit record. */ 3337a0a89d2SRobert Watson err = auditd_gen_record(AUE_audit_startup, NULL); 3347a0a89d2SRobert Watson if (err) 3357a0a89d2SRobert Watson auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m", 3367a0a89d2SRobert Watson auditd_strerror(err)); 3377a0a89d2SRobert Watson 3387a0a89d2SRobert Watson if (auditd_config_controls() == 0) 3397a0a89d2SRobert Watson auditd_log_info("Audit controls init successful"); 3407a0a89d2SRobert Watson else 3417a0a89d2SRobert Watson auditd_log_err("Audit controls init failed"); 3427a0a89d2SRobert Watson } 3437a0a89d2SRobert Watson 3447a0a89d2SRobert Watson 3457a0a89d2SRobert Watson /* 3467a0a89d2SRobert Watson * Close auditd pid file and trigger mechanism. 3477a0a89d2SRobert Watson */ 3487a0a89d2SRobert Watson static int 3497a0a89d2SRobert Watson close_misc(void) 3507a0a89d2SRobert Watson { 3517a0a89d2SRobert Watson 3527a0a89d2SRobert Watson auditd_close_dirs(); 3537a0a89d2SRobert Watson if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) { 3547a0a89d2SRobert Watson auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE); 3557a0a89d2SRobert Watson return (1); 3567a0a89d2SRobert Watson } 3577a0a89d2SRobert Watson endac(); 3587a0a89d2SRobert Watson 3597a0a89d2SRobert Watson if (auditd_close_trigger() != 0) { 3607a0a89d2SRobert Watson auditd_log_err("Error closing trigger messaging mechanism"); 3617a0a89d2SRobert Watson return (1); 3627a0a89d2SRobert Watson } 363ca0716f5SRobert Watson return (0); 364ca0716f5SRobert Watson } 365ca0716f5SRobert Watson 366ca0716f5SRobert Watson /* 367ca0716f5SRobert Watson * Close all log files, control files, and tell the audit system. 368ca0716f5SRobert Watson */ 369ca0716f5SRobert Watson static int 370ca0716f5SRobert Watson close_all(void) 371ca0716f5SRobert Watson { 372ca0716f5SRobert Watson int err_ret = 0; 373aa772005SRobert Watson char TS[TIMESTAMP_LEN + 1]; 3747a0a89d2SRobert Watson int err; 375c0020399SRobert Watson int cond; 3767a0a89d2SRobert Watson time_t tt; 377ca0716f5SRobert Watson 3787a0a89d2SRobert Watson err = auditd_gen_record(AUE_audit_shutdown, NULL); 3797a0a89d2SRobert Watson if (err) 3807a0a89d2SRobert Watson auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m", 3817a0a89d2SRobert Watson auditd_strerror(err)); 382ca0716f5SRobert Watson 383ca0716f5SRobert Watson /* Flush contents. */ 384ca0716f5SRobert Watson cond = AUC_DISABLED; 385c0020399SRobert Watson err_ret = audit_set_cond(&cond); 386ca0716f5SRobert Watson if (err_ret != 0) { 3877a0a89d2SRobert Watson auditd_log_err("Disabling audit failed! : %s", strerror(errno)); 388ca0716f5SRobert Watson err_ret = 1; 389ca0716f5SRobert Watson } 3907a0a89d2SRobert Watson 39152267f74SRobert Watson /* 3927a0a89d2SRobert Watson * Updated the cached state that auditing has been disabled. 39352267f74SRobert Watson */ 3947a0a89d2SRobert Watson auditd_set_state(AUD_STATE_DISABLED); 3957a0a89d2SRobert Watson 396aa772005SRobert Watson if (getTSstr(tt, TS, sizeof(TS)) == 0) 397ca0716f5SRobert Watson close_lastfile(TS); 398ca0716f5SRobert Watson if (lastfile != NULL) 399ca0716f5SRobert Watson free(lastfile); 400ca0716f5SRobert Watson 4017a0a89d2SRobert Watson err_ret += close_misc(); 4027a0a89d2SRobert Watson 4037a0a89d2SRobert Watson if (err_ret) { 4047a0a89d2SRobert Watson auditd_log_err("Could not unregister"); 405ca0716f5SRobert Watson audit_warn_postsigterm(); 406ca0716f5SRobert Watson } 407ca0716f5SRobert Watson 4087a0a89d2SRobert Watson auditd_log_info("Finished"); 4097a0a89d2SRobert Watson return (err_ret); 410ca0716f5SRobert Watson } 411ca0716f5SRobert Watson 412ca0716f5SRobert Watson /* 4137a0a89d2SRobert Watson * Register the daemon with the signal handler and the auditd pid file. 414ca0716f5SRobert Watson */ 415ca0716f5SRobert Watson static int 416ca0716f5SRobert Watson register_daemon(void) 417ca0716f5SRobert Watson { 418ca0716f5SRobert Watson FILE * pidfile; 419ca0716f5SRobert Watson int fd; 420ca0716f5SRobert Watson pid_t pid; 421ca0716f5SRobert Watson 422ca0716f5SRobert Watson /* Set up the signal hander. */ 4237a0a89d2SRobert Watson if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) { 4247a0a89d2SRobert Watson auditd_log_err( 425506764c6SRobert Watson "Could not set signal handler for SIGTERM"); 426ca0716f5SRobert Watson fail_exit(); 427ca0716f5SRobert Watson } 4287a0a89d2SRobert Watson if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) { 4297a0a89d2SRobert Watson auditd_log_err( 430506764c6SRobert Watson "Could not set signal handler for SIGCHLD"); 431ca0716f5SRobert Watson fail_exit(); 432ca0716f5SRobert Watson } 4337a0a89d2SRobert Watson if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) { 4347a0a89d2SRobert Watson auditd_log_err( 435506764c6SRobert Watson "Could not set signal handler for SIGHUP"); 436ca0716f5SRobert Watson fail_exit(); 437ca0716f5SRobert Watson } 4387a0a89d2SRobert Watson if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) { 4397a0a89d2SRobert Watson auditd_log_err( 4407a0a89d2SRobert Watson "Could not set signal handler for SIGALRM"); 4417a0a89d2SRobert Watson fail_exit(); 4427a0a89d2SRobert Watson } 443ca0716f5SRobert Watson 444ca0716f5SRobert Watson if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { 4457a0a89d2SRobert Watson auditd_log_err("Could not open PID file"); 446ca0716f5SRobert Watson audit_warn_tmpfile(); 447ca0716f5SRobert Watson return (-1); 448ca0716f5SRobert Watson } 449ca0716f5SRobert Watson 450ca0716f5SRobert Watson /* Attempt to lock the pid file; if a lock is present, exit. */ 451ca0716f5SRobert Watson fd = fileno(pidfile); 452ca0716f5SRobert Watson if (flock(fd, LOCK_EX | LOCK_NB) < 0) { 4537a0a89d2SRobert Watson auditd_log_err( 454506764c6SRobert Watson "PID file is locked (is another auditd running?)."); 455ca0716f5SRobert Watson audit_warn_ebusy(); 456ca0716f5SRobert Watson return (-1); 457ca0716f5SRobert Watson } 458ca0716f5SRobert Watson 459ca0716f5SRobert Watson pid = getpid(); 460ca0716f5SRobert Watson ftruncate(fd, 0); 461ca0716f5SRobert Watson if (fprintf(pidfile, "%u\n", pid) < 0) { 462ca0716f5SRobert Watson /* Should not start the daemon. */ 463ca0716f5SRobert Watson fail_exit(); 464ca0716f5SRobert Watson } 465ca0716f5SRobert Watson 466ca0716f5SRobert Watson fflush(pidfile); 467ca0716f5SRobert Watson return (0); 468ca0716f5SRobert Watson } 469ca0716f5SRobert Watson 470ca0716f5SRobert Watson /* 471bb97b418SRobert Watson * Handle the audit trigger event. 472bb97b418SRobert Watson * 473bb97b418SRobert Watson * We suppress (ignore) duplicated triggers in close succession in order to 474bb97b418SRobert Watson * try to avoid thrashing-like behavior. However, not all triggers can be 475bb97b418SRobert Watson * ignored, as triggers generally represent edge triggers, not level 476bb97b418SRobert Watson * triggers, and won't be retransmitted if the condition persists. Of 477bb97b418SRobert Watson * specific concern is the rotate trigger -- if one is dropped, then it will 478bb97b418SRobert Watson * not be retransmitted, and the log file will grow in an unbounded fashion. 479ca0716f5SRobert Watson */ 480ca0716f5SRobert Watson #define DUPLICATE_INTERVAL 30 4817a0a89d2SRobert Watson void 4827a0a89d2SRobert Watson auditd_handle_trigger(int trigger) 483ca0716f5SRobert Watson { 484bb97b418SRobert Watson static int last_trigger, last_warning; 485ca0716f5SRobert Watson static time_t last_time; 486ca0716f5SRobert Watson struct timeval ts; 487ca0716f5SRobert Watson struct timezone tzp; 488ca0716f5SRobert Watson time_t tt; 4897a0a89d2SRobert Watson int au_state; 4907a0a89d2SRobert Watson int err = 0; 491ca0716f5SRobert Watson 492bb97b418SRobert Watson /* 493bb97b418SRobert Watson * Suppress duplicate messages from the kernel within the specified 494bb97b418SRobert Watson * interval. 495bb97b418SRobert Watson */ 496ca0716f5SRobert Watson if (gettimeofday(&ts, &tzp) == 0) { 497ca0716f5SRobert Watson tt = (time_t)ts.tv_sec; 498bb97b418SRobert Watson switch (trigger) { 499bb97b418SRobert Watson case AUDIT_TRIGGER_LOW_SPACE: 500bb97b418SRobert Watson case AUDIT_TRIGGER_NO_SPACE: 501bb97b418SRobert Watson /* 502bb97b418SRobert Watson * Triggers we can suppress. Of course, we also need 503bb97b418SRobert Watson * to rate limit the warnings, so apply the same 504bb97b418SRobert Watson * interval limit on syslog messages. 505bb97b418SRobert Watson */ 506ca0716f5SRobert Watson if ((trigger == last_trigger) && 507bb97b418SRobert Watson (tt < (last_time + DUPLICATE_INTERVAL))) { 508bb97b418SRobert Watson if (tt >= (last_warning + DUPLICATE_INTERVAL)) 5097a0a89d2SRobert Watson auditd_log_info( 510bb97b418SRobert Watson "Suppressing duplicate trigger %d", 511bb97b418SRobert Watson trigger); 5127a0a89d2SRobert Watson return; 513bb97b418SRobert Watson } 514bb97b418SRobert Watson last_warning = tt; 515bb97b418SRobert Watson break; 516bb97b418SRobert Watson 517bb97b418SRobert Watson case AUDIT_TRIGGER_ROTATE_KERNEL: 518bb97b418SRobert Watson case AUDIT_TRIGGER_ROTATE_USER: 519bb97b418SRobert Watson case AUDIT_TRIGGER_READ_FILE: 5207a0a89d2SRobert Watson case AUDIT_TRIGGER_CLOSE_AND_DIE: 5217a0a89d2SRobert Watson case AUDIT_TRIGGER_INITIALIZE: 522bb97b418SRobert Watson /* 523bb97b418SRobert Watson * Triggers that we cannot suppress. 524bb97b418SRobert Watson */ 525bb97b418SRobert Watson break; 526bb97b418SRobert Watson } 527bb97b418SRobert Watson 528bb97b418SRobert Watson /* 529bb97b418SRobert Watson * Only update last_trigger after aborting due to a duplicate 530bb97b418SRobert Watson * trigger, not before, or we will never allow that trigger 531bb97b418SRobert Watson * again. 532bb97b418SRobert Watson */ 533ca0716f5SRobert Watson last_trigger = trigger; 534ca0716f5SRobert Watson last_time = tt; 535ca0716f5SRobert Watson } 536ca0716f5SRobert Watson 5377a0a89d2SRobert Watson au_state = auditd_get_state(); 5387a0a89d2SRobert Watson 539ca0716f5SRobert Watson /* 540ca0716f5SRobert Watson * Message processing is done here. 541ca0716f5SRobert Watson */ 542ca0716f5SRobert Watson switch(trigger) { 543ca0716f5SRobert Watson case AUDIT_TRIGGER_LOW_SPACE: 5447a0a89d2SRobert Watson auditd_log_notice("Got low space trigger"); 5457a0a89d2SRobert Watson if (do_trail_file() == -1) 5467a0a89d2SRobert Watson auditd_log_err("Error swapping audit file"); 547ca0716f5SRobert Watson break; 548ca0716f5SRobert Watson 549ca0716f5SRobert Watson case AUDIT_TRIGGER_NO_SPACE: 5507a0a89d2SRobert Watson auditd_log_notice("Got no space trigger"); 5517a0a89d2SRobert Watson if (do_trail_file() == -1) 5527a0a89d2SRobert Watson auditd_log_err("Error swapping audit file"); 553ca0716f5SRobert Watson break; 554ca0716f5SRobert Watson 555bb97b418SRobert Watson case AUDIT_TRIGGER_ROTATE_KERNEL: 556bb97b418SRobert Watson case AUDIT_TRIGGER_ROTATE_USER: 5577a0a89d2SRobert Watson auditd_log_info("Got open new trigger from %s", trigger == 558bb97b418SRobert Watson AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user"); 5597a0a89d2SRobert Watson if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1) 5607a0a89d2SRobert Watson auditd_log_err("Error swapping audit file"); 561ca0716f5SRobert Watson break; 562ca0716f5SRobert Watson 563ca0716f5SRobert Watson case AUDIT_TRIGGER_READ_FILE: 5647a0a89d2SRobert Watson auditd_log_info("Got read file trigger"); 565c0020399SRobert Watson if (au_state == AUD_STATE_ENABLED) { 566c0020399SRobert Watson if (auditd_config_controls() == -1) 5677a0a89d2SRobert Watson auditd_log_err("Error setting audit controls"); 568c0020399SRobert Watson else if (do_trail_file() == -1) 569c0020399SRobert Watson auditd_log_err("Error swapping audit file"); 570c0020399SRobert Watson } 571ca0716f5SRobert Watson break; 572ca0716f5SRobert Watson 5737a0a89d2SRobert Watson case AUDIT_TRIGGER_CLOSE_AND_DIE: 5747a0a89d2SRobert Watson auditd_log_info("Got close and die trigger"); 5757a0a89d2SRobert Watson if (au_state == AUD_STATE_ENABLED) 5767a0a89d2SRobert Watson err = close_all(); 57752267f74SRobert Watson /* 5787a0a89d2SRobert Watson * Running under launchd don't exit. Wait for launchd to 5797a0a89d2SRobert Watson * send SIGTERM. 58052267f74SRobert Watson */ 5817a0a89d2SRobert Watson if (!launchd_flag) { 5827a0a89d2SRobert Watson auditd_log_info("auditd exiting."); 5837a0a89d2SRobert Watson exit (err); 58452267f74SRobert Watson } 58552267f74SRobert Watson break; 5867a0a89d2SRobert Watson 5877a0a89d2SRobert Watson case AUDIT_TRIGGER_INITIALIZE: 5887a0a89d2SRobert Watson auditd_log_info("Got audit initialize trigger"); 5897a0a89d2SRobert Watson if (au_state == AUD_STATE_DISABLED) 5907a0a89d2SRobert Watson audit_setup(); 59152267f74SRobert Watson break; 5927a0a89d2SRobert Watson 59306edd2f1SRobert Watson case AUDIT_TRIGGER_EXPIRE_TRAILS: 59406edd2f1SRobert Watson auditd_log_info("Got audit expire trails trigger"); 59506edd2f1SRobert Watson err = auditd_expire_trails(audit_warn_expired); 59606edd2f1SRobert Watson if (err) 59706edd2f1SRobert Watson auditd_log_err("auditd_expire_trails(): %s", 59806edd2f1SRobert Watson auditd_strerror(err)); 59906edd2f1SRobert Watson break; 60006edd2f1SRobert Watson 60152267f74SRobert Watson default: 6027a0a89d2SRobert Watson auditd_log_err("Got unknown trigger %d", trigger); 6037a0a89d2SRobert Watson break; 60452267f74SRobert Watson } 60552267f74SRobert Watson } 60652267f74SRobert Watson 607ca0716f5SRobert Watson /* 608ca0716f5SRobert Watson * Reap our children. 609ca0716f5SRobert Watson */ 6107a0a89d2SRobert Watson void 6117a0a89d2SRobert Watson auditd_reap_children(void) 612ca0716f5SRobert Watson { 613ca0716f5SRobert Watson pid_t child; 614ca0716f5SRobert Watson int wstatus; 615ca0716f5SRobert Watson 616ca0716f5SRobert Watson while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { 617ca0716f5SRobert Watson if (!wstatus) 618ca0716f5SRobert Watson continue; 6197a0a89d2SRobert Watson auditd_log_info("warn process [pid=%d] %s %d.", child, 620ca0716f5SRobert Watson ((WIFEXITED(wstatus)) ? "exited with non-zero status" : 621ca0716f5SRobert Watson "exited as a result of signal"), 622ca0716f5SRobert Watson ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : 623ca0716f5SRobert Watson WTERMSIG(wstatus))); 624ca0716f5SRobert Watson } 625ca0716f5SRobert Watson } 626ca0716f5SRobert Watson 627506764c6SRobert Watson /* 6287a0a89d2SRobert Watson * Reap any children and terminate. If under launchd don't shutdown auditing 6297a0a89d2SRobert Watson * but just the other stuff. 630506764c6SRobert Watson */ 6317a0a89d2SRobert Watson void 6327a0a89d2SRobert Watson auditd_terminate(void) 63352267f74SRobert Watson { 63452267f74SRobert Watson int ret; 63552267f74SRobert Watson 6367a0a89d2SRobert Watson auditd_reap_children(); 63752267f74SRobert Watson 6387a0a89d2SRobert Watson if (launchd_flag) 6397a0a89d2SRobert Watson ret = close_misc(); 640506764c6SRobert Watson else 6417a0a89d2SRobert Watson ret = close_all(); 6427a0a89d2SRobert Watson 6437a0a89d2SRobert Watson exit(ret); 644506764c6SRobert Watson } 645506764c6SRobert Watson 646ca0716f5SRobert Watson /* 647ca0716f5SRobert Watson * Configure the audit controls in the kernel: the event to class mapping, 648ca0716f5SRobert Watson * kernel preselection mask, etc. 649ca0716f5SRobert Watson */ 6507a0a89d2SRobert Watson int 6517a0a89d2SRobert Watson auditd_config_controls(void) 652ca0716f5SRobert Watson { 6537a0a89d2SRobert Watson int cnt, err; 6547a0a89d2SRobert Watson int ret = 0; 655ca0716f5SRobert Watson 656ca0716f5SRobert Watson /* 6577a0a89d2SRobert Watson * Configure event to class mappings in kernel. 658ca0716f5SRobert Watson */ 6597a0a89d2SRobert Watson cnt = auditd_set_evcmap(); 6607a0a89d2SRobert Watson if (cnt < 0) { 6617a0a89d2SRobert Watson auditd_log_err("auditd_set_evcmap() failed: %m"); 6627a0a89d2SRobert Watson ret = -1; 6637a0a89d2SRobert Watson } else if (cnt == 0) { 6647a0a89d2SRobert Watson auditd_log_err("No events to class mappings registered."); 6657a0a89d2SRobert Watson ret = -1; 666ca0716f5SRobert Watson } else 6677a0a89d2SRobert Watson auditd_log_debug("Registered %d event to class mappings.", cnt); 668ca0716f5SRobert Watson 669ca0716f5SRobert Watson /* 6707a0a89d2SRobert Watson * Configure non-attributable event mask in kernel. 671ca0716f5SRobert Watson */ 6727a0a89d2SRobert Watson err = auditd_set_namask(); 6737a0a89d2SRobert Watson if (err) { 6747a0a89d2SRobert Watson auditd_log_err("auditd_set_namask() %s: %m", 6757a0a89d2SRobert Watson auditd_strerror(err)); 6767a0a89d2SRobert Watson ret = -1; 6774bd0c025SRobert Watson } else 6787a0a89d2SRobert Watson auditd_log_debug("Registered non-attributable event mask."); 67952267f74SRobert Watson 68052267f74SRobert Watson /* 6817a0a89d2SRobert Watson * Configure audit policy in kernel. 68252267f74SRobert Watson */ 6837a0a89d2SRobert Watson err = auditd_set_policy(); 6847a0a89d2SRobert Watson if (err) { 6857a0a89d2SRobert Watson auditd_log_err("auditd_set_policy() %s: %m", 6867a0a89d2SRobert Watson auditd_strerror(err)); 6877a0a89d2SRobert Watson ret = -1; 68852267f74SRobert Watson } else 6897a0a89d2SRobert Watson auditd_log_debug("Set audit policy in kernel."); 69052267f74SRobert Watson 6917a0a89d2SRobert Watson /* 6927a0a89d2SRobert Watson * Configure audit trail log size in kernel. 6937a0a89d2SRobert Watson */ 6947a0a89d2SRobert Watson err = auditd_set_fsize(); 6957a0a89d2SRobert Watson if (err) { 6967a0a89d2SRobert Watson auditd_log_err("audit_set_fsize() %s: %m", 6977a0a89d2SRobert Watson auditd_strerror(err)); 6987a0a89d2SRobert Watson ret = -1; 6997a0a89d2SRobert Watson } else 7007a0a89d2SRobert Watson auditd_log_debug("Set audit trail size in kernel."); 7017a0a89d2SRobert Watson 7027a0a89d2SRobert Watson /* 703*5e386598SRobert Watson * Configure audit trail queue size in kernel. 704*5e386598SRobert Watson */ 705*5e386598SRobert Watson err = auditd_set_qsize(); 706*5e386598SRobert Watson if (err) { 707*5e386598SRobert Watson auditd_log_err("audit_set_qsize() %s: %m", 708*5e386598SRobert Watson auditd_strerror(err)); 709*5e386598SRobert Watson ret = -1; 710*5e386598SRobert Watson } else 711*5e386598SRobert Watson auditd_log_debug("Set audit trail queue in kernel."); 712*5e386598SRobert Watson 713*5e386598SRobert Watson /* 7147a0a89d2SRobert Watson * Configure audit trail volume minimum free percentage of blocks in 7157a0a89d2SRobert Watson * kernel. 7167a0a89d2SRobert Watson */ 7177a0a89d2SRobert Watson err = auditd_set_minfree(); 7187a0a89d2SRobert Watson if (err) { 7197a0a89d2SRobert Watson auditd_log_err("auditd_set_minfree() %s: %m", 7207a0a89d2SRobert Watson auditd_strerror(err)); 7217a0a89d2SRobert Watson ret = -1; 7227a0a89d2SRobert Watson } else 7237a0a89d2SRobert Watson auditd_log_debug( 7247a0a89d2SRobert Watson "Set audit trail min free percent in kernel."); 7257a0a89d2SRobert Watson 7267a0a89d2SRobert Watson /* 7277a0a89d2SRobert Watson * Configure host address in the audit kernel information. 7287a0a89d2SRobert Watson */ 7297a0a89d2SRobert Watson err = auditd_set_host(); 7307a0a89d2SRobert Watson if (err) { 73106edd2f1SRobert Watson if (err == ADE_PARSE) { 73206edd2f1SRobert Watson auditd_log_notice( 73306edd2f1SRobert Watson "audit_control(5) may be missing 'host:' field"); 73406edd2f1SRobert Watson } else { 7357a0a89d2SRobert Watson auditd_log_err("auditd_set_host() %s: %m", 7367a0a89d2SRobert Watson auditd_strerror(err)); 7377a0a89d2SRobert Watson ret = -1; 73806edd2f1SRobert Watson } 7397a0a89d2SRobert Watson } else 7407a0a89d2SRobert Watson auditd_log_debug( 7417a0a89d2SRobert Watson "Set audit host address information in kernel."); 7427a0a89d2SRobert Watson 7437a0a89d2SRobert Watson return (ret); 7447a0a89d2SRobert Watson } 7457a0a89d2SRobert Watson 7467a0a89d2SRobert Watson /* 7477a0a89d2SRobert Watson * Setup and initialize auditd. 7487a0a89d2SRobert Watson */ 749ca0716f5SRobert Watson static void 750ca0716f5SRobert Watson setup(void) 751ca0716f5SRobert Watson { 7527a0a89d2SRobert Watson int err; 753ca0716f5SRobert Watson 7547a0a89d2SRobert Watson if (auditd_open_trigger(launchd_flag) < 0) { 7557a0a89d2SRobert Watson auditd_log_err("Error opening trigger messaging mechanism"); 756506764c6SRobert Watson fail_exit(); 757506764c6SRobert Watson } 758506764c6SRobert Watson 759506764c6SRobert Watson /* 76052267f74SRobert Watson * To prevent event feedback cycles and avoid auditd becoming 761506764c6SRobert Watson * stalled if auditing is suspended, auditd and its children run 762506764c6SRobert Watson * without their events being audited. We allow the uid, tid, and 763506764c6SRobert Watson * mask fields to be implicitly set to zero, but do set the pid. We 764506764c6SRobert Watson * run this after opening the trigger device to avoid configuring 765506764c6SRobert Watson * audit state without audit present in the system. 766506764c6SRobert Watson */ 7677a0a89d2SRobert Watson err = auditd_prevent_audit(); 7687a0a89d2SRobert Watson if (err) { 7697a0a89d2SRobert Watson auditd_log_err("auditd_prevent_audit() %s: %m", 7707a0a89d2SRobert Watson auditd_strerror(err)); 771ca0716f5SRobert Watson fail_exit(); 772ca0716f5SRobert Watson } 773ca0716f5SRobert Watson 774fdb4472cSRobert Watson /* 7757a0a89d2SRobert Watson * Make sure auditd auditing state is correct. 776fdb4472cSRobert Watson */ 7777a0a89d2SRobert Watson auditd_set_state(AUD_STATE_INIT); 778ca0716f5SRobert Watson 7797a0a89d2SRobert Watson /* 7807a0a89d2SRobert Watson * If under launchd, don't start auditing. Wait for a trigger to 7817a0a89d2SRobert Watson * do so. 7827a0a89d2SRobert Watson */ 7837a0a89d2SRobert Watson if (!launchd_flag) 7847a0a89d2SRobert Watson audit_setup(); 785ca0716f5SRobert Watson } 786ca0716f5SRobert Watson 787ca0716f5SRobert Watson int 788ca0716f5SRobert Watson main(int argc, char **argv) 789ca0716f5SRobert Watson { 79023bf6e20SRobert Watson int ch; 791ca0716f5SRobert Watson int debug = 0; 7927a0a89d2SRobert Watson #ifdef AUDIT_REVIEW_GROUP 7937a0a89d2SRobert Watson struct group *grp; 7947a0a89d2SRobert Watson #endif 795ca0716f5SRobert Watson 7967a0a89d2SRobert Watson while ((ch = getopt(argc, argv, "dl")) != -1) { 797ca0716f5SRobert Watson switch(ch) { 798ca0716f5SRobert Watson case 'd': 799ca0716f5SRobert Watson /* Debug option. */ 800ca0716f5SRobert Watson debug = 1; 801ca0716f5SRobert Watson break; 802ca0716f5SRobert Watson 8037a0a89d2SRobert Watson case 'l': 8047a0a89d2SRobert Watson /* Be launchd friendly. */ 8057a0a89d2SRobert Watson launchd_flag = 1; 8067a0a89d2SRobert Watson break; 8077a0a89d2SRobert Watson 808ca0716f5SRobert Watson case '?': 809ca0716f5SRobert Watson default: 810ca0716f5SRobert Watson (void)fprintf(stderr, 8117a0a89d2SRobert Watson "usage: auditd [-d] [-l]\n"); 812ca0716f5SRobert Watson exit(1); 813ca0716f5SRobert Watson } 814ca0716f5SRobert Watson } 815ca0716f5SRobert Watson 8167a0a89d2SRobert Watson audit_review_gid = getgid(); 81752267f74SRobert Watson 8187a0a89d2SRobert Watson #ifdef AUDIT_REVIEW_GROUP 8197a0a89d2SRobert Watson /* 8207a0a89d2SRobert Watson * XXXRW: Currently, this code falls back to the daemon gid, which is 8217a0a89d2SRobert Watson * likely the wheel group. Is there a better way to deal with this? 8227a0a89d2SRobert Watson */ 8237a0a89d2SRobert Watson grp = getgrnam(AUDIT_REVIEW_GROUP); 8247a0a89d2SRobert Watson if (grp != NULL) 8257a0a89d2SRobert Watson audit_review_gid = grp->gr_gid; 8263b97a967SRobert Watson #endif 827ca0716f5SRobert Watson 8287a0a89d2SRobert Watson auditd_openlog(debug, audit_review_gid); 8297a0a89d2SRobert Watson 8307a0a89d2SRobert Watson if (launchd_flag) 8317a0a89d2SRobert Watson auditd_log_info("started by launchd..."); 8327a0a89d2SRobert Watson else 8337a0a89d2SRobert Watson auditd_log_info("starting..."); 8347a0a89d2SRobert Watson 8357a0a89d2SRobert Watson #ifdef AUDIT_REVIEW_GROUP 8367a0a89d2SRobert Watson if (grp == NULL) 8377a0a89d2SRobert Watson auditd_log_info( 8387a0a89d2SRobert Watson "Audit review group '%s' not available, using daemon gid (%d)", 8397a0a89d2SRobert Watson AUDIT_REVIEW_GROUP, audit_review_gid); 8407a0a89d2SRobert Watson #endif 8417a0a89d2SRobert Watson if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) { 8427a0a89d2SRobert Watson auditd_log_err("Failed to daemonize"); 843ca0716f5SRobert Watson exit(1); 844ca0716f5SRobert Watson } 845ca0716f5SRobert Watson 846ca0716f5SRobert Watson if (register_daemon() == -1) { 8477a0a89d2SRobert Watson auditd_log_err("Could not register as daemon"); 848ca0716f5SRobert Watson exit(1); 849ca0716f5SRobert Watson } 850ca0716f5SRobert Watson 851ca0716f5SRobert Watson setup(); 852ca0716f5SRobert Watson 8537a0a89d2SRobert Watson /* 8547a0a89d2SRobert Watson * auditd_wait_for_events() shouldn't return unless something is wrong. 8557a0a89d2SRobert Watson */ 8567a0a89d2SRobert Watson auditd_wait_for_events(); 857ca0716f5SRobert Watson 8587a0a89d2SRobert Watson auditd_log_err("abnormal exit."); 8597a0a89d2SRobert Watson close_all(); 8607a0a89d2SRobert Watson exit(-1); 861ca0716f5SRobert Watson } 862