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