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