1 2/* 3 * Licensed Materials - Property of IBM 4 * 5 * trousers - An open source TCG Software Stack 6 * 7 * (C) Copyright International Business Machines Corp. 2004 8 * 9 */ 10 11 12#include <stdio.h> 13#include <pwd.h> 14#include <sys/types.h> 15#include <sys/stat.h> 16#include <fcntl.h> 17#include <ctype.h> 18#include <string.h> 19#include <strings.h> 20#include <errno.h> 21#include <grp.h> 22#include <stdlib.h> 23 24#ifdef SOLARIS 25#include <libscf.h> 26#endif 27 28#include "trousers/tss.h" 29#include "trousers_types.h" 30#include "tcs_tsp.h" 31#include "tcs_utils.h" 32#include "tcsps.h" 33#include "tcslog.h" 34#include "tcsd_wrap.h" 35#include "tcsd.h" 36#include "tcsd_ops.h" 37 38 39struct tcsd_config_options options_list[] = { 40 {"port", opt_port}, 41 {"num_threads", opt_max_threads}, 42 {"system_ps_file", opt_system_ps_file}, 43 {"firmware_log_file", opt_firmware_log}, 44 {"firmware_pcrs", opt_firmware_pcrs}, 45 {"kernel_log_file", opt_kernel_log}, 46 {"kernel_pcrs", opt_kernel_pcrs}, 47 {"platform_cred", opt_platform_cred}, 48 {"conformance_cred", opt_conformance_cred}, 49 {"endorsement_cred", opt_endorsement_cred}, 50 {"remote_ops", opt_remote_ops}, 51 {"enforce_exclusive_transport", opt_exclusive_transport}, 52 {"host_platform_class", opt_host_platform_class}, 53 {"all_platform_classes", opt_all_platform_classes}, 54 {NULL, 0} 55}; 56 57struct tcg_platform_spec tcg_platform_specs[] = { 58 {"PC_11", TPM_PS_PC_11, TPM_PS_PC_11_URI}, 59 {"PC_12", TPM_PS_PC_12, TPM_PS_PC_12_URI}, 60 {"PDA_12", TPM_PS_PDA_12, TPM_PS_PDA_12_URI}, 61 {"SERVER_12", TPM_PS_Server_12, TPM_PS_Server_12_URI}, 62 {"MOBILE_12", TPM_PS_Mobile_12, TPM_PS_Mobile_12_URI}, 63 {NULL, 0, 0} 64}; 65 66 67void 68init_tcsd_config(struct tcsd_config *conf) 69{ 70 conf->port = -1; 71 conf->num_threads = -1; 72 conf->system_ps_file = NULL; 73 conf->system_ps_dir = NULL; 74 conf->firmware_log_file = NULL; 75 conf->firmware_pcrs = 0; 76 conf->kernel_log_file = NULL; 77 conf->kernel_pcrs = 0; 78 conf->platform_cred = NULL; 79 conf->conformance_cred = NULL; 80 conf->endorsement_cred = NULL; 81 memset(conf->remote_ops, 0, sizeof(conf->remote_ops)); 82 conf->unset = 0xffffffff; 83 conf->exclusive_transport = 0; 84 conf->host_platform_class = NULL; 85 conf->all_platform_classes = NULL; 86} 87 88TSS_RESULT 89platform_class_list_append(struct tcsd_config *conf, char *specName, TSS_BOOL is_main) 90{ 91 int i; 92 struct platform_class *tmp, *new_class; 93 94 LogDebugFn("platform_class_list_append start:"); 95 for (i = 0; tcg_platform_specs[i].name; i++) { 96 if (!strncasecmp(specName, tcg_platform_specs[i].name, 97 strlen(tcg_platform_specs[i].name))) { 98 /* Allocate the new structure */ 99 new_class = malloc(sizeof(struct platform_class)); 100 if (new_class == NULL) { 101 LogError("malloc of %zd bytes failed", 102 sizeof(struct platform_class)); 103 return TCSERR(TSS_E_OUTOFMEMORY); 104 } 105 new_class->simpleID = tcg_platform_specs[i].specNo; 106 new_class->classURISize = strlen(tcg_platform_specs[i].specURI) + 1; 107 new_class->classURI = malloc(new_class->classURISize); 108 if (new_class->classURI == NULL) { 109 LogError("malloc of %u bytes failed", new_class->classURISize); 110 return TCSERR(TSS_E_OUTOFMEMORY); 111 } 112 memcpy(new_class->classURI, tcg_platform_specs[i].specURI, 113 new_class->classURISize); 114 115 /* Append to the start of the list */ 116 if (is_main) { 117 tmp = conf->host_platform_class; 118 conf->host_platform_class = new_class; 119 } else { 120 tmp = conf->all_platform_classes; 121 conf->all_platform_classes = new_class; 122 } 123 new_class->next = tmp; 124 125 LogDebugFn("Platform Class Added."); 126 return TSS_SUCCESS; 127 } 128 } 129 130 LogError("TCG Specification not supported: \"%s\"", specName); 131 return TCSERR(TSS_E_INTERNAL_ERROR); 132} 133 134void 135config_set_defaults(struct tcsd_config *conf) 136{ 137 /* give all unset options their default values */ 138 if (conf->unset & TCSD_OPTION_PORT) 139 conf->port = TCSD_DEFAULT_PORT; 140 141 if (conf->unset & TCSD_OPTION_MAX_THREADS) 142 conf->num_threads = TCSD_DEFAULT_MAX_THREADS; 143 144 if (conf->unset & TCSD_OPTION_FIRMWARE_PCRS) 145 conf->firmware_pcrs = TCSD_DEFAULT_FIRMWARE_PCRS; 146 147 if (conf->unset & TCSD_OPTION_KERNEL_PCRS) 148 conf->kernel_pcrs = TCSD_DEFAULT_KERNEL_PCRS; 149 150 /* these are strdup'd so we know we can free them at shutdown time */ 151 if (conf->unset & TCSD_OPTION_SYSTEM_PSFILE) { 152 conf->system_ps_file = strdup(TCSD_DEFAULT_SYSTEM_PS_FILE); 153 conf->system_ps_dir = strdup(TCSD_DEFAULT_SYSTEM_PS_DIR); 154 } 155 156 if (conf->unset & TCSD_OPTION_FIRMWARE_LOGFILE) 157 conf->firmware_log_file = strdup(TCSD_DEFAULT_FIRMWARE_LOG_FILE); 158 159 if (conf->unset & TCSD_OPTION_KERNEL_LOGFILE) 160 conf->kernel_log_file = strdup(TCSD_DEFAULT_KERNEL_LOG_FILE); 161 162 if (conf->unset & TCSD_OPTION_HOST_PLATFORM_CLASS) 163 platform_class_list_append(conf, "PC_12", TRUE); 164} 165 166int 167get_config_option(char *ptr, char **arg) 168{ 169 int i; 170 171 for (i = 0; options_list[i].name; i++) { 172 if (!strncasecmp(ptr, options_list[i].name, strlen(options_list[i].name))) { 173 /* move ptr past our recognized token */ 174 ptr += strlen(options_list[i].name); 175 176 /* try to move ptr to the start of the option's argument */ 177 while (*ptr == '=' || *ptr == ' ' || *ptr == '\t') 178 ptr++; 179 180 *arg = ptr; 181 return options_list[i].option; 182 } 183 } 184 /* on error we'll print the whole line to the log */ 185 *arg = ptr; 186 return 0; 187} 188 189/* copy a file path from a string into a newly malloc'd string */ 190int 191get_file_path(char *ptr, char **dest) 192{ 193 char tmp_buf[1024]; 194 int i = 0; 195 196 while (isalpha((unsigned char)*ptr) || isdigit((unsigned char)*ptr) || 197 *ptr == '/' || *ptr == '.' || *ptr == '#' || *ptr == '_' || *ptr == '-') 198 { 199 tmp_buf[i] = *ptr; 200 ptr++; 201 i++; 202 } 203 204 /* move through whitespace after the path */ 205 while (*ptr == ' ' || *ptr == '\t') 206 ptr++; 207 208 /* if we're not at a comment or EOL, there's junk */ 209 if (*ptr != '#' && *ptr != '\n') { 210 *dest = ptr; 211 return 1; 212 } 213 214 /* too short a path */ 215 if (i == 0) 216 return -1; 217 218 tmp_buf[i] = '\0'; 219 *dest = strdup(tmp_buf); 220 if (*dest == NULL) { 221 LogError("malloc of %zd bytes failed", strlen(tmp_buf)); 222 } 223 224 return 0; 225} 226 227/* add an op ordinal, checking for duplicates along the way */ 228void 229tcsd_add_op(int *remote_ops, int *op) 230{ 231 int i = 0, j; 232 233 while (op[i] != 0) { 234 j = 0; 235 while (remote_ops[j] != 0) { 236 if (remote_ops[j] == op[i]) { 237 break; 238 } 239 j++; 240 } 241 remote_ops[j] = op[i]; 242 i++; 243 } 244} 245 246int 247tcsd_set_remote_op(struct tcsd_config *conf, char *op_name) 248{ 249 int i = 0; 250 251 while(tcsd_ops[i]) { 252 if (!strcasecmp(tcsd_ops[i]->name, op_name)) { 253 /* match found */ 254 tcsd_add_op(conf->remote_ops, tcsd_ops[i]->op); 255 return 0; 256 } 257 i++; 258 } 259 260 /* fail, op not found */ 261 return 1; 262} 263 264TSS_RESULT 265read_conf_line(char *buf, int line_num, struct tcsd_config *conf) 266{ 267 char *ptr = buf, *tmp_ptr = NULL, *arg, *comma; 268 int option, tmp_int; 269 TSS_RESULT result; 270 271 if (ptr == NULL || *ptr == '\0' || *ptr == '#' || *ptr == '\n') 272 return TSS_SUCCESS; 273 274 /* read through whitespace */ 275 while (*ptr == ' ' || *ptr == '\t') 276 ptr++; 277 278 /* ignore comments */ 279 if (*ptr == '#') 280 return TSS_SUCCESS; 281 282 option = get_config_option(ptr, &arg); 283 284 switch (option) { 285 case opt_port: 286 tmp_int = atoi(arg); 287 if (tmp_int < 0 || tmp_int > 65535) { 288 LogError("Config option \"port\" out of range. %s:%d: \"%d\"", 289 tcsd_config_file, line_num, tmp_int); 290 return TCSERR(TSS_E_INTERNAL_ERROR); 291 } else { 292 conf->port = tmp_int; 293 conf->unset &= ~TCSD_OPTION_PORT; 294 } 295 break; 296 case opt_max_threads: 297 tmp_int = atoi(arg); 298 if (tmp_int <= 0) { 299 LogError("Config option \"num_threads\" out of range. %s:%d: \"%d\"", 300 tcsd_config_file, line_num, tmp_int); 301 return TCSERR(TSS_E_INTERNAL_ERROR); 302 } else { 303 conf->num_threads = tmp_int; 304 conf->unset &= ~TCSD_OPTION_MAX_THREADS; 305 } 306 break; 307 case opt_firmware_pcrs: 308 conf->unset &= ~TCSD_OPTION_FIRMWARE_PCRS; 309 while (1) { 310 comma = rindex(arg, ','); 311 312 if (comma == NULL) { 313 if (!isdigit((unsigned char)*arg)) 314 break; 315 316 comma = arg; 317 tmp_int = atoi(comma); 318 if (tmp_int >= 0 && tmp_int < TCSD_MAX_PCRS) 319 conf->firmware_pcrs |= (1 << tmp_int); 320 else 321 LogError("Config option \"firmware_pcrs\" is out of range." 322 "%s:%d: \"%d\"", tcsd_config_file, line_num, 323 tmp_int); 324 break; 325 } 326 327 *comma++ = '\0'; 328 tmp_int = atoi(comma); 329 if (tmp_int >= 0 && tmp_int < TCSD_MAX_PCRS) 330 conf->firmware_pcrs |= (1 << tmp_int); 331 else 332 LogError("Config option \"firmware_pcrs\" is out of range. " 333 "%s:%d: \"%d\"", tcsd_config_file, line_num, tmp_int); 334 } 335 break; 336 case opt_kernel_pcrs: 337 conf->unset &= ~TCSD_OPTION_KERNEL_PCRS; 338 while (1) { 339 comma = rindex(arg, ','); 340 341 if (comma == NULL) { 342 if (!isdigit((unsigned char)*arg)) 343 break; 344 345 comma = arg; 346 tmp_int = atoi(comma); 347 if (tmp_int >= 0 && tmp_int < TCSD_MAX_PCRS) 348 conf->kernel_pcrs |= (1 << tmp_int); 349 else 350 LogError("Config option \"kernel_pcrs\" is out of range. " 351 "%s:%d: \"%d\"", tcsd_config_file, line_num, 352 tmp_int); 353 break; 354 } 355 356 *comma++ = '\0'; 357 tmp_int = atoi(comma); 358 if (tmp_int >= 0 && tmp_int < TCSD_MAX_PCRS) 359 conf->kernel_pcrs |= (1 << tmp_int); 360 else 361 LogError("Config option \"kernel_pcrs\" is out of range. " 362 "%s:%d: \"%d\"", tcsd_config_file, line_num, tmp_int); 363 } 364 break; 365 case opt_system_ps_file: 366 if (*arg != '/') { 367 LogError("Config option \"system_ps_dir\" must be an absolute path name. " 368 "%s:%d: \"%s\"", tcsd_config_file, line_num, arg); 369 } else { 370 char *dir_ptr; 371 int rc; 372 373 if ((rc = get_file_path(arg, &tmp_ptr)) < 0) { 374 LogError("Config option \"system_ps_file\" is invalid." 375 " %s:%d: \"%s\"", tcsd_config_file, line_num, arg); 376 return TCSERR(TSS_E_INTERNAL_ERROR); 377 } else if (rc > 0) { 378 LogError("Config option \"system_ps_file\" is invalid. %s:%d:" 379 " \"%s\"", tcsd_config_file, line_num, tmp_ptr); 380 return TCSERR(TSS_E_INTERNAL_ERROR); 381 } 382 if (tmp_ptr == NULL) 383 return TCSERR(TSS_E_OUTOFMEMORY); 384 385 if (conf->system_ps_file) 386 free(conf->system_ps_file); 387 if (conf->system_ps_dir) 388 free(conf->system_ps_dir); 389 390 /* break out the system ps directory from the file path */ 391 dir_ptr = rindex(tmp_ptr, '/'); 392 *dir_ptr = '\0'; 393 if (strlen(tmp_ptr) == 0) 394 conf->system_ps_dir = strdup("/"); 395 else 396 conf->system_ps_dir = strdup(tmp_ptr); 397 398 if (conf->system_ps_dir == NULL) { 399 LogError("malloc failed."); 400 free(tmp_ptr); 401 return TCSERR(TSS_E_OUTOFMEMORY); 402 } 403 *dir_ptr = '/'; 404 conf->system_ps_file = tmp_ptr; 405 conf->unset &= ~TCSD_OPTION_SYSTEM_PSFILE; 406 } 407 break; 408 case opt_kernel_log: 409 if (*arg != '/') { 410 LogError("Config option \"kernel_log\" must be an absolute path name." 411 " %s:%d: \"%s\"", tcsd_config_file, line_num, arg); 412 } else { 413 int rc; 414 415 if ((rc = get_file_path(arg, &tmp_ptr)) < 0) { 416 LogError("Config option \"kernel_log\" is invalid. %s:%d: \"%s\"", 417 tcsd_config_file, line_num, arg); 418 return TCSERR(TSS_E_INTERNAL_ERROR); 419 } else if (rc > 0) { 420 LogError("Config option \"kernel_log\" is invalid. %s:%d: \"%s\"", 421 tcsd_config_file, line_num, tmp_ptr); 422 return TCSERR(TSS_E_INTERNAL_ERROR); 423 } 424 if (tmp_ptr == NULL) 425 return TCSERR(TSS_E_OUTOFMEMORY); 426 427 if (conf->kernel_log_file) 428 free(conf->kernel_log_file); 429 430 conf->kernel_log_file = tmp_ptr; 431 conf->unset &= ~TCSD_OPTION_KERNEL_LOGFILE; 432 } 433 break; 434 case opt_firmware_log: 435 if (*arg != '/') { 436 LogError("Config option \"firmware_log\" must be an absolute path name." 437 " %s:%d: \"%s\"", tcsd_config_file, line_num, arg); 438 } else { 439 int rc; 440 441 if ((rc = get_file_path(arg, &tmp_ptr)) < 0) { 442 LogError("Config option \"firmware_log\" is invalid. %s:%d: \"%s\"", 443 tcsd_config_file, line_num, arg); 444 return TCSERR(TSS_E_INTERNAL_ERROR); 445 } else if (rc > 0) { 446 LogError("Config option \"firmware_log\" is invalid. %s:%d: \"%s\"", 447 tcsd_config_file, line_num, tmp_ptr); 448 return TCSERR(TSS_E_INTERNAL_ERROR); 449 } 450 if (tmp_ptr == NULL) 451 return TCSERR(TSS_E_OUTOFMEMORY); 452 453 if (conf->firmware_log_file) 454 free(conf->firmware_log_file); 455 456 conf->firmware_log_file = tmp_ptr; 457 conf->unset &= ~TCSD_OPTION_FIRMWARE_LOGFILE; 458 } 459 break; 460 case opt_platform_cred: 461 if (*arg != '/') { 462 LogError("Config option \"platform_cred\" must be an absolute path name. " 463 "%s:%d: \"%s\"", tcsd_config_file, line_num, arg); 464 } else { 465 int rc; 466 467 if ((rc = get_file_path(arg, &tmp_ptr)) < 0) { 468 LogError("Config option \"platform_cred\" is invalid. %s:%d: " 469 "\"%s\"", tcsd_config_file, line_num, arg); 470 return TCSERR(TSS_E_INTERNAL_ERROR); 471 } else if (rc > 0) { 472 LogError("Config option \"platform_cred\" is invalid. %s:%d: " 473 "\"%s\"", tcsd_config_file, line_num, tmp_ptr); 474 return TCSERR(TSS_E_INTERNAL_ERROR); 475 } 476 if (tmp_ptr == NULL) 477 return TCSERR(TSS_E_OUTOFMEMORY); 478 479 if (conf->platform_cred) 480 free(conf->platform_cred); 481 482 conf->platform_cred = tmp_ptr; 483 conf->unset &= ~TCSD_OPTION_PLATFORM_CRED; 484 } 485 break; 486 case opt_conformance_cred: 487 if (*arg != '/') { 488 LogError("Config option \"conformance_cred\" must be an absolute path name." 489 " %s:%d: \"%s\"", tcsd_config_file, line_num, arg); 490 } else { 491 int rc; 492 493 if ((rc = get_file_path(arg, &tmp_ptr)) < 0) { 494 LogError("Config option \"conformance_cred\" is invalid. %s:%d: " 495 "\"%s\"", tcsd_config_file, line_num, arg); 496 return TCSERR(TSS_E_INTERNAL_ERROR); 497 } else if (rc > 0) { 498 LogError("Config option \"conformance_cred\" is invalid. %s:%d: " 499 "\"%s\"", tcsd_config_file, line_num, tmp_ptr); 500 return TCSERR(TSS_E_INTERNAL_ERROR); 501 } 502 if (tmp_ptr == NULL) 503 return TCSERR(TSS_E_OUTOFMEMORY); 504 505 if (conf->conformance_cred) 506 free(conf->conformance_cred); 507 508 conf->conformance_cred = tmp_ptr; 509 conf->unset &= ~TCSD_OPTION_CONFORMANCE_CRED; 510 } 511 break; 512 case opt_endorsement_cred: 513 if (*arg != '/') { 514 LogError("Config option \"endorsement_cred\" must be an absolute path name." 515 " %s:%d: \"%s\"", tcsd_config_file, line_num, arg); 516 } else { 517 int rc; 518 519 if ((rc = get_file_path(arg, &tmp_ptr)) < 0) { 520 LogError("Config option \"endorsement_cred\" is invalid. %s:%d: " 521 "\"%s\"", tcsd_config_file, line_num, arg); 522 return TCSERR(TSS_E_INTERNAL_ERROR); 523 } else if (rc > 0) { 524 LogError("Config option \"endorsement_cred\" is invalid. %s:%d: " 525 "\"%s\"", tcsd_config_file, line_num, tmp_ptr); 526 return TCSERR(TSS_E_INTERNAL_ERROR); 527 } 528 if (tmp_ptr == NULL) 529 return TCSERR(TSS_E_OUTOFMEMORY); 530 531 if (conf->endorsement_cred) 532 free(conf->endorsement_cred); 533 534 conf->endorsement_cred = tmp_ptr; 535 conf->unset &= ~TCSD_OPTION_ENDORSEMENT_CRED; 536 } 537 break; 538 case opt_remote_ops: 539 conf->unset &= ~TCSD_OPTION_REMOTE_OPS; 540 comma = rindex(arg, '\n'); 541 *comma = '\0'; 542 while (1) { 543 comma = rindex(arg, ','); 544 545 if (comma == NULL) { 546 comma = arg; 547 548 if (comma != NULL) { 549 if (tcsd_set_remote_op(conf, comma)) { 550 LogError("Config option \"remote_ops\" is invalid. " 551 "%s:%d: \"%s\"", tcsd_config_file, 552 line_num, comma); 553 } 554 } 555 break; 556 } 557 558 *comma++ = '\0'; 559 if (tcsd_set_remote_op(conf, comma)) { 560 LogError("Config option \"remote_ops\" is invalid. " 561 "%s:%d: \"%s\"", tcsd_config_file, line_num, comma); 562 } 563 } 564 break; 565 case opt_exclusive_transport: 566 tmp_int = atoi(arg); 567 if (tmp_int < 0 || tmp_int > 1) { 568 LogError("Config option \"enforce_exclusive_transport\" out of range." 569 " %s:%d: \"%d\"", tcsd_config_file, line_num, tmp_int); 570 return TCSERR(TSS_E_INTERNAL_ERROR); 571 } else { 572 conf->exclusive_transport = tmp_int; 573 conf->unset &= ~TCSD_OPTION_EXCLUSIVE_TRANSPORT; 574 } 575 break; 576 case opt_host_platform_class: 577 /* append the host class on the list */ 578 conf->unset &= ~TCSD_OPTION_HOST_PLATFORM_CLASS; 579 comma = rindex(arg,'\n'); 580 *comma = '\0'; 581 582 comma = rindex(arg,','); 583 /* At least one comma: error - more than one host class defined */ 584 if (comma != NULL) { 585 LogError("Config option \"host_platform_class\" error: more than one " 586 "defined. %s:%d: \"%s\"", tcsd_config_file, line_num, comma); 587 return TCSERR(TSS_E_INTERNAL_ERROR); 588 } else { 589 comma = arg; 590 /* Add the platform class on the list */ 591 if ((result = platform_class_list_append(conf, comma, TRUE))){ 592 LogError("Config option \"host_platform_class\" invalid. " 593 "%s:%d: \"%s\"", tcsd_config_file, line_num, comma); 594 return result; 595 } 596 } 597 break; 598 case opt_all_platform_classes: 599 /* append each of the comma separated values on the list */ 600 comma = rindex(arg, '\n'); 601 *comma = '\0'; 602 while (1) { 603 comma = rindex(arg, ','); 604 605 if (comma == NULL) { 606 comma = arg; 607 608 if (comma != NULL) { 609 /* Add the platform class on the list */ 610 if ((result = platform_class_list_append(conf, comma, 611 FALSE))) { 612 LogError("Config option \"all_platform_class\" " 613 "invalid. %s:%d: \"%s\"", tcsd_config_file, 614 line_num, comma); 615 return result; 616 } 617 } 618 break; 619 } 620 *comma++ = '\0'; 621 /* Add the platform class on the list */ 622 if ((result = platform_class_list_append(conf, comma, FALSE))) { 623 LogError("Config option \"all_platform_class\" invalid. " 624 "%s:%d: \"%s\"", tcsd_config_file, line_num, comma); 625 return result; 626 } 627 } 628 break; 629 default: 630 /* bail out on any unknown option */ 631 LogError("Unknown config option %s:%d \"%s\"!", tcsd_config_file, line_num, arg); 632 return TCSERR(TSS_E_INTERNAL_ERROR); 633 } 634 635 return TSS_SUCCESS; 636} 637 638TSS_RESULT 639read_conf_file(FILE *f, struct tcsd_config *conf) 640{ 641 int line_num = 0; 642 char buf[1024]; 643 644 while (fgets(buf, 1024, f)) { 645 line_num++; 646 if (read_conf_line(buf, line_num, conf)) 647 return TCSERR(TSS_E_INTERNAL_ERROR); 648 } 649 650 return TSS_SUCCESS; 651} 652 653void 654free_platform_lists(struct platform_class *list) 655{ 656 struct platform_class *tmp; 657 658 while (list != NULL){ 659 if (list->classURISize > 0) 660 free(list->classURI); 661 tmp = list->next; 662 free(list); 663 list = tmp; 664 } 665} 666 667void 668conf_file_final(struct tcsd_config *conf) 669{ 670 free(conf->system_ps_file); 671 free(conf->system_ps_dir); 672 free(conf->kernel_log_file); 673 free(conf->firmware_log_file); 674 free(conf->platform_cred); 675 free(conf->conformance_cred); 676 free(conf->endorsement_cred); 677 free_platform_lists(conf->host_platform_class); 678 free_platform_lists(conf->all_platform_classes); 679} 680 681#ifdef SOLARIS 682static int 683get_smf_prop(const char *var, boolean_t def_val) 684{ 685 scf_simple_prop_t *prop; 686 uint8_t *val; 687 boolean_t res = def_val; 688 prop = scf_simple_prop_get(NULL, "svc:/application/security/tcsd:default", 689 "config", var); 690 if (prop) { 691 if ((val = scf_simple_prop_next_boolean(prop)) != NULL) 692 res = (*val == 0) ? B_FALSE : B_TRUE; 693 scf_simple_prop_free(prop); 694 } 695 if (prop == NULL || val == NULL) { 696 syslog(LOG_ALERT, "no value for config/%s (%s). " 697 "Using default \"%s\"", var, scf_strerror(scf_error()), 698 def_val ? "true" : "false"); 699 } 700 return (res); 701} 702#endif 703 704TSS_RESULT 705conf_file_init(struct tcsd_config *conf) 706{ 707 FILE *f = NULL; 708 struct stat stat_buf; 709#ifndef SOLARIS 710 struct group *grp; 711 struct passwd *pw; 712 mode_t mode = (S_IRUSR|S_IWUSR); 713#endif /* SOLARIS */ 714 TSS_RESULT result; 715 716 init_tcsd_config(conf); 717 718#ifdef SOLARIS 719 /* 720 * Solaris runs as Rajiv Andrade <srajiv@linux.vnet.:sys but with reduced privileges 721 * so we don't need to create a new user/group and also so 722 * we can have auditing support. The permissions on 723 * the tcsd configuration file are not checked on Solaris. 724 */ 725#endif 726 /* look for a config file, create if it doesn't exist */ 727 if (stat(tcsd_config_file, &stat_buf) == -1) { 728 if (errno == ENOENT) { 729 /* no config file? use defaults */ 730 config_set_defaults(conf); 731 LogInfo("Config file %s not found, using defaults.", tcsd_config_file); 732 return TSS_SUCCESS; 733 } else { 734 LogError("stat(%s): %s", tcsd_config_file, strerror(errno)); 735 return TCSERR(TSS_E_INTERNAL_ERROR); 736 } 737 } 738 739#ifndef SOLARIS 740 /* find the gid that owns the conf file */ 741 errno = 0; 742 grp = getgrnam(TSS_GROUP_NAME); 743 if (grp == NULL) { 744 if (errno == 0) { 745 LogError("Group \"%s\" not found, please add this group" 746 " manually.", TSS_GROUP_NAME); 747 } else { 748 LogError("getgrnam(%s): %s", TSS_GROUP_NAME, strerror(errno)); 749 } 750 return TCSERR(TSS_E_INTERNAL_ERROR); 751 } 752 753 errno = 0; 754 pw = getpwnam(TSS_USER_NAME); 755 if (pw == NULL) { 756 if (errno == 0) { 757 LogError("User \"%s\" not found, please add this user" 758 " manually.", TSS_USER_NAME); 759 } else { 760 LogError("getpwnam(%s): %s", TSS_USER_NAME, strerror(errno)); 761 } 762 return TCSERR(TSS_E_INTERNAL_ERROR); 763 } 764 765 /* make sure user/group TSS owns the conf file */ 766 if (pw->pw_uid != stat_buf.st_uid || grp->gr_gid != stat_buf.st_gid) { 767 LogError("TCSD config file (%s) must be user/group %s/%s", tcsd_config_file, 768 TSS_USER_NAME, TSS_GROUP_NAME); 769 return TCSERR(TSS_E_INTERNAL_ERROR); 770 } 771 772 /* make sure only the tss user can manipulate the config file */ 773 if (((stat_buf.st_mode & 0777) ^ mode) != 0) { 774 LogError("TCSD config file (%s) must be mode 0600", tcsd_config_file); 775 return TCSERR(TSS_E_INTERNAL_ERROR); 776 } 777#endif /* SOLARIS */ 778 779 if ((f = fopen(tcsd_config_file, "r")) == NULL) { 780 LogError("fopen(%s): %s", tcsd_config_file, strerror(errno)); 781 return TCSERR(TSS_E_INTERNAL_ERROR); 782 } 783 784 result = read_conf_file(f, conf); 785 fclose(f); 786 787 /* fill out any uninitialized options */ 788 config_set_defaults(conf); 789 790#ifdef SOLARIS 791 /* 792 * The SMF value for "local_only" overrides the config file and 793 * disables all remote operations. 794 */ 795if (get_smf_prop("local_only", B_TRUE)) { 796 (void) memset(conf->remote_ops, 0, sizeof(conf->remote_ops)); 797 conf->unset |= TCSD_OPTION_REMOTE_OPS; 798 799 } 800#endif 801 return result; 802} 803 804TSS_RESULT 805ps_dirs_init() 806{ 807 struct stat stat_buf; 808 mode_t mode = S_IRWXU; /* 0700 */ 809 810 /* query the key storage directory to make sure it exists and is of the right mode */ 811 if (stat(tcsd_options.system_ps_dir, &stat_buf) == -1) { 812 if (errno == ENOENT) { 813 /* The dir DNE, create it with mode drwxrwxrwt */ 814 if (mkdir(tcsd_options.system_ps_dir, mode) == -1) { 815 LogError("mkdir(%s) failed: %s. If you'd like to use %s to " 816 "store your system persistent data, please" 817 " create it. Otherwise, change the location" 818 " in your tcsd config file.", 819 tcsd_options.system_ps_dir, strerror(errno), 820 tcsd_options.system_ps_dir); 821 return TCSERR(TSS_E_INTERNAL_ERROR); 822 } 823 } else { 824 LogError("stat failed: %s", strerror(errno)); 825 return TCSERR(TSS_E_INTERNAL_ERROR); 826 } 827 } 828 829 /* stat should not fail now */ 830 if (stat(tcsd_options.system_ps_dir, &stat_buf) == -1) { 831 LogError("stat %s failed: %s", tcsd_options.system_ps_dir, strerror(errno)); 832 return TCSERR(TSS_E_INTERNAL_ERROR); 833 } 834 835 /* tcsd_options.system_ps_dir should be a directory with mode equal to mode */ 836 if (!S_ISDIR(stat_buf.st_mode)) { 837 LogError("PS dir %s is not a directory! Exiting.", tcsd_options.system_ps_dir); 838 return TCSERR(TSS_E_INTERNAL_ERROR); 839 } else if (((stat_buf.st_mode & 0777) ^ mode) != 0) { 840 /* This path is likely to be hit since open &'s mode with ~umask */ 841 LogInfo("resetting mode of %s from %o to: %o", tcsd_options.system_ps_dir, 842 (unsigned int) stat_buf.st_mode, (unsigned int) mode); 843 if (chmod(tcsd_options.system_ps_dir, mode) == -1) { 844 LogError("chmod(%s) failed: %s", tcsd_options.system_ps_dir, 845 strerror(errno)); 846 return TCSERR(TSS_E_INTERNAL_ERROR); 847 } 848 } 849 850 return TSS_SUCCESS; 851} 852 853