1 /* 2 * Copyright (c) 2004 Apple Computer, Inc. 3 * All rights reserved. 4 * 5 * @APPLE_BSD_LICENSE_HEADER_START@ 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * @APPLE_BSD_LICENSE_HEADER_END@ 32 * 33 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#13 $ 34 */ 35 36 #include <sys/types.h> 37 #include <sys/dirent.h> 38 #include <sys/mman.h> 39 #include <sys/queue.h> 40 #include <sys/stat.h> 41 #include <sys/wait.h> 42 43 #include <bsm/audit.h> 44 #include <bsm/audit_uevents.h> 45 #include <bsm/libbsm.h> 46 47 #include <errno.h> 48 #include <fcntl.h> 49 #include <grp.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <time.h> 53 #include <unistd.h> 54 #include <signal.h> 55 #include <string.h> 56 #include <syslog.h> 57 58 #include "auditd.h" 59 60 #define NA_EVENT_STR_SIZE 25 61 62 static int ret, minval; 63 static char *lastfile = NULL; 64 static int allhardcount = 0; 65 static int triggerfd = 0; 66 static int sighups, sighups_handled; 67 static int sigterms, sigterms_handled; 68 static long global_flags; 69 70 static TAILQ_HEAD(, dir_ent) dir_q; 71 72 static int config_audit_controls(void); 73 74 /* 75 * Error starting auditd 76 */ 77 static void 78 fail_exit(void) 79 { 80 81 audit_warn_nostart(); 82 exit(1); 83 } 84 85 /* 86 * Free our local list of directory names. 87 */ 88 static void 89 free_dir_q() 90 { 91 struct dir_ent *dirent; 92 93 while ((dirent = TAILQ_FIRST(&dir_q))) { 94 TAILQ_REMOVE(&dir_q, dirent, dirs); 95 free(dirent->dirname); 96 free(dirent); 97 } 98 } 99 100 /* 101 * Generate the timestamp string. 102 */ 103 static int 104 getTSstr(char *buf, int len) 105 { 106 struct timeval ts; 107 struct timezone tzp; 108 time_t tt; 109 110 if (gettimeofday(&ts, &tzp) != 0) 111 return (-1); 112 tt = (time_t)ts.tv_sec; 113 if (!strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&tt))) 114 return (-1); 115 return (0); 116 } 117 118 /* 119 * Concat the directory name to the given file name. 120 * XXX We should affix the hostname also 121 */ 122 static char * 123 affixdir(char *name, struct dir_ent *dirent) 124 { 125 char *fn; 126 char *curdir; 127 const char *sep = "/"; 128 129 curdir = dirent->dirname; 130 syslog(LOG_INFO, "dir = %s\n", dirent->dirname); 131 132 fn = malloc(strlen(curdir) + strlen(sep) + (2 * POSTFIX_LEN) + 1); 133 if (fn == NULL) 134 return (NULL); 135 strcpy(fn, curdir); 136 strcat(fn, sep); 137 strcat(fn, name); 138 return (fn); 139 } 140 141 /* 142 * Close the previous audit trail file. 143 */ 144 static int 145 close_lastfile(char *TS) 146 { 147 char *ptr; 148 char *oldname; 149 150 if (lastfile != NULL) { 151 oldname = (char *)malloc(strlen(lastfile) + 1); 152 if (oldname == NULL) 153 return (-1); 154 strcpy(oldname, lastfile); 155 156 /* Rename the last file -- append timestamp. */ 157 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { 158 *ptr = '.'; 159 strcpy(ptr+1, TS); 160 if (rename(oldname, lastfile) != 0) 161 syslog(LOG_ERR, "Could not rename %s to %s \n", 162 oldname, lastfile); 163 else 164 syslog(LOG_INFO, "renamed %s to %s \n", 165 oldname, lastfile); 166 } 167 free(lastfile); 168 free(oldname); 169 lastfile = NULL; 170 } 171 return (0); 172 } 173 174 /* 175 * Create the new audit file with appropriate permissions and ownership. Try 176 * to clean up if something goes wrong. 177 */ 178 static int 179 #ifdef AUDIT_REVIEW_GROUP 180 open_trail(const char *fname, uid_t uid, gid_t gid) 181 #else 182 open_trail(const char *fname) 183 #endif 184 { 185 int error, fd; 186 187 fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP); 188 if (fd < 0) 189 return (-1); 190 #ifdef AUDIT_REVIEW_GROUP 191 if (fchown(fd, uid, gid) < 0) { 192 error = errno; 193 close(fd); 194 (void)unlink(fname); 195 errno = error; 196 return (-1); 197 } 198 #endif 199 return (fd); 200 } 201 202 /* 203 * Create the new file name, swap with existing audit file. 204 */ 205 static int 206 swap_audit_file(void) 207 { 208 char timestr[2 * POSTFIX_LEN]; 209 char *fn; 210 char TS[POSTFIX_LEN]; 211 struct dir_ent *dirent; 212 #ifdef AUDIT_REVIEW_GROUP 213 struct group *grp; 214 gid_t gid; 215 uid_t uid; 216 #endif 217 int error, fd; 218 219 if (getTSstr(TS, POSTFIX_LEN) != 0) 220 return (-1); 221 222 strcpy(timestr, TS); 223 strcat(timestr, NOT_TERMINATED); 224 225 #ifdef AUDIT_REVIEW_GROUP 226 /* 227 * XXXRW: Currently, this code falls back to the daemon gid, which is 228 * likely the wheel group. Is there a better way to deal with this? 229 */ 230 grp = getgrnam(AUDIT_REVIEW_GROUP); 231 if (grp == NULL) { 232 syslog(LOG_INFO, 233 "Audit review group '%s' not available, using daemon gid", 234 AUDIT_REVIEW_GROUP); 235 gid = -1; 236 } else 237 gid = grp->gr_gid; 238 uid = getuid(); 239 #endif 240 241 /* Try until we succeed. */ 242 while ((dirent = TAILQ_FIRST(&dir_q))) { 243 if ((fn = affixdir(timestr, dirent)) == NULL) { 244 syslog(LOG_INFO, "Failed to swap log at time %s\n", 245 timestr); 246 return (-1); 247 } 248 249 /* 250 * Create and open the file; then close and pass to the 251 * kernel if all went well. 252 */ 253 syslog(LOG_INFO, "New audit file is %s\n", fn); 254 #ifdef AUDIT_REVIEW_GROUP 255 fd = open_trail(fn, uid, gid); 256 #else 257 fd = open_trail(fn); 258 #endif 259 if (fd < 0) 260 warn("open(%s)", fn); 261 if (fd >= 0) { 262 error = auditctl(fn); 263 if (error) { 264 syslog(LOG_ERR, 265 "auditctl failed setting log file! : %s\n", 266 strerror(errno)); 267 close(fd); 268 } else { 269 /* Success. */ 270 close_lastfile(TS); 271 lastfile = fn; 272 close(fd); 273 return (0); 274 } 275 } 276 277 /* 278 * Tell the administrator about lack of permissions for dir. 279 */ 280 audit_warn_getacdir(dirent->dirname); 281 282 /* Try again with a different directory. */ 283 TAILQ_REMOVE(&dir_q, dirent, dirs); 284 free(dirent->dirname); 285 free(dirent); 286 } 287 syslog(LOG_INFO, "Log directories exhausted\n"); 288 return (-1); 289 } 290 291 /* 292 * Read the audit_control file contents. 293 */ 294 static int 295 read_control_file(void) 296 { 297 char cur_dir[MAXNAMLEN]; 298 struct dir_ent *dirent; 299 au_qctrl_t qctrl; 300 301 /* 302 * Clear old values. Force a re-read of the file the next time. 303 */ 304 free_dir_q(); 305 endac(); 306 307 /* 308 * Read the list of directories into a local linked list. 309 * 310 * XXX We should use the reentrant interfaces once they are 311 * available. 312 */ 313 while (getacdir(cur_dir, MAXNAMLEN) >= 0) { 314 dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent)); 315 if (dirent == NULL) 316 return (-1); 317 dirent->softlim = 0; 318 dirent->dirname = (char *) malloc(MAXNAMLEN); 319 if (dirent->dirname == NULL) { 320 free(dirent); 321 return (-1); 322 } 323 strcpy(dirent->dirname, cur_dir); 324 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); 325 } 326 327 allhardcount = 0; 328 if (swap_audit_file() == -1) { 329 syslog(LOG_ERR, "Could not swap audit file\n"); 330 /* 331 * XXX Faulty directory listing? - user should be given 332 * XXX an opportunity to change the audit_control file 333 * XXX switch to a reduced mode of auditing? 334 */ 335 return (-1); 336 } 337 338 /* 339 * XXX There are synchronization problems here 340 * XXX what should we do if a trigger for the earlier limit 341 * XXX is generated here? 342 */ 343 if (0 == (ret = getacmin(&minval))) { 344 syslog(LOG_INFO, "min free = %d\n", minval); 345 if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) { 346 syslog(LOG_ERR, 347 "could not get audit queue settings\n"); 348 return (-1); 349 } 350 qctrl.aq_minfree = minval; 351 if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) { 352 syslog(LOG_ERR, 353 "could not set audit queue settings\n"); 354 return (-1); 355 } 356 } 357 358 return (0); 359 } 360 361 /* 362 * Close all log files, control files, and tell the audit system. 363 */ 364 static int 365 close_all(void) 366 { 367 int err_ret = 0; 368 char TS[POSTFIX_LEN]; 369 int aufd; 370 token_t *tok; 371 long cond; 372 373 /* Generate an audit record. */ 374 if ((aufd = au_open()) == -1) 375 syslog(LOG_ERR, "Could not create audit shutdown event.\n"); 376 else { 377 if ((tok = au_to_text("auditd::Audit shutdown")) != NULL) 378 au_write(aufd, tok); 379 if (au_close(aufd, 1, AUE_audit_shutdown) == -1) 380 syslog(LOG_ERR, 381 "Could not close audit shutdown event.\n"); 382 } 383 384 /* Flush contents. */ 385 cond = AUC_DISABLED; 386 err_ret = auditon(A_SETCOND, &cond, sizeof(cond)); 387 if (err_ret != 0) { 388 syslog(LOG_ERR, "Disabling audit failed! : %s\n", 389 strerror(errno)); 390 err_ret = 1; 391 } 392 if (getTSstr(TS, POSTFIX_LEN) == 0) 393 close_lastfile(TS); 394 if (lastfile != NULL) 395 free(lastfile); 396 397 free_dir_q(); 398 if ((remove(AUDITD_PIDFILE) == -1) || err_ret) { 399 syslog(LOG_ERR, "Could not unregister\n"); 400 audit_warn_postsigterm(); 401 return (1); 402 } 403 endac(); 404 405 if (close(triggerfd) != 0) 406 syslog(LOG_ERR, "Error closing control file\n"); 407 syslog(LOG_INFO, "Finished.\n"); 408 return (0); 409 } 410 411 /* 412 * When we get a signal, we are often not at a clean point. So, little can 413 * be done in the signal handler itself. Instead, we send a message to the 414 * main servicing loop to do proper handling from a non-signal-handler 415 * context. 416 */ 417 static void 418 relay_signal(int signal) 419 { 420 421 if (signal == SIGHUP) 422 sighups++; 423 if (signal == SIGTERM) 424 sigterms++; 425 } 426 427 /* 428 * Registering the daemon. 429 */ 430 static int 431 register_daemon(void) 432 { 433 FILE * pidfile; 434 int fd; 435 pid_t pid; 436 437 /* Set up the signal hander. */ 438 if (signal(SIGTERM, relay_signal) == SIG_ERR) { 439 syslog(LOG_ERR, 440 "Could not set signal handler for SIGTERM\n"); 441 fail_exit(); 442 } 443 if (signal(SIGCHLD, relay_signal) == SIG_ERR) { 444 syslog(LOG_ERR, 445 "Could not set signal handler for SIGCHLD\n"); 446 fail_exit(); 447 } 448 if (signal(SIGHUP, relay_signal) == SIG_ERR) { 449 syslog(LOG_ERR, 450 "Could not set signal handler for SIGHUP\n"); 451 fail_exit(); 452 } 453 454 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { 455 syslog(LOG_ERR, 456 "Could not open PID file\n"); 457 audit_warn_tmpfile(); 458 return (-1); 459 } 460 461 /* Attempt to lock the pid file; if a lock is present, exit. */ 462 fd = fileno(pidfile); 463 if (flock(fd, LOCK_EX | LOCK_NB) < 0) { 464 syslog(LOG_ERR, 465 "PID file is locked (is another auditd running?).\n"); 466 audit_warn_ebusy(); 467 return (-1); 468 } 469 470 pid = getpid(); 471 ftruncate(fd, 0); 472 if (fprintf(pidfile, "%u\n", pid) < 0) { 473 /* Should not start the daemon. */ 474 fail_exit(); 475 } 476 477 fflush(pidfile); 478 return (0); 479 } 480 481 /* 482 * Suppress duplicate messages within a 30 second interval. This should be 483 * enough to time to rotate log files without thrashing from soft warnings 484 * generated before the log is actually rotated. 485 */ 486 #define DUPLICATE_INTERVAL 30 487 static void 488 handle_audit_trigger(int trigger) 489 { 490 static int last_trigger; 491 static time_t last_time; 492 struct dir_ent *dirent; 493 int rc; 494 495 /* 496 * Suppres duplicate messages from the kernel within the specified 497 * interval. 498 */ 499 struct timeval ts; 500 struct timezone tzp; 501 time_t tt; 502 503 if (gettimeofday(&ts, &tzp) == 0) { 504 tt = (time_t)ts.tv_sec; 505 if ((trigger == last_trigger) && 506 (tt < (last_time + DUPLICATE_INTERVAL))) 507 return; 508 last_trigger = trigger; 509 last_time = tt; 510 } 511 512 /* 513 * Message processing is done here. 514 */ 515 dirent = TAILQ_FIRST(&dir_q); 516 switch(trigger) { 517 518 case AUDIT_TRIGGER_LOW_SPACE: 519 syslog(LOG_INFO, "Got low space trigger\n"); 520 if (dirent && (dirent->softlim != 1)) { 521 TAILQ_REMOVE(&dir_q, dirent, dirs); 522 /* Add this node to the end of the list. */ 523 TAILQ_INSERT_TAIL(&dir_q, dirent, dirs); 524 audit_warn_soft(dirent->dirname); 525 dirent->softlim = 1; 526 527 if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL && 528 swap_audit_file() == -1) 529 syslog(LOG_ERR, "Error swapping audit file\n"); 530 531 /* 532 * Check if the next dir has already reached its soft 533 * limit. 534 */ 535 dirent = TAILQ_FIRST(&dir_q); 536 if (dirent->softlim == 1) { 537 /* All dirs have reached their soft limit. */ 538 audit_warn_allsoft(); 539 } 540 } else { 541 /* 542 * Continue auditing to the current file. Also 543 * generate an allsoft warning. 544 * XXX do we want to do this ? 545 */ 546 audit_warn_allsoft(); 547 } 548 break; 549 550 case AUDIT_TRIGGER_NO_SPACE: 551 syslog(LOG_INFO, "Got no space trigger\n"); 552 553 /* Delete current dir, go on to next. */ 554 TAILQ_REMOVE(&dir_q, dirent, dirs); 555 audit_warn_hard(dirent->dirname); 556 free(dirent->dirname); 557 free(dirent); 558 559 if (swap_audit_file() == -1) 560 syslog(LOG_ERR, "Error swapping audit file\n"); 561 562 /* We are out of log directories. */ 563 audit_warn_allhard(++allhardcount); 564 break; 565 566 case AUDIT_TRIGGER_OPEN_NEW: 567 /* 568 * Create a new file and swap with the one being used in 569 * kernel 570 */ 571 syslog(LOG_INFO, "Got open new trigger\n"); 572 if (swap_audit_file() == -1) 573 syslog(LOG_ERR, "Error swapping audit file\n"); 574 break; 575 576 case AUDIT_TRIGGER_READ_FILE: 577 syslog(LOG_INFO, "Got read file trigger\n"); 578 if (read_control_file() == -1) 579 syslog(LOG_ERR, "Error in audit control file\n"); 580 if (config_audit_controls() == -1) 581 syslog(LOG_ERR, "Error setting audit controls\n"); 582 break; 583 584 default: 585 syslog(LOG_ERR, "Got unknown trigger %d\n", trigger); 586 break; 587 } 588 } 589 590 static void 591 handle_sighup(void) 592 { 593 594 sighups_handled = sighups; 595 config_audit_controls(); 596 } 597 598 /* 599 * Read the control file for triggers and handle appropriately. 600 */ 601 static int 602 wait_for_triggers(void) 603 { 604 int num; 605 unsigned int trigger; 606 607 for (;;) { 608 num = read(triggerfd, &trigger, sizeof(trigger)); 609 if ((num == -1) && (errno != EINTR)) { 610 syslog(LOG_ERR, "%s: error %d\n", __FUNCTION__, errno); 611 return (-1); 612 } 613 if (sigterms != sigterms_handled) { 614 syslog(LOG_INFO, "%s: SIGTERM", __FUNCTION__); 615 break; 616 } 617 if (sighups != sighups_handled) { 618 syslog(LOG_INFO, "%s: SIGHUP", __FUNCTION__); 619 handle_sighup(); 620 } 621 if ((num == -1) && (errno == EINTR)) 622 continue; 623 if (num == 0) { 624 syslog(LOG_INFO, "%s: read EOF\n", __FUNCTION__); 625 return (-1); 626 } 627 syslog(LOG_INFO, "%s: read %d\n", __FUNCTION__, trigger); 628 if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE) 629 break; 630 else 631 handle_audit_trigger(trigger); 632 } 633 return (close_all()); 634 } 635 636 /* 637 * Reap our children. 638 */ 639 static void 640 reap_children(void) 641 { 642 pid_t child; 643 int wstatus; 644 645 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { 646 if (!wstatus) 647 continue; 648 syslog(LOG_INFO, "warn process [pid=%d] %s %d.\n", child, 649 ((WIFEXITED(wstatus)) ? "exited with non-zero status" : 650 "exited as a result of signal"), 651 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : 652 WTERMSIG(wstatus))); 653 } 654 } 655 656 /* 657 * Configure the audit controls in the kernel: the event to class mapping, 658 * kernel preselection mask, etc. 659 */ 660 static int 661 config_audit_controls(void) 662 { 663 au_event_ent_t ev, *evp; 664 au_evclass_map_t evc_map; 665 au_mask_t aumask; 666 int ctr = 0; 667 char naeventstr[NA_EVENT_STR_SIZE]; 668 669 /* 670 * Process the audit event file, obtaining a class mapping for each 671 * event, and send that mapping into the kernel. 672 * XXX There's a risk here that the BSM library will return NULL 673 * for an event when it can't properly map it to a class. In that 674 * case, we will not process any events beyond the one that failed, 675 * but should. We need a way to get a count of the events. 676 */ 677 ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX); 678 ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX); 679 if ((ev.ae_name == NULL) || (ev.ae_desc == NULL)) { 680 syslog(LOG_ERR, 681 "Memory allocation error when configuring audit controls."); 682 return (-1); 683 } 684 evp = &ev; 685 setauevent(); 686 while ((evp = getauevent_r(evp)) != NULL) { 687 evc_map.ec_number = evp->ae_number; 688 evc_map.ec_class = evp->ae_class; 689 if (auditon(A_SETCLASS, &evc_map, sizeof(au_evclass_map_t)) 690 != 0) 691 syslog(LOG_ERR, 692 "Failed to register class mapping for event %s", 693 evp->ae_name); 694 else 695 ctr++; 696 } 697 endauevent(); 698 free(ev.ae_name); 699 free(ev.ae_desc); 700 if (ctr == 0) 701 syslog(LOG_ERR, "No events to class mappings registered."); 702 else 703 syslog(LOG_INFO, "Registered %d event to class mappings.", 704 ctr); 705 706 /* 707 * Get the non-attributable event string and set the kernel mask from 708 * that. 709 */ 710 if ((getacna(naeventstr, NA_EVENT_STR_SIZE) == 0) && 711 (getauditflagsbin(naeventstr, &aumask) == 0)) { 712 if (auditon(A_SETKMASK, &aumask, sizeof(au_mask_t))) 713 syslog(LOG_ERR, 714 "Failed to register non-attributable event mask."); 715 else 716 syslog(LOG_INFO, 717 "Registered non-attributable event mask."); 718 } else 719 syslog(LOG_ERR, 720 "Failed to obtain non-attributable event mask."); 721 722 /* 723 * Set the audit policy flags based on passed in parameter values. 724 */ 725 if (auditon(A_SETPOLICY, &global_flags, sizeof(global_flags))) 726 syslog(LOG_ERR, "Failed to set audit policy."); 727 728 return (0); 729 } 730 731 static void 732 setup(void) 733 { 734 int aufd; 735 token_t *tok; 736 737 if ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)) < 0) { 738 syslog(LOG_ERR, "Error opening trigger file\n"); 739 fail_exit(); 740 } 741 742 TAILQ_INIT(&dir_q); 743 if (read_control_file() == -1) { 744 syslog(LOG_ERR, "Error reading control file\n"); 745 fail_exit(); 746 } 747 748 /* Generate an audit record. */ 749 if ((aufd = au_open()) == -1) 750 syslog(LOG_ERR, "Could not create audit startup event.\n"); 751 else { 752 if ((tok = au_to_text("auditd::Audit startup")) != NULL) 753 au_write(aufd, tok); 754 if (au_close(aufd, 1, AUE_audit_startup) == -1) 755 syslog(LOG_ERR, 756 "Could not close audit startup event.\n"); 757 } 758 759 if (config_audit_controls() == 0) 760 syslog(LOG_INFO, "Audit controls init successful\n"); 761 else 762 syslog(LOG_INFO, "Audit controls init failed\n"); 763 } 764 765 int 766 main(int argc, char **argv) 767 { 768 int ch; 769 int debug = 0; 770 int rc; 771 772 global_flags |= AUDIT_CNT; 773 while ((ch = getopt(argc, argv, "dhs")) != -1) { 774 switch(ch) { 775 case 'd': 776 /* Debug option. */ 777 debug = 1; 778 break; 779 780 case 's': 781 /* Fail-stop option. */ 782 global_flags &= ~(AUDIT_CNT); 783 break; 784 785 case 'h': 786 /* Halt-stop option. */ 787 global_flags |= AUDIT_AHLT; 788 break; 789 790 case '?': 791 default: 792 (void)fprintf(stderr, 793 "usage: auditd [-h | -s] [-d] \n"); 794 exit(1); 795 } 796 } 797 798 #ifdef LOG_SECURITY 799 openlog("auditd", LOG_CONS | LOG_PID, LOG_SECURITY); 800 #else 801 openlog("auditd", LOG_CONS | LOG_PID, LOG_AUTH); 802 #endif 803 syslog(LOG_INFO, "starting...\n"); 804 805 if (debug == 0 && daemon(0, 0) == -1) { 806 syslog(LOG_ERR, "Failed to daemonize\n"); 807 exit(1); 808 } 809 810 if (register_daemon() == -1) { 811 syslog(LOG_ERR, "Could not register as daemon\n"); 812 exit(1); 813 } 814 815 setup(); 816 817 rc = wait_for_triggers(); 818 syslog(LOG_INFO, "auditd exiting.\n"); 819 820 exit(rc); 821 } 822