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 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 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 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 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 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