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 <stdlib.h>
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <sys/resource.h>
19 #include <sys/wait.h>
20 #include <sys/stat.h>
21 #include <sys/socket.h>
22 #include <netdb.h>
23 #include <pwd.h>
24 #if (defined (__OpenBSD__) || defined (__FreeBSD__) || defined(__NetBSD__))
25 #include <netinet/in.h>
26 #endif
27 #include <arpa/inet.h>
28 #include <errno.h>
29 #include <getopt.h>
30 #include <sys/select.h>
31 #include "trousers/tss.h"
32 #include "trousers_types.h"
33 #include "tcs_tsp.h"
34 #include "tcs_utils.h"
35 #include "tcs_int_literals.h"
36 #include "capabilities.h"
37 #include "tcslog.h"
38 #include "tcsd_wrap.h"
39 #include "tcsps.h"
40 #include "tcsd.h"
41 #include "req_mgr.h"
42
43 struct tcsd_config tcsd_options;
44 struct tpm_properties tpm_metrics;
45 static volatile int hup = 0, term = 0;
46 extern char *optarg;
47 char *tcsd_config_file = NULL;
48
49 struct srv_sock_info {
50 int sd;
51 int domain; // AF_INET or AF_INET6
52 socklen_t addr_len;
53 };
54 #define MAX_IP_PROTO 2
55 #define INVALID_ADDR_STR "<Invalid client address>"
56
close_server_socks(struct srv_sock_info * socks_info)57 static void close_server_socks(struct srv_sock_info *socks_info)
58 {
59 int i, rv;
60
61 for (i=0; i < MAX_IP_PROTO; i++) {
62 if (socks_info[i].sd != -1) {
63 do {
64 rv = close(socks_info[i].sd);
65 if (rv == -1 && errno != EINTR) {
66 LogError("Error closing server socket descriptor - %s",
67 strerror(errno));
68 continue;
69 }
70 } while (rv == -1 && errno == EINTR);
71 }
72 }
73 }
74
75 static void
tcsd_shutdown(struct srv_sock_info socks_info[])76 tcsd_shutdown(struct srv_sock_info socks_info[])
77 {
78 close_server_socks(socks_info);
79 /* order is important here:
80 * allow all threads to complete their current request */
81 tcsd_threads_final();
82 PS_close_disk_cache();
83 auth_mgr_final();
84 (void)req_mgr_final();
85 conf_file_final(&tcsd_options);
86 EVENT_LOG_final();
87 }
88
89 static void
tcsd_signal_term(int signal)90 tcsd_signal_term(int signal)
91 {
92 term = 1;
93 }
94
95 void
tcsd_signal_hup(int signal)96 tcsd_signal_hup(int signal)
97 {
98 hup = 1;
99 }
100
101 static TSS_RESULT
signals_init(void)102 signals_init(void)
103 {
104 int rc;
105 sigset_t sigmask;
106 struct sigaction sa;
107
108 sigemptyset(&sigmask);
109 if ((rc = sigaddset(&sigmask, SIGTERM))) {
110 LogError("sigaddset: %s", strerror(errno));
111 return TCSERR(TSS_E_INTERNAL_ERROR);
112 }
113 if ((rc = sigaddset(&sigmask, SIGHUP))) {
114 LogError("sigaddset: %s", strerror(errno));
115 return TCSERR(TSS_E_INTERNAL_ERROR);
116 }
117
118 if ((rc = THREAD_SET_SIGNAL_MASK(SIG_UNBLOCK, &sigmask, NULL))) {
119 LogError("Setting thread signal mask: %s", strerror(rc));
120 return TCSERR(TSS_E_INTERNAL_ERROR);
121 }
122
123 sa.sa_flags = 0;
124 sigemptyset(&sa.sa_mask);
125 sa.sa_handler = tcsd_signal_term;
126 if ((rc = sigaction(SIGTERM, &sa, NULL))) {
127 LogError("signal SIGTERM not registered: %s", strerror(errno));
128 return TCSERR(TSS_E_INTERNAL_ERROR);
129 }
130
131 sa.sa_handler = tcsd_signal_hup;
132 if ((rc = sigaction(SIGHUP, &sa, NULL))) {
133 LogError("signal SIGHUP not registered: %s", strerror(errno));
134 return TCSERR(TSS_E_INTERNAL_ERROR);
135 }
136
137 return TSS_SUCCESS;
138 }
139
140 static TSS_RESULT
tcsd_startup(void)141 tcsd_startup(void)
142 {
143 TSS_RESULT result;
144
145 #ifdef TSS_DEBUG
146 /* Set stdout to be unbuffered to match stderr and interleave output correctly */
147 setvbuf(stdout, (char *)NULL, _IONBF, 0);
148 #endif
149
150 if ((result = signals_init()))
151 return result;
152
153 if ((result = conf_file_init(&tcsd_options)))
154 return result;
155
156 if ((result = tcsd_threads_init())) {
157 conf_file_final(&tcsd_options);
158 return result;
159 }
160
161 if ((result = req_mgr_init())) {
162 conf_file_final(&tcsd_options);
163 return result;
164 }
165
166 if ((result = ps_dirs_init())) {
167 conf_file_final(&tcsd_options);
168 (void)req_mgr_final();
169 return result;
170 }
171
172 result = PS_init_disk_cache();
173 if (result != TSS_SUCCESS) {
174 conf_file_final(&tcsd_options);
175 (void)req_mgr_final();
176 return result;
177 }
178
179 if ((result = get_tpm_metrics(&tpm_metrics))) {
180 conf_file_final(&tcsd_options);
181 PS_close_disk_cache();
182 (void)req_mgr_final();
183 return result;
184 }
185
186 /* must happen after get_tpm_metrics() */
187 if ((result = auth_mgr_init())) {
188 conf_file_final(&tcsd_options);
189 PS_close_disk_cache();
190 (void)req_mgr_final();
191 return result;
192 }
193
194 result = EVENT_LOG_init();
195 if (result != TSS_SUCCESS) {
196 auth_mgr_final();
197 conf_file_final(&tcsd_options);
198 PS_close_disk_cache();
199 (void)req_mgr_final();
200 return result;
201 }
202
203 result = owner_evict_init();
204 if (result != TSS_SUCCESS) {
205 auth_mgr_final();
206 conf_file_final(&tcsd_options);
207 PS_close_disk_cache();
208 (void)req_mgr_final();
209 return result;
210 }
211
212 return TSS_SUCCESS;
213 }
214
215
216 void
usage(void)217 usage(void)
218 {
219 fprintf(stderr, "\tusage: tcsd [-f] [-e] [-c <config file> [-h]\n\n");
220 fprintf(stderr, "\t-f|--foreground\trun in the foreground. Logging goes to stderr "
221 "instead of syslog.\n");
222 fprintf(stderr, "\t-e| attempts to connect to software TPMs over TCP\n");
223 fprintf(stderr, "\t-c|--config\tpath to configuration file\n");
224 fprintf(stderr, "\t-h|--help\tdisplay this help message\n");
225 fprintf(stderr, "\n");
226 }
227
228 static TSS_RESULT
reload_config(void)229 reload_config(void)
230 {
231 TSS_RESULT result;
232 hup = 0;
233
234 // FIXME: reload the config - work in progress
235 result = TSS_SUCCESS;
236
237 return result;
238 }
239
setup_ipv4_socket(struct srv_sock_info ssi[])240 int setup_ipv4_socket(struct srv_sock_info ssi[])
241 {
242 struct sockaddr_in serv_addr;
243 int sd, opt;
244
245 ssi->sd = -1;
246
247 // Initialization of IPv4 socket.
248 sd = socket(AF_INET, SOCK_STREAM, 0);
249 if (sd < 0) {
250 LogWarn("Failed IPv4 socket: %s", strerror(errno));
251 goto err;
252 }
253
254 memset(&serv_addr, 0, sizeof (serv_addr));
255 serv_addr.sin_family = AF_INET;
256 serv_addr.sin_port = htons(tcsd_options.port);
257
258 /* If no remote_ops are defined, restrict connections to localhost
259 * only at the socket. */
260 if (tcsd_options.remote_ops[0] == 0)
261 serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
262 else
263 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
264
265 opt = 1;
266 setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
267 if (bind(sd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
268 LogWarn("Failed IPv4 bind: %s", strerror(errno));
269 goto err;
270 }
271
272 if (listen(sd, TCSD_MAX_SOCKETS_QUEUED) < 0) {
273 LogWarn("Failed IPv4 listen: %s", strerror(errno));
274 goto err;
275 }
276
277 ssi->domain = AF_INET;
278 ssi->sd = sd;
279 ssi->addr_len = sizeof(serv_addr);
280
281 return 0;
282
283 err:
284 if (sd != -1)
285 close(sd);
286
287 return -1;
288 }
289
setup_ipv6_socket(struct srv_sock_info * ssi)290 int setup_ipv6_socket(struct srv_sock_info *ssi)
291 {
292 struct sockaddr_in6 serv6_addr;
293 int sd6, opt;
294
295 ssi->sd = -1;
296
297 sd6 = socket(AF_INET6, SOCK_STREAM, 0);
298 if (sd6 < 0) {
299 LogWarn("Failed IPv6 socket: %s", strerror(errno));
300 goto err;
301 }
302
303 memset(&serv6_addr, 0, sizeof (serv6_addr));
304 serv6_addr.sin6_family = AF_INET6;
305 serv6_addr.sin6_port = htons(tcsd_options.port);
306
307 /* If no remote_ops are defined, restrict connections to localhost
308 * only at the socket. */
309 if (tcsd_options.remote_ops[0] == 0)
310 serv6_addr.sin6_addr = in6addr_loopback;
311 else
312 serv6_addr.sin6_addr = in6addr_any;
313
314 #ifdef __linux__
315 /* Linux, by default, allows one socket to be used by both IP stacks
316 * This option disables that behavior, so you must have one socket for
317 * each IP protocol. */
318 opt = 1;
319 if(setsockopt(sd6, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) {
320 LogWarn("Could not set IPv6 socket option properly.\n");
321 goto err;
322 }
323 #endif
324
325 opt = 1;
326 setsockopt(sd6, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
327 if (bind(sd6, (struct sockaddr *) &serv6_addr, sizeof (serv6_addr)) < 0) {
328 LogWarn("Failed IPv6 bind: %s", strerror(errno));
329 goto err;
330 }
331
332 if (listen(sd6, TCSD_MAX_SOCKETS_QUEUED) < 0) {
333 LogWarn("Failed IPv6 listen: %s", strerror(errno));
334 goto err;
335 }
336
337 ssi->domain = AF_INET6;
338 ssi->sd = sd6;
339 ssi->addr_len = sizeof(serv6_addr);
340
341 return 0;
342
343 err:
344 if (sd6 != -1)
345 close(sd6);
346
347 return -1;
348 }
349
setup_server_sockets(struct srv_sock_info ssi[])350 int setup_server_sockets(struct srv_sock_info ssi[])
351 {
352 int i=0;
353
354 ssi[0].sd = ssi[1].sd = -1;
355 // Only enqueue sockets successfully bound or that weren't disabled.
356 if (tcsd_options.disable_ipv4) {
357 LogWarn("IPv4 support disabled by configuration option");
358 } else {
359 if (setup_ipv4_socket(&ssi[i]) == 0)
360 i++;
361 }
362
363 if (tcsd_options.disable_ipv6) {
364 LogWarn("IPv6 support disabled by configuration option");
365 } else {
366 setup_ipv6_socket(&ssi[i]);
367 }
368
369 // It's only a failure if both sockets are unavailable.
370 if ((ssi[0].sd == -1) && (ssi[1].sd == -1)) {
371 return -1;
372 }
373
374 return 0;
375 }
376
fetch_hostname(struct sockaddr_storage * client_addr,socklen_t socklen)377 char *fetch_hostname(struct sockaddr_storage *client_addr, socklen_t socklen)
378 {
379 char buf[NI_MAXHOST];
380
381 if (getnameinfo((struct sockaddr *)client_addr, socklen, buf,
382 sizeof(buf), NULL, 0, 0) != 0) {
383 LogWarn("Could not retrieve client address info");
384 return NULL;
385 } else {
386 return strdup(buf);
387 }
388 }
389
prepare_for_select(struct srv_sock_info * socks_info,int * num_fds,fd_set * rdfd_set,int * nfds)390 void prepare_for_select(struct srv_sock_info *socks_info, int *num_fds,
391 fd_set *rdfd_set, int *nfds)
392 {
393 int i;
394
395 FD_ZERO(rdfd_set);
396 *num_fds = 0;
397 *nfds = 0;
398 // Filter out socket descriptors in the queue that
399 // has the -1 value.
400 for (i=0; i < MAX_IP_PROTO; i++) {
401 if (socks_info[i].sd == -1)
402 break;
403
404 FD_SET(socks_info[i].sd, rdfd_set);
405 (*num_fds)++;
406 if (*nfds < socks_info[i].sd) // grab highest sd for select call
407 *nfds = socks_info[i].sd;
408 }
409 }
410
411 int
main(int argc,char ** argv)412 main(int argc, char **argv)
413 {
414 TSS_RESULT result;
415 int newsd, c, rv, option_index = 0;
416 int i;
417 socklen_t client_len;
418 char *hostname = NULL;
419 fd_set rdfd_set;
420 int num_fds = 0;
421 int nfds = 0;
422 int stor_errno;
423 sigset_t sigmask, termmask, oldsigmask;
424 struct sockaddr_storage client_addr;
425 struct srv_sock_info socks_info[MAX_IP_PROTO];
426 struct passwd *pwd;
427 struct option long_options[] = {
428 {"help", 0, NULL, 'h'},
429 {"foreground", 0, NULL, 'f'},
430 {"config", 1, NULL, 'c'},
431 {0, 0, 0, 0}
432 };
433
434 unsetenv("TCSD_USE_TCP_DEVICE");
435 while ((c = getopt_long(argc, argv, "fhec:", long_options, &option_index)) != -1) {
436 switch (c) {
437 case 'f':
438 setenv("TCSD_FOREGROUND", "1", 1);
439 break;
440 case 'c':
441 tcsd_config_file = optarg;
442 break;
443 case 'e':
444 setenv("TCSD_USE_TCP_DEVICE", "1", 1);
445 break;
446 case 'h':
447 /* fall through */
448 default:
449 usage();
450 return -1;
451 break;
452 }
453 }
454
455 if (!tcsd_config_file)
456 tcsd_config_file = TCSD_DEFAULT_CONFIG_FILE;
457
458 if ((result = tcsd_startup()))
459 return (int)result;
460
461 #ifdef NOUSERCHECK
462 LogWarn("will not switch user or check for file permissions. "
463 "(Compiled with --disable-usercheck)");
464 #else
465 #ifndef SOLARIS
466 pwd = getpwnam(TSS_USER_NAME);
467 if (pwd == NULL) {
468 if (errno == 0) {
469 LogError("User \"%s\" not found, please add this user"
470 " manually.", TSS_USER_NAME);
471 } else {
472 LogError("getpwnam(%s): %s", TSS_USER_NAME, strerror(errno));
473 }
474 return TCSERR(TSS_E_INTERNAL_ERROR);
475 }
476 setuid(pwd->pw_uid);
477 #endif
478 #endif
479
480 if (setup_server_sockets(socks_info) == -1) {
481 LogError("Could not create sockets to listen to connections. Aborting...");
482 return -1;
483 }
484
485 if (getenv("TCSD_FOREGROUND") == NULL) {
486 if (daemon(0, 0) == -1) {
487 perror("daemon");
488 tcsd_shutdown(socks_info);
489 return -1;
490 }
491 }
492
493 LogInfo("%s: TCSD up and running.", PACKAGE_STRING);
494
495 sigemptyset(&sigmask);
496 sigaddset(&sigmask, SIGTERM);
497 sigaddset(&sigmask, SIGHUP);
498
499 sigemptyset(&termmask);
500 sigaddset(&termmask, SIGTERM);
501
502 do {
503 prepare_for_select(socks_info, &num_fds, &rdfd_set, &nfds);
504 // Sanity check
505 if (num_fds == 0) {
506 LogError("No server sockets available to listen connections. Aborting...");
507 return -1;
508 }
509
510 // Block TERM and HUP signals to prevent race condition
511 if (sigprocmask(SIG_BLOCK, &sigmask, &oldsigmask) == -1) {
512 LogError("Error setting interrupt mask before accept");
513 }
514
515 // TERM and HUP are blocked here, so its safe to test flags.
516 if (hup) {
517 // Config reading can be slow, so unmask SIGTERM.
518 if (sigprocmask(SIG_UNBLOCK, &termmask, NULL) == -1) {
519 LogError("Error unblocking SIGTERM before config reload");
520 }
521 if (reload_config() != TSS_SUCCESS)
522 LogError("Failed reloading config");
523 if (sigprocmask(SIG_BLOCK, &termmask, NULL) == -1) {
524 LogError("Error blocking SIGTERM after config reload");
525 }
526 }
527 if (term)
528 break;
529
530 // Select IPv4 and IPv6 socket descriptors with appropriate sigmask.
531 LogDebug("Waiting for connections");
532 rv = pselect(nfds+1, &rdfd_set, NULL, NULL, NULL, &oldsigmask);
533 stor_errno = errno; // original mask must be set ASAP, so store errno.
534 if (sigprocmask(SIG_SETMASK, &oldsigmask, NULL) == -1) {
535 LogError("Error reseting signal mask to the original configuration.");
536 }
537 if (rv == -1) {
538 if (stor_errno != EINTR) {
539 LogError("Error monitoring server socket descriptors.");
540 return -1;
541 }
542 continue;
543 }
544
545 for (i=0; i < num_fds; i++) { // accept connections from all IP versions (with valid sd)
546 if (!FD_ISSET(socks_info[i].sd, &rdfd_set)) {
547 continue;
548 }
549 client_len = socks_info[i].addr_len;
550 newsd = accept(socks_info[i].sd, (struct sockaddr *) &client_addr, &client_len);
551 if (newsd < 0) {
552 if (errno != EINTR)
553 LogError("Failed accept: %s", strerror(errno));
554 continue;
555 }
556 LogDebug("accepted socket %i", newsd);
557
558 hostname = fetch_hostname(&client_addr, client_len);
559 if (hostname == NULL)
560 hostname=INVALID_ADDR_STR;
561
562 tcsd_thread_create(newsd, hostname);
563 hostname = NULL;
564 } // for (i=0; i < MAX_IP_PROTO; i++)
565 } while (term ==0);
566
567 /* To close correctly, we must receive a SIGTERM */
568 tcsd_shutdown(socks_info);
569 return 0;
570 }
571