summaryrefslogtreecommitdiff
path: root/src/tcsd/tcsd_conf.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
commitc3649a2def02c41d837ae1f79dda729ccb91e677 (patch)
treebea46dff212fdef977fe9094a70a939e8cc21885 /src/tcsd/tcsd_conf.c
downloadtrousers-upstream/0.3.9.tar.gz
Imported Upstream version 0.3.9upstream/0.3.9upstream
Diffstat (limited to 'src/tcsd/tcsd_conf.c')
-rw-r--r--src/tcsd/tcsd_conf.c852
1 files changed, 852 insertions, 0 deletions
diff --git a/src/tcsd/tcsd_conf.c b/src/tcsd/tcsd_conf.c
new file mode 100644
index 0000000..afc1dcb
--- /dev/null
+++ b/src/tcsd/tcsd_conf.c
@@ -0,0 +1,852 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2004
+ *
+ */
+
+
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <grp.h>
+#include <stdlib.h>
+
+#ifdef SOLARIS
+#include <libscf.h>
+#endif
+
+#include "trousers/tss.h"
+#include "trousers_types.h"
+#include "tcs_tsp.h"
+#include "tcs_utils.h"
+#include "tcsps.h"
+#include "tcslog.h"
+#include "tcsd_wrap.h"
+#include "tcsd.h"
+#include "tcsd_ops.h"
+
+
+struct tcsd_config_options options_list[] = {
+ {"port", opt_port},
+ {"num_threads", opt_max_threads},
+ {"system_ps_file", opt_system_ps_file},
+ {"firmware_log_file", opt_firmware_log},
+ {"firmware_pcrs", opt_firmware_pcrs},
+ {"kernel_log_file", opt_kernel_log},
+ {"kernel_pcrs", opt_kernel_pcrs},
+ {"platform_cred", opt_platform_cred},
+ {"conformance_cred", opt_conformance_cred},
+ {"endorsement_cred", opt_endorsement_cred},
+ {"remote_ops", opt_remote_ops},
+ {"enforce_exclusive_transport", opt_exclusive_transport},
+ {"host_platform_class", opt_host_platform_class},
+ {"all_platform_classes", opt_all_platform_classes},
+ {NULL, 0}
+};
+
+struct tcg_platform_spec tcg_platform_specs[] = {
+ {"PC_11", TPM_PS_PC_11, TPM_PS_PC_11_URI},
+ {"PC_12", TPM_PS_PC_12, TPM_PS_PC_12_URI},
+ {"PDA_12", TPM_PS_PDA_12, TPM_PS_PDA_12_URI},
+ {"SERVER_12", TPM_PS_Server_12, TPM_PS_Server_12_URI},
+ {"MOBILE_12", TPM_PS_Mobile_12, TPM_PS_Mobile_12_URI},
+ {NULL, 0, 0}
+};
+
+
+void
+init_tcsd_config(struct tcsd_config *conf)
+{
+ conf->port = -1;
+ conf->num_threads = -1;
+ conf->system_ps_file = NULL;
+ conf->system_ps_dir = NULL;
+ conf->firmware_log_file = NULL;
+ conf->firmware_pcrs = 0;
+ conf->kernel_log_file = NULL;
+ conf->kernel_pcrs = 0;
+ conf->platform_cred = NULL;
+ conf->conformance_cred = NULL;
+ conf->endorsement_cred = NULL;
+ memset(conf->remote_ops, 0, sizeof(conf->remote_ops));
+ conf->unset = 0xffffffff;
+ conf->exclusive_transport = 0;
+ conf->host_platform_class = NULL;
+ conf->all_platform_classes = NULL;
+}
+
+TSS_RESULT
+platform_class_list_append(struct tcsd_config *conf, char *specName, TSS_BOOL is_main)
+{
+ int i;
+ struct platform_class *tmp, *new_class;
+
+ LogDebugFn("platform_class_list_append start:");
+ for (i = 0; tcg_platform_specs[i].name; i++) {
+ if (!strncasecmp(specName, tcg_platform_specs[i].name,
+ strlen(tcg_platform_specs[i].name))) {
+ /* Allocate the new structure */
+ new_class = malloc(sizeof(struct platform_class));
+ if (new_class == NULL) {
+ LogError("malloc of %zd bytes failed",
+ sizeof(struct platform_class));
+ return TCSERR(TSS_E_OUTOFMEMORY);
+ }
+ new_class->simpleID = tcg_platform_specs[i].specNo;
+ new_class->classURISize = strlen(tcg_platform_specs[i].specURI) + 1;
+ new_class->classURI = malloc(new_class->classURISize);
+ if (new_class->classURI == NULL) {
+ LogError("malloc of %u bytes failed", new_class->classURISize);
+ return TCSERR(TSS_E_OUTOFMEMORY);
+ }
+ memcpy(new_class->classURI, tcg_platform_specs[i].specURI,
+ new_class->classURISize);
+
+ /* Append to the start of the list */
+ if (is_main) {
+ tmp = conf->host_platform_class;
+ conf->host_platform_class = new_class;
+ } else {
+ tmp = conf->all_platform_classes;
+ conf->all_platform_classes = new_class;
+ }
+ new_class->next = tmp;
+
+ LogDebugFn("Platform Class Added.");
+ return TSS_SUCCESS;
+ }
+ }
+
+ LogError("TCG Specification not supported: \"%s\"", specName);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+}
+
+void
+config_set_defaults(struct tcsd_config *conf)
+{
+ /* give all unset options their default values */
+ if (conf->unset & TCSD_OPTION_PORT)
+ conf->port = TCSD_DEFAULT_PORT;
+
+ if (conf->unset & TCSD_OPTION_MAX_THREADS)
+ conf->num_threads = TCSD_DEFAULT_MAX_THREADS;
+
+ if (conf->unset & TCSD_OPTION_FIRMWARE_PCRS)
+ conf->firmware_pcrs = TCSD_DEFAULT_FIRMWARE_PCRS;
+
+ if (conf->unset & TCSD_OPTION_KERNEL_PCRS)
+ conf->kernel_pcrs = TCSD_DEFAULT_KERNEL_PCRS;
+
+ /* these are strdup'd so we know we can free them at shutdown time */
+ if (conf->unset & TCSD_OPTION_SYSTEM_PSFILE) {
+ conf->system_ps_file = strdup(TCSD_DEFAULT_SYSTEM_PS_FILE);
+ conf->system_ps_dir = strdup(TCSD_DEFAULT_SYSTEM_PS_DIR);
+ }
+
+ if (conf->unset & TCSD_OPTION_FIRMWARE_LOGFILE)
+ conf->firmware_log_file = strdup(TCSD_DEFAULT_FIRMWARE_LOG_FILE);
+
+ if (conf->unset & TCSD_OPTION_KERNEL_LOGFILE)
+ conf->kernel_log_file = strdup(TCSD_DEFAULT_KERNEL_LOG_FILE);
+
+ if (conf->unset & TCSD_OPTION_HOST_PLATFORM_CLASS)
+ platform_class_list_append(conf, "PC_12", TRUE);
+}
+
+int
+get_config_option(char *ptr, char **arg)
+{
+ int i;
+
+ for (i = 0; options_list[i].name; i++) {
+ if (!strncasecmp(ptr, options_list[i].name, strlen(options_list[i].name))) {
+ /* move ptr past our recognized token */
+ ptr += strlen(options_list[i].name);
+
+ /* try to move ptr to the start of the option's argument */
+ while (*ptr == '=' || *ptr == ' ' || *ptr == '\t')
+ ptr++;
+
+ *arg = ptr;
+ return options_list[i].option;
+ }
+ }
+ /* on error we'll print the whole line to the log */
+ *arg = ptr;
+ return 0;
+}
+
+/* copy a file path from a string into a newly malloc'd string */
+int
+get_file_path(char *ptr, char **dest)
+{
+ char tmp_buf[1024];
+ int i = 0;
+
+ while (isalpha(*ptr) || isdigit(*ptr) ||
+ *ptr == '/' || *ptr == '.' || *ptr == '#' || *ptr == '_' || *ptr == '-')
+ {
+ tmp_buf[i] = *ptr;
+ ptr++;
+ i++;
+ }
+
+ /* move through whitespace after the path */
+ while (*ptr == ' ' || *ptr == '\t')
+ ptr++;
+
+ /* if we're not at a comment or EOL, there's junk */
+ if (*ptr != '#' && *ptr != '\n') {
+ *dest = ptr;
+ return 1;
+ }
+
+ /* too short a path */
+ if (i == 0)
+ return -1;
+
+ tmp_buf[i] = '\0';
+ *dest = strdup(tmp_buf);
+ if (*dest == NULL) {
+ LogError("malloc of %zd bytes failed", strlen(tmp_buf));
+ }
+
+ return 0;
+}
+
+/* add an op ordinal, checking for duplicates along the way */
+void
+tcsd_add_op(int *remote_ops, int *op)
+{
+ int i = 0, j;
+
+ while (op[i] != 0) {
+ j = 0;
+ while (remote_ops[j] != 0) {
+ if (remote_ops[j] == op[i]) {
+ break;
+ }
+ j++;
+ }
+ remote_ops[j] = op[i];
+ i++;
+ }
+}
+
+int
+tcsd_set_remote_op(struct tcsd_config *conf, char *op_name)
+{
+ int i = 0;
+
+ while(tcsd_ops[i]) {
+ if (!strcasecmp(tcsd_ops[i]->name, op_name)) {
+ /* match found */
+ tcsd_add_op(conf->remote_ops, tcsd_ops[i]->op);
+ return 0;
+ }
+ i++;
+ }
+
+ /* fail, op not found */
+ return 1;
+}
+
+TSS_RESULT
+read_conf_line(char *buf, int line_num, struct tcsd_config *conf)
+{
+ char *ptr = buf, *tmp_ptr = NULL, *arg, *comma;
+ int option, tmp_int;
+ TSS_RESULT result;
+
+ if (ptr == NULL || *ptr == '\0' || *ptr == '#' || *ptr == '\n')
+ return TSS_SUCCESS;
+
+ /* read through whitespace */
+ while (*ptr == ' ' || *ptr == '\t')
+ ptr++;
+
+ /* ignore comments */
+ if (*ptr == '#')
+ return TSS_SUCCESS;
+
+ option = get_config_option(ptr, &arg);
+
+ switch (option) {
+ case opt_port:
+ tmp_int = atoi(arg);
+ if (tmp_int < 0 || tmp_int > 65535) {
+ LogError("Config option \"port\" out of range. %s:%d: \"%d\"",
+ tcsd_config_file, line_num, tmp_int);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else {
+ conf->port = tmp_int;
+ conf->unset &= ~TCSD_OPTION_PORT;
+ }
+ break;
+ case opt_max_threads:
+ tmp_int = atoi(arg);
+ if (tmp_int <= 0) {
+ LogError("Config option \"num_threads\" out of range. %s:%d: \"%d\"",
+ tcsd_config_file, line_num, tmp_int);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else {
+ conf->num_threads = tmp_int;
+ conf->unset &= ~TCSD_OPTION_MAX_THREADS;
+ }
+ break;
+ case opt_firmware_pcrs:
+ conf->unset &= ~TCSD_OPTION_FIRMWARE_PCRS;
+ while (1) {
+ comma = rindex(arg, ',');
+
+ if (comma == NULL) {
+ if (!isdigit(*arg))
+ break;
+
+ comma = arg;
+ tmp_int = atoi(comma);
+ if (tmp_int >= 0 && tmp_int < TCSD_MAX_PCRS)
+ conf->firmware_pcrs |= (1 << tmp_int);
+ else
+ LogError("Config option \"firmware_pcrs\" is out of range."
+ "%s:%d: \"%d\"", tcsd_config_file, line_num,
+ tmp_int);
+ break;
+ }
+
+ *comma++ = '\0';
+ tmp_int = atoi(comma);
+ if (tmp_int >= 0 && tmp_int < TCSD_MAX_PCRS)
+ conf->firmware_pcrs |= (1 << tmp_int);
+ else
+ LogError("Config option \"firmware_pcrs\" is out of range. "
+ "%s:%d: \"%d\"", tcsd_config_file, line_num, tmp_int);
+ }
+ break;
+ case opt_kernel_pcrs:
+ conf->unset &= ~TCSD_OPTION_KERNEL_PCRS;
+ while (1) {
+ comma = rindex(arg, ',');
+
+ if (comma == NULL) {
+ if (!isdigit(*arg))
+ break;
+
+ comma = arg;
+ tmp_int = atoi(comma);
+ if (tmp_int >= 0 && tmp_int < TCSD_MAX_PCRS)
+ conf->kernel_pcrs |= (1 << tmp_int);
+ else
+ LogError("Config option \"kernel_pcrs\" is out of range. "
+ "%s:%d: \"%d\"", tcsd_config_file, line_num,
+ tmp_int);
+ break;
+ }
+
+ *comma++ = '\0';
+ tmp_int = atoi(comma);
+ if (tmp_int >= 0 && tmp_int < TCSD_MAX_PCRS)
+ conf->kernel_pcrs |= (1 << tmp_int);
+ else
+ LogError("Config option \"kernel_pcrs\" is out of range. "
+ "%s:%d: \"%d\"", tcsd_config_file, line_num, tmp_int);
+ }
+ break;
+ case opt_system_ps_file:
+ if (*arg != '/') {
+ LogError("Config option \"system_ps_dir\" must be an absolute path name. "
+ "%s:%d: \"%s\"", tcsd_config_file, line_num, arg);
+ } else {
+ char *dir_ptr;
+ int rc;
+
+ if ((rc = get_file_path(arg, &tmp_ptr)) < 0) {
+ LogError("Config option \"system_ps_file\" is invalid."
+ " %s:%d: \"%s\"", tcsd_config_file, line_num, arg);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else if (rc > 0) {
+ LogError("Config option \"system_ps_file\" is invalid. %s:%d:"
+ " \"%s\"", tcsd_config_file, line_num, tmp_ptr);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ if (tmp_ptr == NULL)
+ return TCSERR(TSS_E_OUTOFMEMORY);
+
+ if (conf->system_ps_file)
+ free(conf->system_ps_file);
+ if (conf->system_ps_dir)
+ free(conf->system_ps_dir);
+
+ /* break out the system ps directory from the file path */
+ dir_ptr = rindex(tmp_ptr, '/');
+ *dir_ptr = '\0';
+ if (strlen(tmp_ptr) == 0)
+ conf->system_ps_dir = strdup("/");
+ else
+ conf->system_ps_dir = strdup(tmp_ptr);
+
+ if (conf->system_ps_dir == NULL) {
+ LogError("malloc failed.");
+ free(tmp_ptr);
+ return TCSERR(TSS_E_OUTOFMEMORY);
+ }
+ *dir_ptr = '/';
+ conf->system_ps_file = tmp_ptr;
+ conf->unset &= ~TCSD_OPTION_SYSTEM_PSFILE;
+ }
+ break;
+ case opt_kernel_log:
+ if (*arg != '/') {
+ LogError("Config option \"kernel_log\" must be an absolute path name."
+ " %s:%d: \"%s\"", tcsd_config_file, line_num, arg);
+ } else {
+ int rc;
+
+ if ((rc = get_file_path(arg, &tmp_ptr)) < 0) {
+ LogError("Config option \"kernel_log\" is invalid. %s:%d: \"%s\"",
+ tcsd_config_file, line_num, arg);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else if (rc > 0) {
+ LogError("Config option \"kernel_log\" is invalid. %s:%d: \"%s\"",
+ tcsd_config_file, line_num, tmp_ptr);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ if (tmp_ptr == NULL)
+ return TCSERR(TSS_E_OUTOFMEMORY);
+
+ if (conf->kernel_log_file)
+ free(conf->kernel_log_file);
+
+ conf->kernel_log_file = tmp_ptr;
+ conf->unset &= ~TCSD_OPTION_KERNEL_LOGFILE;
+ }
+ break;
+ case opt_firmware_log:
+ if (*arg != '/') {
+ LogError("Config option \"firmware_log\" must be an absolute path name."
+ " %s:%d: \"%s\"", tcsd_config_file, line_num, arg);
+ } else {
+ int rc;
+
+ if ((rc = get_file_path(arg, &tmp_ptr)) < 0) {
+ LogError("Config option \"firmware_log\" is invalid. %s:%d: \"%s\"",
+ tcsd_config_file, line_num, arg);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else if (rc > 0) {
+ LogError("Config option \"firmware_log\" is invalid. %s:%d: \"%s\"",
+ tcsd_config_file, line_num, tmp_ptr);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ if (tmp_ptr == NULL)
+ return TCSERR(TSS_E_OUTOFMEMORY);
+
+ if (conf->firmware_log_file)
+ free(conf->firmware_log_file);
+
+ conf->firmware_log_file = tmp_ptr;
+ conf->unset &= ~TCSD_OPTION_FIRMWARE_LOGFILE;
+ }
+ break;
+ case opt_platform_cred:
+ if (*arg != '/') {
+ LogError("Config option \"platform_cred\" must be an absolute path name. "
+ "%s:%d: \"%s\"", tcsd_config_file, line_num, arg);
+ } else {
+ int rc;
+
+ if ((rc = get_file_path(arg, &tmp_ptr)) < 0) {
+ LogError("Config option \"platform_cred\" is invalid. %s:%d: "
+ "\"%s\"", tcsd_config_file, line_num, arg);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else if (rc > 0) {
+ LogError("Config option \"platform_cred\" is invalid. %s:%d: "
+ "\"%s\"", tcsd_config_file, line_num, tmp_ptr);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ if (tmp_ptr == NULL)
+ return TCSERR(TSS_E_OUTOFMEMORY);
+
+ if (conf->platform_cred)
+ free(conf->platform_cred);
+
+ conf->platform_cred = tmp_ptr;
+ conf->unset &= ~TCSD_OPTION_PLATFORM_CRED;
+ }
+ break;
+ case opt_conformance_cred:
+ if (*arg != '/') {
+ LogError("Config option \"conformance_cred\" must be an absolute path name."
+ " %s:%d: \"%s\"", tcsd_config_file, line_num, arg);
+ } else {
+ int rc;
+
+ if ((rc = get_file_path(arg, &tmp_ptr)) < 0) {
+ LogError("Config option \"conformance_cred\" is invalid. %s:%d: "
+ "\"%s\"", tcsd_config_file, line_num, arg);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else if (rc > 0) {
+ LogError("Config option \"conformance_cred\" is invalid. %s:%d: "
+ "\"%s\"", tcsd_config_file, line_num, tmp_ptr);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ if (tmp_ptr == NULL)
+ return TCSERR(TSS_E_OUTOFMEMORY);
+
+ if (conf->conformance_cred)
+ free(conf->conformance_cred);
+
+ conf->conformance_cred = tmp_ptr;
+ conf->unset &= ~TCSD_OPTION_CONFORMANCE_CRED;
+ }
+ break;
+ case opt_endorsement_cred:
+ if (*arg != '/') {
+ LogError("Config option \"endorsement_cred\" must be an absolute path name."
+ " %s:%d: \"%s\"", tcsd_config_file, line_num, arg);
+ } else {
+ int rc;
+
+ if ((rc = get_file_path(arg, &tmp_ptr)) < 0) {
+ LogError("Config option \"endorsement_cred\" is invalid. %s:%d: "
+ "\"%s\"", tcsd_config_file, line_num, arg);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else if (rc > 0) {
+ LogError("Config option \"endorsement_cred\" is invalid. %s:%d: "
+ "\"%s\"", tcsd_config_file, line_num, tmp_ptr);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ if (tmp_ptr == NULL)
+ return TCSERR(TSS_E_OUTOFMEMORY);
+
+ if (conf->endorsement_cred)
+ free(conf->endorsement_cred);
+
+ conf->endorsement_cred = tmp_ptr;
+ conf->unset &= ~TCSD_OPTION_ENDORSEMENT_CRED;
+ }
+ break;
+ case opt_remote_ops:
+ conf->unset &= ~TCSD_OPTION_REMOTE_OPS;
+ comma = rindex(arg, '\n');
+ *comma = '\0';
+ while (1) {
+ comma = rindex(arg, ',');
+
+ if (comma == NULL) {
+ comma = arg;
+
+ if (comma != NULL) {
+ if (tcsd_set_remote_op(conf, comma)) {
+ LogError("Config option \"remote_ops\" is invalid. "
+ "%s:%d: \"%s\"", tcsd_config_file,
+ line_num, comma);
+ }
+ }
+ break;
+ }
+
+ *comma++ = '\0';
+ if (tcsd_set_remote_op(conf, comma)) {
+ LogError("Config option \"remote_ops\" is invalid. "
+ "%s:%d: \"%s\"", tcsd_config_file, line_num, comma);
+ }
+ }
+ break;
+ case opt_exclusive_transport:
+ tmp_int = atoi(arg);
+ if (tmp_int < 0 || tmp_int > 1) {
+ LogError("Config option \"enforce_exclusive_transport\" out of range."
+ " %s:%d: \"%d\"", tcsd_config_file, line_num, tmp_int);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else {
+ conf->exclusive_transport = tmp_int;
+ conf->unset &= ~TCSD_OPTION_EXCLUSIVE_TRANSPORT;
+ }
+ break;
+ case opt_host_platform_class:
+ /* append the host class on the list */
+ conf->unset &= ~TCSD_OPTION_HOST_PLATFORM_CLASS;
+ comma = rindex(arg,'\n');
+ *comma = '\0';
+
+ comma = rindex(arg,',');
+ /* At least one comma: error - more than one host class defined */
+ if (comma != NULL) {
+ LogError("Config option \"host_platform_class\" error: more than one "
+ "defined. %s:%d: \"%s\"", tcsd_config_file, line_num, comma);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else {
+ comma = arg;
+ /* Add the platform class on the list */
+ if ((result = platform_class_list_append(conf, comma, TRUE))){
+ LogError("Config option \"host_platform_class\" invalid. "
+ "%s:%d: \"%s\"", tcsd_config_file, line_num, comma);
+ return result;
+ }
+ }
+ break;
+ case opt_all_platform_classes:
+ /* append each of the comma separated values on the list */
+ comma = rindex(arg, '\n');
+ *comma = '\0';
+ while (1) {
+ comma = rindex(arg, ',');
+
+ if (comma == NULL) {
+ comma = arg;
+
+ if (comma != NULL) {
+ /* Add the platform class on the list */
+ if ((result = platform_class_list_append(conf, comma,
+ FALSE))) {
+ LogError("Config option \"all_platform_class\" "
+ "invalid. %s:%d: \"%s\"", tcsd_config_file,
+ line_num, comma);
+ return result;
+ }
+ }
+ break;
+ }
+ *comma++ = '\0';
+ /* Add the platform class on the list */
+ if ((result = platform_class_list_append(conf, comma, FALSE))) {
+ LogError("Config option \"all_platform_class\" invalid. "
+ "%s:%d: \"%s\"", tcsd_config_file, line_num, comma);
+ return result;
+ }
+ }
+ break;
+ default:
+ /* bail out on any unknown option */
+ LogError("Unknown config option %s:%d \"%s\"!", tcsd_config_file, line_num, arg);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+read_conf_file(FILE *f, struct tcsd_config *conf)
+{
+ int line_num = 0;
+ char buf[1024];
+
+ while (fgets(buf, 1024, f)) {
+ line_num++;
+ if (read_conf_line(buf, line_num, conf))
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ return TSS_SUCCESS;
+}
+
+void
+free_platform_lists(struct platform_class *list)
+{
+ struct platform_class *tmp;
+
+ while (list != NULL){
+ if (list->classURISize > 0)
+ free(list->classURI);
+ tmp = list->next;
+ free(list);
+ list = tmp;
+ }
+}
+
+void
+conf_file_final(struct tcsd_config *conf)
+{
+ free(conf->system_ps_file);
+ free(conf->system_ps_dir);
+ free(conf->kernel_log_file);
+ free(conf->firmware_log_file);
+ free(conf->platform_cred);
+ free(conf->conformance_cred);
+ free(conf->endorsement_cred);
+ free_platform_lists(conf->host_platform_class);
+ free_platform_lists(conf->all_platform_classes);
+}
+
+#ifdef SOLARIS
+static int
+get_smf_prop(const char *var, boolean_t def_val)
+{
+ scf_simple_prop_t *prop;
+ uint8_t *val;
+ boolean_t res = def_val;
+ prop = scf_simple_prop_get(NULL, "svc:/application/security/tcsd:default",
+ "config", var);
+ if (prop) {
+ if ((val = scf_simple_prop_next_boolean(prop)) != NULL)
+ res = (*val == 0) ? B_FALSE : B_TRUE;
+ scf_simple_prop_free(prop);
+ }
+ if (prop == NULL || val == NULL) {
+ syslog(LOG_ALERT, "no value for config/%s (%s). "
+ "Using default \"%s\"", var, scf_strerror(scf_error()),
+ def_val ? "true" : "false");
+ }
+ return (res);
+}
+#endif
+
+TSS_RESULT
+conf_file_init(struct tcsd_config *conf)
+{
+ FILE *f = NULL;
+ struct stat stat_buf;
+#ifndef SOLARIS
+ struct group *grp;
+ struct passwd *pw;
+ mode_t mode = (S_IRUSR|S_IWUSR);
+#endif /* SOLARIS */
+ TSS_RESULT result;
+
+ init_tcsd_config(conf);
+
+#ifdef SOLARIS
+ /*
+ * Solaris runs as Rajiv Andrade <srajiv@linux.vnet.:sys but with reduced privileges
+ * so we don't need to create a new user/group and also so
+ * we can have auditing support. The permissions on
+ * the tcsd configuration file are not checked on Solaris.
+ */
+#endif
+ /* look for a config file, create if it doesn't exist */
+ if (stat(tcsd_config_file, &stat_buf) == -1) {
+ if (errno == ENOENT) {
+ /* no config file? use defaults */
+ config_set_defaults(conf);
+ LogInfo("Config file %s not found, using defaults.", tcsd_config_file);
+ return TSS_SUCCESS;
+ } else {
+ LogError("stat(%s): %s", tcsd_config_file, strerror(errno));
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ }
+
+#ifndef SOLARIS
+ /* find the gid that owns the conf file */
+ errno = 0;
+ grp = getgrnam(TSS_GROUP_NAME);
+ if (grp == NULL) {
+ if (errno == 0) {
+ LogError("Group \"%s\" not found, please add this group"
+ " manually.", TSS_GROUP_NAME);
+ } else {
+ LogError("getgrnam(%s): %s", TSS_GROUP_NAME, strerror(errno));
+ }
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ errno = 0;
+ pw = getpwnam(TSS_USER_NAME);
+ if (pw == NULL) {
+ if (errno == 0) {
+ LogError("User \"%s\" not found, please add this user"
+ " manually.", TSS_USER_NAME);
+ } else {
+ LogError("getpwnam(%s): %s", TSS_USER_NAME, strerror(errno));
+ }
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ /* make sure user/group TSS owns the conf file */
+ if (pw->pw_uid != stat_buf.st_uid || grp->gr_gid != stat_buf.st_gid) {
+ LogError("TCSD config file (%s) must be user/group %s/%s", tcsd_config_file,
+ TSS_USER_NAME, TSS_GROUP_NAME);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ /* make sure only the tss user can manipulate the config file */
+ if (((stat_buf.st_mode & 0777) ^ mode) != 0) {
+ LogError("TCSD config file (%s) must be mode 0600", tcsd_config_file);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+#endif /* SOLARIS */
+
+ if ((f = fopen(tcsd_config_file, "r")) == NULL) {
+ LogError("fopen(%s): %s", tcsd_config_file, strerror(errno));
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ result = read_conf_file(f, conf);
+ fclose(f);
+
+ /* fill out any uninitialized options */
+ config_set_defaults(conf);
+
+#ifdef SOLARIS
+ /*
+ * The SMF value for "local_only" overrides the config file and
+ * disables all remote operations.
+ */
+if (get_smf_prop("local_only", B_TRUE)) {
+ (void) memset(conf->remote_ops, 0, sizeof(conf->remote_ops));
+ conf->unset |= TCSD_OPTION_REMOTE_OPS;
+
+ }
+#endif
+ return result;
+}
+
+TSS_RESULT
+ps_dirs_init()
+{
+ struct stat stat_buf;
+ mode_t mode = S_IRWXU; /* 0700 */
+
+ /* query the key storage directory to make sure it exists and is of the right mode */
+ if (stat(tcsd_options.system_ps_dir, &stat_buf) == -1) {
+ if (errno == ENOENT) {
+ /* The dir DNE, create it with mode drwxrwxrwt */
+ if (mkdir(tcsd_options.system_ps_dir, mode) == -1) {
+ LogError("mkdir(%s) failed: %s. If you'd like to use %s to "
+ "store your system persistent data, please"
+ " create it. Otherwise, change the location"
+ " in your tcsd config file.",
+ tcsd_options.system_ps_dir, strerror(errno),
+ tcsd_options.system_ps_dir);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ } else {
+ LogError("stat failed: %s", strerror(errno));
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ }
+
+ /* stat should not fail now */
+ if (stat(tcsd_options.system_ps_dir, &stat_buf) == -1) {
+ LogError("stat %s failed: %s", tcsd_options.system_ps_dir, strerror(errno));
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ /* tcsd_options.system_ps_dir should be a directory with mode equal to mode */
+ if (!S_ISDIR(stat_buf.st_mode)) {
+ LogError("PS dir %s is not a directory! Exiting.", tcsd_options.system_ps_dir);
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ } else if (((stat_buf.st_mode & 0777) ^ mode) != 0) {
+ /* This path is likely to be hit since open &'s mode with ~umask */
+ LogInfo("resetting mode of %s from %o to: %o", tcsd_options.system_ps_dir,
+ (unsigned int) stat_buf.st_mode, (unsigned int) mode);
+ if (chmod(tcsd_options.system_ps_dir, mode) == -1) {
+ LogError("chmod(%s) failed: %s", tcsd_options.system_ps_dir,
+ strerror(errno));
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+ }
+ }
+
+ return TSS_SUCCESS;
+}
+