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