| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Licensed Materials - Property of IBM | 3 * Licensed Materials - Property of IBM |
| 4 * | 4 * |
| 5 * trousers - An open source TCG Software Stack | 5 * trousers - An open source TCG Software Stack |
| 6 * | 6 * |
| 7 * (C) Copyright International Business Machines Corp. 2004 | 7 * (C) Copyright International Business Machines Corp. 2004 |
| 8 * | 8 * |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 | 11 |
| 12 #include <stdlib.h> | 12 #include <stdlib.h> |
| 13 #include <stdio.h> | 13 #include <stdio.h> |
| 14 #include <unistd.h> | 14 #include <unistd.h> |
| 15 #include <string.h> | 15 #include <string.h> |
| 16 #include <sys/types.h> | 16 #include <sys/types.h> |
| 17 #include <sys/time.h> | 17 #include <sys/time.h> |
| 18 #include <sys/resource.h> | 18 #include <sys/resource.h> |
| 19 #include <sys/wait.h> | 19 #include <sys/wait.h> |
| 20 #include <sys/stat.h> | 20 #include <sys/stat.h> |
| 21 #include <sys/socket.h> | 21 #include <sys/socket.h> |
| 22 #include <netdb.h> | 22 #include <netdb.h> |
| 23 #include <pwd.h> |
| 23 #if (defined (__OpenBSD__) || defined (__FreeBSD__)) | 24 #if (defined (__OpenBSD__) || defined (__FreeBSD__)) |
| 24 #include <netinet/in.h> | 25 #include <netinet/in.h> |
| 25 #endif | 26 #endif |
| 26 #include <arpa/inet.h> | 27 #include <arpa/inet.h> |
| 27 #include <errno.h> | 28 #include <errno.h> |
| 28 #include <getopt.h> | 29 #include <getopt.h> |
| 29 #include "trousers/tss.h" | 30 #include "trousers/tss.h" |
| 30 #include "trousers_types.h" | 31 #include "trousers_types.h" |
| 31 #include "tcs_tsp.h" | 32 #include "tcs_tsp.h" |
| 32 #include "tcs_utils.h" | 33 #include "tcs_utils.h" |
| 33 #include "tcs_int_literals.h" | 34 #include "tcs_int_literals.h" |
| 34 #include "capabilities.h" | 35 #include "capabilities.h" |
| 35 #include "tcslog.h" | 36 #include "tcslog.h" |
| 36 #include "tcsd_wrap.h" | 37 #include "tcsd_wrap.h" |
| 37 #include "tcsps.h" | 38 #include "tcsps.h" |
| 38 #include "tcsd.h" | 39 #include "tcsd.h" |
| 39 #include "req_mgr.h" | 40 #include "req_mgr.h" |
| 40 | 41 |
| 41 struct tcsd_config tcsd_options; | 42 struct tcsd_config tcsd_options; |
| 42 struct tpm_properties tpm_metrics; | 43 struct tpm_properties tpm_metrics; |
| 44 static volatile int hup = 0, term = 0; |
| 45 extern char *optarg; |
| 43 | 46 |
| 44 void | 47 static void |
| 45 tcsd_shutdown() | 48 tcsd_shutdown(void) |
| 46 { | 49 { |
| 47 /* order is important here: | 50 /* order is important here: |
| 48 * allow all threads to complete their current request */ | 51 * allow all threads to complete their current request */ |
| 49 tcsd_threads_final(); | 52 tcsd_threads_final(); |
| 50 PS_close_disk_cache(); | 53 PS_close_disk_cache(); |
| 51 auth_mgr_final(); | 54 auth_mgr_final(); |
| 52 (void)req_mgr_final(); | 55 (void)req_mgr_final(); |
| 53 conf_file_final(&tcsd_options); | 56 conf_file_final(&tcsd_options); |
| 54 EVENT_LOG_final(); | 57 EVENT_LOG_final(); |
| 55 } | 58 } |
| 56 | 59 |
| 57 void | 60 static void |
| 58 tcsd_signal_int(int signal) | 61 tcsd_signal_term(int signal) |
| 59 { | 62 { |
| 60 » switch (signal) { | 63 » term = 1; |
| 61 » » case SIGINT: | |
| 62 » » » LogInfo("Caught SIGINT. Cleaning up and exiting."); | |
| 63 » » » break; | |
| 64 » » case SIGHUP: | |
| 65 » » » LogInfo("Caught SIGHUP. Cleaning up and exiting."); | |
| 66 » » » break; | |
| 67 » » default: | |
| 68 » » » LogError("Caught signal %d (which I didn't register for!
)." | |
| 69 » » » » » " Ignoring.", signal); | |
| 70 » » » break; | |
| 71 » } | |
| 72 » tcsd_shutdown(); | |
| 73 » exit(signal); | |
| 74 } | 64 } |
| 75 | 65 |
| 76 void | 66 void |
| 77 tcsd_signal_chld(int signal) | 67 tcsd_signal_hup(int signal) |
| 78 { | 68 { |
| 79 » /* kill zombies */ | 69 » hup = 1; |
| 80 » wait3(NULL, WNOHANG, NULL); | |
| 81 } | 70 } |
| 82 | 71 |
| 83 TSS_RESULT | 72 static TSS_RESULT |
| 84 signals_init() | 73 signals_init(void) |
| 85 { | 74 { |
| 86 int rc; | 75 int rc; |
| 87 sigset_t sigmask; | 76 sigset_t sigmask; |
| 77 struct sigaction sa; |
| 88 | 78 |
| 89 sigemptyset(&sigmask); | 79 sigemptyset(&sigmask); |
| 90 » if ((rc = sigaddset(&sigmask, SIGCHLD))) { | 80 » if ((rc = sigaddset(&sigmask, SIGTERM))) { |
| 91 LogError("sigaddset: %s", strerror(errno)); | 81 LogError("sigaddset: %s", strerror(errno)); |
| 92 return TCSERR(TSS_E_INTERNAL_ERROR); | 82 return TCSERR(TSS_E_INTERNAL_ERROR); |
| 93 } | 83 } |
| 94 if ((rc = sigaddset(&sigmask, SIGINT))) { | |
| 95 LogError("sigaddset: %s", strerror(errno)); | |
| 96 return TCSERR(TSS_E_INTERNAL_ERROR); | |
| 97 } | |
| 98 if ((rc = sigaddset(&sigmask, SIGHUP))) { | 84 if ((rc = sigaddset(&sigmask, SIGHUP))) { |
| 99 LogError("sigaddset: %s", strerror(errno)); | 85 LogError("sigaddset: %s", strerror(errno)); |
| 100 return TCSERR(TSS_E_INTERNAL_ERROR); | 86 return TCSERR(TSS_E_INTERNAL_ERROR); |
| 101 } | 87 } |
| 102 | 88 |
| 103 if ((rc = THREAD_SET_SIGNAL_MASK(SIG_UNBLOCK, &sigmask, NULL))) { | 89 if ((rc = THREAD_SET_SIGNAL_MASK(SIG_UNBLOCK, &sigmask, NULL))) { |
| 104 LogError("Setting thread signal mask: %s", strerror(rc)); | 90 LogError("Setting thread signal mask: %s", strerror(rc)); |
| 105 return TCSERR(TSS_E_INTERNAL_ERROR); | 91 return TCSERR(TSS_E_INTERNAL_ERROR); |
| 106 } | 92 } |
| 107 | 93 |
| 108 » tcsd_sa_int.sa_handler = tcsd_signal_int; | 94 » sa.sa_flags = 0; |
| 109 » tcsd_sa_chld.sa_handler = tcsd_signal_chld; | 95 » sigemptyset(&sa.sa_mask); |
| 110 » tcsd_sa_chld.sa_flags = SA_RESTART; | 96 » sa.sa_handler = tcsd_signal_term; |
| 111 | 97 » if ((rc = sigaction(SIGTERM, &sa, NULL))) { |
| 112 » if ((rc = sigaction(SIGINT, &tcsd_sa_int, NULL))) { | 98 » » LogError("signal SIGTERM not registered: %s", strerror(errno)); |
| 113 » » LogError("signal SIGINT not registered: %s", strerror(errno)); | |
| 114 return TCSERR(TSS_E_INTERNAL_ERROR); | 99 return TCSERR(TSS_E_INTERNAL_ERROR); |
| 115 } | 100 } |
| 116 | 101 |
| 117 » if ((rc = sigaction(SIGHUP, &tcsd_sa_int, NULL))) { | 102 » sa.sa_handler = tcsd_signal_hup;» |
| 103 » if ((rc = sigaction(SIGHUP, &sa, NULL))) { |
| 118 LogError("signal SIGHUP not registered: %s", strerror(errno)); | 104 LogError("signal SIGHUP not registered: %s", strerror(errno)); |
| 119 return TCSERR(TSS_E_INTERNAL_ERROR); | 105 return TCSERR(TSS_E_INTERNAL_ERROR); |
| 120 } | 106 } |
| 121 | 107 |
| 122 if ((rc = sigaction(SIGCHLD, &tcsd_sa_chld, NULL))) { | |
| 123 LogError("signal SIGCHLD not registered: %s", strerror(errno)); | |
| 124 return TCSERR(TSS_E_INTERNAL_ERROR); | |
| 125 } | |
| 126 | |
| 127 return TSS_SUCCESS; | 108 return TSS_SUCCESS; |
| 128 } | 109 } |
| 129 | 110 |
| 130 TSS_RESULT | 111 static TSS_RESULT |
| 131 tcsd_startup() | 112 tcsd_startup(void) |
| 132 { | 113 { |
| 133 TSS_RESULT result; | 114 TSS_RESULT result; |
| 134 | 115 |
| 135 #ifdef TSS_DEBUG | 116 #ifdef TSS_DEBUG |
| 136 /* Set stdout to be unbuffered to match stderr and interleave output cor
rectly */ | 117 /* Set stdout to be unbuffered to match stderr and interleave output cor
rectly */ |
| 137 setvbuf(stdout, (char *)NULL, _IONBF, 0); | 118 setvbuf(stdout, (char *)NULL, _IONBF, 0); |
| 138 #endif | 119 #endif |
| 139 | 120 |
| 140 if ((result = signals_init())) | 121 if ((result = signals_init())) |
| 141 return result; | 122 return result; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 auth_mgr_final(); | 176 auth_mgr_final(); |
| 196 conf_file_final(&tcsd_options); | 177 conf_file_final(&tcsd_options); |
| 197 PS_close_disk_cache(); | 178 PS_close_disk_cache(); |
| 198 (void)req_mgr_final(); | 179 (void)req_mgr_final(); |
| 199 return result; | 180 return result; |
| 200 } | 181 } |
| 201 | 182 |
| 202 return TSS_SUCCESS; | 183 return TSS_SUCCESS; |
| 203 } | 184 } |
| 204 | 185 |
| 186 |
| 205 void | 187 void |
| 206 usage(void) | 188 usage(void) |
| 207 { | 189 { |
| 208 fprintf(stderr, "\tusage: tcsd [-f] [-h]\n\n"); | 190 fprintf(stderr, "\tusage: tcsd [-f] [-h]\n\n"); |
| 209 fprintf(stderr, "\t-f|--foreground\trun in the foreground. Logging goes
to stderr " | 191 fprintf(stderr, "\t-f|--foreground\trun in the foreground. Logging goes
to stderr " |
| 210 "instead of syslog.\n"); | 192 "instead of syslog.\n"); |
| 193 fprintf(stderr, "\t-e| attempts to connect to software TPMs over TCP"); |
| 211 fprintf(stderr, "\t-h|--help\tdisplay this help message\n"); | 194 fprintf(stderr, "\t-h|--help\tdisplay this help message\n"); |
| 212 fprintf(stderr, "\n"); | 195 fprintf(stderr, "\n"); |
| 213 } | 196 } |
| 214 | 197 |
| 198 static TSS_RESULT |
| 199 reload_config(void) |
| 200 { |
| 201 TSS_RESULT result; |
| 202 hup = 0; |
| 203 |
| 204 // FIXME: reload the config - work in progress |
| 205 result = TSS_SUCCESS; |
| 206 |
| 207 return result; |
| 208 } |
| 209 |
| 210 |
| 215 int | 211 int |
| 216 main(int argc, char **argv) | 212 main(int argc, char **argv) |
| 217 { | 213 { |
| 218 struct sockaddr_in serv_addr, client_addr; | 214 struct sockaddr_in serv_addr, client_addr; |
| 219 TSS_RESULT result; | 215 TSS_RESULT result; |
| 220 int sd, newsd, c, option_index = 0; | 216 int sd, newsd, c, option_index = 0; |
| 221 unsigned client_len; | 217 unsigned client_len; |
| 222 char *hostname = NULL; | 218 char *hostname = NULL; |
| 219 struct passwd *pwd; |
| 223 struct hostent *client_hostent = NULL; | 220 struct hostent *client_hostent = NULL; |
| 224 struct option long_options[] = { | 221 struct option long_options[] = { |
| 225 {"help", 0, NULL, 'h'}, | 222 {"help", 0, NULL, 'h'}, |
| 226 {"foreground", 0, NULL, 'f'}, | 223 {"foreground", 0, NULL, 'f'}, |
| 227 {0, 0, 0, 0} | 224 {0, 0, 0, 0} |
| 228 }; | 225 }; |
| 229 | 226 |
| 230 » while ((c = getopt_long(argc, argv, "fh", long_options, &option_index))
!= -1) { | 227 » unsetenv("TCSD_USE_TCP_DEVICE"); |
| 228 » while ((c = getopt_long(argc, argv, "fhe", long_options, &option_index))
!= -1) { |
| 231 switch (c) { | 229 switch (c) { |
| 232 case 'f': | 230 case 'f': |
| 233 setenv("TCSD_FOREGROUND", "1", 1); | 231 setenv("TCSD_FOREGROUND", "1", 1); |
| 234 break; | 232 break; |
| 235 case 'h': | 233 case 'h': |
| 236 /* fall through */ | 234 /* fall through */ |
| 235 case 'e': |
| 236 setenv("TCSD_USE_TCP_DEVICE", "1", 1); |
| 237 break; |
| 237 default: | 238 default: |
| 238 usage(); | 239 usage(); |
| 239 return -1; | 240 return -1; |
| 240 break; | 241 break; |
| 241 } | 242 } |
| 242 } | 243 } |
| 243 | 244 |
| 244 if ((result = tcsd_startup())) | 245 if ((result = tcsd_startup())) |
| 245 return (int)result; | 246 return (int)result; |
| 246 | 247 |
| 247 if (getenv("TCSD_FOREGROUND") == NULL) { | |
| 248 if (daemon(0, 0) == -1) { | |
| 249 perror("daemon"); | |
| 250 tcsd_shutdown(); | |
| 251 return -1; | |
| 252 } | |
| 253 } | |
| 254 | |
| 255 sd = socket(AF_INET, SOCK_STREAM, 0); | 248 sd = socket(AF_INET, SOCK_STREAM, 0); |
| 256 if (sd < 0) { | 249 if (sd < 0) { |
| 257 LogError("Failed socket: %s", strerror(errno)); | 250 LogError("Failed socket: %s", strerror(errno)); |
| 258 return -1; | 251 return -1; |
| 259 } | 252 } |
| 260 | 253 |
| 261 memset(&serv_addr, 0, sizeof (serv_addr)); | 254 memset(&serv_addr, 0, sizeof (serv_addr)); |
| 262 serv_addr.sin_family = AF_INET; | 255 serv_addr.sin_family = AF_INET; |
| 263 serv_addr.sin_port = htons(tcsd_options.port); | 256 serv_addr.sin_port = htons(tcsd_options.port); |
| 264 | 257 |
| 265 /* If no remote_ops are defined, restrict connections to localhost | 258 /* If no remote_ops are defined, restrict connections to localhost |
| 266 * only at the socket. */ | 259 * only at the socket. */ |
| 267 if (tcsd_options.remote_ops[0] == 0) | 260 if (tcsd_options.remote_ops[0] == 0) |
| 268 serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | 261 serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 269 else | 262 else |
| 270 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); | 263 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 271 | 264 |
| 272 c = 1; | 265 c = 1; |
| 273 setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &c, sizeof(c)); | 266 setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &c, sizeof(c)); |
| 274 if (bind(sd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { | 267 if (bind(sd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { |
| 275 LogError("Failed bind: %s", strerror(errno)); | 268 LogError("Failed bind: %s", strerror(errno)); |
| 276 return -1; | 269 return -1; |
| 277 } | 270 } |
| 271 #ifndef SOLARIS |
| 272 pwd = getpwnam(TSS_USER_NAME); |
| 273 if (pwd == NULL) { |
| 274 if (errno == 0) { |
| 275 LogError("User \"%s\" not found, please add this user" |
| 276 " manually.", TSS_USER_NAME); |
| 277 } else { |
| 278 LogError("getpwnam(%s): %s", TSS_USER_NAME, strerror(err
no)); |
| 279 } |
| 280 return TCSERR(TSS_E_INTERNAL_ERROR); |
| 281 } |
| 282 setuid(pwd->pw_uid); |
| 283 #endif |
| 278 if (listen(sd, TCSD_MAX_SOCKETS_QUEUED) < 0) { | 284 if (listen(sd, TCSD_MAX_SOCKETS_QUEUED) < 0) { |
| 279 LogError("Failed listen: %s", strerror(errno)); | 285 LogError("Failed listen: %s", strerror(errno)); |
| 280 return -1; | 286 return -1; |
| 281 } | 287 } |
| 282 client_len = (unsigned)sizeof(client_addr); | 288 client_len = (unsigned)sizeof(client_addr); |
| 289 |
| 290 if (getenv("TCSD_FOREGROUND") == NULL) { |
| 291 if (daemon(0, 0) == -1) { |
| 292 perror("daemon"); |
| 293 tcsd_shutdown(); |
| 294 return -1; |
| 295 } |
| 296 } |
| 297 |
| 283 LogInfo("%s: TCSD up and running.", PACKAGE_STRING); | 298 LogInfo("%s: TCSD up and running.", PACKAGE_STRING); |
| 284 do { | 299 do { |
| 285 newsd = accept(sd, (struct sockaddr *) &client_addr, &client_len
); | 300 newsd = accept(sd, (struct sockaddr *) &client_addr, &client_len
); |
| 301 if (newsd < 0) { |
| 302 if (errno == EINTR) { |
| 303 if (term) |
| 304 break; |
| 305 else if (hup) { |
| 306 if (reload_config() != TSS_SUCCESS) |
| 307 LogError("Failed reloading confi
g"); |
| 308 } |
| 309 continue; |
| 310 } else { |
| 311 LogError("Failed accept: %s", strerror(errno)); |
| 312 continue; |
| 313 } |
| 314 } |
| 286 LogDebug("accepted socket %i", newsd); | 315 LogDebug("accepted socket %i", newsd); |
| 287 if (newsd < 0) { | |
| 288 LogError("Failed accept: %s", strerror(errno)); | |
| 289 break; | |
| 290 } | |
| 291 | 316 |
| 292 if ((client_hostent = gethostbyaddr((char *) &client_addr.sin_ad
dr, | 317 if ((client_hostent = gethostbyaddr((char *) &client_addr.sin_ad
dr, |
| 293 sizeof(client_addr.sin_addr)
, | 318 sizeof(client_addr.sin_addr)
, |
| 294 AF_INET)) == NULL) { | 319 AF_INET)) == NULL) { |
| 295 char buf[16]; | 320 char buf[16]; |
| 296 uint32_t addr = htonl(client_addr.sin_addr.s_addr); | 321 uint32_t addr = htonl(client_addr.sin_addr.s_addr); |
| 297 | 322 |
| 298 snprintf(buf, 16, "%d.%d.%d.%d", (addr & 0xff000000) >>
24, | 323 snprintf(buf, 16, "%d.%d.%d.%d", (addr & 0xff000000) >>
24, |
| 299 (addr & 0x00ff0000) >> 16, (addr & 0x0000ff00)
>> 8, | 324 (addr & 0x00ff0000) >> 16, (addr & 0x0000ff00)
>> 8, |
| 300 addr & 0x000000ff); | 325 addr & 0x000000ff); |
| 301 | 326 |
| 302 LogWarn("Host name for connecting IP %s could not be res
olved", buf); | 327 LogWarn("Host name for connecting IP %s could not be res
olved", buf); |
| 303 hostname = strdup(buf); | 328 hostname = strdup(buf); |
| 304 } else { | 329 } else { |
| 305 hostname = strdup(client_hostent->h_name); | 330 hostname = strdup(client_hostent->h_name); |
| 306 } | 331 } |
| 307 | 332 |
| 308 tcsd_thread_create(newsd, hostname); | 333 tcsd_thread_create(newsd, hostname); |
| 309 hostname = NULL; | 334 hostname = NULL; |
| 310 » } while (1); | 335 » » if (hup) { |
| 336 » » » if (reload_config() != TSS_SUCCESS) |
| 337 » » » » LogError("Failed reloading config"); |
| 338 » » } |
| 339 » } while (term ==0); |
| 311 | 340 |
| 312 » /* To close correctly, we must recieve a SIGHUP */ | 341 » /* To close correctly, we must receive a SIGTERM */ |
| 313 » return -1; | 342 » return 0; |
| 314 } | 343 } |
| OLD | NEW |