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