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 43struct tcsd_config tcsd_options; 44struct tpm_properties tpm_metrics; 45static volatile int hup = 0, term = 0; 46extern char *optarg; 47char *tcsd_config_file = NULL; 48 49struct 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 57static 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 75static void 76tcsd_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 89static void 90tcsd_signal_term(int signal) 91{ 92 term = 1; 93} 94 95void 96tcsd_signal_hup(int signal) 97{ 98 hup = 1; 99} 100 101static TSS_RESULT 102signals_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 140static TSS_RESULT 141tcsd_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 216void 217usage(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 228static TSS_RESULT 229reload_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 240int 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 290int 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 350int 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 377char *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 390void 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 411int 412main(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