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