xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tcsd/svrside.c (revision 1cebe59da2b9fbff2d2acd9c253d00a9ee60e9eb)
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