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 |