bsm_control.c revision 186647
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 */ 56static FILE *fp = NULL; 57static char linestr[AU_LINE_MAX]; 58static char *delim = ":"; 59 60static char inacdir = 0; 61static char ptrmoved = 0; 62 63#ifdef HAVE_PTHREAD_MUTEX_LOCK 64static 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 */ 73static int 74getstrfromtype_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 */ 119ssize_t 120au_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 */ 258int 259au_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 */ 312static void 313setac_locked(void) 314{ 315 316 ptrmoved = 1; 317 if (fp != NULL) 318 fseek(fp, 0, SEEK_SET); 319} 320 321void 322setac(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 */ 337void 338endac(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 */ 357int 358getacdir(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 */ 404int 405getacmin(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 */ 435int 436getacfilesz(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 */ 487int 488getacflg(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 */ 524int 525getacna(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 */ 561int 562getacpol(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 595int 596getachost(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