1 /*- 2 * Copyright (c) 2004 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 * 30 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#24 $ 31 */ 32 33 #include <config/config.h> 34 35 #include <bsm/libbsm.h> 36 37 #include <errno.h> 38 #include <string.h> 39 #ifdef HAVE_PTHREAD_MUTEX_LOCK 40 #include <pthread.h> 41 #endif 42 #include <stdio.h> 43 #include <stdlib.h> 44 45 #ifndef HAVE_STRLCAT 46 #include <compat/strlcat.h> 47 #endif 48 #ifndef HAVE_STRLCPY 49 #include <compat/strlcpy.h> 50 #endif 51 52 /* 53 * Parse the contents of the audit_control file to return the audit control 54 * parameters. These static fields are protected by 'mutex'. 55 */ 56 static FILE *fp = NULL; 57 static char linestr[AU_LINE_MAX]; 58 static char *delim = ":"; 59 60 static char inacdir = 0; 61 static char ptrmoved = 0; 62 63 #ifdef HAVE_PTHREAD_MUTEX_LOCK 64 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 65 #endif 66 67 /* 68 * Returns the string value corresponding to the given label from the 69 * configuration file. 70 * 71 * Must be called with mutex held. 72 */ 73 static int 74 getstrfromtype_locked(char *name, char **str) 75 { 76 char *type, *nl; 77 char *tokptr; 78 char *last; 79 80 *str = NULL; 81 82 if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL)) 83 return (-1); /* Error */ 84 85 while (1) { 86 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) { 87 if (ferror(fp)) 88 return (-1); 89 return (0); /* EOF */ 90 } 91 92 if (linestr[0] == '#') 93 continue; 94 95 /* Remove trailing new line character. */ 96 if ((nl = strrchr(linestr, '\n')) != NULL) 97 *nl = '\0'; 98 99 tokptr = linestr; 100 if ((type = strtok_r(tokptr, delim, &last)) != NULL) { 101 if (strcmp(name, type) == 0) { 102 /* Found matching name. */ 103 *str = strtok_r(NULL, delim, &last); 104 if (*str == NULL) { 105 errno = EINVAL; 106 return (-1); /* Parse error in file */ 107 } 108 return (0); /* Success */ 109 } 110 } 111 } 112 } 113 114 /* 115 * Convert a policy to a string. Return -1 on failure, or >= 0 representing 116 * the actual size of the string placed in the buffer (excluding terminating 117 * nul). 118 */ 119 ssize_t 120 au_poltostr(long policy, size_t maxsize, char *buf) 121 { 122 int first; 123 124 if (maxsize < 1) 125 return (-1); 126 first = 1; 127 buf[0] = '\0'; 128 129 if (policy & AUDIT_CNT) { 130 if (strlcat(buf, "cnt", maxsize) >= maxsize) 131 return (-1); 132 first = 0; 133 } 134 if (policy & AUDIT_AHLT) { 135 if (!first) { 136 if (strlcat(buf, ",", maxsize) >= maxsize) 137 return (-1); 138 } 139 if (strlcat(buf, "ahlt", maxsize) >= maxsize) 140 return (-1); 141 first = 0; 142 } 143 if (policy & AUDIT_ARGV) { 144 if (!first) { 145 if (strlcat(buf, ",", maxsize) >= maxsize) 146 return (-1); 147 } 148 if (strlcat(buf, "argv", maxsize) >= maxsize) 149 return (-1); 150 first = 0; 151 } 152 if (policy & AUDIT_ARGE) { 153 if (!first) { 154 if (strlcat(buf, ",", maxsize) >= maxsize) 155 return (-1); 156 } 157 if (strlcat(buf, "arge", maxsize) >= maxsize) 158 return (-1); 159 first = 0; 160 } 161 if (policy & AUDIT_SEQ) { 162 if (!first) { 163 if (strlcat(buf, ",", maxsize) >= maxsize) 164 return (-1); 165 } 166 if (strlcat(buf, "seq", maxsize) >= maxsize) 167 return (-1); 168 first = 0; 169 } 170 if (policy & AUDIT_WINDATA) { 171 if (!first) { 172 if (strlcat(buf, ",", maxsize) >= maxsize) 173 return (-1); 174 } 175 if (strlcat(buf, "windata", maxsize) >= maxsize) 176 return (-1); 177 first = 0; 178 } 179 if (policy & AUDIT_USER) { 180 if (!first) { 181 if (strlcat(buf, ",", maxsize) >= maxsize) 182 return (-1); 183 } 184 if (strlcat(buf, "user", maxsize) >= maxsize) 185 return (-1); 186 first = 0; 187 } 188 if (policy & AUDIT_GROUP) { 189 if (!first) { 190 if (strlcat(buf, ",", maxsize) >= maxsize) 191 return (-1); 192 } 193 if (strlcat(buf, "group", maxsize) >= maxsize) 194 return (-1); 195 first = 0; 196 } 197 if (policy & AUDIT_TRAIL) { 198 if (!first) { 199 if (strlcat(buf, ",", maxsize) >= maxsize) 200 return (-1); 201 } 202 if (strlcat(buf, "trail", maxsize) >= maxsize) 203 return (-1); 204 first = 0; 205 } 206 if (policy & AUDIT_PATH) { 207 if (!first) { 208 if (strlcat(buf, ",", maxsize) >= maxsize) 209 return (-1); 210 } 211 if (strlcat(buf, "path", maxsize) >= maxsize) 212 return (-1); 213 first = 0; 214 } 215 if (policy & AUDIT_SCNT) { 216 if (!first) { 217 if (strlcat(buf, ",", maxsize) >= maxsize) 218 return (-1); 219 } 220 if (strlcat(buf, "scnt", maxsize) >= maxsize) 221 return (-1); 222 first = 0; 223 } 224 if (policy & AUDIT_PUBLIC) { 225 if (!first) { 226 if (strlcat(buf, ",", maxsize) >= maxsize) 227 return (-1); 228 } 229 if (strlcat(buf, "public", maxsize) >= maxsize) 230 return (-1); 231 first = 0; 232 } 233 if (policy & AUDIT_ZONENAME) { 234 if (!first) { 235 if (strlcat(buf, ",", maxsize) >= maxsize) 236 return (-1); 237 } 238 if (strlcat(buf, "zonename", maxsize) >= maxsize) 239 return (-1); 240 first = 0; 241 } 242 if (policy & AUDIT_PERZONE) { 243 if (!first) { 244 if (strlcat(buf, ",", maxsize) >= maxsize) 245 return (-1); 246 } 247 if (strlcat(buf, "perzone", maxsize) >= maxsize) 248 return (-1); 249 first = 0; 250 } 251 return (strlen(buf)); 252 } 253 254 /* 255 * Convert a string to a policy. Return -1 on failure (with errno EINVAL, 256 * ENOMEM) or 0 on success. 257 */ 258 int 259 au_strtopol(const char *polstr, long *policy) 260 { 261 char *bufp, *string; 262 char *buffer; 263 264 *policy = 0; 265 buffer = strdup(polstr); 266 if (buffer == NULL) 267 return (-1); 268 269 bufp = buffer; 270 while ((string = strsep(&bufp, ",")) != NULL) { 271 if (strcmp(string, "cnt") == 0) 272 *policy |= AUDIT_CNT; 273 else if (strcmp(string, "ahlt") == 0) 274 *policy |= AUDIT_AHLT; 275 else if (strcmp(string, "argv") == 0) 276 *policy |= AUDIT_ARGV; 277 else if (strcmp(string, "arge") == 0) 278 *policy |= AUDIT_ARGE; 279 else if (strcmp(string, "seq") == 0) 280 *policy |= AUDIT_SEQ; 281 else if (strcmp(string, "winau_fstat") == 0) 282 *policy |= AUDIT_WINDATA; 283 else if (strcmp(string, "user") == 0) 284 *policy |= AUDIT_USER; 285 else if (strcmp(string, "group") == 0) 286 *policy |= AUDIT_GROUP; 287 else if (strcmp(string, "trail") == 0) 288 *policy |= AUDIT_TRAIL; 289 else if (strcmp(string, "path") == 0) 290 *policy |= AUDIT_PATH; 291 else if (strcmp(string, "scnt") == 0) 292 *policy |= AUDIT_SCNT; 293 else if (strcmp(string, "public") == 0) 294 *policy |= AUDIT_PUBLIC; 295 else if (strcmp(string, "zonename") == 0) 296 *policy |= AUDIT_ZONENAME; 297 else if (strcmp(string, "perzone") == 0) 298 *policy |= AUDIT_PERZONE; 299 else { 300 free(buffer); 301 errno = EINVAL; 302 return (-1); 303 } 304 } 305 free(buffer); 306 return (0); 307 } 308 309 /* 310 * Rewind the file pointer to beginning. 311 */ 312 static void 313 setac_locked(void) 314 { 315 316 ptrmoved = 1; 317 if (fp != NULL) 318 fseek(fp, 0, SEEK_SET); 319 } 320 321 void 322 setac(void) 323 { 324 325 #ifdef HAVE_PTHREAD_MUTEX_LOCK 326 pthread_mutex_lock(&mutex); 327 #endif 328 setac_locked(); 329 #ifdef HAVE_PTHREAD_MUTEX_LOCK 330 pthread_mutex_unlock(&mutex); 331 #endif 332 } 333 334 /* 335 * Close the audit_control file. 336 */ 337 void 338 endac(void) 339 { 340 341 #ifdef HAVE_PTHREAD_MUTEX_LOCK 342 pthread_mutex_lock(&mutex); 343 #endif 344 ptrmoved = 1; 345 if (fp != NULL) { 346 fclose(fp); 347 fp = NULL; 348 } 349 #ifdef HAVE_PTHREAD_MUTEX_LOCK 350 pthread_mutex_unlock(&mutex); 351 #endif 352 } 353 354 /* 355 * Return audit directory information from the audit control file. 356 */ 357 int 358 getacdir(char *name, int len) 359 { 360 char *dir; 361 int ret = 0; 362 363 /* 364 * Check if another function was called between successive calls to 365 * getacdir. 366 */ 367 #ifdef HAVE_PTHREAD_MUTEX_LOCK 368 pthread_mutex_lock(&mutex); 369 #endif 370 if (inacdir && ptrmoved) { 371 ptrmoved = 0; 372 if (fp != NULL) 373 fseek(fp, 0, SEEK_SET); 374 ret = 2; 375 } 376 if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) { 377 #ifdef HAVE_PTHREAD_MUTEX_LOCK 378 pthread_mutex_unlock(&mutex); 379 #endif 380 return (-2); 381 } 382 if (dir == NULL) { 383 #ifdef HAVE_PTHREAD_MUTEX_LOCK 384 pthread_mutex_unlock(&mutex); 385 #endif 386 return (-1); 387 } 388 if (strlen(dir) >= (size_t)len) { 389 #ifdef HAVE_PTHREAD_MUTEX_LOCK 390 pthread_mutex_unlock(&mutex); 391 #endif 392 return (-3); 393 } 394 strlcpy(name, dir, len); 395 #ifdef HAVE_PTHREAD_MUTEX_LOCK 396 pthread_mutex_unlock(&mutex); 397 #endif 398 return (ret); 399 } 400 401 /* 402 * Return the minimum free diskspace value from the audit control file. 403 */ 404 int 405 getacmin(int *min_val) 406 { 407 char *min; 408 409 #ifdef HAVE_PTHREAD_MUTEX_LOCK 410 pthread_mutex_lock(&mutex); 411 #endif 412 setac_locked(); 413 if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) { 414 #ifdef HAVE_PTHREAD_MUTEX_LOCK 415 pthread_mutex_unlock(&mutex); 416 #endif 417 return (-2); 418 } 419 if (min == NULL) { 420 #ifdef HAVE_PTHREAD_MUTEX_LOCK 421 pthread_mutex_unlock(&mutex); 422 #endif 423 return (1); 424 } 425 *min_val = atoi(min); 426 #ifdef HAVE_PTHREAD_MUTEX_LOCK 427 pthread_mutex_unlock(&mutex); 428 #endif 429 return (0); 430 } 431 432 /* 433 * Return the desired trail rotation size from the audit control file. 434 */ 435 int 436 getacfilesz(size_t *filesz_val) 437 { 438 char *filesz, *dummy; 439 long long ll; 440 441 #ifdef HAVE_PTHREAD_MUTEX_LOCK 442 pthread_mutex_lock(&mutex); 443 #endif 444 setac_locked(); 445 if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &filesz) < 0) { 446 #ifdef HAVE_PTHREAD_MUTEX_LOCK 447 pthread_mutex_unlock(&mutex); 448 #endif 449 return (-2); 450 } 451 if (filesz == NULL) { 452 #ifdef HAVE_PTHREAD_MUTEX_LOCK 453 pthread_mutex_unlock(&mutex); 454 #endif 455 errno = EINVAL; 456 return (1); 457 } 458 ll = strtoll(filesz, &dummy, 10); 459 if (*dummy != '\0') { 460 #ifdef HAVE_PTHREAD_MUTEX_LOCK 461 pthread_mutex_unlock(&mutex); 462 #endif 463 errno = EINVAL; 464 return (-1); 465 } 466 /* 467 * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0 468 * indicates no rotation size. 469 */ 470 if (ll < 0 || (ll > 0 && ll < MIN_AUDIT_FILE_SIZE)) { 471 #ifdef HAVE_PTHREAD_MUTEX_LOCK 472 pthread_mutex_unlock(&mutex); 473 #endif 474 errno = EINVAL; 475 return (-1); 476 } 477 *filesz_val = ll; 478 #ifdef HAVE_PTHREAD_MUTEX_LOCK 479 pthread_mutex_unlock(&mutex); 480 #endif 481 return (0); 482 } 483 484 /* 485 * Return the system audit value from the audit contol file. 486 */ 487 int 488 getacflg(char *auditstr, int len) 489 { 490 char *str; 491 492 #ifdef HAVE_PTHREAD_MUTEX_LOCK 493 pthread_mutex_lock(&mutex); 494 #endif 495 setac_locked(); 496 if (getstrfromtype_locked(FLAGS_CONTROL_ENTRY, &str) < 0) { 497 #ifdef HAVE_PTHREAD_MUTEX_LOCK 498 pthread_mutex_unlock(&mutex); 499 #endif 500 return (-2); 501 } 502 if (str == NULL) { 503 #ifdef HAVE_PTHREAD_MUTEX_LOCK 504 pthread_mutex_unlock(&mutex); 505 #endif 506 return (1); 507 } 508 if (strlen(str) >= (size_t)len) { 509 #ifdef HAVE_PTHREAD_MUTEX_LOCK 510 pthread_mutex_unlock(&mutex); 511 #endif 512 return (-3); 513 } 514 strlcpy(auditstr, str, len); 515 #ifdef HAVE_PTHREAD_MUTEX_LOCK 516 pthread_mutex_unlock(&mutex); 517 #endif 518 return (0); 519 } 520 521 /* 522 * Return the non attributable flags from the audit contol file. 523 */ 524 int 525 getacna(char *auditstr, int len) 526 { 527 char *str; 528 529 #ifdef HAVE_PTHREAD_MUTEX_LOCK 530 pthread_mutex_lock(&mutex); 531 #endif 532 setac_locked(); 533 if (getstrfromtype_locked(NA_CONTROL_ENTRY, &str) < 0) { 534 #ifdef HAVE_PTHREAD_MUTEX_LOCK 535 pthread_mutex_unlock(&mutex); 536 #endif 537 return (-2); 538 } 539 if (str == NULL) { 540 #ifdef HAVE_PTHREAD_MUTEX_LOCK 541 pthread_mutex_unlock(&mutex); 542 #endif 543 return (1); 544 } 545 if (strlen(str) >= (size_t)len) { 546 #ifdef HAVE_PTHREAD_MUTEX_LOCK 547 pthread_mutex_unlock(&mutex); 548 #endif 549 return (-3); 550 } 551 strlcpy(auditstr, str, len); 552 #ifdef HAVE_PTHREAD_MUTEX_LOCK 553 pthread_mutex_unlock(&mutex); 554 #endif 555 return (0); 556 } 557 558 /* 559 * Return the policy field from the audit control file. 560 */ 561 int 562 getacpol(char *auditstr, size_t len) 563 { 564 char *str; 565 566 #ifdef HAVE_PTHREAD_MUTEX_LOCK 567 pthread_mutex_lock(&mutex); 568 #endif 569 setac_locked(); 570 if (getstrfromtype_locked(POLICY_CONTROL_ENTRY, &str) < 0) { 571 #ifdef HAVE_PTHREAD_MUTEX_LOCK 572 pthread_mutex_unlock(&mutex); 573 #endif 574 return (-2); 575 } 576 if (str == NULL) { 577 #ifdef HAVE_PTHREAD_MUTEX_LOCK 578 pthread_mutex_unlock(&mutex); 579 #endif 580 return (-1); 581 } 582 if (strlen(str) >= len) { 583 #ifdef HAVE_PTHREAD_MUTEX_LOCK 584 pthread_mutex_unlock(&mutex); 585 #endif 586 return (-3); 587 } 588 strlcpy(auditstr, str, len); 589 #ifdef HAVE_PTHREAD_MUTEX_LOCK 590 pthread_mutex_unlock(&mutex); 591 #endif 592 return (0); 593 } 594 595 int 596 getachost(char *auditstr, size_t len) 597 { 598 char *str; 599 600 #ifdef HAVE_PTHREAD_MUTEX_LOCK 601 pthread_mutex_lock(&mutex); 602 #endif 603 setac_locked(); 604 if (getstrfromtype_locked(AUDIT_HOST_CONTROL_ENTRY, &str) < 0) { 605 #ifdef HAVE_PTHREAD_MUTEX_LOCK 606 pthread_mutex_unlock(&mutex); 607 #endif 608 return (-2); 609 } 610 if (str == NULL) { 611 #ifdef HAVE_PTHREAD_MUTEX_LOCK 612 pthread_mutex_unlock(&mutex); 613 #endif 614 return (1); 615 } 616 if (strlen(str) >= len) { 617 #ifdef HAVE_PTHREAD_MUTEX_LOCK 618 pthread_mutex_unlock(&mutex); 619 #endif 620 return (-3); 621 } 622 strcpy(auditstr, str); 623 #ifdef HAVE_PTHREAD_MUTEX_LOCK 624 pthread_mutex_unlock(&mutex); 625 #endif 626 return (0); 627 } 628