~ubuntu-branches/ubuntu/vivid/trousers/vivid

« back to all changes in this revision

Viewing changes to src/tcsd/svrside.c

  • Committer: Package Import Robot
  • Author(s): Pierre Chifflier
  • Date: 2014-06-29 17:45:25 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20140629174525-3bumeiu42woiem8l
Tags: 0.3.13-1
* Imported Upstream version 0.3.13
* Refreshed quilt patches
* Include utmp.h, should fix FTBFS on Hurd (Closes: #729179)
* Try to workaround systemd/udev names when reloading rules (Closes: #739485)
* Update symbols
* Bump Standards Version to 3.9.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include <arpa/inet.h>
28
28
#include <errno.h>
29
29
#include <getopt.h>
 
30
#include <sys/select.h>
30
31
#include "trousers/tss.h"
31
32
#include "trousers_types.h"
32
33
#include "tcs_tsp.h"
43
44
struct tpm_properties tpm_metrics;
44
45
static volatile int hup = 0, term = 0;
45
46
extern char *optarg;
46
 
int sd;
47
47
char *tcsd_config_file = NULL;
48
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
 
49
75
static void
50
 
tcsd_shutdown(void)
 
76
tcsd_shutdown(struct srv_sock_info socks_info[])
51
77
{
 
78
        close_server_socks(socks_info);
52
79
        /* order is important here:
53
80
         * allow all threads to complete their current request */
54
81
        tcsd_threads_final();
63
90
tcsd_signal_term(int signal)
64
91
{
65
92
        term = 1;
66
 
        close(sd);
67
93
}
68
94
 
69
95
void
211
237
        return result;
212
238
}
213
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
}
214
410
 
215
411
int
216
412
main(int argc, char **argv)
217
413
{
218
 
        struct sockaddr_in serv_addr, client_addr;
219
414
        TSS_RESULT result;
220
 
        int newsd, c, option_index = 0;
221
 
        unsigned client_len;
 
415
        int newsd, c, rv, option_index = 0;
 
416
        int i;
 
417
        socklen_t client_len;
222
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];
223
426
        struct passwd *pwd;
224
 
        struct hostent *client_hostent = NULL;
225
427
        struct option long_options[] = {
226
428
                {"help", 0, NULL, 'h'},
227
429
                {"foreground", 0, NULL, 'f'},
256
458
        if ((result = tcsd_startup()))
257
459
                return (int)result;
258
460
 
259
 
        sd = socket(AF_INET, SOCK_STREAM, 0);
260
 
        if (sd < 0) {
261
 
                LogError("Failed socket: %s", strerror(errno));
262
 
                return -1;
263
 
        }
264
 
 
265
 
        memset(&serv_addr, 0, sizeof (serv_addr));
266
 
        serv_addr.sin_family = AF_INET;
267
 
        serv_addr.sin_port = htons(tcsd_options.port);
268
 
 
269
 
        /* If no remote_ops are defined, restrict connections to localhost
270
 
         * only at the socket. */
271
 
        if (tcsd_options.remote_ops[0] == 0)
272
 
                serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
273
 
        else
274
 
                serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
275
 
 
276
 
        c = 1;
277
 
        setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &c, sizeof(c));
278
 
        if (bind(sd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
279
 
                LogError("Failed bind: %s", strerror(errno));
280
 
                return -1;
281
 
        }
 
461
#ifdef NOUSERCHECK
 
462
    LogWarn("will not switch user or check for file permissions. "
 
463
            "(Compiled with --disable-usercheck)");
 
464
#else
282
465
#ifndef SOLARIS
283
466
        pwd = getpwnam(TSS_USER_NAME);
284
467
        if (pwd == NULL) {
292
475
        }
293
476
        setuid(pwd->pw_uid);
294
477
#endif
295
 
        if (listen(sd, TCSD_MAX_SOCKETS_QUEUED) < 0) {
296
 
                LogError("Failed listen: %s", strerror(errno));
 
478
#endif
 
479
 
 
480
        if (setup_server_sockets(socks_info) == -1) {
 
481
                LogError("Could not create sockets to listen to connections. Aborting...");
297
482
                return -1;
298
483
        }
299
 
        client_len = (unsigned)sizeof(client_addr);
300
 
        
 
484
 
301
485
        if (getenv("TCSD_FOREGROUND") == NULL) {
302
486
                if (daemon(0, 0) == -1) {
303
487
                        perror("daemon");
304
 
                        tcsd_shutdown();
 
488
                        tcsd_shutdown(socks_info);
305
489
                        return -1;
306
490
                }
307
491
        }
308
492
 
309
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
 
310
502
        do {
311
 
                newsd = accept(sd, (struct sockaddr *) &client_addr, &client_len);
312
 
                if (newsd < 0) {
313
 
                        if (errno == EINTR) {
314
 
                                if (term)
315
 
                                        break;
316
 
                                else if (hup) {
317
 
                                        if (reload_config() != TSS_SUCCESS)
318
 
                                                LogError("Failed reloading config");
319
 
                                }
320
 
                                continue;
321
 
                        } else {
322
 
                                LogError("Failed accept: %s", strerror(errno));
323
 
                                continue;
324
 
                        }
325
 
                }
326
 
                LogDebug("accepted socket %i", newsd);
327
 
 
328
 
                if ((client_hostent = gethostbyaddr((char *) &client_addr.sin_addr,
329
 
                                                    sizeof(client_addr.sin_addr),
330
 
                                                    AF_INET)) == NULL) {
331
 
                        char buf[16];
332
 
                        uint32_t addr = htonl(client_addr.sin_addr.s_addr);
333
 
 
334
 
                        snprintf(buf, 16, "%d.%d.%d.%d", (addr & 0xff000000) >> 24,
335
 
                                 (addr & 0x00ff0000) >> 16, (addr & 0x0000ff00) >> 8,
336
 
                                 addr & 0x000000ff);
337
 
 
338
 
                        LogWarn("Host name for connecting IP %s could not be resolved", buf);
339
 
                        hostname = strdup(buf);
340
 
                } else {
341
 
                        hostname = strdup(client_hostent->h_name);
342
 
                }
343
 
 
344
 
                tcsd_thread_create(newsd, hostname);
345
 
                hostname = NULL;
 
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.
346
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
                        }
347
521
                        if (reload_config() != TSS_SUCCESS)
348
522
                                LogError("Failed reloading config");
349
 
                }
 
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++)
350
565
        } while (term ==0);
351
566
 
352
567
        /* To close correctly, we must receive a SIGTERM */
353
 
        tcsd_shutdown();
 
568
        tcsd_shutdown(socks_info);
354
569
        return 0;
355
570
}