1/*- 2 * Copyright (c) 2004, 2009 Apple Inc. 3 * Copyright (c) 2006 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 *
| 1/*- 2 * Copyright (c) 2004, 2009 Apple Inc. 3 * Copyright (c) 2006 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 *
|
31 */ 32 33#include <config/config.h> 34 35#include <bsm/libbsm.h> 36 37#include <ctype.h> 38#include <errno.h> 39#include <string.h> 40#ifdef HAVE_PTHREAD_MUTEX_LOCK 41#include <pthread.h> 42#endif 43#include <stdio.h> 44#include <stdlib.h> 45 46#ifndef HAVE_STRLCAT 47#include <compat/strlcat.h> 48#endif 49#ifndef HAVE_STRLCPY 50#include <compat/strlcpy.h> 51#endif 52 53#include <sys/stat.h> 54 55/* 56 * Parse the contents of the audit_control file to return the audit control 57 * parameters. These static fields are protected by 'mutex'. 58 */ 59static FILE *fp = NULL; 60static char linestr[AU_LINE_MAX]; 61static char *delim = ":"; 62 63static char inacdir = 0; 64static char ptrmoved = 0; 65 66#ifdef HAVE_PTHREAD_MUTEX_LOCK 67static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 68#endif 69 70/* 71 * Audit policy string token table for au_poltostr() and au_strtopol(). 72 */ 73struct audit_polstr { 74 long ap_policy; 75 const char *ap_str; 76}; 77 78static struct audit_polstr au_polstr[] = { 79 { AUDIT_CNT, "cnt" }, 80 { AUDIT_AHLT, "ahlt" }, 81 { AUDIT_ARGV, "argv" }, 82 { AUDIT_ARGE, "arge" }, 83 { AUDIT_SEQ, "seq" }, 84 { AUDIT_WINDATA, "windata" }, 85 { AUDIT_USER, "user" }, 86 { AUDIT_GROUP, "group" }, 87 { AUDIT_TRAIL, "trail" }, 88 { AUDIT_PATH, "path" }, 89 { AUDIT_SCNT, "scnt" }, 90 { AUDIT_PUBLIC, "public" }, 91 { AUDIT_ZONENAME, "zonename" }, 92 { AUDIT_PERZONE, "perzone" }, 93 { -1, NULL } 94}; 95 96/* 97 * Returns the string value corresponding to the given label from the 98 * configuration file. 99 * 100 * Must be called with mutex held. 101 */ 102static int 103getstrfromtype_locked(char *name, char **str) 104{ 105 char *type, *nl; 106 char *tokptr; 107 char *last; 108 109 *str = NULL; 110 111 if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL)) 112 return (-1); /* Error */ 113 114 while (1) { 115 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) { 116 if (ferror(fp)) 117 return (-1); 118 return (0); /* EOF */ 119 } 120 121 if (linestr[0] == '#') 122 continue; 123
| 31 */ 32 33#include <config/config.h> 34 35#include <bsm/libbsm.h> 36 37#include <ctype.h> 38#include <errno.h> 39#include <string.h> 40#ifdef HAVE_PTHREAD_MUTEX_LOCK 41#include <pthread.h> 42#endif 43#include <stdio.h> 44#include <stdlib.h> 45 46#ifndef HAVE_STRLCAT 47#include <compat/strlcat.h> 48#endif 49#ifndef HAVE_STRLCPY 50#include <compat/strlcpy.h> 51#endif 52 53#include <sys/stat.h> 54 55/* 56 * Parse the contents of the audit_control file to return the audit control 57 * parameters. These static fields are protected by 'mutex'. 58 */ 59static FILE *fp = NULL; 60static char linestr[AU_LINE_MAX]; 61static char *delim = ":"; 62 63static char inacdir = 0; 64static char ptrmoved = 0; 65 66#ifdef HAVE_PTHREAD_MUTEX_LOCK 67static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 68#endif 69 70/* 71 * Audit policy string token table for au_poltostr() and au_strtopol(). 72 */ 73struct audit_polstr { 74 long ap_policy; 75 const char *ap_str; 76}; 77 78static struct audit_polstr au_polstr[] = { 79 { AUDIT_CNT, "cnt" }, 80 { AUDIT_AHLT, "ahlt" }, 81 { AUDIT_ARGV, "argv" }, 82 { AUDIT_ARGE, "arge" }, 83 { AUDIT_SEQ, "seq" }, 84 { AUDIT_WINDATA, "windata" }, 85 { AUDIT_USER, "user" }, 86 { AUDIT_GROUP, "group" }, 87 { AUDIT_TRAIL, "trail" }, 88 { AUDIT_PATH, "path" }, 89 { AUDIT_SCNT, "scnt" }, 90 { AUDIT_PUBLIC, "public" }, 91 { AUDIT_ZONENAME, "zonename" }, 92 { AUDIT_PERZONE, "perzone" }, 93 { -1, NULL } 94}; 95 96/* 97 * Returns the string value corresponding to the given label from the 98 * configuration file. 99 * 100 * Must be called with mutex held. 101 */ 102static int 103getstrfromtype_locked(char *name, char **str) 104{ 105 char *type, *nl; 106 char *tokptr; 107 char *last; 108 109 *str = NULL; 110 111 if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL)) 112 return (-1); /* Error */ 113 114 while (1) { 115 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) { 116 if (ferror(fp)) 117 return (-1); 118 return (0); /* EOF */ 119 } 120 121 if (linestr[0] == '#') 122 continue; 123
|
127 128 tokptr = linestr; 129 if ((type = strtok_r(tokptr, delim, &last)) != NULL) { 130 if (strcmp(name, type) == 0) { 131 /* Found matching name. */ 132 *str = strtok_r(NULL, delim, &last); 133 if (*str == NULL) { 134 errno = EINVAL; 135 return (-1); /* Parse error in file */ 136 } 137 return (0); /* Success */ 138 } 139 } 140 } 141} 142 143/* 144 * Convert a given time value with a multiplier (seconds, hours, days, years) to 145 * seconds. Return 0 on success. 146 */ 147static int 148au_timetosec(time_t *seconds, u_long value, char mult) 149{ 150 if (NULL == seconds) 151 return (-1); 152 153 switch(mult) { 154 case 's': 155 /* seconds */ 156 *seconds = (time_t)value; 157 break; 158 159 case 'h': 160 /* hours */ 161 *seconds = (time_t)value * 60 * 60; 162 break; 163 164 case 'd': 165 /* days */ 166 *seconds = (time_t)value * 60 * 60 * 24; 167 break; 168 169 case 'y': 170 /* years. Add a day for each 4th (leap) year. */ 171 *seconds = (time_t)value * 60 * 60 * 24 * 364 + 172 ((time_t)value / 4) * 60 * 60 * 24; 173 break; 174 175 default: 176 return (-1); 177 } 178 return (0); 179} 180 181/* 182 * Convert a given disk space value with a multiplier (bytes, kilobytes, 183 * megabytes, gigabytes) to bytes. Return 0 on success. 184 */ 185static int 186au_spacetobytes(size_t *bytes, u_long value, char mult) 187{ 188 if (NULL == bytes) 189 return (-1); 190 191 switch(mult) { 192 case 'B': 193 case ' ': 194 /* Bytes */ 195 *bytes = (size_t)value; 196 break; 197 198 case 'K': 199 /* Kilobytes */ 200 *bytes = (size_t)value * 1024; 201 break; 202 203 case 'M': 204 /* Megabytes */ 205 *bytes = (size_t)value * 1024 * 1024; 206 break; 207 208 case 'G': 209 /* Gigabytes */ 210 *bytes = (size_t)value * 1024 * 1024 * 1024; 211 break; 212 213 default: 214 return (-1); 215 } 216 return (0); 217} 218 219/* 220 * Convert a policy to a string. Return -1 on failure, or >= 0 representing 221 * the actual size of the string placed in the buffer (excluding terminating 222 * nul). 223 */ 224ssize_t 225au_poltostr(int policy, size_t maxsize, char *buf) 226{ 227 int first = 1; 228 int i = 0; 229 230 if (maxsize < 1) 231 return (-1); 232 buf[0] = '\0'; 233 234 do { 235 if (policy & au_polstr[i].ap_policy) { 236 if (!first && strlcat(buf, ",", maxsize) >= maxsize) 237 return (-1); 238 if (strlcat(buf, au_polstr[i].ap_str, maxsize) >= 239 maxsize) 240 return (-1); 241 first = 0; 242 } 243 } while (NULL != au_polstr[++i].ap_str); 244 245 return (strlen(buf)); 246} 247 248/* 249 * Convert a string to a policy. Return -1 on failure (with errno EINVAL, 250 * ENOMEM) or 0 on success. 251 */ 252int 253au_strtopol(const char *polstr, int *policy) 254{ 255 char *bufp, *string; 256 char *buffer; 257 int i, matched; 258 259 *policy = 0; 260 buffer = strdup(polstr); 261 if (buffer == NULL) 262 return (-1); 263 264 bufp = buffer; 265 while ((string = strsep(&bufp, ",")) != NULL) { 266 matched = i = 0; 267 268 do { 269 if (strcmp(string, au_polstr[i].ap_str) == 0) { 270 *policy |= au_polstr[i].ap_policy; 271 matched = 1; 272 break; 273 } 274 } while (NULL != au_polstr[++i].ap_str); 275 276 if (!matched) { 277 free(buffer); 278 errno = EINVAL; 279 return (-1); 280 } 281 } 282 free(buffer); 283 return (0); 284} 285 286/* 287 * Rewind the file pointer to beginning. 288 */ 289static void 290setac_locked(void) 291{ 292 static time_t lastctime = 0; 293 struct stat sbuf; 294 295 ptrmoved = 1; 296 if (fp != NULL) { 297 /* 298 * Check to see if the file on disk has changed. If so, 299 * force a re-read of the file by closing it. 300 */ 301 if (fstat(fileno(fp), &sbuf) < 0) 302 goto closefp; 303 if (lastctime != sbuf.st_ctime) { 304 lastctime = sbuf.st_ctime; 305closefp: 306 fclose(fp); 307 fp = NULL; 308 return; 309 } 310 311 fseek(fp, 0, SEEK_SET); 312 } 313} 314 315void 316setac(void) 317{ 318 319#ifdef HAVE_PTHREAD_MUTEX_LOCK 320 pthread_mutex_lock(&mutex); 321#endif 322 setac_locked(); 323#ifdef HAVE_PTHREAD_MUTEX_LOCK 324 pthread_mutex_unlock(&mutex); 325#endif 326} 327 328/* 329 * Close the audit_control file. 330 */ 331void 332endac(void) 333{ 334 335#ifdef HAVE_PTHREAD_MUTEX_LOCK 336 pthread_mutex_lock(&mutex); 337#endif 338 ptrmoved = 1; 339 if (fp != NULL) { 340 fclose(fp); 341 fp = NULL; 342 } 343#ifdef HAVE_PTHREAD_MUTEX_LOCK 344 pthread_mutex_unlock(&mutex); 345#endif 346} 347 348/* 349 * Return audit directory information from the audit control file. 350 */ 351int 352getacdir(char *name, int len) 353{ 354 char *dir; 355 int ret = 0; 356 357 /* 358 * Check if another function was called between successive calls to 359 * getacdir. 360 */ 361#ifdef HAVE_PTHREAD_MUTEX_LOCK 362 pthread_mutex_lock(&mutex); 363#endif 364 if (inacdir && ptrmoved) { 365 ptrmoved = 0; 366 if (fp != NULL) 367 fseek(fp, 0, SEEK_SET); 368 ret = 2; 369 } 370 if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) { 371#ifdef HAVE_PTHREAD_MUTEX_LOCK 372 pthread_mutex_unlock(&mutex); 373#endif 374 return (-2); 375 } 376 if (dir == NULL) { 377#ifdef HAVE_PTHREAD_MUTEX_LOCK 378 pthread_mutex_unlock(&mutex); 379#endif 380 return (-1); 381 } 382 if (strlen(dir) >= (size_t)len) { 383#ifdef HAVE_PTHREAD_MUTEX_LOCK 384 pthread_mutex_unlock(&mutex); 385#endif 386 return (-3); 387 } 388 strlcpy(name, dir, len); 389#ifdef HAVE_PTHREAD_MUTEX_LOCK 390 pthread_mutex_unlock(&mutex); 391#endif 392 return (ret); 393} 394 395/* 396 * Return the minimum free diskspace value from the audit control file. 397 */ 398int 399getacmin(int *min_val) 400{ 401 char *min; 402 403#ifdef HAVE_PTHREAD_MUTEX_LOCK 404 pthread_mutex_lock(&mutex); 405#endif 406 setac_locked(); 407 if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) { 408#ifdef HAVE_PTHREAD_MUTEX_LOCK 409 pthread_mutex_unlock(&mutex); 410#endif 411 return (-2); 412 } 413 if (min == NULL) { 414#ifdef HAVE_PTHREAD_MUTEX_LOCK 415 pthread_mutex_unlock(&mutex); 416#endif 417 return (1); 418 } 419 *min_val = atoi(min); 420#ifdef HAVE_PTHREAD_MUTEX_LOCK 421 pthread_mutex_unlock(&mutex); 422#endif 423 return (0); 424} 425 426/* 427 * Return the desired trail rotation size from the audit control file. 428 */ 429int 430getacfilesz(size_t *filesz_val) 431{ 432 char *str; 433 size_t val; 434 char mult; 435 int nparsed; 436 437#ifdef HAVE_PTHREAD_MUTEX_LOCK 438 pthread_mutex_lock(&mutex); 439#endif 440 setac_locked(); 441 if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) { 442#ifdef HAVE_PTHREAD_MUTEX_LOCK 443 pthread_mutex_unlock(&mutex); 444#endif 445 return (-2); 446 } 447 if (str == NULL) { 448#ifdef HAVE_PTHREAD_MUTEX_LOCK 449 pthread_mutex_unlock(&mutex); 450#endif 451 errno = EINVAL; 452 return (1); 453 } 454 455 /* Trim off any leading white space. */ 456 while (*str == ' ' || *str == '\t') 457 str++; 458 459 nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult); 460 461 switch (nparsed) { 462 case 1: 463 /* If no multiplier then assume 'B' (bytes). */ 464 mult = 'B'; 465 /* fall through */ 466 case 2: 467 if (au_spacetobytes(filesz_val, val, mult) == 0) 468 break; 469 /* fall through */ 470 default: 471 errno = EINVAL; 472#ifdef HAVE_PTHREAD_MUTEX_LOCK 473 pthread_mutex_unlock(&mutex); 474#endif 475 return (-1); 476 } 477 478 /* 479 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0 480 * indicates no rotation size. 481 */ 482 if (*filesz_val < 0 || (*filesz_val > 0 && 483 *filesz_val < MIN_AUDIT_FILE_SIZE)) { 484#ifdef HAVE_PTHREAD_MUTEX_LOCK 485 pthread_mutex_unlock(&mutex); 486#endif 487 filesz_val = 0L; 488 errno = EINVAL; 489 return (-1); 490 } 491#ifdef HAVE_PTHREAD_MUTEX_LOCK 492 pthread_mutex_unlock(&mutex); 493#endif 494 return (0); 495} 496 497/* 498 * Return the system audit value from the audit contol file. 499 */ 500int 501getacflg(char *auditstr, int len) 502{ 503 char *str; 504 505#ifdef HAVE_PTHREAD_MUTEX_LOCK 506 pthread_mutex_lock(&mutex); 507#endif 508 setac_locked(); 509 if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) { 510#ifdef HAVE_PTHREAD_MUTEX_LOCK 511 pthread_mutex_unlock(&mutex); 512#endif 513 return (-2); 514 } 515 if (str == NULL) { 516#ifdef HAVE_PTHREAD_MUTEX_LOCK 517 pthread_mutex_unlock(&mutex); 518#endif 519 return (1); 520 } 521 if (strlen(str) >= (size_t)len) { 522#ifdef HAVE_PTHREAD_MUTEX_LOCK 523 pthread_mutex_unlock(&mutex); 524#endif 525 return (-3); 526 } 527 strlcpy(auditstr, str, len); 528#ifdef HAVE_PTHREAD_MUTEX_LOCK 529 pthread_mutex_unlock(&mutex); 530#endif 531 return (0); 532} 533 534/* 535 * Return the non attributable flags from the audit contol file. 536 */ 537int 538getacna(char *auditstr, int len) 539{ 540 char *str; 541 542#ifdef HAVE_PTHREAD_MUTEX_LOCK 543 pthread_mutex_lock(&mutex); 544#endif 545 setac_locked(); 546 if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) { 547#ifdef HAVE_PTHREAD_MUTEX_LOCK 548 pthread_mutex_unlock(&mutex); 549#endif 550 return (-2); 551 } 552 if (str == NULL) { 553#ifdef HAVE_PTHREAD_MUTEX_LOCK 554 pthread_mutex_unlock(&mutex); 555#endif 556 return (1); 557 } 558 if (strlen(str) >= (size_t)len) { 559#ifdef HAVE_PTHREAD_MUTEX_LOCK 560 pthread_mutex_unlock(&mutex); 561#endif 562 return (-3); 563 } 564 strlcpy(auditstr, str, len); 565#ifdef HAVE_PTHREAD_MUTEX_LOCK 566 pthread_mutex_unlock(&mutex); 567#endif 568 return (0); 569} 570 571/* 572 * Return the policy field from the audit control file. 573 */ 574int 575getacpol(char *auditstr, size_t len) 576{ 577 char *str; 578 579#ifdef HAVE_PTHREAD_MUTEX_LOCK 580 pthread_mutex_lock(&mutex); 581#endif 582 setac_locked(); 583 if (getstrfromtype_locked(POLICY_CONTROL_ENTRY, &str) < 0) { 584#ifdef HAVE_PTHREAD_MUTEX_LOCK 585 pthread_mutex_unlock(&mutex); 586#endif 587 return (-2); 588 } 589 if (str == NULL) { 590#ifdef HAVE_PTHREAD_MUTEX_LOCK 591 pthread_mutex_unlock(&mutex); 592#endif 593 return (-1); 594 } 595 if (strlen(str) >= len) { 596#ifdef HAVE_PTHREAD_MUTEX_LOCK 597 pthread_mutex_unlock(&mutex); 598#endif 599 return (-3); 600 } 601 strlcpy(auditstr, str, len); 602#ifdef HAVE_PTHREAD_MUTEX_LOCK 603 pthread_mutex_unlock(&mutex); 604#endif 605 return (0); 606} 607 608int 609getachost(char *auditstr, size_t len) 610{ 611 char *str; 612 613#ifdef HAVE_PTHREAD_MUTEX_LOCK 614 pthread_mutex_lock(&mutex); 615#endif 616 setac_locked(); 617 if (getstrfromtype_locked(AUDIT_HOST_CONTROL_ENTRY, &str) < 0) { 618#ifdef HAVE_PTHREAD_MUTEX_LOCK 619 pthread_mutex_unlock(&mutex); 620#endif 621 return (-2); 622 } 623 if (str == NULL) { 624#ifdef HAVE_PTHREAD_MUTEX_LOCK 625 pthread_mutex_unlock(&mutex); 626#endif 627 return (1); 628 } 629 if (strlen(str) >= len) { 630#ifdef HAVE_PTHREAD_MUTEX_LOCK 631 pthread_mutex_unlock(&mutex); 632#endif 633 return (-3); 634 } 635 strlcpy(auditstr, str, len); 636#ifdef HAVE_PTHREAD_MUTEX_LOCK 637 pthread_mutex_unlock(&mutex); 638#endif 639 return (0); 640} 641 642/* 643 * Set expiration conditions. 644 */ 645static int 646setexpirecond(time_t *age, size_t *size, u_long value, char mult) 647{ 648 649 if (isupper(mult) || ' ' == mult) 650 return (au_spacetobytes(size, value, mult)); 651 else 652 return (au_timetosec(age, value, mult)); 653} 654 655/* 656 * Return the expire-after field from the audit control file. 657 */ 658int 659getacexpire(int *andflg, time_t *age, size_t *size) 660{ 661 char *str; 662 int nparsed; 663 u_long val1, val2; 664 char mult1, mult2; 665 char andor[AU_LINE_MAX]; 666 667 *age = 0L; 668 *size = 0LL; 669 *andflg = 0; 670 671#ifdef HAVE_PTHREAD_MUTEX_LOCK 672 pthread_mutex_lock(&mutex); 673#endif 674 setac_locked(); 675 if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) { 676#ifdef HAVE_PTHREAD_MUTEX_LOCK 677 pthread_mutex_unlock(&mutex); 678#endif 679 return (-2); 680 } 681 if (str == NULL) { 682#ifdef HAVE_PTHREAD_MUTEX_LOCK 683 pthread_mutex_unlock(&mutex); 684#endif 685 return (1); 686 } 687 688 /* First, trim off any leading white space. */ 689 while (*str == ' ' || *str == '\t') 690 str++; 691 692 nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1, 693 andor, &val2, &mult2); 694 695 switch (nparsed) { 696 case 1: 697 /* If no multiplier then assume 'B' (Bytes). */ 698 mult1 = 'B'; 699 /* fall through */ 700 case 2: 701 /* One expiration condition. */ 702 if (setexpirecond(age, size, val1, mult1) != 0) { 703#ifdef HAVE_PTHREAD_MUTEX_LOCK 704 pthread_mutex_unlock(&mutex); 705#endif 706 return (-1); 707 } 708 break; 709 710 case 5: 711 /* Two expiration conditions. */ 712 if (setexpirecond(age, size, val1, mult1) != 0 || 713 setexpirecond(age, size, val2, mult2) != 0) { 714#ifdef HAVE_PTHREAD_MUTEX_LOCK 715 pthread_mutex_unlock(&mutex); 716#endif 717 return (-1); 718 } 719 if (strcasestr(andor, "and") != NULL) 720 *andflg = 1; 721 else if (strcasestr(andor, "or") != NULL) 722 *andflg = 0; 723 else { 724#ifdef HAVE_PTHREAD_MUTEX_LOCK 725 pthread_mutex_unlock(&mutex); 726#endif 727 return (-1); 728 } 729 break; 730 731 default: 732#ifdef HAVE_PTHREAD_MUTEX_LOCK 733 pthread_mutex_unlock(&mutex); 734#endif 735 return (-1); 736 } 737 738#ifdef HAVE_PTHREAD_MUTEX_LOCK 739 pthread_mutex_unlock(&mutex); 740#endif 741 return (0); 742}
| 131 132 tokptr = linestr; 133 if ((type = strtok_r(tokptr, delim, &last)) != NULL) { 134 if (strcmp(name, type) == 0) { 135 /* Found matching name. */ 136 *str = strtok_r(NULL, delim, &last); 137 if (*str == NULL) { 138 errno = EINVAL; 139 return (-1); /* Parse error in file */ 140 } 141 return (0); /* Success */ 142 } 143 } 144 } 145} 146 147/* 148 * Convert a given time value with a multiplier (seconds, hours, days, years) to 149 * seconds. Return 0 on success. 150 */ 151static int 152au_timetosec(time_t *seconds, u_long value, char mult) 153{ 154 if (NULL == seconds) 155 return (-1); 156 157 switch(mult) { 158 case 's': 159 /* seconds */ 160 *seconds = (time_t)value; 161 break; 162 163 case 'h': 164 /* hours */ 165 *seconds = (time_t)value * 60 * 60; 166 break; 167 168 case 'd': 169 /* days */ 170 *seconds = (time_t)value * 60 * 60 * 24; 171 break; 172 173 case 'y': 174 /* years. Add a day for each 4th (leap) year. */ 175 *seconds = (time_t)value * 60 * 60 * 24 * 364 + 176 ((time_t)value / 4) * 60 * 60 * 24; 177 break; 178 179 default: 180 return (-1); 181 } 182 return (0); 183} 184 185/* 186 * Convert a given disk space value with a multiplier (bytes, kilobytes, 187 * megabytes, gigabytes) to bytes. Return 0 on success. 188 */ 189static int 190au_spacetobytes(size_t *bytes, u_long value, char mult) 191{ 192 if (NULL == bytes) 193 return (-1); 194 195 switch(mult) { 196 case 'B': 197 case ' ': 198 /* Bytes */ 199 *bytes = (size_t)value; 200 break; 201 202 case 'K': 203 /* Kilobytes */ 204 *bytes = (size_t)value * 1024; 205 break; 206 207 case 'M': 208 /* Megabytes */ 209 *bytes = (size_t)value * 1024 * 1024; 210 break; 211 212 case 'G': 213 /* Gigabytes */ 214 *bytes = (size_t)value * 1024 * 1024 * 1024; 215 break; 216 217 default: 218 return (-1); 219 } 220 return (0); 221} 222 223/* 224 * Convert a policy to a string. Return -1 on failure, or >= 0 representing 225 * the actual size of the string placed in the buffer (excluding terminating 226 * nul). 227 */ 228ssize_t 229au_poltostr(int policy, size_t maxsize, char *buf) 230{ 231 int first = 1; 232 int i = 0; 233 234 if (maxsize < 1) 235 return (-1); 236 buf[0] = '\0'; 237 238 do { 239 if (policy & au_polstr[i].ap_policy) { 240 if (!first && strlcat(buf, ",", maxsize) >= maxsize) 241 return (-1); 242 if (strlcat(buf, au_polstr[i].ap_str, maxsize) >= 243 maxsize) 244 return (-1); 245 first = 0; 246 } 247 } while (NULL != au_polstr[++i].ap_str); 248 249 return (strlen(buf)); 250} 251 252/* 253 * Convert a string to a policy. Return -1 on failure (with errno EINVAL, 254 * ENOMEM) or 0 on success. 255 */ 256int 257au_strtopol(const char *polstr, int *policy) 258{ 259 char *bufp, *string; 260 char *buffer; 261 int i, matched; 262 263 *policy = 0; 264 buffer = strdup(polstr); 265 if (buffer == NULL) 266 return (-1); 267 268 bufp = buffer; 269 while ((string = strsep(&bufp, ",")) != NULL) { 270 matched = i = 0; 271 272 do { 273 if (strcmp(string, au_polstr[i].ap_str) == 0) { 274 *policy |= au_polstr[i].ap_policy; 275 matched = 1; 276 break; 277 } 278 } while (NULL != au_polstr[++i].ap_str); 279 280 if (!matched) { 281 free(buffer); 282 errno = EINVAL; 283 return (-1); 284 } 285 } 286 free(buffer); 287 return (0); 288} 289 290/* 291 * Rewind the file pointer to beginning. 292 */ 293static void 294setac_locked(void) 295{ 296 static time_t lastctime = 0; 297 struct stat sbuf; 298 299 ptrmoved = 1; 300 if (fp != NULL) { 301 /* 302 * Check to see if the file on disk has changed. If so, 303 * force a re-read of the file by closing it. 304 */ 305 if (fstat(fileno(fp), &sbuf) < 0) 306 goto closefp; 307 if (lastctime != sbuf.st_ctime) { 308 lastctime = sbuf.st_ctime; 309closefp: 310 fclose(fp); 311 fp = NULL; 312 return; 313 } 314 315 fseek(fp, 0, SEEK_SET); 316 } 317} 318 319void 320setac(void) 321{ 322 323#ifdef HAVE_PTHREAD_MUTEX_LOCK 324 pthread_mutex_lock(&mutex); 325#endif 326 setac_locked(); 327#ifdef HAVE_PTHREAD_MUTEX_LOCK 328 pthread_mutex_unlock(&mutex); 329#endif 330} 331 332/* 333 * Close the audit_control file. 334 */ 335void 336endac(void) 337{ 338 339#ifdef HAVE_PTHREAD_MUTEX_LOCK 340 pthread_mutex_lock(&mutex); 341#endif 342 ptrmoved = 1; 343 if (fp != NULL) { 344 fclose(fp); 345 fp = NULL; 346 } 347#ifdef HAVE_PTHREAD_MUTEX_LOCK 348 pthread_mutex_unlock(&mutex); 349#endif 350} 351 352/* 353 * Return audit directory information from the audit control file. 354 */ 355int 356getacdir(char *name, int len) 357{ 358 char *dir; 359 int ret = 0; 360 361 /* 362 * Check if another function was called between successive calls to 363 * getacdir. 364 */ 365#ifdef HAVE_PTHREAD_MUTEX_LOCK 366 pthread_mutex_lock(&mutex); 367#endif 368 if (inacdir && ptrmoved) { 369 ptrmoved = 0; 370 if (fp != NULL) 371 fseek(fp, 0, SEEK_SET); 372 ret = 2; 373 } 374 if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) { 375#ifdef HAVE_PTHREAD_MUTEX_LOCK 376 pthread_mutex_unlock(&mutex); 377#endif 378 return (-2); 379 } 380 if (dir == NULL) { 381#ifdef HAVE_PTHREAD_MUTEX_LOCK 382 pthread_mutex_unlock(&mutex); 383#endif 384 return (-1); 385 } 386 if (strlen(dir) >= (size_t)len) { 387#ifdef HAVE_PTHREAD_MUTEX_LOCK 388 pthread_mutex_unlock(&mutex); 389#endif 390 return (-3); 391 } 392 strlcpy(name, dir, len); 393#ifdef HAVE_PTHREAD_MUTEX_LOCK 394 pthread_mutex_unlock(&mutex); 395#endif 396 return (ret); 397} 398 399/* 400 * Return the minimum free diskspace value from the audit control file. 401 */ 402int 403getacmin(int *min_val) 404{ 405 char *min; 406 407#ifdef HAVE_PTHREAD_MUTEX_LOCK 408 pthread_mutex_lock(&mutex); 409#endif 410 setac_locked(); 411 if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) { 412#ifdef HAVE_PTHREAD_MUTEX_LOCK 413 pthread_mutex_unlock(&mutex); 414#endif 415 return (-2); 416 } 417 if (min == NULL) { 418#ifdef HAVE_PTHREAD_MUTEX_LOCK 419 pthread_mutex_unlock(&mutex); 420#endif 421 return (1); 422 } 423 *min_val = atoi(min); 424#ifdef HAVE_PTHREAD_MUTEX_LOCK 425 pthread_mutex_unlock(&mutex); 426#endif 427 return (0); 428} 429 430/* 431 * Return the desired trail rotation size from the audit control file. 432 */ 433int 434getacfilesz(size_t *filesz_val) 435{ 436 char *str; 437 size_t val; 438 char mult; 439 int nparsed; 440 441#ifdef HAVE_PTHREAD_MUTEX_LOCK 442 pthread_mutex_lock(&mutex); 443#endif 444 setac_locked(); 445 if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) { 446#ifdef HAVE_PTHREAD_MUTEX_LOCK 447 pthread_mutex_unlock(&mutex); 448#endif 449 return (-2); 450 } 451 if (str == NULL) { 452#ifdef HAVE_PTHREAD_MUTEX_LOCK 453 pthread_mutex_unlock(&mutex); 454#endif 455 errno = EINVAL; 456 return (1); 457 } 458 459 /* Trim off any leading white space. */ 460 while (*str == ' ' || *str == '\t') 461 str++; 462 463 nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult); 464 465 switch (nparsed) { 466 case 1: 467 /* If no multiplier then assume 'B' (bytes). */ 468 mult = 'B'; 469 /* fall through */ 470 case 2: 471 if (au_spacetobytes(filesz_val, val, mult) == 0) 472 break; 473 /* fall through */ 474 default: 475 errno = EINVAL; 476#ifdef HAVE_PTHREAD_MUTEX_LOCK 477 pthread_mutex_unlock(&mutex); 478#endif 479 return (-1); 480 } 481 482 /* 483 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0 484 * indicates no rotation size. 485 */ 486 if (*filesz_val < 0 || (*filesz_val > 0 && 487 *filesz_val < MIN_AUDIT_FILE_SIZE)) { 488#ifdef HAVE_PTHREAD_MUTEX_LOCK 489 pthread_mutex_unlock(&mutex); 490#endif 491 filesz_val = 0L; 492 errno = EINVAL; 493 return (-1); 494 } 495#ifdef HAVE_PTHREAD_MUTEX_LOCK 496 pthread_mutex_unlock(&mutex); 497#endif 498 return (0); 499} 500 501/* 502 * Return the system audit value from the audit contol file. 503 */ 504int 505getacflg(char *auditstr, int len) 506{ 507 char *str; 508 509#ifdef HAVE_PTHREAD_MUTEX_LOCK 510 pthread_mutex_lock(&mutex); 511#endif 512 setac_locked(); 513 if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) { 514#ifdef HAVE_PTHREAD_MUTEX_LOCK 515 pthread_mutex_unlock(&mutex); 516#endif 517 return (-2); 518 } 519 if (str == NULL) { 520#ifdef HAVE_PTHREAD_MUTEX_LOCK 521 pthread_mutex_unlock(&mutex); 522#endif 523 return (1); 524 } 525 if (strlen(str) >= (size_t)len) { 526#ifdef HAVE_PTHREAD_MUTEX_LOCK 527 pthread_mutex_unlock(&mutex); 528#endif 529 return (-3); 530 } 531 strlcpy(auditstr, str, len); 532#ifdef HAVE_PTHREAD_MUTEX_LOCK 533 pthread_mutex_unlock(&mutex); 534#endif 535 return (0); 536} 537 538/* 539 * Return the non attributable flags from the audit contol file. 540 */ 541int 542getacna(char *auditstr, int len) 543{ 544 char *str; 545 546#ifdef HAVE_PTHREAD_MUTEX_LOCK 547 pthread_mutex_lock(&mutex); 548#endif 549 setac_locked(); 550 if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) { 551#ifdef HAVE_PTHREAD_MUTEX_LOCK 552 pthread_mutex_unlock(&mutex); 553#endif 554 return (-2); 555 } 556 if (str == NULL) { 557#ifdef HAVE_PTHREAD_MUTEX_LOCK 558 pthread_mutex_unlock(&mutex); 559#endif 560 return (1); 561 } 562 if (strlen(str) >= (size_t)len) { 563#ifdef HAVE_PTHREAD_MUTEX_LOCK 564 pthread_mutex_unlock(&mutex); 565#endif 566 return (-3); 567 } 568 strlcpy(auditstr, str, len); 569#ifdef HAVE_PTHREAD_MUTEX_LOCK 570 pthread_mutex_unlock(&mutex); 571#endif 572 return (0); 573} 574 575/* 576 * Return the policy field from the audit control file. 577 */ 578int 579getacpol(char *auditstr, size_t len) 580{ 581 char *str; 582 583#ifdef HAVE_PTHREAD_MUTEX_LOCK 584 pthread_mutex_lock(&mutex); 585#endif 586 setac_locked(); 587 if (getstrfromtype_locked(POLICY_CONTROL_ENTRY, &str) < 0) { 588#ifdef HAVE_PTHREAD_MUTEX_LOCK 589 pthread_mutex_unlock(&mutex); 590#endif 591 return (-2); 592 } 593 if (str == NULL) { 594#ifdef HAVE_PTHREAD_MUTEX_LOCK 595 pthread_mutex_unlock(&mutex); 596#endif 597 return (-1); 598 } 599 if (strlen(str) >= len) { 600#ifdef HAVE_PTHREAD_MUTEX_LOCK 601 pthread_mutex_unlock(&mutex); 602#endif 603 return (-3); 604 } 605 strlcpy(auditstr, str, len); 606#ifdef HAVE_PTHREAD_MUTEX_LOCK 607 pthread_mutex_unlock(&mutex); 608#endif 609 return (0); 610} 611 612int 613getachost(char *auditstr, size_t len) 614{ 615 char *str; 616 617#ifdef HAVE_PTHREAD_MUTEX_LOCK 618 pthread_mutex_lock(&mutex); 619#endif 620 setac_locked(); 621 if (getstrfromtype_locked(AUDIT_HOST_CONTROL_ENTRY, &str) < 0) { 622#ifdef HAVE_PTHREAD_MUTEX_LOCK 623 pthread_mutex_unlock(&mutex); 624#endif 625 return (-2); 626 } 627 if (str == NULL) { 628#ifdef HAVE_PTHREAD_MUTEX_LOCK 629 pthread_mutex_unlock(&mutex); 630#endif 631 return (1); 632 } 633 if (strlen(str) >= len) { 634#ifdef HAVE_PTHREAD_MUTEX_LOCK 635 pthread_mutex_unlock(&mutex); 636#endif 637 return (-3); 638 } 639 strlcpy(auditstr, str, len); 640#ifdef HAVE_PTHREAD_MUTEX_LOCK 641 pthread_mutex_unlock(&mutex); 642#endif 643 return (0); 644} 645 646/* 647 * Set expiration conditions. 648 */ 649static int 650setexpirecond(time_t *age, size_t *size, u_long value, char mult) 651{ 652 653 if (isupper(mult) || ' ' == mult) 654 return (au_spacetobytes(size, value, mult)); 655 else 656 return (au_timetosec(age, value, mult)); 657} 658 659/* 660 * Return the expire-after field from the audit control file. 661 */ 662int 663getacexpire(int *andflg, time_t *age, size_t *size) 664{ 665 char *str; 666 int nparsed; 667 u_long val1, val2; 668 char mult1, mult2; 669 char andor[AU_LINE_MAX]; 670 671 *age = 0L; 672 *size = 0LL; 673 *andflg = 0; 674 675#ifdef HAVE_PTHREAD_MUTEX_LOCK 676 pthread_mutex_lock(&mutex); 677#endif 678 setac_locked(); 679 if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) { 680#ifdef HAVE_PTHREAD_MUTEX_LOCK 681 pthread_mutex_unlock(&mutex); 682#endif 683 return (-2); 684 } 685 if (str == NULL) { 686#ifdef HAVE_PTHREAD_MUTEX_LOCK 687 pthread_mutex_unlock(&mutex); 688#endif 689 return (1); 690 } 691 692 /* First, trim off any leading white space. */ 693 while (*str == ' ' || *str == '\t') 694 str++; 695 696 nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1, 697 andor, &val2, &mult2); 698 699 switch (nparsed) { 700 case 1: 701 /* If no multiplier then assume 'B' (Bytes). */ 702 mult1 = 'B'; 703 /* fall through */ 704 case 2: 705 /* One expiration condition. */ 706 if (setexpirecond(age, size, val1, mult1) != 0) { 707#ifdef HAVE_PTHREAD_MUTEX_LOCK 708 pthread_mutex_unlock(&mutex); 709#endif 710 return (-1); 711 } 712 break; 713 714 case 5: 715 /* Two expiration conditions. */ 716 if (setexpirecond(age, size, val1, mult1) != 0 || 717 setexpirecond(age, size, val2, mult2) != 0) { 718#ifdef HAVE_PTHREAD_MUTEX_LOCK 719 pthread_mutex_unlock(&mutex); 720#endif 721 return (-1); 722 } 723 if (strcasestr(andor, "and") != NULL) 724 *andflg = 1; 725 else if (strcasestr(andor, "or") != NULL) 726 *andflg = 0; 727 else { 728#ifdef HAVE_PTHREAD_MUTEX_LOCK 729 pthread_mutex_unlock(&mutex); 730#endif 731 return (-1); 732 } 733 break; 734 735 default: 736#ifdef HAVE_PTHREAD_MUTEX_LOCK 737 pthread_mutex_unlock(&mutex); 738#endif 739 return (-1); 740 } 741 742#ifdef HAVE_PTHREAD_MUTEX_LOCK 743 pthread_mutex_unlock(&mutex); 744#endif 745 return (0); 746}
|