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
init_tcsd_config(struct tcsd_config * conf)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
platform_class_list_append(struct tcsd_config * conf,char * specName,TSS_BOOL is_main)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
config_set_defaults(struct tcsd_config * conf)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
get_config_option(char * ptr,char ** arg)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
get_file_path(char * ptr,char ** dest)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
tcsd_add_op(int * remote_ops,int * op)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
tcsd_set_remote_op(struct tcsd_config * conf,char * op_name)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
read_conf_line(char * buf,int line_num,struct tcsd_config * conf)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
read_conf_file(FILE * f,struct tcsd_config * conf)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
free_platform_lists(struct platform_class * list)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
conf_file_final(struct tcsd_config * conf)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
get_smf_prop(const char * var,boolean_t def_val)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
conf_file_init(struct tcsd_config * conf)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
ps_dirs_init()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