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