1 /*- 2 * Copyright (c) 2008-2009 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 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $P4: //depot/projects/trustedbsd/openbsm/libauditd/auditd_lib.c#18 $ 30 */ 31 32 #include <sys/param.h> 33 34 #include <config/config.h> 35 36 #include <sys/dirent.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/mount.h> 43 #include <sys/socket.h> 44 45 #include <sys/stat.h> 46 #include <sys/time.h> 47 48 #include <netinet/in.h> 49 50 #include <bsm/audit.h> 51 #include <bsm/audit_uevents.h> 52 #include <bsm/auditd_lib.h> 53 #include <bsm/libbsm.h> 54 55 #include <assert.h> 56 #include <dirent.h> 57 #include <err.h> 58 #include <errno.h> 59 #include <fcntl.h> 60 #include <stdio.h> 61 #include <string.h> 62 #include <stdlib.h> 63 #include <time.h> 64 #include <unistd.h> 65 #include <netdb.h> 66 67 #ifdef __APPLE__ 68 #include <notify.h> 69 #ifndef __BSM_INTERNAL_NOTIFY_KEY 70 #define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" 71 #endif /* __BSM_INTERNAL_NOTIFY_KEY */ 72 #endif /* __APPLE__ */ 73 74 /* 75 * XXX This is temporary until this is moved to <bsm/audit.h> and shared with 76 * the kernel. 77 */ 78 #ifndef AUDIT_HARD_LIMIT_FREE_BLOCKS 79 #define AUDIT_HARD_LIMIT_FREE_BLOCKS 4 80 #endif 81 82 /* 83 * Number of seconds to January 1, 2000 84 */ 85 #define JAN_01_2000 946598400 86 87 struct dir_ent { 88 char *dirname; 89 uint8_t softlim; 90 uint8_t hardlim; 91 TAILQ_ENTRY(dir_ent) dirs; 92 }; 93 94 static TAILQ_HEAD(, dir_ent) dir_q; 95 96 struct audit_trail { 97 time_t at_time; 98 char *at_path; 99 off_t at_size; 100 101 TAILQ_ENTRY(audit_trail) at_trls; 102 }; 103 104 static int auditd_minval = -1; 105 static int auditd_dist = 0; 106 107 static char auditd_host[MAXHOSTNAMELEN]; 108 static int auditd_hostlen = -1; 109 110 static char *auditd_errmsg[] = { 111 "no error", /* ADE_NOERR ( 0) */ 112 "could not parse audit_control(5) file", /* ADE_PARSE ( 1) */ 113 "auditon(2) failed", /* ADE_AUDITON ( 2) */ 114 "malloc(3) failed", /* ADE_NOMEM ( 3) */ 115 "all audit log directories over soft limit", /* ADE_SOFTLIM ( 4) */ 116 "all audit log directories over hard limit", /* ADE_HARDLIM ( 5) */ 117 "could not create file name string", /* ADE_STRERR ( 6) */ 118 "could not open audit record", /* ADE_AU_OPEN ( 7) */ 119 "could not close audit record", /* ADE_AU_CLOSE ( 8) */ 120 "could not set active audit session state", /* ADE_SETAUDIT ( 9) */ 121 "auditctl(2) failed (trail still swapped)", /* ADE_ACTL (10) */ 122 "auditctl(2) failed (trail not swapped)", /* ADE_ACTLERR (11) */ 123 "could not swap audit trail file", /* ADE_SWAPERR (12) */ 124 "could not rename crash recovery file", /* ADE_RENAME (13) */ 125 "could not read 'current' link file", /* ADE_READLINK (14) */ 126 "could not create 'current' link file", /* ADE_SYMLINK (15) */ 127 "invalid argument", /* ADE_INVAL (16) */ 128 "could not resolve hostname to address", /* ADE_GETADDR (17) */ 129 "address family not supported", /* ADE_ADDRFAM (18) */ 130 "error expiring audit trail files", /* ADE_EXPIRE (19) */ 131 }; 132 133 #define MAXERRCODE (sizeof(auditd_errmsg) / sizeof(auditd_errmsg[0])) 134 135 #define NA_EVENT_STR_SIZE 128 136 #define POL_STR_SIZE 128 137 138 139 /* 140 * Look up and return the error string for the given audit error code. 141 */ 142 const char * 143 auditd_strerror(int errcode) 144 { 145 int idx = -errcode; 146 147 if (idx < 0 || idx > (int)MAXERRCODE) 148 return ("Invalid auditd error code"); 149 150 return (auditd_errmsg[idx]); 151 } 152 153 154 /* 155 * Free our local list of directory names and init list. 156 */ 157 static void 158 free_dir_q(void) 159 { 160 struct dir_ent *d1, *d2; 161 162 d1 = TAILQ_FIRST(&dir_q); 163 while (d1 != NULL) { 164 d2 = TAILQ_NEXT(d1, dirs); 165 free(d1->dirname); 166 free(d1); 167 d1 = d2; 168 } 169 TAILQ_INIT(&dir_q); 170 } 171 172 /* 173 * Concat the directory name to the given file name. 174 * XXX We should affix the hostname also 175 */ 176 static char * 177 affixdir(char *name, struct dir_ent *dirent) 178 { 179 char *fn = NULL; 180 181 /* 182 * Sanity check on file name. 183 */ 184 if (strlen(name) != FILENAME_LEN) { 185 errno = EINVAL; 186 return (NULL); 187 } 188 189 /* 190 * If the host is set then also add the hostname to the filename. 191 */ 192 if (auditd_hostlen != -1) 193 asprintf(&fn, "%s/%s.%s", dirent->dirname, name, auditd_host); 194 else 195 asprintf(&fn, "%s/%s", dirent->dirname, name); 196 return (fn); 197 } 198 199 /* 200 * Insert the directory entry in the list by the way they are ordered in 201 * audit_control(5). Move the entries that are over the soft and hard limits 202 * toward the tail. 203 */ 204 static void 205 insert_orderly(struct dir_ent *denew) 206 { 207 struct dir_ent *dep; 208 209 TAILQ_FOREACH(dep, &dir_q, dirs) { 210 if (dep->softlim == 1 && denew->softlim == 0) { 211 TAILQ_INSERT_BEFORE(dep, denew, dirs); 212 return; 213 } 214 if (dep->hardlim == 1 && denew->hardlim == 0) { 215 TAILQ_INSERT_BEFORE(dep, denew, dirs); 216 return; 217 } 218 } 219 TAILQ_INSERT_TAIL(&dir_q, denew, dirs); 220 } 221 222 /* 223 * Get the min percentage of free blocks from audit_control(5) and that 224 * value in the kernel. Return: 225 * ADE_NOERR on success, 226 * ADE_PARSE error parsing audit_control(5), 227 */ 228 int 229 auditd_set_dist(void) 230 { 231 int ret; 232 233 ret = getacdist(); 234 if (ret < 0) 235 return (ADE_PARSE); 236 237 auditd_dist = ret; 238 239 return (ADE_NOERR); 240 } 241 242 /* 243 * Get the host from audit_control(5) and set it in the audit kernel 244 * information. Return: 245 * ADE_NOERR on success. 246 * ADE_PARSE error parsing audit_control(5). 247 * ADE_AUDITON error getting/setting auditon(2) value. 248 * ADE_GETADDR error getting address info for host. 249 * ADE_ADDRFAM un-supported address family. 250 */ 251 int 252 auditd_set_host(void) 253 { 254 struct sockaddr_in6 *sin6; 255 struct sockaddr_in *sin; 256 struct addrinfo *res; 257 struct auditinfo_addr aia; 258 int error, ret = ADE_NOERR; 259 260 if (getachost(auditd_host, sizeof(auditd_host)) != 0) { 261 ret = ADE_PARSE; 262 263 /* 264 * To maintain reverse compatability with older audit_control 265 * files, simply drop a warning if the host parameter has not 266 * been set. However, we will explicitly disable the 267 * generation of extended audit header by passing in a zeroed 268 * termid structure. 269 */ 270 bzero(&aia, sizeof(aia)); 271 aia.ai_termid.at_type = AU_IPv4; 272 error = audit_set_kaudit(&aia, sizeof(aia)); 273 if (error < 0 && errno != ENOSYS) 274 ret = ADE_AUDITON; 275 return (ret); 276 } 277 auditd_hostlen = strlen(auditd_host); 278 error = getaddrinfo(auditd_host, NULL, NULL, &res); 279 if (error) 280 return (ADE_GETADDR); 281 switch (res->ai_family) { 282 case PF_INET6: 283 sin6 = (struct sockaddr_in6 *) res->ai_addr; 284 bcopy(&sin6->sin6_addr.s6_addr, 285 &aia.ai_termid.at_addr[0], sizeof(struct in6_addr)); 286 aia.ai_termid.at_type = AU_IPv6; 287 break; 288 289 case PF_INET: 290 sin = (struct sockaddr_in *) res->ai_addr; 291 bcopy(&sin->sin_addr.s_addr, 292 &aia.ai_termid.at_addr[0], sizeof(struct in_addr)); 293 aia.ai_termid.at_type = AU_IPv4; 294 break; 295 296 default: 297 /* Un-supported address family in host parameter. */ 298 errno = EAFNOSUPPORT; 299 return (ADE_ADDRFAM); 300 } 301 302 if (audit_set_kaudit(&aia, sizeof(aia)) < 0) 303 ret = ADE_AUDITON; 304 305 return (ret); 306 } 307 308 /* 309 * Get the min percentage of free blocks from audit_control(5) and that 310 * value in the kernel. Return: 311 * ADE_NOERR on success, 312 * ADE_PARSE error parsing audit_control(5), 313 * ADE_AUDITON error getting/setting auditon(2) value. 314 */ 315 int 316 auditd_set_minfree(void) 317 { 318 au_qctrl_t qctrl; 319 320 if (getacmin(&auditd_minval) != 0) 321 return (ADE_PARSE); 322 323 if (audit_get_qctrl(&qctrl, sizeof(qctrl)) != 0) 324 return (ADE_AUDITON); 325 326 if (qctrl.aq_minfree != auditd_minval) { 327 qctrl.aq_minfree = auditd_minval; 328 if (audit_set_qctrl(&qctrl, sizeof(qctrl)) != 0) 329 return (ADE_AUDITON); 330 } 331 332 return (0); 333 } 334 335 /* 336 * Convert a trailname into a timestamp (seconds). Return 0 if the conversion 337 * was successful. 338 */ 339 static int 340 trailname_to_tstamp(char *fn, time_t *tstamp) 341 { 342 struct tm tm; 343 char ts[TIMESTAMP_LEN + 1]; 344 char *p; 345 346 *tstamp = 0; 347 348 /* 349 * Get the ending time stamp. 350 */ 351 if ((p = strchr(fn, '.')) == NULL) 352 return (1); 353 strlcpy(ts, ++p, sizeof(ts)); 354 if (strlen(ts) != POSTFIX_LEN) 355 return (1); 356 357 bzero(&tm, sizeof(tm)); 358 359 /* seconds (0-60) */ 360 p = ts + POSTFIX_LEN - 2; 361 tm.tm_sec = atol(p); 362 if (tm.tm_sec < 0 || tm.tm_sec > 60) 363 return (1); 364 365 /* minutes (0-59) */ 366 *p = '\0'; p -= 2; 367 tm.tm_min = atol(p); 368 if (tm.tm_min < 0 || tm.tm_min > 59) 369 return (1); 370 371 /* hours (0 - 23) */ 372 *p = '\0'; p -= 2; 373 tm.tm_hour = atol(p); 374 if (tm.tm_hour < 0 || tm.tm_hour > 23) 375 return (1); 376 377 /* day of month (1-31) */ 378 *p = '\0'; p -= 2; 379 tm.tm_mday = atol(p); 380 if (tm.tm_mday < 1 || tm.tm_mday > 31) 381 return (1); 382 383 /* month (0 - 11) */ 384 *p = '\0'; p -= 2; 385 tm.tm_mon = atol(p) - 1; 386 if (tm.tm_mon < 0 || tm.tm_mon > 11) 387 return (1); 388 389 /* year (year - 1900) */ 390 *p = '\0'; p -= 4; 391 tm.tm_year = atol(p) - 1900; 392 if (tm.tm_year < 0) 393 return (1); 394 395 *tstamp = timegm(&tm); 396 397 return (0); 398 } 399 400 /* 401 * Remove audit trails files according to the expiration conditions. Returns: 402 * ADE_NOERR on success or there is nothing to do. 403 * ADE_PARSE if error parsing audit_control(5). 404 * ADE_NOMEM if could not allocate memory. 405 * ADE_EXPIRE if there was an unespected error. 406 */ 407 int 408 auditd_expire_trails(int (*warn_expired)(char *)) 409 { 410 int andflg, ret = ADE_NOERR; 411 size_t expire_size, total_size = 0L; 412 time_t expire_age, oldest_time, current_time = time(NULL); 413 struct dir_ent *traildir; 414 struct audit_trail *at; 415 char *afnp, *pn; 416 TAILQ_HEAD(au_trls_head, audit_trail) head = 417 TAILQ_HEAD_INITIALIZER(head); 418 struct stat stbuf; 419 char activefn[MAXPATHLEN]; 420 421 /* 422 * Read the expiration conditions. If no conditions then return no 423 * error. 424 */ 425 if (getacexpire(&andflg, &expire_age, &expire_size) < 0) 426 return (ADE_PARSE); 427 if (!expire_age && !expire_size) 428 return (ADE_NOERR); 429 430 /* 431 * Read the 'current' trail file name. Trim off directory path. 432 */ 433 activefn[0] = '\0'; 434 readlink(AUDIT_CURRENT_LINK, activefn, MAXPATHLEN - 1); 435 if ((afnp = strrchr(activefn, '/')) != NULL) 436 afnp++; 437 438 439 /* 440 * Build tail queue of the trail files. 441 */ 442 TAILQ_FOREACH(traildir, &dir_q, dirs) { 443 DIR *dirp; 444 struct dirent *dp; 445 446 dirp = opendir(traildir->dirname); 447 while ((dp = readdir(dirp)) != NULL) { 448 time_t tstamp = 0; 449 struct audit_trail *new; 450 451 /* 452 * Quickly filter non-trail files. 453 */ 454 if (dp->d_namlen < FILENAME_LEN || 455 dp->d_name[POSTFIX_LEN] != '.') 456 continue; 457 458 if (asprintf(&pn, "%s/%s", traildir->dirname, 459 dp->d_name) < 0) { 460 ret = ADE_NOMEM; 461 break; 462 } 463 464 if (stat(pn, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) { 465 free(pn); 466 continue; 467 } 468 469 total_size += stbuf.st_size; 470 471 /* 472 * If this is the 'current' audit trail then 473 * don't add it to the tail queue. 474 */ 475 if (NULL != afnp && strcmp(dp->d_name, afnp) == 0) { 476 free(pn); 477 continue; 478 } 479 480 /* 481 * Get the ending time stamp encoded in the trail 482 * name. If we can't read it or if it is older 483 * than Jan 1, 2000 then use the mtime. 484 */ 485 if (trailname_to_tstamp(dp->d_name, &tstamp) != 0 || 486 tstamp < JAN_01_2000) 487 tstamp = stbuf.st_mtime; 488 489 /* 490 * If the time stamp is older than Jan 1, 2000 then 491 * update the mtime of the trail file to the current 492 * time. This is so we don't prematurely remove a trail 493 * file that was created while the system clock reset 494 * to the * "beginning of time" but later the system 495 * clock is set to the correct current time. 496 */ 497 if (current_time >= JAN_01_2000 && 498 tstamp < JAN_01_2000) { 499 struct timeval tv[2]; 500 501 tstamp = stbuf.st_mtime = current_time; 502 TIMESPEC_TO_TIMEVAL(&tv[0], 503 &stbuf.st_atimespec); 504 TIMESPEC_TO_TIMEVAL(&tv[1], 505 &stbuf.st_mtimespec); 506 utimes(pn, tv); 507 } 508 509 /* 510 * Allocate and populate the new entry. 511 */ 512 new = malloc(sizeof(*new)); 513 if (NULL == new) { 514 free(pn); 515 ret = ADE_NOMEM; 516 break; 517 } 518 new->at_time = tstamp; 519 new->at_size = stbuf.st_size; 520 new->at_path = pn; 521 522 /* 523 * Check to see if we have a new head. Otherwise, 524 * walk the tailq from the tail first and do a simple 525 * insertion sort. 526 */ 527 if (TAILQ_EMPTY(&head) || 528 new->at_time <= TAILQ_FIRST(&head)->at_time) { 529 TAILQ_INSERT_HEAD(&head, new, at_trls); 530 continue; 531 } 532 533 TAILQ_FOREACH_REVERSE(at, &head, au_trls_head, at_trls) 534 if (new->at_time >= at->at_time) { 535 TAILQ_INSERT_AFTER(&head, at, new, 536 at_trls); 537 break; 538 } 539 540 } 541 closedir(dirp); 542 } 543 544 oldest_time = current_time - expire_age; 545 546 /* 547 * Expire trail files, oldest (mtime) first, if the given 548 * conditions are met. 549 */ 550 at = TAILQ_FIRST(&head); 551 while (NULL != at) { 552 struct audit_trail *at_next = TAILQ_NEXT(at, at_trls); 553 554 if (andflg) { 555 if ((expire_size && total_size > expire_size) && 556 (expire_age && at->at_time < oldest_time)) { 557 if (warn_expired) 558 (*warn_expired)(at->at_path); 559 if (unlink(at->at_path) < 0) 560 ret = ADE_EXPIRE; 561 total_size -= at->at_size; 562 } 563 } else { 564 if ((expire_size && total_size > expire_size) || 565 (expire_age && at->at_time < oldest_time)) { 566 if (warn_expired) 567 (*warn_expired)(at->at_path); 568 if (unlink(at->at_path) < 0) 569 ret = ADE_EXPIRE; 570 total_size -= at->at_size; 571 } 572 } 573 574 free(at->at_path); 575 free(at); 576 at = at_next; 577 } 578 579 return (ret); 580 } 581 582 /* 583 * Parses the "dir" entry in audit_control(5) into an ordered list. Also, will 584 * set the minfree and host values if not already set. Arguments include 585 * function pointers to audit_warn functions for soft and hard limits. Returns: 586 * ADE_NOERR on success, 587 * ADE_PARSE error parsing audit_control(5), 588 * ADE_AUDITON error getting/setting auditon(2) value, 589 * ADE_NOMEM error allocating memory, 590 * ADE_SOFTLIM if all the directories are over the soft limit, 591 * ADE_HARDLIM if all the directories are over the hard limit, 592 */ 593 int 594 auditd_read_dirs(int (*warn_soft)(char *), int (*warn_hard)(char *)) 595 { 596 char cur_dir[MAXNAMLEN]; 597 struct dir_ent *dirent; 598 struct statfs sfs; 599 int err; 600 char soft, hard; 601 int tcnt = 0; 602 int scnt = 0; 603 int hcnt = 0; 604 605 if (auditd_minval == -1 && (err = auditd_set_minfree()) != 0) 606 return (err); 607 608 if (auditd_hostlen == -1) 609 auditd_set_host(); 610 611 /* 612 * Init directory q. Force a re-read of the file the next time. 613 */ 614 free_dir_q(); 615 endac(); 616 617 /* 618 * Read the list of directories into an ordered linked list 619 * admin's preference, then those over soft limit and, finally, 620 * those over the hard limit. 621 * 622 * XXX We should use the reentrant interfaces once they are 623 * available. 624 */ 625 while (getacdir(cur_dir, MAXNAMLEN) >= 0) { 626 if (statfs(cur_dir, &sfs) < 0) 627 continue; /* XXX should warn */ 628 soft = (sfs.f_bfree < (sfs.f_blocks * auditd_minval / 100 )) ? 629 1 : 0; 630 hard = (sfs.f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) ? 1 : 0; 631 if (soft) { 632 if (warn_soft) 633 (*warn_soft)(cur_dir); 634 scnt++; 635 } 636 if (hard) { 637 if (warn_hard) 638 (*warn_hard)(cur_dir); 639 hcnt++; 640 } 641 dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent)); 642 if (dirent == NULL) 643 return (ADE_NOMEM); 644 dirent->softlim = soft; 645 dirent->hardlim = hard; 646 dirent->dirname = (char *) malloc(MAXNAMLEN); 647 if (dirent->dirname == NULL) { 648 free(dirent); 649 return (ADE_NOMEM); 650 } 651 strlcpy(dirent->dirname, cur_dir, MAXNAMLEN); 652 insert_orderly(dirent); 653 tcnt++; 654 } 655 656 if (hcnt == tcnt) 657 return (ADE_HARDLIM); 658 if (scnt == tcnt) 659 return (ADE_SOFTLIM); 660 return (0); 661 } 662 663 void 664 auditd_close_dirs(void) 665 { 666 free_dir_q(); 667 auditd_minval = -1; 668 auditd_hostlen = -1; 669 } 670 671 672 /* 673 * Process the audit event file, obtaining a class mapping for each event, and 674 * set that mapping into the kernel. Return: 675 * n number of event mappings that were successfully processed, 676 * ADE_NOMEM if there was an error allocating memory. 677 */ 678 int 679 auditd_set_evcmap(void) 680 { 681 au_event_ent_t ev, *evp; 682 au_evclass_map_t evc_map; 683 int ctr = 0; 684 685 /* 686 * XXX There's a risk here that the BSM library will return NULL 687 * for an event when it can't properly map it to a class. In that 688 * case, we will not process any events beyond the one that failed, 689 * but should. We need a way to get a count of the events. 690 */ 691 ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX); 692 ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX); 693 if (ev.ae_name == NULL || ev.ae_desc == NULL) { 694 if (ev.ae_name != NULL) 695 free(ev.ae_name); 696 return (ADE_NOMEM); 697 } 698 699 /* 700 * XXXRW: Currently we have no way to remove mappings from the kernel 701 * when they are removed from the file-based mappings. 702 */ 703 evp = &ev; 704 setauevent(); 705 while ((evp = getauevent_r(evp)) != NULL) { 706 evc_map.ec_number = evp->ae_number; 707 evc_map.ec_class = evp->ae_class; 708 if (audit_set_class(&evc_map, sizeof(evc_map)) == 0) 709 ctr++; 710 } 711 endauevent(); 712 free(ev.ae_name); 713 free(ev.ae_desc); 714 715 return (ctr); 716 } 717 718 /* 719 * Get the non-attributable event string and set the kernel mask. Return: 720 * ADE_NOERR on success, 721 * ADE_PARSE error parsing audit_control(5), 722 * ADE_AUDITON error setting the mask using auditon(2). 723 */ 724 int 725 auditd_set_namask(void) 726 { 727 au_mask_t aumask; 728 char naeventstr[NA_EVENT_STR_SIZE]; 729 730 if (getacna(naeventstr, NA_EVENT_STR_SIZE) != 0 || 731 getauditflagsbin(naeventstr, &aumask) != 0) 732 return (ADE_PARSE); 733 734 if (audit_set_kmask(&aumask, sizeof(aumask)) != 0) 735 return (ADE_AUDITON); 736 737 return (ADE_NOERR); 738 } 739 740 /* 741 * Set the audit control policy if a policy is configured in audit_control(5), 742 * implement the policy. However, if one isn't defined or if there is an error 743 * parsing the control file, set AUDIT_CNT to avoid leaving the system in a 744 * fragile state. Return: 745 * ADE_NOERR on success, 746 * ADE_PARSE error parsing audit_control(5), 747 * ADE_AUDITON error setting policy using auditon(2). 748 */ 749 int 750 auditd_set_policy(void) 751 { 752 int policy; 753 char polstr[POL_STR_SIZE]; 754 755 if (getacpol(polstr, POL_STR_SIZE) != 0 || 756 au_strtopol(polstr, &policy) != 0) { 757 policy = AUDIT_CNT; 758 if (audit_set_policy(&policy) != 0) 759 return (ADE_AUDITON); 760 return (ADE_PARSE); 761 } 762 763 if (audit_set_policy(&policy) != 0) 764 return (ADE_AUDITON); 765 766 return (ADE_NOERR); 767 } 768 769 /* 770 * Set trail rotation size. Return: 771 * ADE_NOERR on success, 772 * ADE_PARSE error parsing audit_control(5), 773 * ADE_AUDITON error setting file size using auditon(2). 774 */ 775 int 776 auditd_set_fsize(void) 777 { 778 size_t filesz; 779 au_fstat_t au_fstat; 780 781 /* 782 * Set trail rotation size. 783 */ 784 if (getacfilesz(&filesz) != 0) 785 return (ADE_PARSE); 786 787 bzero(&au_fstat, sizeof(au_fstat)); 788 au_fstat.af_filesz = filesz; 789 if (audit_set_fsize(&au_fstat, sizeof(au_fstat)) != 0) 790 return (ADE_AUDITON); 791 792 return (ADE_NOERR); 793 } 794 795 static void 796 inject_dist(const char *fromname, char *toname, size_t tonamesize) 797 { 798 char *ptr; 799 800 ptr = strrchr(fromname, '/'); 801 assert(ptr != NULL); 802 assert(ptr - fromname < (ssize_t)tonamesize); 803 strlcpy(toname, fromname, ptr - fromname + 1); 804 strlcat(toname, "/dist/", tonamesize); 805 strlcat(toname, ptr + 1, tonamesize); 806 } 807 808 static int 809 auditdist_link(const char *filename) 810 { 811 char fname[MAXPATHLEN]; 812 813 if (auditd_dist) { 814 inject_dist(filename, fname, sizeof(fname)); 815 /* Ignore errors. */ 816 (void) link(filename, fname); 817 } 818 819 return (0); 820 } 821 822 int 823 auditd_rename(const char *fromname, const char *toname) 824 { 825 char fname[MAXPATHLEN], tname[MAXPATHLEN]; 826 827 if (auditd_dist) { 828 inject_dist(fromname, fname, sizeof(fname)); 829 inject_dist(toname, tname, sizeof(tname)); 830 /* Ignore errors. */ 831 (void) rename(fname, tname); 832 } 833 834 return (rename(fromname, toname)); 835 } 836 837 /* 838 * Create the new audit file with appropriate permissions and ownership. 839 * Call auditctl(2) for this file. 840 * Try to clean up if something goes wrong. 841 * *errorp is modified only on auditctl(2) failure. 842 */ 843 static int 844 open_trail(char *fname, gid_t gid, int *errorp) 845 { 846 int fd; 847 848 /* XXXPJD: What should we do if the file already exists? */ 849 fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR); 850 if (fd < 0) 851 return (-1); 852 if (fchown(fd, -1, gid) < 0 || fchmod(fd, S_IRUSR | S_IRGRP) < 0) { 853 (void) close(fd); 854 (void) unlink(fname); 855 return (-1); 856 } 857 (void) close(fd); 858 if (auditctl(fname) < 0) { 859 *errorp = errno; 860 (void) unlink(fname); 861 return (-1); 862 } 863 (void) auditdist_link(fname); 864 return (0); 865 } 866 867 /* 868 * Create the new audit trail file, swap with existing audit file. Arguments 869 * include timestamp for the filename, a pointer to a string for returning the 870 * new file name, GID for trail file, and audit_warn function pointer for 871 * 'getacdir()' errors. Returns: 872 * ADE_NOERR on success, 873 * ADE_STRERR if the file name string could not be created, 874 * ADE_SWAPERR if the audit trail file could not be swapped, 875 * ADE_ACTL if the auditctl(2) call failed but file swap still 876 * successful. 877 * ADE_ACTLERR if the auditctl(2) call failed and file swap failed. 878 * ADE_SYMLINK if symlink(2) failed updating the current link. 879 */ 880 int 881 auditd_swap_trail(char *TS, char **newfile, gid_t gid, 882 int (*warn_getacdir)(char *)) 883 { 884 char timestr[FILENAME_LEN + 1]; 885 char *fn; 886 struct dir_ent *dirent; 887 int saverrno = 0; 888 889 if (strlen(TS) != TIMESTAMP_LEN || 890 snprintf(timestr, sizeof(timestr), "%s.%s", TS, 891 NOT_TERMINATED) < 0) { 892 errno = EINVAL; 893 return (ADE_STRERR); 894 } 895 896 /* Try until we succeed. */ 897 TAILQ_FOREACH(dirent, &dir_q, dirs) { 898 if (dirent->hardlim) 899 continue; 900 if ((fn = affixdir(timestr, dirent)) == NULL) 901 return (ADE_STRERR); 902 903 /* 904 * Create the file and pass to the kernel if all went well. 905 */ 906 if (open_trail(fn, gid, &saverrno) == 0) { 907 /* Success. */ 908 *newfile = fn; 909 if (saverrno) { 910 /* 911 * auditctl() failed but still 912 * successful. Return errno and "soft" 913 * error. 914 */ 915 errno = saverrno; 916 return (ADE_ACTL); 917 } 918 return (ADE_NOERR); 919 } 920 /* 921 * auditctl failed setting log file. Try again. 922 */ 923 /* 924 * Tell the administrator about lack of permissions for dir. 925 */ 926 if (warn_getacdir != NULL) 927 (*warn_getacdir)(dirent->dirname); 928 } 929 if (saverrno) { 930 errno = saverrno; 931 return (ADE_ACTLERR); 932 } else 933 return (ADE_SWAPERR); 934 } 935 936 /* 937 * Mask calling process from being audited. Returns: 938 * ADE_NOERR on success, 939 * ADE_SETAUDIT if setaudit(2) fails. 940 */ 941 #ifdef __APPLE__ 942 int 943 auditd_prevent_audit(void) 944 { 945 auditinfo_addr_t aia; 946 947 /* 948 * To prevent event feedback cycles and avoid audit becoming stalled if 949 * auditing is suspended we mask this processes events from being 950 * audited. We allow the uid, tid, and mask fields to be implicitly 951 * set to zero, but do set the audit session ID to the PID. 952 * 953 * XXXRW: Is there more to it than this? 954 */ 955 bzero(&aia, sizeof(aia)); 956 aia.ai_asid = AU_ASSIGN_ASID; 957 aia.ai_termid.at_type = AU_IPv4; 958 if (setaudit_addr(&aia, sizeof(aia)) != 0) 959 return (ADE_SETAUDIT); 960 return (ADE_NOERR); 961 } 962 #else 963 int 964 auditd_prevent_audit(void) 965 { 966 auditinfo_t ai; 967 968 /* 969 * To prevent event feedback cycles and avoid audit becoming stalled if 970 * auditing is suspended we mask this processes events from being 971 * audited. We allow the uid, tid, and mask fields to be implicitly 972 * set to zero, but do set the audit session ID to the PID. 973 * 974 * XXXRW: Is there more to it than this? 975 */ 976 bzero(&ai, sizeof(ai)); 977 ai.ai_asid = getpid(); 978 if (setaudit(&ai) != 0) 979 return (ADE_SETAUDIT); 980 return (ADE_NOERR); 981 } 982 #endif /* !__APPLE__ */ 983 984 /* 985 * Generate and submit audit record for audit startup or shutdown. The event 986 * argument can be AUE_audit_recovery, AUE_audit_startup or 987 * AUE_audit_shutdown. The path argument will add a path token, if not NULL. 988 * Returns: 989 * AUE_NOERR on success, 990 * ADE_NOMEM if memory allocation fails, 991 * ADE_AU_OPEN if au_open(3) fails, 992 * ADE_AU_CLOSE if au_close(3) fails. 993 */ 994 int 995 auditd_gen_record(int event, char *path) 996 { 997 int aufd; 998 uid_t uid; 999 pid_t pid; 1000 char *autext = NULL; 1001 token_t *tok; 1002 struct auditinfo_addr aia; 1003 1004 if (event == AUE_audit_startup) 1005 asprintf(&autext, "%s::Audit startup", getprogname()); 1006 else if (event == AUE_audit_shutdown) 1007 asprintf(&autext, "%s::Audit shutdown", getprogname()); 1008 else if (event == AUE_audit_recovery) 1009 asprintf(&autext, "%s::Audit recovery", getprogname()); 1010 else 1011 return (ADE_INVAL); 1012 if (autext == NULL) 1013 return (ADE_NOMEM); 1014 1015 if ((aufd = au_open()) == -1) { 1016 free(autext); 1017 return (ADE_AU_OPEN); 1018 } 1019 bzero(&aia, sizeof(aia)); 1020 uid = getuid(); pid = getpid(); 1021 if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, getgid(), 1022 pid, pid, &aia.ai_termid)) != NULL) 1023 au_write(aufd, tok); 1024 if ((tok = au_to_text(autext)) != NULL) 1025 au_write(aufd, tok); 1026 free(autext); 1027 if (path != NULL && (tok = au_to_path(path)) != NULL) 1028 au_write(aufd, tok); 1029 if ((tok = au_to_return32(0, 0)) != NULL) 1030 au_write(aufd, tok); 1031 if (au_close(aufd, 1, event) == -1) 1032 return (ADE_AU_CLOSE); 1033 1034 return (ADE_NOERR); 1035 } 1036 1037 /* 1038 * Check for a 'current' symlink and do crash recovery, if needed. Create a new 1039 * 'current' symlink. The argument 'curfile' is the file the 'current' symlink 1040 * should point to. Returns: 1041 * ADE_NOERR on success, 1042 * ADE_AU_OPEN if au_open(3) fails, 1043 * ADE_AU_CLOSE if au_close(3) fails. 1044 * ADE_RENAME if error renaming audit trail file, 1045 * ADE_READLINK if error reading the 'current' link, 1046 * ADE_SYMLINK if error creating 'current' link. 1047 */ 1048 int 1049 auditd_new_curlink(char *curfile) 1050 { 1051 int len, err; 1052 char *ptr; 1053 char *path = NULL; 1054 struct stat sb; 1055 char recoveredname[MAXPATHLEN]; 1056 char newname[MAXPATHLEN]; 1057 1058 /* 1059 * Check to see if audit was shutdown properly. If not, clean up, 1060 * recover previous audit trail file, and generate audit record. 1061 */ 1062 len = readlink(AUDIT_CURRENT_LINK, recoveredname, 1063 sizeof(recoveredname) - 1); 1064 if (len > 0) { 1065 /* 'current' exist but is it pointing at a valid file? */ 1066 recoveredname[len++] = '\0'; 1067 if (stat(recoveredname, &sb) == 0) { 1068 /* Yes, rename it to a crash recovery file. */ 1069 strlcpy(newname, recoveredname, sizeof(newname)); 1070 1071 if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) { 1072 memcpy(ptr, CRASH_RECOVERY, POSTFIX_LEN); 1073 if (auditd_rename(recoveredname, newname) != 0) 1074 return (ADE_RENAME); 1075 } else 1076 return (ADE_STRERR); 1077 1078 path = newname; 1079 } 1080 1081 /* 'current' symlink is (now) invalid so remove it. */ 1082 (void) unlink(AUDIT_CURRENT_LINK); 1083 1084 /* Note the crash recovery in current audit trail */ 1085 err = auditd_gen_record(AUE_audit_recovery, path); 1086 if (err) 1087 return (err); 1088 } 1089 1090 if (len < 0 && errno != ENOENT) 1091 return (ADE_READLINK); 1092 1093 if (symlink(curfile, AUDIT_CURRENT_LINK) != 0) 1094 return (ADE_SYMLINK); 1095 1096 return (0); 1097 } 1098 1099 /* 1100 * Do just what we need to quickly start auditing. Assume no system logging or 1101 * notify. Return: 1102 * 0 on success, 1103 * -1 on failure. 1104 */ 1105 int 1106 audit_quick_start(void) 1107 { 1108 int err; 1109 char *newfile = NULL; 1110 time_t tt; 1111 char TS[TIMESTAMP_LEN + 1]; 1112 int ret = 0; 1113 1114 /* 1115 * Mask auditing of this process. 1116 */ 1117 if (auditd_prevent_audit() != 0) 1118 return (-1); 1119 1120 /* 1121 * Read audit_control and get log directories. 1122 */ 1123 err = auditd_read_dirs(NULL, NULL); 1124 if (err != ADE_NOERR && err != ADE_SOFTLIM) 1125 return (-1); 1126 1127 /* 1128 * Setup trail file distribution. 1129 */ 1130 (void) auditd_set_dist(); 1131 1132 /* 1133 * Create a new audit trail log. 1134 */ 1135 if (getTSstr(tt, TS, sizeof(TS)) != 0) 1136 return (-1); 1137 err = auditd_swap_trail(TS, &newfile, getgid(), NULL); 1138 if (err != ADE_NOERR && err != ADE_ACTL) { 1139 ret = -1; 1140 goto out; 1141 } 1142 1143 /* 1144 * Add the current symlink and recover from crash, if needed. 1145 */ 1146 if (auditd_new_curlink(newfile) != 0) { 1147 ret = -1; 1148 goto out; 1149 } 1150 1151 /* 1152 * At this point auditing has started so generate audit start-up record. 1153 */ 1154 if (auditd_gen_record(AUE_audit_startup, NULL) != 0) { 1155 ret = -1; 1156 goto out; 1157 } 1158 1159 /* 1160 * Configure the audit controls. 1161 */ 1162 (void) auditd_set_evcmap(); 1163 (void) auditd_set_namask(); 1164 (void) auditd_set_policy(); 1165 (void) auditd_set_fsize(); 1166 (void) auditd_set_minfree(); 1167 (void) auditd_set_host(); 1168 1169 out: 1170 if (newfile != NULL) 1171 free(newfile); 1172 1173 return (ret); 1174 } 1175 1176 /* 1177 * Shut down auditing quickly. Assumes that is only called on system shutdown. 1178 * Returns: 1179 * 0 on success, 1180 * -1 on failure. 1181 */ 1182 int 1183 audit_quick_stop(void) 1184 { 1185 int len; 1186 int cond; 1187 char *ptr; 1188 time_t tt; 1189 char oldname[MAXPATHLEN]; 1190 char newname[MAXPATHLEN]; 1191 char TS[TIMESTAMP_LEN + 1]; 1192 1193 /* 1194 * Auditing already disabled? 1195 */ 1196 if (audit_get_cond(&cond) != 0) 1197 return (-1); 1198 if (cond == AUC_NOAUDIT) 1199 return (0); 1200 1201 /* 1202 * Generate audit shutdown record. 1203 */ 1204 (void) auditd_gen_record(AUE_audit_shutdown, NULL); 1205 1206 /* 1207 * Shutdown auditing in the kernel. 1208 */ 1209 cond = AUC_DISABLED; 1210 if (audit_set_cond(&cond) != 0) 1211 return (-1); 1212 #ifdef __BSM_INTERNAL_NOTIFY_KEY 1213 notify_post(__BSM_INTERNAL_NOTIFY_KEY); 1214 #endif 1215 1216 /* 1217 * Rename last audit trail and remove 'current' link. 1218 */ 1219 len = readlink(AUDIT_CURRENT_LINK, oldname, sizeof(oldname) - 1); 1220 if (len < 0) 1221 return (-1); 1222 oldname[len++] = '\0'; 1223 1224 if (getTSstr(tt, TS, sizeof(TS)) != 0) 1225 return (-1); 1226 1227 strlcpy(newname, oldname, sizeof(newname)); 1228 1229 if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) { 1230 memcpy(ptr, TS, POSTFIX_LEN); 1231 if (auditd_rename(oldname, newname) != 0) 1232 return (-1); 1233 } else 1234 return (-1); 1235 1236 (void) unlink(AUDIT_CURRENT_LINK); 1237 1238 return (0); 1239 } 1240