1/*
2 * kickoff_time_sync.c - network time synchronization
3 * Copyright (c) 2013 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
8#include "config.h"
9
10#ifdef USE_POLARSSL
11#include <polarssl/entropy.h>
12#include <polarssl/ctr_drbg.h>
13#else
14#include <openssl/rand.h>
15#endif
16#include <stdlib.h>
17#include <time.h>
18#include <unistd.h>
19#include <event2/event.h>
20
21#include "src/conf.h"
22#include "src/util.h"
23#include "src/tlsdate.h"
24
25#ifdef USE_POLARSSL
26static int random_init = 0;
27static entropy_context entropy;
28static ctr_drbg_context ctr_drbg;
29static char *pers = "tlsdated";
30#endif
31
32int
33add_jitter (int base, int jitter)
34{
35  int n = 0;
36  if (!jitter)
37    return base;
38#ifdef USE_POLARSSL
39  if (0 == random_init)
40  {
41    entropy_init(&entropy);
42    if (0 > ctr_drbg_init(&ctr_drbg, entropy_func, &entropy,
43                          (unsigned char *) pers, strlen(pers)))
44    {
45      pfatal ("Failed to initialize random source");
46    }
47    random_init = 1;
48  }
49  if (0 != ctr_drbg_random(&ctr_drbg, (unsigned char *)&n, sizeof(n)))
50    fatal ("ctr_drbg_random() failed");
51#else
52  if (RAND_bytes ( (unsigned char *) &n, sizeof (n)) != 1)
53    fatal ("RAND_bytes() failed");
54#endif
55  return base + (abs (n) % (2 * jitter)) - jitter;
56}
57
58void
59invalidate_time (struct state *state)
60{
61  state->last_sync_type = SYNC_TYPE_RTC;
62  state->last_time = time (NULL);
63  /* Note(!) this does not invalidate the clock_delta implicitly.
64   * This allows forced invalidation to not lose synchronization
65   * data.
66   */
67}
68
69void
70action_invalidate_time (evutil_socket_t fd, short what, void *arg)
71{
72  struct state *state = arg;
73  verb_debug ("[event:%s] fired", __func__);
74  /* If time is already invalid and being acquired, do nothing. */
75  if (state->last_sync_type == SYNC_TYPE_RTC &&
76      event_pending (state->events[E_TLSDATE], EV_TIMEOUT, NULL))
77    return;
78  /* Time out our trust in network synchronization but don't persist
79   * the change to disk or notify the system.  Let a network sync
80   * failure or success do that.
81   */
82  invalidate_time (state);
83  /* Then trigger a network sync if possible. */
84  action_kickoff_time_sync (-1, EV_TIMEOUT, arg);
85}
86
87int
88setup_event_timer_sync (struct state *state)
89{
90  int wait_time = add_jitter (state->opts.steady_state_interval,
91                              state->opts.jitter);
92  struct timeval interval = { wait_time, 0 };
93  state->events[E_STEADYSTATE] = event_new (state->base, -1,
94                                 EV_TIMEOUT|EV_PERSIST,
95                                 action_invalidate_time, state);
96  if (!state->events[E_STEADYSTATE])
97    {
98      error ("Failed to create interval event");
99      return 1;
100    }
101  event_priority_set (state->events[E_STEADYSTATE], PRI_ANY);
102  return event_add (state->events[E_STEADYSTATE], &interval);
103}
104
105/* Begins a network synchronization attempt.  If the local clocks
106 * are synchronized, then make sure that the _current_ synchronization
107 * source is set to the real-time clock and note that the clock_delta
108 * is unreliable.  If the clock was in sync and the last synchronization
109 * source was the network, then this action does nothing.
110 *
111 * In the case of desynchronization, the clock_delta value is used as a
112 * guard to indicate that even if the synchronization source isn't the
113 * network, the source is still tracking the clock delta that was
114 * established from a network source.
115 * TODO(wad) Change the name of clock_delta to indicate that it is the local
116 *           clock delta after the last network sync.
117 */
118void action_kickoff_time_sync (evutil_socket_t fd, short what, void *arg)
119{
120  struct state *state = arg;
121  verb_debug ("[event:%s] fired", __func__);
122  time_t delta = state->clock_delta;
123  int jitter = 0;
124  if (check_continuity (&delta) > 0)
125    {
126      info ("[event:%s] clock delta desync detected (%d != %d)", __func__,
127            state->clock_delta, delta);
128      /* Add jitter iff we had network synchronization once before. */
129      if (state->clock_delta)
130        jitter = add_jitter (30, 30); /* TODO(wad) make configurable */
131      /* Forget the old delta until we have time again. */
132      state->clock_delta = 0;
133      invalidate_time (state);
134    }
135  if (state->last_sync_type == SYNC_TYPE_NET)
136    {
137      verb_debug ("[event:%s] time in sync. skipping", __func__);
138      return;
139    }
140  /* Keep parity with run_tlsdate: for every wake, allow it to retry again. */
141  if (state->tries > 0)
142    {
143      state->tries -= 1;
144      /* Don't bother re-triggering tlsdate */
145      verb_debug ("[event:%s] called while tries are in progress", __func__);
146      return;
147    }
148  /* Don't over-schedule if the first attempt hasn't fired. If a wake event
149   * impacts the result of a proxy resolution, then the updated value can be
150   * acquired on the next run. If the wake comes in after E_TLSDATE is
151   * serviced, then the tries count will be decremented.
152   */
153  if (event_pending (state->events[E_TLSDATE], EV_TIMEOUT, NULL))
154    {
155      verb_debug ("[event:%s] called while tlsdate is pending", __func__);
156      return;
157    }
158  if (!state->events[E_RESOLVER])
159    {
160      trigger_event (state, E_TLSDATE, jitter);
161      return;
162    }
163  /* If the resolver relies on an external response, then make sure that a
164   * tlsdate event is waiting in the wings if the resolver is too slow.  Even
165   * if this fires, it won't stop eventual handling of the resolver since it
166   * doesn't event_del() E_RESOLVER.
167   */
168  trigger_event (state, E_TLSDATE, jitter + RESOLVER_TIMEOUT);
169  trigger_event (state, E_RESOLVER, jitter);
170}
171