Home | History | Annotate | Line # | Download | only in tcsd
      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 
     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
     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
     90 tcsd_signal_term(int signal)
     91 {
     92 	term = 1;
     93 }
     94 
     95 void
     96 tcsd_signal_hup(int signal)
     97 {
     98 	hup = 1;
     99 }
    100 
    101 static TSS_RESULT
    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
    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
    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
    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 
    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 
    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 
    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 
    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 
    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
    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