Home | History | Annotate | Download | only in src
      1 /*
      2  * tlsdated.c - invoke tlsdate when necessary.
      3  * Copyright (c) 2012 The Chromium Authors. All rights reserved.
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  *
      7  * We invoke tlsdate once at system startup, then we start trying to invoke
      8  * tlsdate when a new network route appears. We try a few times after each route
      9  * comes up. As soon as we get a successful tlsdate run, we save that timestamp
     10  * to disk, then linger to wait for system shutdown. At system shutdown
     11  * (indicated by us getting SIGTERM), we save our timestamp to disk.
     12  */
     13 
     14 #include "config.h"
     15 
     16 #include <assert.h>
     17 #include <errno.h>
     18 #include <grp.h> /* setgroups */
     19 #include <fcntl.h>
     20 #include <limits.h>
     21 #include <linux/rtc.h>
     22 #include <stdarg.h>
     23 #include <stdbool.h>
     24 #include <stdio.h>
     25 #include <stdint.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <sys/ioctl.h>
     29 #include <sys/stat.h>
     30 #include <sys/time.h>
     31 #include <sys/wait.h>
     32 #include <time.h>
     33 #include <unistd.h>
     34 
     35 
     36 #include <event2/event.h>
     37 
     38 #include "src/conf.h"
     39 #include "src/routeup.h"
     40 #include "src/util.h"
     41 #include "src/tlsdate.h"
     42 #include "src/dbus.h"
     43 #include "src/platform.h"
     44 
     45 
     46 static const char kTlsdatedOpts[] = "hwrpt:d:T:D:c:a:lsvbm:j:f:x:Uu:g:G:";
     47 const char *kCacheDir = DEFAULT_DAEMON_CACHEDIR;
     48 
     49 int
     50 is_sane_time (time_t ts)
     51 {
     52   return ts > RECENT_COMPILE_DATE && ts < TLSDATED_MAX_DATE;
     53 }
     54 
     55 /*
     56  * Load a time value out of the file named by path. Returns 0 if successful,
     57  * -1 if not. The file contains the time in seconds since epoch in host byte
     58  * order.
     59  */
     60 int
     61 load_disk_timestamp (const char *path, time_t * t)
     62 {
     63   int fd = platform->file_open (path, 0 /* RDONLY */, 1 /* CLOEXEC */);
     64   time_t tmpt = 0;
     65   if (fd < 0)
     66     {
     67       perror ("Can't open %s for reading", path);
     68       return -1;
     69     }
     70   if (platform->file_read(fd, &tmpt, sizeof(tmpt)))
     71     {
     72       perror ("Can't read seconds from %s", path);
     73       platform->file_close (fd);
     74       return -1;
     75     }
     76   platform->file_close (fd);
     77   if (!is_sane_time (tmpt))
     78     {
     79       error ("Disk timestamp is not sane: %ld", tmpt);
     80       return -1;
     81     }
     82   *t = tmpt;
     83   return 0;
     84 }
     85 
     86 
     87 void
     88 usage (const char *progn)
     89 {
     90   printf ("Usage: %s [flags...] [--] [tlsdate command...]\n", progn);
     91   printf ("  -w        don't set hwclock\n");
     92   printf ("  -p        dry run (don't really set time)\n");
     93   printf ("  -r        use stdin instead of netlink for routes\n");
     94   printf ("  -t <n>    try n times to synchronize the time\n");
     95   printf ("  -d <n>    delay n seconds between tries\n");
     96   printf ("  -T <n>    give subprocess n chances to exit\n");
     97   printf ("  -D <n>    delay n seconds between wait attempts\n");
     98   printf ("  -c <path> set the cache directory\n");
     99   printf ("  -a <n>    run at most every n seconds in steady state\n");
    100   printf ("  -m <n>    run at most once every n seconds in steady state\n");
    101   printf ("  -j <n>    add up to n seconds jitter to steady state checks\n");
    102   printf ("  -l        don't load disk timestamps\n");
    103   printf ("  -s        don't save disk timestamps\n");
    104   printf ("  -U        don't use DBus if supported\n");
    105   printf ("  -u <user> user to change to\n");
    106   printf ("  -g <grp>  group to change to\n");
    107   printf ("  -G <grps> comma-separated list of supplementary groups\n");
    108   printf ("  -v        be verbose\n");
    109   printf ("  -b        use verbose debugging\n");
    110   printf ("  -x <h>    set proxy for subprocs to h\n");
    111   printf ("  -h        this\n");
    112 }
    113 
    114 void
    115 set_conf_defaults (struct opts *opts)
    116 {
    117   static char *kDefaultArgv[] =
    118   {
    119     (char *) DEFAULT_TLSDATE, (char *) "-H", (char *) DEFAULT_HOST, NULL
    120   };
    121   opts->user = UNPRIV_USER;
    122   opts->group = UNPRIV_GROUP;
    123   opts->supp_groups = NULL;
    124   opts->max_tries = MAX_TRIES;
    125   opts->min_steady_state_interval = STEADY_STATE_INTERVAL;
    126   opts->wait_between_tries = WAIT_BETWEEN_TRIES;
    127   opts->subprocess_tries = SUBPROCESS_TRIES;
    128   opts->subprocess_wait_between_tries = SUBPROCESS_WAIT_BETWEEN_TRIES;
    129   opts->steady_state_interval = STEADY_STATE_INTERVAL;
    130   opts->continuity_interval = CONTINUITY_INTERVAL;
    131   opts->base_path = kCacheDir;
    132   opts->base_argv = kDefaultArgv;
    133   opts->argv = NULL;
    134   opts->should_dbus = 1;
    135   opts->should_sync_hwclock = DEFAULT_SYNC_HWCLOCK;
    136   opts->should_load_disk = DEFAULT_LOAD_FROM_DISK;
    137   opts->should_save_disk = DEFAULT_SAVE_TO_DISK;
    138   opts->should_netlink = DEFAULT_USE_NETLINK;
    139   opts->dry_run = DEFAULT_DRY_RUN;
    140   opts->jitter = 0;
    141   opts->conf_file = NULL;
    142   opts->sources = NULL;
    143   opts->cur_source = NULL;
    144   opts->proxy = NULL;
    145   opts->leap = 0;
    146 }
    147 
    148 void
    149 parse_argv (struct opts *opts, int argc, char *argv[])
    150 {
    151   int opt;
    152   while ((opt = getopt (argc, argv, kTlsdatedOpts)) != -1)
    153     {
    154       switch (opt)
    155         {
    156         case 'w':
    157           opts->should_sync_hwclock = 0;
    158           break;
    159         case 'r':
    160           opts->should_netlink = 0;
    161           break;
    162         case 'U':
    163           opts->should_dbus = 0;
    164           break;
    165         case 'p':
    166           opts->dry_run = 1;
    167           break;
    168         case 't':
    169           opts->max_tries = atoi (optarg);
    170           break;
    171         case 'd':
    172           opts->wait_between_tries = atoi (optarg);
    173           break;
    174         case 'T':
    175           opts->subprocess_tries = atoi (optarg);
    176           break;
    177         case 'D':
    178           opts->subprocess_wait_between_tries = atoi (optarg);
    179           break;
    180         case 'c':
    181           opts->base_path = optarg;
    182           break;
    183         case 'a':
    184           opts->steady_state_interval = atoi (optarg);
    185           break;
    186         case 'l':
    187           opts->should_load_disk = 0;
    188           break;
    189         case 's':
    190           opts->should_save_disk = 0;
    191           break;
    192         case 'v':
    193           verbose = 1;
    194           break;
    195         case 'b':
    196           verbose_debug = 1;
    197           break;
    198         case 'm':
    199           opts->min_steady_state_interval = atoi (optarg);
    200           break;
    201         case 'j':
    202           opts->jitter = atoi (optarg);
    203           break;
    204         case 'f':
    205           opts->conf_file = optarg;
    206           break;
    207         case 'x':
    208           opts->proxy = optarg;
    209           break;
    210         case 'u':
    211           opts->user = optarg;
    212           break;
    213         case 'g':
    214           opts->group = optarg;
    215           break;
    216         case 'G':
    217           opts->supp_groups = optarg;
    218           break;
    219         case 'h':
    220         default:
    221           usage (argv[0]);
    222           exit (1);
    223         }
    224     }
    225   if (optind < argc)
    226     opts->base_argv = argv + optind;
    227   /* Validate arguments */
    228 }
    229 
    230 static
    231 void add_source_to_conf (struct opts *opts, char *host, char *port, char *proxy)
    232 {
    233   struct source *s;
    234   struct source *source = (struct source *) calloc (1, sizeof *source);
    235   if (!source)
    236     fatal ("out of memory for source");
    237   source->host = strdup (host);
    238   if (!source->host)
    239     fatal ("out of memory for host");
    240   source->port = strdup (port);
    241   if (!source->port)
    242     fatal ("out of memory for port");
    243   if (proxy)
    244     {
    245       source->proxy = strdup (proxy);
    246       if (!source->proxy)
    247         fatal ("out of memory for proxy");
    248     }
    249   if (!opts->sources)
    250     {
    251       opts->sources = source;
    252       source->id = 0;
    253     }
    254   else
    255     {
    256       for (s = opts->sources; s->next; s = s->next)
    257         ;
    258       source->id = s->id + 1;
    259       s->next = source;
    260     }
    261 }
    262 
    263 static struct conf_entry *
    264 parse_source (struct opts *opts, struct conf_entry *conf)
    265 {
    266   char *host = NULL;
    267   char *port = NULL;
    268   char *proxy = NULL;
    269   /* a source entry:
    270    * source
    271    *   host <host>
    272    *   port <port>
    273    *   [proxy <proxy>]
    274    * end
    275    */
    276   assert (!strcmp (conf->key, "source"));
    277   conf = conf->next;
    278   while (conf && strcmp (conf->key, "end"))
    279     {
    280       if (!strcmp (conf->key, "host"))
    281         host = conf->value;
    282       else if (!strcmp (conf->key, "port"))
    283         port = conf->value;
    284       else if (!strcmp (conf->key, "proxy"))
    285         proxy = conf->value;
    286       else
    287         fatal ("malformed config: '%s' in source stanza", conf->key);
    288       conf = conf->next;
    289     }
    290   if (!conf)
    291     fatal ("unclosed source stanza");
    292   if (!host || !port)
    293     fatal ("incomplete source stanza (needs host, port)");
    294   add_source_to_conf (opts, host, port, proxy);
    295   return conf;
    296 }
    297 
    298 void
    299 load_conf (struct opts *opts)
    300 {
    301   FILE *f;
    302   struct conf_entry *conf, *e;
    303   char *conf_file = opts->conf_file;
    304   if (!opts->conf_file)
    305     conf_file = (char *) DEFAULT_CONF_FILE;
    306   f = fopen (conf_file, "r");
    307   if (!f)
    308     {
    309       if (opts->conf_file)
    310         {
    311           pfatal ("can't open conf file '%s'", opts->conf_file);
    312         }
    313       else
    314         {
    315           pinfo ("can't open conf file '%s'", conf_file);
    316           return;
    317         }
    318     }
    319   conf = conf_parse (f);
    320   if (!conf)
    321     pfatal ("can't parse config file");
    322 
    323   for (e = conf; e; e = e->next)
    324     {
    325       if (!strcmp (e->key, "max-tries") && e->value)
    326         {
    327           opts->max_tries = atoi (e->value);
    328         }
    329       else if (!strcmp (e->key, "min-steady-state-interval") && e->value)
    330         {
    331           opts->min_steady_state_interval = atoi (e->value);
    332         }
    333       else if (!strcmp (e->key, "wait-between-tries") && e->value)
    334         {
    335           opts->wait_between_tries = atoi (e->value);
    336         }
    337       else if (!strcmp (e->key, "subprocess-tries") && e->value)
    338         {
    339           opts->subprocess_tries = atoi (e->value);
    340         }
    341       else if (!strcmp (e->key, "subprocess-wait-between-tries") && e->value)
    342         {
    343           opts->subprocess_wait_between_tries = atoi (e->value);
    344         }
    345       else if (!strcmp (e->key, "steady-state-interval") && e->value)
    346         {
    347           opts->steady_state_interval = atoi (e->value);
    348         }
    349       else if (!strcmp (e->key, "base-path") && e->value)
    350         {
    351           opts->base_path = strdup (e->value);
    352           if (!opts->base_path)
    353             fatal ("out of memory for base path");
    354         }
    355       else if (!strcmp (e->key, "should-sync-hwclock"))
    356         {
    357           opts->should_sync_hwclock = e->value ? !strcmp (e->value, "yes") : 1;
    358         }
    359       else if (!strcmp (e->key, "should-load-disk"))
    360         {
    361           opts->should_load_disk = e->value ? !strcmp (e->value, "yes") : 1;
    362         }
    363       else if (!strcmp (e->key, "should-save-disk"))
    364         {
    365           opts->should_save_disk = e->value ? !strcmp (e->value, "yes") : 1;
    366         }
    367       else if (!strcmp (e->key, "should-netlink"))
    368         {
    369           opts->should_netlink = e->value ? !strcmp (e->value, "yes") : 1;
    370         }
    371       else if (!strcmp (e->key, "dry-run"))
    372         {
    373           opts->dry_run = e->value ? !strcmp (e->value, "yes") : 1;
    374         }
    375       else if (!strcmp (e->key, "jitter") && e->value)
    376         {
    377           opts->jitter = atoi (e->value);
    378         }
    379       else if (!strcmp (e->key, "verbose"))
    380         {
    381           verbose = e->value ? !strcmp (e->value, "yes") : 1;
    382         }
    383       else if (!strcmp (e->key, "source"))
    384         {
    385           e = parse_source (opts, e);
    386         }
    387      else if (!strcmp (e->key, "leap"))
    388         {
    389           opts->leap = e->value ? !strcmp (e->value, "yes") : 1;
    390         }
    391    }
    392 }
    393 
    394 void
    395 check_conf (struct state *state)
    396 {
    397   struct opts *opts = &state->opts;
    398   if (!opts->max_tries)
    399     fatal ("-t argument must be nonzero");
    400   if (!opts->wait_between_tries)
    401     fatal ("-d argument must be nonzero");
    402   if (!opts->steady_state_interval)
    403     fatal ("-a argument must be nonzero");
    404   int ret = snprintf (state->timestamp_path, sizeof (state->timestamp_path),
    405 		      "%s/timestamp", opts->base_path);
    406   if (ret < 0 || ((size_t) ret) >= sizeof (state->timestamp_path))
    407     fatal ("supplied base path is too long: '%s'", opts->base_path);
    408   if (opts->jitter >= opts->steady_state_interval)
    409     fatal ("jitter must be less than steady state interval (%d >= %d)",
    410            opts->jitter, opts->steady_state_interval);
    411 }
    412 
    413 int
    414 cleanup_main (struct state *state)
    415 {
    416   int i;
    417   for (i = 0; i < E_MAX; ++i)
    418     {
    419       struct event *e = state->events[i];
    420       if (e)
    421         {
    422           int fd = event_get_fd (e);
    423           if (fd >= 0 && ! (event_get_events (e) & EV_SIGNAL))
    424             close (fd);
    425           event_free (e);
    426         }
    427     }
    428   /* The other half was closed above. */
    429   platform->file_close (state->tlsdate_monitor_fd);
    430   if (state->tlsdate_pid)
    431     {
    432       platform->process_signal (state->tlsdate_pid, SIGKILL);
    433       platform->process_wait (state->tlsdate_pid, NULL, 0 /* !forever */);
    434     }
    435   /* Best effort to tear it down if it is still alive. */
    436   close(state->setter_notify_fd);
    437   close(state->setter_save_fd);
    438   if (state->setter_pid)
    439     {
    440       platform->process_signal (state->setter_pid, SIGKILL);
    441       platform->process_wait (state->setter_pid, NULL, 0 /* !forever */);
    442     }
    443   /* TODO(wad) Add dbus_cleanup() */
    444   if (state->base)
    445     event_base_free (state->base);
    446   memset(state, 0, sizeof(*state));
    447   info ("tlsdated clean up finished; exiting!");
    448   terminate_syslog ();
    449   return 0;
    450 }
    451 
    452 #ifdef TLSDATED_MAIN
    453 static const char **
    454 parse_supp_groups (char *arg)
    455 {
    456   size_t i;
    457   char *scan;
    458   const char **supp_groups;
    459 
    460   for (i = 1, scan = arg; (scan = strchr (scan, ',')); i++, scan++) ;
    461   supp_groups = (const char **) calloc (i + 1, sizeof (const char *));
    462   if (!supp_groups)
    463     die ("Failed to allocate memory for supplementary group names\n");
    464   for (i = 0; (supp_groups[i] = strsep (&arg, ",")); i++) ;
    465   return supp_groups;
    466 }
    467 
    468 int API
    469 main (int argc, char *argv[], char *envp[])
    470 {
    471   const char **supp_groups = NULL;
    472 
    473   initalize_syslog ();
    474   struct state state;
    475   /* TODO(wad) EVENT_BASE_FLAG_PRECISE_TIMER | EVENT_BASE_FLAG_PRECISE_TIMER */
    476   struct event_base *base = event_base_new();
    477   if (!base)
    478     {
    479       fatal ("could not allocated new event base");
    480     }
    481   /* Add three priority levels:
    482    * 0 - time saving.  Must be done before any other events are handled.
    483    * 1 - network synchronization events
    484    * 2 - any other events (wake, platform, etc)
    485    */
    486   event_base_priority_init (base, MAX_EVENT_PRIORITIES);
    487   memset (&state, 0, sizeof (state));
    488   set_conf_defaults (&state.opts);
    489   parse_argv (&state.opts, argc, argv);
    490   check_conf (&state);
    491   load_conf (&state.opts);
    492   check_conf (&state);
    493   if (!state.opts.sources)
    494     add_source_to_conf (&state.opts, DEFAULT_HOST, DEFAULT_PORT, DEFAULT_PROXY);
    495   state.base = base;
    496   state.envp = envp;
    497   state.backoff = state.opts.wait_between_tries;
    498   /* TODO(wad) move this into setup_time_setter */
    499   /* grab a handle to /dev/rtc for time-setter. */
    500   if (state.opts.should_sync_hwclock &&
    501       platform->rtc_open(&state.hwclock))
    502     {
    503       pinfo ("can't open hwclock fd");
    504       state.opts.should_sync_hwclock = 0;
    505     }
    506   /* install the SIGCHLD handler for the setter and tlsdate */
    507   if (setup_sigchld_event (&state, 1))
    508     {
    509       error ("Failed to setup SIGCHLD event");
    510       goto out;
    511     }
    512   /* fork off the privileged helper */
    513   verb ("spawning time setting helper . . .");
    514   if (setup_time_setter (&state))
    515     {
    516       error ("could not fork privileged coprocess");
    517       goto out;
    518     }
    519   /* release the hwclock now that the time-setter is running. */
    520   if (state.opts.should_sync_hwclock)
    521     {
    522       platform->rtc_close (&state.hwclock);
    523     }
    524   /* drop privileges before touching any untrusted data */
    525   if (state.opts.supp_groups)
    526     supp_groups = parse_supp_groups (state.opts.supp_groups);
    527   drop_privs_to (state.opts.user, state.opts.group, supp_groups);
    528   free (supp_groups);
    529   /* register a signal handler to save time at shutdown */
    530   if (state.opts.should_save_disk)
    531     {
    532       struct event *event = event_new (base, SIGTERM, EV_SIGNAL|EV_PERSIST,
    533                                        action_sigterm, &state);
    534       if (!event)
    535         fatal ("Failed to create SIGTERM event");
    536       event_priority_set (event, PRI_SAVE);
    537       event_add (event, NULL);
    538     }
    539   if (state.opts.should_dbus && init_dbus (&state))
    540     {
    541       error ("Failed to initialize DBus");
    542       goto out;
    543     }
    544   /* Register the tlsdate event before any listeners could show up. */
    545   state.events[E_TLSDATE] = event_new (base, -1, EV_TIMEOUT,
    546                                        action_run_tlsdate, &state);
    547   if (!state.events[E_TLSDATE])
    548     {
    549       error ("Failed to create tlsdate event");
    550       goto out;
    551     }
    552   event_priority_set (state.events[E_TLSDATE], PRI_NET);
    553   /* The timeout and fd will be filled in per-call. */
    554   if (setup_tlsdate_status (&state))
    555     {
    556       error ("Failed to create tlsdate status event");
    557       goto out;
    558     }
    559   /* TODO(wad) Could use a timeout on this to catch setter death? */
    560   /* EV_READ is for truncation/EPIPE notification */
    561   state.events[E_SAVE] = event_new (base, state.setter_save_fd,
    562                                     EV_READ|EV_WRITE, action_sync_and_save,
    563                                     &state);
    564   if (!state.events[E_SAVE])
    565     {
    566       error ("Failed to create sync & save event");
    567       goto out;
    568     }
    569   event_priority_set (state.events[E_SAVE], PRI_SAVE);
    570   /* Start by grabbing the system time. */
    571   state.last_sync_type = SYNC_TYPE_RTC;
    572   state.last_time = time (NULL);
    573   /* If possible, grab disk time and check the two. */
    574   if (state.opts.should_load_disk)
    575     {
    576       time_t disk_time = state.last_time;
    577       if (!load_disk_timestamp (state.timestamp_path, &disk_time))
    578         {
    579           verb ("disk timestamp available: yes (%ld)", disk_time);
    580           if (!is_sane_time (state.last_time) ||
    581               state.last_time < disk_time)
    582             {
    583               state.last_sync_type = SYNC_TYPE_DISK;
    584               state.last_time = disk_time;
    585             }
    586         }
    587       else
    588         {
    589           verb ("disk timestamp available: no");
    590         }
    591     }
    592   if (!is_sane_time (state.last_time))
    593     {
    594       state.last_sync_type = SYNC_TYPE_BUILD;
    595       state.last_time = RECENT_COMPILE_DATE + 1;
    596     }
    597   /* Save and announce the initial time source. */
    598   trigger_event (&state, E_SAVE, -1);
    599   verb ("tlsdated parasitic time synchronization initialized");
    600   info ("initial time sync type: %s", sync_type_str (state.last_sync_type));
    601   /* Initialize platform specific loop behavior */
    602   if (platform_init_cros (&state))
    603     {
    604       error ("Failed to initialize platform code");
    605       goto out;
    606     }
    607   if (setup_event_route_up (&state))
    608     {
    609       error ("Failed to setup route up monitoring");
    610       goto out;
    611     }
    612   if (setup_event_timer_sync (&state))
    613     {
    614       error ("Failed to setup a timer event");
    615       goto out;
    616     }
    617   if (setup_event_timer_continuity (&state))
    618     {
    619       error ("Failed to setup continuity timer");
    620       goto out;
    621     }
    622   /* Add a forced sync event to the event list. */
    623   action_kickoff_time_sync (-1, EV_TIMEOUT, &state);
    624   verb ("Entering dispatch . . .");
    625   event_base_dispatch (base);
    626   verb ("tlsdated event dispatch terminating gracefully");
    627 out:
    628   return cleanup_main (&state);
    629 }
    630 #endif /* !TLSDATED_MAIN */
    631