1 /*
2  * tlsdate_status.c - handles tlsdate-monitor responses
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 #include <errno.h>
11 #include <fcntl.h>
12 #include <stdbool.h>
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <unistd.h>
17 
18 #include <event2/event.h>
19 
20 #include "src/conf.h"
21 #include "src/util.h"
22 #include "src/tlsdate.h"
23 
24 /* Returns < 0 on error, > 0 on eagain, and 0 on success */
25 int
read_tlsdate_response(int fd,time_t * t)26 read_tlsdate_response (int fd, time_t *t)
27 {
28   /* TLS passes time as a 32-bit value. */
29   uint32_t server_time = 0;
30   ssize_t ret = IGNORE_EINTR (read (fd, &server_time, sizeof (server_time)));
31   if (ret == -1 && errno == EAGAIN)
32     {
33       /* Full response isn't ready yet. */
34       return 1;
35     }
36   if (ret != sizeof (server_time))
37     {
38       /* End of pipe (0) or truncated: death probable. */
39       error ("[event:(%s)] invalid time read from tlsdate (rd:%d,ret:%zd).",
40              __func__, server_time, ret);
41       return -1;
42     }
43   /* uint32_t moves to signed long so there is room for silliness. */
44   *t = server_time;
45   return 0;
46 }
47 
48 void
action_tlsdate_timeout(evutil_socket_t fd,short what,void * arg)49 action_tlsdate_timeout (evutil_socket_t fd, short what, void *arg)
50 {
51   struct state *state = arg;
52   info ("[event:%s] tlsdate timed out", __func__);
53   /* Force kill it and let action_sigchld rerun. */
54   if (state->tlsdate_pid)
55     kill (state->tlsdate_pid, SIGKILL);
56 }
57 
58 void
action_tlsdate_status(evutil_socket_t fd,short what,void * arg)59 action_tlsdate_status (evutil_socket_t fd, short what, void *arg)
60 {
61   struct state *state = arg;
62   time_t t = 0;
63   int ret = read_tlsdate_response (fd, &t);
64   verb_debug ("[event:%s] fired", __func__);
65   if (ret < 0)
66     {
67       verb_debug ("[event:%s] forcibly timing out tlsdate", __func__);
68       trigger_event (state, E_TLSDATE_TIMEOUT, 0);
69       return;
70     }
71   if (ret)
72     {
73       /* EAGAIN'd: wait for the rest. */
74       trigger_event (state, E_TLSDATE_STATUS, -1);
75       return;
76     }
77   if (is_sane_time (t))
78     {
79       /* Note that last_time is from an online source */
80       state->last_sync_type = SYNC_TYPE_NET;
81       state->last_time = t;
82       trigger_event (state, E_SAVE, -1);
83     }
84   else
85     {
86       error ("[event:%s] invalid time received from tlsdate: %ld",
87              __func__, t);
88     }
89   /* Restore the backoff and tries count on success, insane or not.
90    * On failure, the event handler does it.
91    */
92   state->tries = 0;
93   state->backoff = state->opts.wait_between_tries;
94   return;
95 }
96 
97 /* Returns 0 on success and populates |fds| */
98 int
new_tlsdate_monitor_pipe(int fds[2])99 new_tlsdate_monitor_pipe (int fds[2])
100 {
101   if (pipe (fds) < 0)
102     {
103       perror ("pipe failed");
104       return -1;
105     }
106   /* TODO(wad): CLOEXEC, Don't leak these into tlsdate proper. */
107   return 0;
108 }
109 
110 /* Create a fd pair that the tlsdate runner will communicate over */
111 int
setup_tlsdate_status(struct state * state)112 setup_tlsdate_status (struct state *state)
113 {
114   int fds[2] = { -1, -1 };
115   /* One pair of pipes are reused along with the event. */
116   if (new_tlsdate_monitor_pipe (fds))
117     {
118       return -1;
119     }
120   verb_debug ("[%s] monitor fd pair (%d, %d)", __func__, fds[0], fds[1]);
121   /* The fd that the monitor process will write to */
122   state->tlsdate_monitor_fd = fds[1];
123   /* Make the reader fd non-blocking and not leak into tlsdate. */
124   if (fcntl (fds[0], F_SETFL, O_NONBLOCK|O_CLOEXEC) < 0)
125     {
126       perror ("pipe[0] fcntl(O_NONBLOCK) failed");
127       return 1;
128     }
129   state->events[E_TLSDATE_STATUS] = event_new (state->base, fds[0],
130                                     EV_READ,
131                                     action_tlsdate_status, state);
132   if (!state->events[E_TLSDATE_STATUS])
133     {
134       error ("Failed to allocate tlsdate status event");
135       return 1;
136     }
137   event_priority_set (state->events[E_TLSDATE_STATUS], PRI_NET);
138   state->events[E_TLSDATE_TIMEOUT] = event_new (state->base, -1,
139                                      EV_TIMEOUT,
140                                      action_tlsdate_timeout, state);
141   if (!state->events[E_TLSDATE_TIMEOUT])
142     {
143       error ("Failed to allocate tlsdate timeout event");
144       return 1;
145     }
146   event_priority_set (state->events[E_TLSDATE_TIMEOUT], PRI_SAVE);
147   return 0;
148 }
149