auditd.c (185573) | auditd.c (186647) |
---|---|
1/*- 2 * Copyright (c) 2004-2008 Apple Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 12 unchanged lines hidden (view full) --- 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * | 1/*- 2 * Copyright (c) 2004-2008 Apple Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 12 unchanged lines hidden (view full) --- 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * |
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#39 $ | 29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#40 $ |
30 */ 31 | 30 */ 31 |
32#include <sys/param.h> | 32#include <sys/types.h> |
33 34#include <config/config.h> 35 36#include <sys/dirent.h> | 33 34#include <config/config.h> 35 36#include <sys/dirent.h> |
37#include <sys/mman.h> 38#include <sys/socket.h> | |
39#ifdef HAVE_FULL_QUEUE_H 40#include <sys/queue.h> 41#else /* !HAVE_FULL_QUEUE_H */ 42#include <compat/queue.h> 43#endif /* !HAVE_FULL_QUEUE_H */ | 37#ifdef HAVE_FULL_QUEUE_H 38#include <sys/queue.h> 39#else /* !HAVE_FULL_QUEUE_H */ 40#include <compat/queue.h> 41#endif /* !HAVE_FULL_QUEUE_H */ |
42#include <sys/mman.h> 43#include <sys/param.h> |
|
44#include <sys/stat.h> 45#include <sys/wait.h> 46 47#include <bsm/audit.h> 48#include <bsm/audit_uevents.h> | 44#include <sys/stat.h> 45#include <sys/wait.h> 46 47#include <bsm/audit.h> 48#include <bsm/audit_uevents.h> |
49#include <bsm/auditd_lib.h> |
|
49#include <bsm/libbsm.h> 50 | 50#include <bsm/libbsm.h> 51 |
51#include <netinet/in.h> 52 | |
53#include <err.h> 54#include <errno.h> 55#include <fcntl.h> 56#include <grp.h> 57#include <stdio.h> 58#include <stdlib.h> 59#include <time.h> 60#include <unistd.h> 61#include <signal.h> 62#include <string.h> | 52#include <err.h> 53#include <errno.h> 54#include <fcntl.h> 55#include <grp.h> 56#include <stdio.h> 57#include <stdlib.h> 58#include <time.h> 59#include <unistd.h> 60#include <signal.h> 61#include <string.h> |
63#include <syslog.h> 64#include <netdb.h> | |
65 66#include "auditd.h" | 62 63#include "auditd.h" |
67#ifdef USE_MACH_IPC 68#include <notify.h> 69#include <mach/port.h> 70#include <mach/mach_error.h> 71#include <mach/mach_traps.h> 72#include <mach/mach.h> 73#include <mach/host_special_ports.h> | |
74 | 64 |
75#include "auditd_control_server.h" 76#include "audit_triggers_server.h" 77#endif /* USE_MACH_IPC */ 78 | |
79#ifndef HAVE_STRLCPY 80#include <compat/strlcpy.h> 81#endif 82 | 65#ifndef HAVE_STRLCPY 66#include <compat/strlcpy.h> 67#endif 68 |
83#define NA_EVENT_STR_SIZE 25 84#define POL_STR_SIZE 128 85static int ret, minval; 86static char *lastfile = NULL; 87static int allhardcount = 0; 88static int sigchlds, sigchlds_handled; 89static int sighups, sighups_handled; 90#ifndef USE_MACH_IPC 91static int sigterms, sigterms_handled; 92static int triggerfd = 0; | 69/* 70 * XXX the following is temporary until this can be added to the kernel 71 * audit.h header. 72 */ 73#ifndef AUDIT_TRIGGER_INITIALIZE 74#define AUDIT_TRIGGER_INITIALIZE 7 75#endif |
93 | 76 |
94#else /* USE_MACH_IPC */ | 77/* 78 * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and 79 * http://wiki.freebsd.org/launchd for more information. 80 * 81 * In order for auditd to work "on demand" with launchd(8) it can't: 82 * call daemon(3) 83 * call fork and having the parent process exit 84 * change uids or gids. 85 * set up the current working directory or chroot. 86 * set the session id 87 * change stdio to /dev/null. 88 * call setrusage(2) 89 * call setpriority(2) 90 * Ignore SIGTERM. 91 * auditd (in 'launchd mode') is launched on demand so it must catch 92 * SIGTERM to exit cleanly. 93 */ 94static int launchd_flag = 0; |
95 | 95 |
96static mach_port_t control_port = MACH_PORT_NULL; 97static mach_port_t signal_port = MACH_PORT_NULL; 98static mach_port_t port_set = MACH_PORT_NULL; | 96/* 97 * The GID of the audit review group (if used). The audit trail files and 98 * system logs (Mac OS X only) can only be reviewed by members of this group 99 * or the audit administrator (aka. "root"). 100 */ 101static gid_t audit_review_gid = -1; |
99 | 102 |
100#ifndef __BSM_INTERNAL_NOTIFY_KEY 101#define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" 102#endif /* __BSM_INTERNAL_NOTIFY_KEY */ 103#endif /* USE_MACH_IPC */ | 103/* 104 * The path and file name of the last audit trail file. 105 */ 106static char *lastfile = NULL; |
104 | 107 |
105static TAILQ_HEAD(, dir_ent) dir_q; 106 107static int config_audit_controls(void); 108 | |
109/* | 108/* |
110 * Error starting auditd | 109 * Error starting auditd. Run warn script and exit. |
111 */ 112static void 113fail_exit(void) 114{ 115 116 audit_warn_nostart(); 117 exit(1); 118} 119 120/* | 110 */ 111static void 112fail_exit(void) 113{ 114 115 audit_warn_nostart(); 116 exit(1); 117} 118 119/* |
121 * Free our local list of directory names. | 120 * Follow the 'current' symlink to get the active trail file name. |
122 */ | 121 */ |
123static void 124free_dir_q(void) | 122static char * 123get_curfile(void) |
125{ | 124{ |
126 struct dir_ent *dirent; | 125 char *cf; 126 int len; |
127 | 127 |
128 while ((dirent = TAILQ_FIRST(&dir_q))) { 129 TAILQ_REMOVE(&dir_q, dirent, dirs); 130 free(dirent->dirname); 131 free(dirent); | 128 cf = malloc(MAXPATHLEN); 129 if (cf == NULL) { 130 auditd_log_err("malloc failed: %m"); 131 return (NULL); 132 } 133 134 len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1); 135 if (len < 0) { 136 free(cf); 137 return (NULL); |
132 } | 138 } |
133} | |
134 | 139 |
135/* 136 * Generate the timestamp string. 137 */ 138static int 139getTSstr(char *buf, int len) 140{ 141 struct timeval ts; 142 struct timezone tzp; 143 time_t tt; | 140 /* readlink() doesn't terminate string. */ 141 cf[len] = '\0'; |
144 | 142 |
145 if (gettimeofday(&ts, &tzp) != 0) 146 return (-1); 147 tt = (time_t)ts.tv_sec; 148 if (!strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&tt))) 149 return (-1); 150 return (0); | 143 return (cf); |
151} 152 153/* | 144} 145 146/* |
154 * Concat the directory name to the given file name. 155 * XXX We should affix the hostname also 156 */ 157static char * 158affixdir(char *name, struct dir_ent *dirent) 159{ 160 char *fn = NULL; 161 162 syslog(LOG_DEBUG, "dir = %s", dirent->dirname); 163 /* 164 * Sanity check on file name. 165 */ 166 if (strlen(name) != (FILENAME_LEN - 1)) { 167 syslog(LOG_ERR, "Invalid file name: %s", name); 168 return (NULL); 169 } 170 asprintf(&fn, "%s/%s", dirent->dirname, name); 171 return (fn); 172} 173 174/* | |
175 * Close the previous audit trail file. 176 */ 177static int 178close_lastfile(char *TS) 179{ 180 char *ptr; 181 char *oldname; 182 size_t len; 183 | 147 * Close the previous audit trail file. 148 */ 149static int 150close_lastfile(char *TS) 151{ 152 char *ptr; 153 char *oldname; 154 size_t len; 155 |
156 /* If lastfile is NULL try to get it from the 'current' link. */ 157 if (lastfile == NULL) 158 lastfile = get_curfile(); 159 |
|
184 if (lastfile != NULL) { 185 len = strlen(lastfile) + 1; 186 oldname = (char *)malloc(len); 187 if (oldname == NULL) 188 return (-1); 189 strlcpy(oldname, lastfile, len); 190 191 /* Rename the last file -- append timestamp. */ 192 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { 193 strlcpy(ptr, TS, TIMESTAMP_LEN); 194 if (rename(oldname, lastfile) != 0) | 160 if (lastfile != NULL) { 161 len = strlen(lastfile) + 1; 162 oldname = (char *)malloc(len); 163 if (oldname == NULL) 164 return (-1); 165 strlcpy(oldname, lastfile, len); 166 167 /* Rename the last file -- append timestamp. */ 168 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { 169 strlcpy(ptr, TS, TIMESTAMP_LEN); 170 if (rename(oldname, lastfile) != 0) |
195 syslog(LOG_ERR, | 171 auditd_log_err( |
196 "Could not rename %s to %s: %m", oldname, 197 lastfile); 198 else { | 172 "Could not rename %s to %s: %m", oldname, 173 lastfile); 174 else { |
199 syslog(LOG_INFO, "renamed %s to %s", | 175 /* 176 * Remove the 'current' symlink since the link 177 * is now invalid. 178 */ 179 (void) unlink(AUDIT_CURRENT_LINK); 180 auditd_log_notice( "renamed %s to %s", |
200 oldname, lastfile); 201 audit_warn_closefile(lastfile); 202 } 203 } else | 181 oldname, lastfile); 182 audit_warn_closefile(lastfile); 183 } 184 } else |
204 syslog(LOG_ERR, "Could not rename %s to %s", oldname, | 185 auditd_log_err( "Could not rename %s to %s", oldname, |
205 lastfile); 206 free(lastfile); 207 free(oldname); 208 lastfile = NULL; 209 } 210 return (0); 211} 212 213/* | 186 lastfile); 187 free(lastfile); 188 free(oldname); 189 lastfile = NULL; 190 } 191 return (0); 192} 193 194/* |
214 * Create the new audit file with appropriate permissions and ownership. Try 215 * to clean up if something goes wrong. 216 */ 217static int 218#ifdef AUDIT_REVIEW_GROUP 219open_trail(const char *fname, uid_t uid, gid_t gid) 220#else 221open_trail(const char *fname) 222#endif 223{ 224 int error, fd; 225 226 fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP); 227 if (fd < 0) 228 return (-1); 229#ifdef AUDIT_REVIEW_GROUP 230 if (fchown(fd, uid, gid) < 0) { 231 error = errno; 232 close(fd); 233 (void)unlink(fname); 234 errno = error; 235 return (-1); 236 } 237#endif 238 return (fd); 239} 240 241/* | |
242 * Create the new file name, swap with existing audit file. 243 */ 244static int 245swap_audit_file(void) 246{ | 195 * Create the new file name, swap with existing audit file. 196 */ 197static int 198swap_audit_file(void) 199{ |
247 char timestr[FILENAME_LEN]; 248 char *fn; | 200 int err; 201 char *newfile; |
249 char TS[TIMESTAMP_LEN]; | 202 char TS[TIMESTAMP_LEN]; |
250 struct dir_ent *dirent; 251#ifdef AUDIT_REVIEW_GROUP 252 struct group *grp; 253 gid_t gid; 254 uid_t uid; 255#endif 256 int error, fd; | 203 time_t tt; |
257 | 204 |
258 if (getTSstr(TS, TIMESTAMP_LEN) != 0) | 205 if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0) |
259 return (-1); | 206 return (-1); |
207 err = auditd_swap_trail(TS, &newfile, audit_review_gid, 208 audit_warn_getacdir); 209 if (err != ADE_NOERR) { 210 auditd_log_err( "%s: %m", auditd_strerror(err)); 211 if (err != ADE_ACTL) 212 return (-1); 213 } |
|
260 | 214 |
261 snprintf(timestr, FILENAME_LEN, "%s.%s", TS, NOT_TERMINATED); 262 263#ifdef AUDIT_REVIEW_GROUP | |
264 /* | 215 /* |
265 * XXXRW: Currently, this code falls back to the daemon gid, which is 266 * likely the wheel group. Is there a better way to deal with this? | 216 * Only close the last file if were in an auditing state before 217 * calling swap_audit_file(). We may need to recover from a crash. |
267 */ | 218 */ |
268 grp = getgrnam(AUDIT_REVIEW_GROUP); 269 if (grp == NULL) { 270 syslog(LOG_INFO, 271 "Audit review group '%s' not available, using daemon gid", 272 AUDIT_REVIEW_GROUP); 273 gid = -1; 274 } else 275 gid = grp->gr_gid; 276 uid = getuid(); 277#endif | 219 if (auditd_get_state() == AUD_STATE_ENABLED) 220 close_lastfile(TS); |
278 | 221 |
279 /* Try until we succeed. */ 280 while ((dirent = TAILQ_FIRST(&dir_q))) { 281 if ((fn = affixdir(timestr, dirent)) == NULL) { 282 syslog(LOG_INFO, "Failed to swap log at time %s", 283 timestr); 284 return (-1); 285 } | |
286 | 222 |
287 /* 288 * Create and open the file; then close and pass to the 289 * kernel if all went well. 290 */ 291 syslog(LOG_INFO, "New audit file is %s", fn); 292#ifdef AUDIT_REVIEW_GROUP 293 fd = open_trail(fn, uid, gid); 294#else 295 fd = open_trail(fn); 296#endif 297 if (fd < 0) 298 warn("open(%s)", fn); 299 if (fd >= 0) { 300 error = auditctl(fn); 301 if (error) { 302 syslog(LOG_ERR, 303 "auditctl failed setting log file! : %s", 304 strerror(errno)); 305 close(fd); 306 } else { 307 /* Success. */ 308#ifdef USE_MACH_IPC 309 /* 310 * auditctl() potentially changes the audit 311 * state so post that the audit config (may 312 * have) changed. 313 */ 314 notify_post(__BSM_INTERNAL_NOTIFY_KEY); 315#endif 316 close_lastfile(TS); 317 lastfile = fn; 318 close(fd); 319 return (0); 320 } 321 } | 223 /* 224 * auditd_swap_trail() potentially enables auditing (if not already 225 * enabled) so updated the cached state as well. 226 */ 227 auditd_set_state(AUD_STATE_ENABLED); 228 229 /* 230 * Create 'current' symlink. Recover from crash, if needed. 231 */ 232 if (auditd_new_curlink(newfile) != 0) 233 auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m", 234 newfile, auditd_strerror(err)); |
322 | 235 |
323 /* 324 * Tell the administrator about lack of permissions for dir. 325 */ 326 audit_warn_getacdir(dirent->dirname); | 236 lastfile = newfile; 237 auditd_log_notice("New audit file is %s", newfile); |
327 | 238 |
328 /* Try again with a different directory. */ 329 TAILQ_REMOVE(&dir_q, dirent, dirs); 330 free(dirent->dirname); 331 free(dirent); 332 } 333 syslog(LOG_ERR, "Log directories exhausted"); 334 return (-1); | 239 return (0); |
335} 336 337/* | 240} 241 242/* |
338 * Read the audit_control file contents. | 243 * Create a new audit log trail file and swap with the current one, if any. |
339 */ 340static int | 244 */ 245static int |
341read_control_file(void) | 246do_trail_file(void) |
342{ | 247{ |
343 char cur_dir[MAXNAMLEN]; 344 struct dir_ent *dirent; 345 au_qctrl_t qctrl; | 248 int err; |
346 347 /* | 249 250 /* |
348 * Clear old values. Force a re-read of the file the next time. | 251 * First, refresh the list of audit log directories. |
349 */ | 252 */ |
350 free_dir_q(); 351 endac(); 352 353 /* 354 * Read the list of directories into a local linked list. 355 * 356 * XXX We should use the reentrant interfaces once they are 357 * available. 358 */ 359 while (getacdir(cur_dir, MAXNAMLEN) >= 0) { 360 dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent)); 361 if (dirent == NULL) | 253 err = auditd_read_dirs(audit_warn_soft, audit_warn_hard); 254 if (err) { 255 auditd_log_err("auditd_read_dirs() %s: %m", 256 auditd_strerror(err)); 257 if (err == ADE_HARDLIM) 258 audit_warn_allhard(); 259 if (err != ADE_SOFTLIM) |
362 return (-1); | 260 return (-1); |
363 dirent->softlim = 0; 364 dirent->dirname = (char *) malloc(MAXNAMLEN); 365 if (dirent->dirname == NULL) { 366 free(dirent); 367 return (-1); 368 } 369 strlcpy(dirent->dirname, cur_dir, MAXNAMLEN); 370 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); | 261 else 262 audit_warn_allsoft(); 263 /* continue on with soft limit error */ |
371 } 372 | 264 } 265 |
373 allhardcount = 0; | 266 /* 267 * Create a new file and swap with the one being used in kernel. 268 */ |
374 if (swap_audit_file() == -1) { | 269 if (swap_audit_file() == -1) { |
375 syslog(LOG_ERR, "Could not swap audit file"); | |
376 /* 377 * XXX Faulty directory listing? - user should be given 378 * XXX an opportunity to change the audit_control file 379 * XXX switch to a reduced mode of auditing? 380 */ 381 return (-1); 382 } 383 | 270 /* 271 * XXX Faulty directory listing? - user should be given 272 * XXX an opportunity to change the audit_control file 273 * XXX switch to a reduced mode of auditing? 274 */ 275 return (-1); 276 } 277 |
384 /* 385 * XXX There are synchronization problems here 386 * XXX what should we do if a trigger for the earlier limit 387 * XXX is generated here? 388 */ 389 if (0 == (ret = getacmin(&minval))) { 390 syslog(LOG_DEBUG, "min free = %d", minval); 391 if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) { 392 syslog(LOG_ERR, 393 "could not get audit queue settings"); 394 return (-1); 395 } 396 qctrl.aq_minfree = minval; 397 if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) { 398 syslog(LOG_ERR, 399 "could not set audit queue settings"); 400 return (-1); 401 } | 278 return (0); 279} 280 281/* 282 * Start up auditing. 283 */ 284static void 285audit_setup(void) 286{ 287 int err; 288 289 if (do_trail_file() == -1) { 290 auditd_log_err("Error creating audit trail file"); 291 fail_exit(); |
402 } 403 | 292 } 293 |
294 /* Generate an audit record. */ 295 err = auditd_gen_record(AUE_audit_startup, NULL); 296 if (err) 297 auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m", 298 auditd_strerror(err)); 299 300 if (auditd_config_controls() == 0) 301 auditd_log_info("Audit controls init successful"); 302 else 303 auditd_log_err("Audit controls init failed"); 304 305} 306 307 308/* 309 * Close auditd pid file and trigger mechanism. 310 */ 311static int 312close_misc(void) 313{ 314 315 auditd_close_dirs(); 316 if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) { 317 auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE); 318 return (1); 319 } 320 endac(); 321 322 if (auditd_close_trigger() != 0) { 323 auditd_log_err("Error closing trigger messaging mechanism"); 324 return (1); 325 } |
|
404 return (0); 405} 406 407/* 408 * Close all log files, control files, and tell the audit system. 409 */ 410static int 411close_all(void) 412{ | 326 return (0); 327} 328 329/* 330 * Close all log files, control files, and tell the audit system. 331 */ 332static int 333close_all(void) 334{ |
413 struct auditinfo ai; | |
414 int err_ret = 0; 415 char TS[TIMESTAMP_LEN]; | 335 int err_ret = 0; 336 char TS[TIMESTAMP_LEN]; |
416 int aufd; 417 token_t *tok; | 337 int err; |
418 long cond; | 338 long cond; |
339 time_t tt; |
|
419 | 340 |
420 /* Generate an audit record. */ 421 if ((aufd = au_open()) == -1) 422 syslog(LOG_ERR, "Could not create audit shutdown event."); 423 else { 424 if ((tok = au_to_text("auditd::Audit shutdown")) != NULL) 425 au_write(aufd, tok); 426 /* 427 * XXX we need to implement extended subject tokens so we can 428 * effectively represent terminal lines with this token type. 429 */ 430 bzero(&ai, sizeof(ai)); 431 if ((tok = au_to_subject32(getuid(), geteuid(), getegid(), 432 getuid(), getgid(), getpid(), getpid(), &ai.ai_termid)) 433 != NULL) 434 au_write(aufd, tok); 435 if ((tok = au_to_return32(0, 0)) != NULL) 436 au_write(aufd, tok); 437 if (au_close(aufd, 1, AUE_audit_shutdown) == -1) 438 syslog(LOG_ERR, 439 "Could not close audit shutdown event."); 440 } | 341 err = auditd_gen_record(AUE_audit_shutdown, NULL); 342 if (err) 343 auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m", 344 auditd_strerror(err)); |
441 442 /* Flush contents. */ 443 cond = AUC_DISABLED; 444 err_ret = auditon(A_SETCOND, &cond, sizeof(cond)); 445 if (err_ret != 0) { | 345 346 /* Flush contents. */ 347 cond = AUC_DISABLED; 348 err_ret = auditon(A_SETCOND, &cond, sizeof(cond)); 349 if (err_ret != 0) { |
446 syslog(LOG_ERR, "Disabling audit failed! : %s", 447 strerror(errno)); | 350 auditd_log_err("Disabling audit failed! : %s", strerror(errno)); |
448 err_ret = 1; 449 } | 351 err_ret = 1; 352 } |
450#ifdef USE_MACH_IPC 451 /* 452 * Post a notification that the audit config changed. | 353 354 /* 355 * Updated the cached state that auditing has been disabled. |
453 */ | 356 */ |
454 notify_post(__BSM_INTERNAL_NOTIFY_KEY); 455#endif 456 if (getTSstr(TS, TIMESTAMP_LEN) == 0) | 357 auditd_set_state(AUD_STATE_DISABLED); 358 359 if (getTSstr(tt, TS, TIMESTAMP_LEN) == 0) |
457 close_lastfile(TS); 458 if (lastfile != NULL) 459 free(lastfile); 460 | 360 close_lastfile(TS); 361 if (lastfile != NULL) 362 free(lastfile); 363 |
461 free_dir_q(); 462 if ((remove(AUDITD_PIDFILE) == -1) || err_ret) { 463 syslog(LOG_ERR, "Could not unregister"); | 364 err_ret += close_misc(); 365 366 if (err_ret) { 367 auditd_log_err("Could not unregister"); |
464 audit_warn_postsigterm(); | 368 audit_warn_postsigterm(); |
465 return (1); | |
466 } | 369 } |
467 endac(); | |
468 | 370 |
469#ifndef USE_MACH_IPC 470 if (close(triggerfd) != 0) 471 syslog(LOG_ERR, "Error closing control file"); 472#endif 473 syslog(LOG_INFO, "Finished"); 474 return (0); | 371 auditd_log_info("Finished"); 372 return (err_ret); |
475} 476 477/* | 373} 374 375/* |
478 * When we get a signal, we are often not at a clean point. So, little can 479 * be done in the signal handler itself. Instead, we send a message to the 480 * main servicing loop to do proper handling from a non-signal-handler 481 * context. | 376 * Register the daemon with the signal handler and the auditd pid file. |
482 */ | 377 */ |
483#ifdef USE_MACH_IPC 484static void 485relay_signal(int signal) 486{ 487 mach_msg_empty_send_t msg; 488 489 msg.header.msgh_id = signal; 490 msg.header.msgh_remote_port = signal_port; 491 msg.header.msgh_local_port = MACH_PORT_NULL; 492 msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); 493 mach_msg(&(msg.header), MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof(msg), 494 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 495} 496 497#else /* ! USE_MACH_IPC */ 498 499static void 500relay_signal(int signal) 501{ 502 503 if (signal == SIGHUP) 504 sighups++; 505 if (signal == SIGTERM) 506 sigterms++; 507 if (signal == SIGCHLD) 508 sigchlds++; 509} 510#endif /* ! USE_MACH_IPC */ 511 512/* 513 * Registering the daemon. 514 */ | |
515static int 516register_daemon(void) 517{ 518 FILE * pidfile; 519 int fd; 520 pid_t pid; 521 522 /* Set up the signal hander. */ | 378static int 379register_daemon(void) 380{ 381 FILE * pidfile; 382 int fd; 383 pid_t pid; 384 385 /* Set up the signal hander. */ |
523 if (signal(SIGTERM, relay_signal) == SIG_ERR) { 524 syslog(LOG_ERR, | 386 if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) { 387 auditd_log_err( |
525 "Could not set signal handler for SIGTERM"); 526 fail_exit(); 527 } | 388 "Could not set signal handler for SIGTERM"); 389 fail_exit(); 390 } |
528 if (signal(SIGCHLD, relay_signal) == SIG_ERR) { 529 syslog(LOG_ERR, | 391 if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) { 392 auditd_log_err( |
530 "Could not set signal handler for SIGCHLD"); 531 fail_exit(); 532 } | 393 "Could not set signal handler for SIGCHLD"); 394 fail_exit(); 395 } |
533 if (signal(SIGHUP, relay_signal) == SIG_ERR) { 534 syslog(LOG_ERR, | 396 if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) { 397 auditd_log_err( |
535 "Could not set signal handler for SIGHUP"); 536 fail_exit(); 537 } | 398 "Could not set signal handler for SIGHUP"); 399 fail_exit(); 400 } |
401 if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) { 402 auditd_log_err( 403 "Could not set signal handler for SIGALRM"); 404 fail_exit(); 405 } |
|
538 539 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { | 406 407 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { |
540 syslog(LOG_ERR, "Could not open PID file"); | 408 auditd_log_err("Could not open PID file"); |
541 audit_warn_tmpfile(); 542 return (-1); 543 } 544 545 /* Attempt to lock the pid file; if a lock is present, exit. */ 546 fd = fileno(pidfile); 547 if (flock(fd, LOCK_EX | LOCK_NB) < 0) { | 409 audit_warn_tmpfile(); 410 return (-1); 411 } 412 413 /* Attempt to lock the pid file; if a lock is present, exit. */ 414 fd = fileno(pidfile); 415 if (flock(fd, LOCK_EX | LOCK_NB) < 0) { |
548 syslog(LOG_ERR, | 416 auditd_log_err( |
549 "PID file is locked (is another auditd running?)."); 550 audit_warn_ebusy(); 551 return (-1); 552 } 553 554 pid = getpid(); 555 ftruncate(fd, 0); 556 if (fprintf(pidfile, "%u\n", pid) < 0) { 557 /* Should not start the daemon. */ 558 fail_exit(); 559 } 560 561 fflush(pidfile); 562 return (0); 563} 564 | 417 "PID file is locked (is another auditd running?)."); 418 audit_warn_ebusy(); 419 return (-1); 420 } 421 422 pid = getpid(); 423 ftruncate(fd, 0); 424 if (fprintf(pidfile, "%u\n", pid) < 0) { 425 /* Should not start the daemon. */ 426 fail_exit(); 427 } 428 429 fflush(pidfile); 430 return (0); 431} 432 |
565#ifdef USE_MACH_IPC | |
566/* | 433/* |
567 * Implementation of the auditd_control() MIG simpleroutine. 568 * 569 * React to input from the audit(1) tool. 570 */ 571 572/* ARGSUSED */ 573kern_return_t 574auditd_control(mach_port_t __unused auditd_port, int trigger) 575{ 576 int err_ret = 0; 577 578 switch (trigger) { 579 580 case AUDIT_TRIGGER_ROTATE_USER: 581 /* 582 * Create a new file and swap with the one 583 * being used in kernel. 584 */ 585 if (swap_audit_file() == -1) 586 syslog(LOG_ERR, "Error swapping audit file"); 587 break; 588 589 case AUDIT_TRIGGER_READ_FILE: 590 if (read_control_file() == -1) 591 syslog(LOG_ERR, "Error in audit control file"); 592 break; 593 594 case AUDIT_TRIGGER_CLOSE_AND_DIE: 595 err_ret = close_all(); 596 exit (err_ret); 597 break; 598 599 default: 600 break; 601 } 602 603 return (KERN_SUCCESS); 604} 605#endif /* USE_MACH_IPC */ 606 607/* | |
608 * Handle the audit trigger event. 609 * 610 * We suppress (ignore) duplicated triggers in close succession in order to 611 * try to avoid thrashing-like behavior. However, not all triggers can be 612 * ignored, as triggers generally represent edge triggers, not level 613 * triggers, and won't be retransmitted if the condition persists. Of 614 * specific concern is the rotate trigger -- if one is dropped, then it will 615 * not be retransmitted, and the log file will grow in an unbounded fashion. 616 */ 617#define DUPLICATE_INTERVAL 30 | 434 * Handle the audit trigger event. 435 * 436 * We suppress (ignore) duplicated triggers in close succession in order to 437 * try to avoid thrashing-like behavior. However, not all triggers can be 438 * ignored, as triggers generally represent edge triggers, not level 439 * triggers, and won't be retransmitted if the condition persists. Of 440 * specific concern is the rotate trigger -- if one is dropped, then it will 441 * not be retransmitted, and the log file will grow in an unbounded fashion. 442 */ 443#define DUPLICATE_INTERVAL 30 |
618#ifdef USE_MACH_IPC 619#define AT_SUCCESS KERN_SUCCESS 620 621/* ARGSUSED */ 622kern_return_t 623audit_triggers(mach_port_t __unused audit_port, int trigger) 624#else 625#define AT_SUCCESS 0 626 627static int 628handle_audit_trigger(int trigger) 629#endif | 444void 445auditd_handle_trigger(int trigger) |
630{ 631 static int last_trigger, last_warning; 632 static time_t last_time; | 446{ 447 static int last_trigger, last_warning; 448 static time_t last_time; |
633 struct dir_ent *dirent; | |
634 struct timeval ts; 635 struct timezone tzp; 636 time_t tt; | 449 struct timeval ts; 450 struct timezone tzp; 451 time_t tt; |
452 int au_state; 453 int err = 0; |
|
637 638 /* 639 * Suppress duplicate messages from the kernel within the specified 640 * interval. 641 */ 642 if (gettimeofday(&ts, &tzp) == 0) { 643 tt = (time_t)ts.tv_sec; 644 switch (trigger) { 645 case AUDIT_TRIGGER_LOW_SPACE: 646 case AUDIT_TRIGGER_NO_SPACE: 647 /* 648 * Triggers we can suppress. Of course, we also need 649 * to rate limit the warnings, so apply the same 650 * interval limit on syslog messages. 651 */ 652 if ((trigger == last_trigger) && 653 (tt < (last_time + DUPLICATE_INTERVAL))) { 654 if (tt >= (last_warning + DUPLICATE_INTERVAL)) | 454 455 /* 456 * Suppress duplicate messages from the kernel within the specified 457 * interval. 458 */ 459 if (gettimeofday(&ts, &tzp) == 0) { 460 tt = (time_t)ts.tv_sec; 461 switch (trigger) { 462 case AUDIT_TRIGGER_LOW_SPACE: 463 case AUDIT_TRIGGER_NO_SPACE: 464 /* 465 * Triggers we can suppress. Of course, we also need 466 * to rate limit the warnings, so apply the same 467 * interval limit on syslog messages. 468 */ 469 if ((trigger == last_trigger) && 470 (tt < (last_time + DUPLICATE_INTERVAL))) { 471 if (tt >= (last_warning + DUPLICATE_INTERVAL)) |
655 syslog(LOG_INFO, | 472 auditd_log_info( |
656 "Suppressing duplicate trigger %d", 657 trigger); | 473 "Suppressing duplicate trigger %d", 474 trigger); |
658 return (AT_SUCCESS); | 475 return; |
659 } 660 last_warning = tt; 661 break; 662 663 case AUDIT_TRIGGER_ROTATE_KERNEL: 664 case AUDIT_TRIGGER_ROTATE_USER: 665 case AUDIT_TRIGGER_READ_FILE: | 476 } 477 last_warning = tt; 478 break; 479 480 case AUDIT_TRIGGER_ROTATE_KERNEL: 481 case AUDIT_TRIGGER_ROTATE_USER: 482 case AUDIT_TRIGGER_READ_FILE: |
483 case AUDIT_TRIGGER_CLOSE_AND_DIE: 484 case AUDIT_TRIGGER_INITIALIZE: |
|
666 /* 667 * Triggers that we cannot suppress. 668 */ 669 break; 670 } 671 672 /* 673 * Only update last_trigger after aborting due to a duplicate 674 * trigger, not before, or we will never allow that trigger 675 * again. 676 */ 677 last_trigger = trigger; 678 last_time = tt; 679 } 680 | 485 /* 486 * Triggers that we cannot suppress. 487 */ 488 break; 489 } 490 491 /* 492 * Only update last_trigger after aborting due to a duplicate 493 * trigger, not before, or we will never allow that trigger 494 * again. 495 */ 496 last_trigger = trigger; 497 last_time = tt; 498 } 499 |
500 au_state = auditd_get_state(); 501 |
|
681 /* 682 * Message processing is done here. 683 */ | 502 /* 503 * Message processing is done here. 504 */ |
684 dirent = TAILQ_FIRST(&dir_q); | |
685 switch(trigger) { 686 case AUDIT_TRIGGER_LOW_SPACE: | 505 switch(trigger) { 506 case AUDIT_TRIGGER_LOW_SPACE: |
687 syslog(LOG_INFO, "Got low space trigger"); 688 if (dirent && (dirent->softlim != 1)) { 689 TAILQ_REMOVE(&dir_q, dirent, dirs); 690 /* Add this node to the end of the list. */ 691 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); 692 audit_warn_soft(dirent->dirname); 693 dirent->softlim = 1; 694 695 if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL && 696 swap_audit_file() == -1) 697 syslog(LOG_ERR, "Error swapping audit file"); 698 699 /* 700 * Check if the next dir has already reached its soft 701 * limit. 702 */ 703 dirent = TAILQ_FIRST(&dir_q); 704 if (dirent->softlim == 1) { 705 /* All dirs have reached their soft limit. */ 706 audit_warn_allsoft(); 707 } 708 } else { 709 /* 710 * Continue auditing to the current file. Also 711 * generate an allsoft warning. 712 * 713 * XXX do we want to do this ? 714 */ 715 audit_warn_allsoft(); 716 } | 507 auditd_log_notice("Got low space trigger"); 508 if (do_trail_file() == -1) 509 auditd_log_err("Error swapping audit file"); |
717 break; 718 719 case AUDIT_TRIGGER_NO_SPACE: | 510 break; 511 512 case AUDIT_TRIGGER_NO_SPACE: |
720 syslog(LOG_INFO, "Got no space trigger"); 721 722 /* Delete current dir, go on to next. */ 723 TAILQ_REMOVE(&dir_q, dirent, dirs); 724 audit_warn_hard(dirent->dirname); 725 free(dirent->dirname); 726 free(dirent); 727 728 if (swap_audit_file() == -1) 729 syslog(LOG_ERR, "Error swapping audit file"); 730 731 /* We are out of log directories. */ 732 audit_warn_allhard(++allhardcount); | 513 auditd_log_notice("Got no space trigger"); 514 if (do_trail_file() == -1) 515 auditd_log_err("Error swapping audit file"); |
733 break; 734 735 case AUDIT_TRIGGER_ROTATE_KERNEL: 736 case AUDIT_TRIGGER_ROTATE_USER: | 516 break; 517 518 case AUDIT_TRIGGER_ROTATE_KERNEL: 519 case AUDIT_TRIGGER_ROTATE_USER: |
737 /* 738 * Create a new file and swap with the one being used in 739 * kernel 740 */ 741 syslog(LOG_INFO, "Got open new trigger from %s", trigger == | 520 auditd_log_info("Got open new trigger from %s", trigger == |
742 AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user"); | 521 AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user"); |
743 if (swap_audit_file() == -1) 744 syslog(LOG_ERR, "Error swapping audit file"); | 522 if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1) 523 auditd_log_err("Error swapping audit file"); |
745 break; 746 747 case AUDIT_TRIGGER_READ_FILE: | 524 break; 525 526 case AUDIT_TRIGGER_READ_FILE: |
748 syslog(LOG_INFO, "Got read file trigger"); 749 if (read_control_file() == -1) 750 syslog(LOG_ERR, "Error in audit control file"); 751 if (config_audit_controls() == -1) 752 syslog(LOG_ERR, "Error setting audit controls"); | 527 auditd_log_info("Got read file trigger"); 528 if (au_state == AUD_STATE_ENABLED && 529 auditd_config_controls() == -1) 530 auditd_log_err("Error setting audit controls"); |
753 break; 754 | 531 break; 532 |
755 default: 756 syslog(LOG_ERR, "Got unknown trigger %d", trigger); 757 break; 758 } 759 760 return (AT_SUCCESS); 761} 762 763#undef AT_SUCCESS 764 765static void 766handle_sighup(void) 767{ 768 769 sighups_handled = sighups; 770 config_audit_controls(); 771} 772 773static int 774config_audit_host(void) 775{ 776 char hoststr[MAXHOSTNAMELEN]; 777 struct sockaddr_in6 *sin6; 778 struct sockaddr_in *sin; 779 struct addrinfo *res; 780 struct auditinfo_addr aia; 781 int error; 782 783 if (getachost(hoststr, MAXHOSTNAMELEN) != 0) { 784 syslog(LOG_WARNING, 785 "warning: failed to read 'host' param in control file"); | 533 case AUDIT_TRIGGER_CLOSE_AND_DIE: 534 auditd_log_info("Got close and die trigger"); 535 if (au_state == AUD_STATE_ENABLED) 536 err = close_all(); |
786 /* | 537 /* |
787 * To maintain reverse compatability with older audit_control 788 * files, simply drop a warning if the host parameter has not 789 * been set. However, we will explicitly disable the 790 * generation of extended audit header by passing in a zeroed 791 * termid structure. | 538 * Running under launchd don't exit. Wait for launchd to 539 * send SIGTERM. |
792 */ | 540 */ |
793 bzero(&aia, sizeof(aia)); 794 aia.ai_termid.at_type = AU_IPv4; 795 error = auditon(A_SETKAUDIT, &aia, sizeof(aia)); 796 if (error < 0 && errno == ENOSYS) 797 return (0); 798 else if (error < 0) { 799 syslog(LOG_ERR, 800 "Failed to set audit host info"); 801 return (-1); | 541 if (!launchd_flag) { 542 auditd_log_info("auditd exiting."); 543 exit (err); |
802 } | 544 } |
803 return (0); 804 } 805 error = getaddrinfo(hoststr, NULL, NULL, &res); 806 if (error) { 807 syslog(LOG_ERR, "Failed to lookup hostname: %s", hoststr); 808 return (-1); 809 } 810 switch (res->ai_family) { 811 case PF_INET6: 812 sin6 = (struct sockaddr_in6 *) res->ai_addr; 813 bcopy(&sin6->sin6_addr.s6_addr, 814 &aia.ai_termid.at_addr[0], sizeof(struct in6_addr)); 815 aia.ai_termid.at_type = AU_IPv6; | |
816 break; | 545 break; |
817 case PF_INET: 818 sin = (struct sockaddr_in *) res->ai_addr; 819 bcopy(&sin->sin_addr.s_addr, 820 &aia.ai_termid.at_addr[0], sizeof(struct in_addr)); 821 aia.ai_termid.at_type = AU_IPv4; | 546 547 case AUDIT_TRIGGER_INITIALIZE: 548 auditd_log_info("Got audit initialize trigger"); 549 if (au_state == AUD_STATE_DISABLED) 550 audit_setup(); |
822 break; | 551 break; |
552 |
|
823 default: | 553 default: |
824 syslog(LOG_ERR, 825 "Un-supported address family in host parameter"); 826 return (-1); | 554 auditd_log_err("Got unknown trigger %d", trigger); 555 break; |
827 } | 556 } |
828 if (auditon(A_SETKAUDIT, &aia, sizeof(aia)) < 0) { 829 syslog(LOG_ERR, 830 "auditon: failed to set audit host information"); 831 return (-1); 832 } 833 return (0); | |
834} 835 836/* 837 * Reap our children. 838 */ | 557} 558 559/* 560 * Reap our children. 561 */ |
839static void 840reap_children(void) | 562void 563auditd_reap_children(void) |
841{ 842 pid_t child; 843 int wstatus; 844 845 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { 846 if (!wstatus) 847 continue; | 564{ 565 pid_t child; 566 int wstatus; 567 568 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { 569 if (!wstatus) 570 continue; |
848 syslog(LOG_INFO, "warn process [pid=%d] %s %d.", child, | 571 auditd_log_info("warn process [pid=%d] %s %d.", child, |
849 ((WIFEXITED(wstatus)) ? "exited with non-zero status" : 850 "exited as a result of signal"), 851 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : 852 WTERMSIG(wstatus))); 853 } 854} 855 | 572 ((WIFEXITED(wstatus)) ? "exited with non-zero status" : 573 "exited as a result of signal"), 574 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : 575 WTERMSIG(wstatus))); 576 } 577} 578 |
856static void 857handle_sigchld(void) 858{ 859 860 sigchlds_handled = sigchlds; 861 reap_children(); 862} 863 | |
864/* | 579/* |
865 * Read the control file for triggers/signals and handle appropriately. | 580 * Reap any children and terminate. If under launchd don't shutdown auditing 581 * but just the other stuff. |
866 */ | 582 */ |
867#ifdef USE_MACH_IPC 868#define MAX_MSG_SIZE 4096 869 870static boolean_t 871auditd_combined_server(mach_msg_header_t *InHeadP, 872 mach_msg_header_t *OutHeadP) | 583void 584auditd_terminate(void) |
873{ | 585{ |
874 mach_port_t local_port = InHeadP->msgh_local_port; | 586 int ret; |
875 | 587 |
876 if (local_port == signal_port) { 877 int signo = InHeadP->msgh_id; 878 int ret; | 588 auditd_reap_children(); 589 590 if (launchd_flag) 591 ret = close_misc(); 592 else 593 ret = close_all(); |
879 | 594 |
880 switch(signo) { 881 case SIGTERM: 882 ret = close_all(); 883 exit(ret); 884 885 case SIGCHLD: 886 handle_sigchld(); 887 return (TRUE); 888 889 case SIGHUP: 890 handle_sighup(); 891 return (TRUE); 892 893 default: 894 syslog(LOG_INFO, "Received signal %d", signo); 895 return (TRUE); 896 } 897 } else if (local_port == control_port) { 898 boolean_t result; 899 900 result = audit_triggers_server(InHeadP, OutHeadP); 901 if (!result) 902 result = auditd_control_server(InHeadP, OutHeadP); 903 return (result); 904 } 905 syslog(LOG_INFO, "Recevied msg on bad port 0x%x.", local_port); 906 return (FALSE); | 595 exit(ret); |
907} 908 | 596} 597 |
909static int 910wait_for_events(void) 911{ 912 kern_return_t result; 913 914 result = mach_msg_server(auditd_combined_server, MAX_MSG_SIZE, 915 port_set, MACH_MSG_OPTION_NONE); 916 syslog(LOG_ERR, "abnormal exit\n"); 917 return (close_all()); 918} 919 920#else /* ! USE_MACH_IPC */ 921 922static int 923wait_for_events(void) 924{ 925 int num; 926 unsigned int trigger; 927 928 for (;;) { 929 num = read(triggerfd, &trigger, sizeof(trigger)); 930 if ((num == -1) && (errno != EINTR)) { 931 syslog(LOG_ERR, "%s: error %d", __FUNCTION__, errno); 932 return (-1); 933 } 934 if (sigterms != sigterms_handled) { 935 syslog(LOG_DEBUG, "%s: SIGTERM", __FUNCTION__); 936 break; 937 } 938 if (sigchlds != sigchlds_handled) 939 handle_sigchld(); 940 if (sighups != sighups_handled) { 941 syslog(LOG_DEBUG, "%s: SIGHUP", __FUNCTION__); 942 handle_sighup(); 943 } 944 if ((num == -1) && (errno == EINTR)) 945 continue; 946 if (num == 0) { 947 syslog(LOG_ERR, "%s: read EOF", __FUNCTION__); 948 return (-1); 949 } 950 if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE) 951 break; 952 else 953 (void)handle_audit_trigger(trigger); 954 } 955 return (close_all()); 956} 957#endif /* ! USE_MACH_IPC */ 958 | |
959/* 960 * Configure the audit controls in the kernel: the event to class mapping, 961 * kernel preselection mask, etc. 962 */ | 598/* 599 * Configure the audit controls in the kernel: the event to class mapping, 600 * kernel preselection mask, etc. 601 */ |
963static int 964config_audit_controls(void) | 602int 603auditd_config_controls(void) |
965{ | 604{ |
966 au_event_ent_t ev, *evp; 967 au_evclass_map_t evc_map; 968 au_mask_t aumask; 969 int ctr = 0; 970 char naeventstr[NA_EVENT_STR_SIZE]; 971 char polstr[POL_STR_SIZE]; 972 long policy; 973 au_fstat_t au_fstat; 974 size_t filesz; | 605 int cnt, err; 606 int ret = 0; |
975 976 /* | 607 608 /* |
977 * Process the audit event file, obtaining a class mapping for each 978 * event, and send that mapping into the kernel. 979 * 980 * XXX There's a risk here that the BSM library will return NULL 981 * for an event when it can't properly map it to a class. In that 982 * case, we will not process any events beyond the one that failed, 983 * but should. We need a way to get a count of the events. 984 */ 985 ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX); 986 ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX); 987 if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) { 988 if (ev.ae_name != NULL) 989 free(ev.ae_name); 990 syslog(LOG_ERR, 991 "Memory allocation error when configuring audit controls."); 992 return (-1); 993 } | 609 * Configure event to class mappings in kernel. 610 */ 611 cnt = auditd_set_evcmap(); 612 if (cnt < 0) { 613 auditd_log_err("auditd_set_evcmap() failed: %m"); 614 ret = -1; 615 } else if (cnt == 0) { 616 auditd_log_err("No events to class mappings registered."); 617 ret = -1; 618 } else 619 auditd_log_debug("Registered %d event to class mappings.", cnt); |
994 995 /* | 620 621 /* |
996 * XXXRW: Currently we have no way to remove mappings from the kernel 997 * when they are removed from the file-based mappings. | 622 * Configure non-attributable event mask in kernel. |
998 */ | 623 */ |
999 evp = &ev; 1000 setauevent(); 1001 while ((evp = getauevent_r(evp)) != NULL) { 1002 evc_map.ec_number = evp->ae_number; 1003 evc_map.ec_class = evp->ae_class; 1004 if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t)) 1005 != 0) 1006 syslog(LOG_ERR, 1007 "Failed to register class mapping for event %s", 1008 evp->ae_name); 1009 else 1010 ctr++; 1011 } 1012 endauevent(); 1013 free(ev.ae_name); 1014 free(ev.ae_desc); 1015 if (ctr == 0) 1016 syslog(LOG_ERR, "No events to class mappings registered."); 1017 else 1018 syslog(LOG_DEBUG, "Registered %d event to class mappings.", 1019 ctr); | 624 err = auditd_set_namask(); 625 if (err) { 626 auditd_log_err("auditd_set_namask() %s: %m", 627 auditd_strerror(err)); 628 ret = -1; 629 } else 630 auditd_log_debug("Registered non-attributable event mask."); |
1020 1021 /* | 631 632 /* |
1022 * Get the non-attributable event string and set the kernel mask from 1023 * that. | 633 * Configure audit policy in kernel. |
1024 */ | 634 */ |
1025 if ((getacna(naeventstr, NA_EVENT_STR_SIZE) == 0) && 1026 (getauditflagsbin(naeventstr, &aumask) == 0)) { 1027 if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t))) 1028 syslog(LOG_ERR, 1029 "Failed to register non-attributable event mask."); 1030 else 1031 syslog(LOG_DEBUG, 1032 "Registered non-attributable event mask."); | 635 err = auditd_set_policy(); 636 if (err) { 637 auditd_log_err("auditd_set_policy() %s: %m", 638 auditd_strerror(err)); 639 ret = -1; |
1033 } else | 640 } else |
1034 syslog(LOG_ERR, 1035 "Failed to obtain non-attributable event mask."); 1036 | 641 auditd_log_debug("Set audit policy in kernel."); 642 |
1037 /* | 643 /* |
1038 * If a policy is configured in audit_control(5), implement the 1039 * policy. However, if one isn't defined, set AUDIT_CNT to avoid 1040 * leaving the system in a fragile state. | 644 * Configure audit trail log size in kernel. |
1041 */ | 645 */ |
1042 if ((getacpol(polstr, POL_STR_SIZE) == 0) && 1043 (au_strtopol(polstr, &policy) == 0)) { 1044 if (auditon(A_SETPOLICY, &policy, sizeof(policy))) 1045 syslog(LOG_ERR, "Failed to set audit policy: %m"); 1046 } else { 1047 syslog(LOG_ERR, "Failed to obtain policy flags: %m"); 1048 policy = AUDIT_CNT; 1049 if (auditon(A_SETPOLICY, &policy, sizeof(policy))) 1050 syslog(LOG_ERR, 1051 "Failed to set default audit policy: %m"); 1052 } 1053 | 646 err = auditd_set_fsize(); 647 if (err) { 648 auditd_log_err("audit_set_fsize() %s: %m", 649 auditd_strerror(err)); 650 ret = -1; 651 } else 652 auditd_log_debug("Set audit trail size in kernel."); 653 |
1054 /* | 654 /* |
1055 * Set trail rotation size. | 655 * Configure audit trail volume minimum free percentage of blocks in 656 * kernel. |
1056 */ | 657 */ |
1057 if (getacfilesz(&filesz) == 0) { 1058 bzero(&au_fstat, sizeof(au_fstat)); 1059 au_fstat.af_filesz = filesz; 1060 if (auditon(A_SETFSIZE, &au_fstat, sizeof(au_fstat)) < 0) 1061 syslog(LOG_ERR, "Failed to set filesz: %m"); | 658 err = auditd_set_minfree(); 659 if (err) { 660 auditd_log_err("auditd_set_minfree() %s: %m", 661 auditd_strerror(err)); 662 ret = -1; |
1062 } else | 663 } else |
1063 syslog(LOG_ERR, "Failed to obtain filesz: %m"); | 664 auditd_log_debug( 665 "Set audit trail min free percent in kernel."); |
1064 | 666 |
1065 return (config_audit_host()); 1066} 1067 1068#ifdef USE_MACH_IPC 1069static void 1070mach_setup(void) 1071{ 1072 mach_msg_type_name_t poly; 1073 | |
1074 /* | 667 /* |
1075 * Allocate a port set | 668 * Configure host address in the audit kernel information. |
1076 */ | 669 */ |
1077 if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, 1078 &port_set) != KERN_SUCCESS) { 1079 syslog(LOG_ERR, "Allocation of port set failed"); 1080 fail_exit(); 1081 } 1082 1083 /* 1084 * Allocate a signal reflection port 1085 */ 1086 if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, 1087 &signal_port) != KERN_SUCCESS || 1088 mach_port_move_member(mach_task_self(), signal_port, port_set) != 1089 KERN_SUCCESS) { 1090 syslog(LOG_ERR, "Allocation of signal port failed"); 1091 fail_exit(); 1092 } 1093 1094 /* 1095 * Allocate a trigger port 1096 */ 1097 if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, 1098 &control_port) != KERN_SUCCESS || 1099 mach_port_move_member(mach_task_self(), control_port, port_set) 1100 != KERN_SUCCESS) 1101 syslog(LOG_ERR, "Allocation of trigger port failed"); 1102 1103 /* 1104 * Create a send right on our trigger port. 1105 */ 1106 mach_port_extract_right(mach_task_self(), control_port, 1107 MACH_MSG_TYPE_MAKE_SEND, &control_port, &poly); 1108 1109 /* 1110 * Register the trigger port with the kernel. 1111 */ 1112 if (host_set_audit_control_port(mach_host_self(), control_port) != 1113 KERN_SUCCESS) { 1114 syslog(LOG_ERR, "Cannot set Mach control port"); 1115 fail_exit(); | 670 err = auditd_set_host(); 671 if (err) { 672 auditd_log_err("auditd_set_host() %s: %m", 673 auditd_strerror(err)); 674 ret = -1; |
1116 } else | 675 } else |
1117 syslog(LOG_DEBUG, "Mach control port registered"); | 676 auditd_log_debug( 677 "Set audit host address information in kernel."); 678 679 return (ret); |
1118} | 680} |
1119#endif /* USE_MACH_IPC */ | |
1120 | 681 |
682/* 683 * Setup and initialize auditd. 684 */ |
|
1121static void 1122setup(void) 1123{ | 685static void 686setup(void) 687{ |
1124 struct auditinfo ai; 1125 auditinfo_t auinfo; 1126 int aufd; 1127 token_t *tok; | 688 int err; |
1128 | 689 |
1129#ifdef USE_MACH_IPC 1130 mach_setup(); 1131#else 1132 if ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)) < 0) { 1133 syslog(LOG_ERR, "Error opening trigger file"); | 690 if (auditd_open_trigger(launchd_flag) < 0) { 691 auditd_log_err("Error opening trigger messaging mechanism"); |
1134 fail_exit(); 1135 } | 692 fail_exit(); 693 } |
1136#endif | |
1137 1138 /* 1139 * To prevent event feedback cycles and avoid auditd becoming 1140 * stalled if auditing is suspended, auditd and its children run 1141 * without their events being audited. We allow the uid, tid, and 1142 * mask fields to be implicitly set to zero, but do set the pid. We 1143 * run this after opening the trigger device to avoid configuring 1144 * audit state without audit present in the system. | 694 695 /* 696 * To prevent event feedback cycles and avoid auditd becoming 697 * stalled if auditing is suspended, auditd and its children run 698 * without their events being audited. We allow the uid, tid, and 699 * mask fields to be implicitly set to zero, but do set the pid. We 700 * run this after opening the trigger device to avoid configuring 701 * audit state without audit present in the system. |
1145 * 1146 * XXXRW: Is there more to it than this? | |
1147 */ | 702 */ |
1148 bzero(&auinfo, sizeof(auinfo)); 1149 auinfo.ai_asid = getpid(); 1150 if (setaudit(&auinfo) == -1) { 1151 syslog(LOG_ERR, "Error setting audit stat"); | 703 err = auditd_prevent_audit(); 704 if (err) { 705 auditd_log_err("auditd_prevent_audit() %s: %m", 706 auditd_strerror(err)); |
1152 fail_exit(); 1153 } 1154 | 707 fail_exit(); 708 } 709 |
1155 TAILQ_INIT(&dir_q); 1156 if (read_control_file() == -1) { 1157 syslog(LOG_ERR, "Error reading control file"); 1158 fail_exit(); 1159 } | 710 /* 711 * Make sure auditd auditing state is correct. 712 */ 713 auditd_set_state(AUD_STATE_INIT); |
1160 | 714 |
1161 /* Generate an audit record. */ 1162 if ((aufd = au_open()) == -1) 1163 syslog(LOG_ERR, "Could not create audit startup event."); 1164 else { 1165 /* 1166 * XXXCSJP Perhaps we want more robust audit records for 1167 * audit start up and shutdown. This might include capturing 1168 * failures to initialize the audit subsystem? 1169 */ 1170 bzero(&ai, sizeof(ai)); 1171 if ((tok = au_to_subject32(getuid(), geteuid(), getegid(), 1172 getuid(), getgid(), getpid(), getpid(), &ai.ai_termid)) 1173 != NULL) 1174 au_write(aufd, tok); 1175 if ((tok = au_to_text("auditd::Audit startup")) != NULL) 1176 au_write(aufd, tok); 1177 if ((tok = au_to_return32(0, 0)) != NULL) 1178 au_write(aufd, tok); 1179 if (au_close(aufd, 1, AUE_audit_startup) == -1) 1180 syslog(LOG_ERR, 1181 "Could not close audit startup event."); 1182 } 1183 1184 if (config_audit_controls() == 0) 1185 syslog(LOG_INFO, "Audit controls init successful"); 1186 else 1187 syslog(LOG_ERR, "Audit controls init failed"); | 715 /* 716 * If under launchd, don't start auditing. Wait for a trigger to 717 * do so. 718 */ 719 if (!launchd_flag) 720 audit_setup(); |
1188} 1189 1190int 1191main(int argc, char **argv) 1192{ 1193 int ch; 1194 int debug = 0; | 721} 722 723int 724main(int argc, char **argv) 725{ 726 int ch; 727 int debug = 0; |
1195 int rc, logopts; | 728#ifdef AUDIT_REVIEW_GROUP 729 struct group *grp; 730#endif |
1196 | 731 |
1197 while ((ch = getopt(argc, argv, "d")) != -1) { | 732 while ((ch = getopt(argc, argv, "dl")) != -1) { |
1198 switch(ch) { 1199 case 'd': 1200 /* Debug option. */ 1201 debug = 1; 1202 break; 1203 | 733 switch(ch) { 734 case 'd': 735 /* Debug option. */ 736 debug = 1; 737 break; 738 |
739 case 'l': 740 /* Be launchd friendly. */ 741 launchd_flag = 1; 742 break; 743 |
|
1204 case '?': 1205 default: 1206 (void)fprintf(stderr, | 744 case '?': 745 default: 746 (void)fprintf(stderr, |
1207 "usage: auditd [-d] \n"); | 747 "usage: auditd [-d] [-l]\n"); |
1208 exit(1); 1209 } 1210 } 1211 | 748 exit(1); 749 } 750 } 751 |
1212 logopts = LOG_CONS | LOG_PID; 1213 if (debug != 0) 1214 logopts |= LOG_PERROR; | 752 audit_review_gid = getgid(); |
1215 | 753 |
1216#ifdef LOG_SECURITY 1217 openlog("auditd", logopts, LOG_SECURITY); 1218#else 1219 openlog("auditd", logopts, LOG_AUTH); | 754#ifdef AUDIT_REVIEW_GROUP 755 /* 756 * XXXRW: Currently, this code falls back to the daemon gid, which is 757 * likely the wheel group. Is there a better way to deal with this? 758 */ 759 grp = getgrnam(AUDIT_REVIEW_GROUP); 760 if (grp != NULL) 761 audit_review_gid = grp->gr_gid; |
1220#endif | 762#endif |
1221 syslog(LOG_INFO, "starting..."); | |
1222 | 763 |
1223 if (debug == 0 && daemon(0, 0) == -1) { 1224 syslog(LOG_ERR, "Failed to daemonize"); | 764 auditd_openlog(debug, audit_review_gid); 765 766 if (launchd_flag) 767 auditd_log_info("started by launchd..."); 768 else 769 auditd_log_info("starting..."); 770 771#ifdef AUDIT_REVIEW_GROUP 772 if (grp == NULL) 773 auditd_log_info( 774 "Audit review group '%s' not available, using daemon gid (%d)", 775 AUDIT_REVIEW_GROUP, audit_review_gid); 776#endif 777 if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) { 778 auditd_log_err("Failed to daemonize"); |
1225 exit(1); 1226 } 1227 1228 if (register_daemon() == -1) { | 779 exit(1); 780 } 781 782 if (register_daemon() == -1) { |
1229 syslog(LOG_ERR, "Could not register as daemon"); | 783 auditd_log_err("Could not register as daemon"); |
1230 exit(1); 1231 } 1232 1233 setup(); 1234 | 784 exit(1); 785 } 786 787 setup(); 788 |
1235 rc = wait_for_events(); 1236 syslog(LOG_INFO, "auditd exiting."); | 789 /* 790 * auditd_wait_for_events() shouldn't return unless something is wrong. 791 */ 792 auditd_wait_for_events(); |
1237 | 793 |
1238 exit(rc); | 794 auditd_log_err("abnormal exit."); 795 close_all(); 796 exit(-1); |
1239} | 797} |