• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * dbus.c - event loop dbus integration
3  * Copyright (c) 2013 The Chromium OS 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 #include "config.h"
8 
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <time.h>
13 #include <unistd.h>
14 
15 #include <dbus/dbus.h>
16 #include <event2/event.h>
17 #include "src/dbus.h"
18 #include "src/tlsdate.h"
19 #include "src/util.h"
20 
21 /* Pointers are needed so that we don't have to deal with array-to-pointer
22  * weirdness with DBus argument passing.
23  */
24 static const char kServiceInterfaceData[] = "org.torproject.tlsdate";
25 static const char *kServiceInterface = kServiceInterfaceData;
26 static const char kServicePathData[] = "/org/torproject/tlsdate";
27 static const char *kServicePath = kServicePathData;
28 static const char kServiceSetTimeData[] = "SetTime";
29 static const char *kServiceSetTime = kServiceSetTimeData;
30 static const char kServiceCanSetTimeData[] = "CanSetTime";
31 static const char *kServiceCanSetTime = kServiceCanSetTimeData;
32 static const char kServiceLastSyncInfoData[] = "LastSyncInfo";
33 static const char *kServiceLastSyncInfo = kServiceLastSyncInfoData;
34 
35 static const char kTimeUpdatedData[] = "TimeUpdated";
36 static const char *kTimeUpdated = kTimeUpdatedData;
37 
38 static
39 short
dbus_to_event(unsigned int flags)40 dbus_to_event (unsigned int flags)
41 {
42   short events = 0;
43   if (flags & DBUS_WATCH_READABLE)
44     events |= EV_READ;
45   if (flags & DBUS_WATCH_WRITABLE)
46     events |= EV_WRITE;
47   return events;
48 }
49 
50 static
51 unsigned int
event_to_dbus(short events)52 event_to_dbus (short events)
53 {
54   unsigned int flags = 0;
55   if (events & EV_READ)
56     flags |= DBUS_WATCH_READABLE;
57   if (events & EV_WRITE)
58     flags |= DBUS_WATCH_WRITABLE;
59   return flags;
60 }
61 
62 static
63 void
watch_handler(evutil_socket_t fd,short what,void * arg)64 watch_handler (evutil_socket_t fd, short what, void *arg)
65 {
66   DBusWatch *watch = arg;
67   struct dbus_event_data *data = dbus_watch_get_data (watch);
68   unsigned int flags = event_to_dbus (what);
69   dbus_connection_ref (data->state->conn);
70   while (!dbus_watch_handle (watch, flags))
71     {
72       info ("dbus_watch_handle waiting for memory . . .");
73       /* TODO(wad) this seems like a bad idea. */
74       sleep (1);
75     }
76   while (dbus_connection_dispatch (data->state->conn) ==
77          DBUS_DISPATCH_DATA_REMAINS);
78   dbus_connection_unref (data->state->conn);
79 }
80 
81 static
82 dbus_bool_t
add_watch(DBusWatch * watch,void * user_data)83 add_watch (DBusWatch *watch, void *user_data)
84 {
85   struct state *tlsdate_state = user_data;
86   struct dbus_state *state = tlsdate_state->dbus;
87   struct dbus_event_data *data;
88   /* Don't add anything if it isn't active. */
89   data = dbus_malloc0 (sizeof (struct dbus_event_data));
90   if (!data)
91     return FALSE;
92   data->state = state;
93   data->event = event_new (tlsdate_state->base,
94                            dbus_watch_get_unix_fd (watch),
95                            EV_PERSIST|dbus_to_event (dbus_watch_get_flags (watch)),
96                            watch_handler,
97                            watch);
98   if (!data->event)
99     {
100       dbus_free (data);
101       return FALSE;
102     }
103   event_priority_set (data->event, PRI_WAKE);
104 
105   dbus_watch_set_data (watch, data, dbus_free);
106   if (!dbus_watch_get_enabled (watch))
107     return TRUE;
108   /* Only add the event if it is enabled. */
109   if (event_add (data->event, NULL))
110     {
111       error ("Could not add a new watch!");
112       event_free (data->event);
113       dbus_free (data);
114       return FALSE;
115     }
116   return TRUE;
117 }
118 
119 static
120 void
remove_watch(DBusWatch * watch,void * user_data)121 remove_watch (DBusWatch *watch, void *user_data)
122 {
123   struct dbus_event_data *data = dbus_watch_get_data (watch);
124   /* TODO(wad) should this just be in a free_function? */
125   if (data && data->event)
126     {
127       event_del (data->event);
128       event_free (data->event);
129     }
130 }
131 
132 static
133 void
toggle_watch(DBusWatch * watch,void * user_data)134 toggle_watch (DBusWatch *watch, void *user_data)
135 {
136   struct dbus_event_data *data = dbus_watch_get_data (watch);
137   if (!data || !data->event)  /* should not be possible */
138     return;
139   /* If the event is pending, then we have to remove it to
140    * disable it or remove it before re-enabling it.
141    */
142   if (event_pending (data->event,
143                      dbus_to_event (dbus_watch_get_flags (watch)), NULL))
144     event_del (data->event);
145   if (dbus_watch_get_enabled (watch))
146     {
147       event_add (data->event, NULL);
148     }
149 }
150 
151 static
152 void
timeout_handler(evutil_socket_t fd,short what,void * arg)153 timeout_handler (evutil_socket_t fd, short what, void *arg)
154 {
155   DBusTimeout *t = arg;
156   struct dbus_event_data *data = dbus_timeout_get_data (t);
157   dbus_connection_ref (data->state->conn);
158   dbus_timeout_handle (t);
159   dbus_connection_unref (data->state->conn);
160 }
161 
162 static
163 dbus_bool_t
add_timeout(DBusTimeout * t,void * user_data)164 add_timeout (DBusTimeout *t, void *user_data)
165 {
166   struct state *tlsdate_state = user_data;
167   struct dbus_state *state = tlsdate_state->dbus;
168   struct dbus_event_data *data;
169   int ms = dbus_timeout_get_interval (t);
170   struct timeval interval;
171   data = dbus_malloc0 (sizeof (struct dbus_event_data));
172   if (!data)
173     return FALSE;
174   interval.tv_sec = ms / 1000;
175   interval.tv_usec = (ms % 1000) * 1000;
176   data->state = state;
177   data->event = event_new (tlsdate_state->base,
178                            -1,
179                            EV_TIMEOUT|EV_PERSIST,
180                            timeout_handler,
181                            t);
182   if (!data->event)
183     {
184       dbus_free (data);
185       return FALSE;
186     }
187   event_priority_set (data->event, PRI_WAKE);
188   dbus_timeout_set_data (t, data, dbus_free);
189   /* Only add it to the queue if it is enabled. */
190   if (!dbus_timeout_get_enabled (t))
191     return TRUE;
192   if (event_add (data->event, &interval))
193     {
194       error ("Could not add a new timeout!");
195       event_free (data->event);
196       dbus_free (data);
197       return FALSE;
198     }
199   return TRUE;
200 }
201 
202 static
203 void
remove_timeout(DBusTimeout * t,void * user_data)204 remove_timeout (DBusTimeout *t, void *user_data)
205 {
206   struct dbus_event_data *data = dbus_timeout_get_data (t);
207   if (data && data->event)
208     {
209       event_del (data->event);
210       event_free (data->event);
211     }
212 }
213 
214 static
215 void
toggle_timeout(DBusTimeout * t,void * user_data)216 toggle_timeout (DBusTimeout *t, void *user_data)
217 {
218   struct dbus_event_data *data = dbus_timeout_get_data (t);
219   int ms = dbus_timeout_get_interval (t);
220   struct timeval interval;
221   /* If the event is pending, then we have to remove it to
222    * disable it or remove it before re-enabling it.
223    */
224   if (evtimer_pending (data->event, NULL))
225     event_del (data->event);
226   if (dbus_timeout_get_enabled (t))
227     {
228       interval.tv_sec = ms / 1000;
229       interval.tv_usec = (ms % 1000) * 1000;
230       event_add (data->event, &interval);
231     }
232 }
233 
234 void
dbus_announce(struct state * global_state)235 dbus_announce (struct state *global_state)
236 {
237   struct dbus_state *state = global_state->dbus;
238   DBusConnection *conn;
239   DBusMessage *msg;
240   uint32_t ignored;
241   const char *sync_type = sync_type_str (global_state->last_sync_type);
242 
243 #ifndef TLSDATED_MAIN
244   /* Return early if we're not linked to tlsdated. */
245   return;
246 #endif
247 
248   conn = state->conn;
249   msg = dbus_message_new_signal (kServicePath, kServiceInterface, kTimeUpdated);
250   if (!msg)
251     {
252       error ("[dbus] could not allocate new announce signal");
253       return;
254     }
255   if (!dbus_message_append_args (msg,
256                                  DBUS_TYPE_STRING, &sync_type,
257                                  DBUS_TYPE_INVALID))
258     {
259       error ("[dbus] could not allocate new announce args");
260       return;
261     }
262   if (!dbus_connection_send (conn, msg, &ignored))
263     {
264       error ("[dbus] could not send announce signal");
265       return;
266     }
267 }
268 
269 static
270 DBusHandlerResult
send_time_reply(DBusConnection * connection,DBusMessage * message,dbus_uint32_t code)271 send_time_reply (DBusConnection *connection,
272                  DBusMessage *message,
273                  dbus_uint32_t code)
274 {
275    DBusMessage *reply;
276    DBusMessageIter args;
277    dbus_uint32_t serial = dbus_message_get_serial (message);
278 
279    reply = dbus_message_new_method_return (message);
280    if (!reply)
281      {
282        error ("[dbus] no memory to reply to SetTime");
283        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
284      }
285 
286   if (!dbus_message_set_reply_serial (reply, serial))
287     {
288       error ("[dbus] no memory to set serial for reply to SetTime");
289       dbus_message_unref (reply);
290       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
291     }
292 
293   dbus_message_iter_init_append (reply, &args);
294   if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_UINT32, &code))
295     {
296       error ("[dbus] no memory to add reply args to SetTime");
297       dbus_message_unref (reply);
298       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
299     }
300 
301   if (!dbus_connection_send (connection, reply, &serial))
302    {
303       error ("[dbus] unable to send SetTime reply");
304       dbus_message_unref (reply);
305       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
306    }
307   dbus_connection_flush (connection);
308   dbus_message_unref (reply);
309   return DBUS_HANDLER_RESULT_HANDLED;
310 }
311 
312 static
313 DBusHandlerResult
send_can_reply(DBusConnection * connection,DBusMessage * message,dbus_bool_t allowed)314 send_can_reply (DBusConnection *connection,
315                 DBusMessage *message,
316                 dbus_bool_t allowed)
317 {
318   DBusMessage *reply;
319   DBusMessageIter args;
320   dbus_uint32_t serial = dbus_message_get_serial (message);
321 
322   reply = dbus_message_new_method_return (message);
323   if (!reply)
324     {
325       error ("[dbus] no memory to reply to CanSetTime");
326       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
327     }
328 
329   if (!dbus_message_set_reply_serial (reply, serial))
330     {
331       error ("[dbus] no memory to set serial for reply to CanSetTime");
332       dbus_message_unref (reply);
333       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
334     }
335 
336   dbus_message_iter_init_append (reply, &args);
337   if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_BOOLEAN, &allowed))
338     {
339       error ("[dbus] no memory to add reply args to CanSetTime");
340       dbus_message_unref (reply);
341       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
342     }
343 
344   if (!dbus_connection_send (connection, reply, &serial))
345    {
346       error ("[dbus] unable to send CanSetTime reply");
347       dbus_message_unref (reply);
348       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
349    }
350   dbus_connection_flush (connection);
351   dbus_message_unref (reply);
352   return DBUS_HANDLER_RESULT_HANDLED;
353 }
354 
355 /* Returns 0 if time cannot be set, and 1 otherwise. */
356 static
357 int
can_set_time(struct state * state)358 can_set_time (struct state *state)
359 {
360   time_t delta = state->clock_delta;
361   /* Force a synchronization check. */
362   if (check_continuity (&delta) > 0)
363     {
364       info ("[event:%s] clock delta desync detected (%ld != %ld)",
365             __func__, state->clock_delta, delta);
366       delta = state->clock_delta = 0;
367       invalidate_time (state);
368     }
369   /* Only use the time if we're not synchronized. */
370   return !state->clock_delta;
371 }
372 
373 static
374 DBusHandlerResult
handle_set_time(DBusConnection * connection,DBusMessage * message,struct state * state)375 handle_set_time (DBusConnection *connection,
376                  DBusMessage *message,
377                  struct state *state)
378 {
379   DBusMessageIter iter;
380   DBusError error;
381   dbus_int64_t requested_time = 0;
382   verb_debug ("[event:%s]: fired", __func__);
383   dbus_error_init (&error);
384 
385   /* Expects DBUS_TYPE_INT64:<time_t> */
386   if (!dbus_message_iter_init (message, &iter))
387     return send_time_reply (connection, message, SET_TIME_BAD_CALL);
388   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT64)
389     return send_time_reply (connection, message, SET_TIME_BAD_CALL);
390   dbus_message_iter_get_basic (&iter, &requested_time);
391   if (!is_sane_time ((time_t) requested_time))
392     {
393       error ("event:%s] invalid time from user: %ld", __func__,
394              (time_t) requested_time);
395       return send_time_reply (connection, message, SET_TIME_INVALID);
396     }
397   if (!can_set_time (state))
398     {
399       info ("[event:%s]: time is already synchronized.", __func__);
400       return send_time_reply (connection, message, SET_TIME_NOT_ALLOWED);
401     }
402 
403   state->last_time = requested_time;
404   state->last_sync_type = SYNC_TYPE_PLATFORM;
405   trigger_event (state, E_SAVE, -1);
406   /* Kick off a network sync for good measure. */
407   action_kickoff_time_sync (-1, EV_TIMEOUT, state);
408 
409   return send_time_reply (connection, message, SET_TIME_OK);
410 }
411 
412 static
413 DBusHandlerResult
handle_can_set_time(DBusConnection * connection,DBusMessage * message,struct state * state)414 handle_can_set_time (DBusConnection *connection,
415                      DBusMessage *message,
416                      struct state *state)
417 {
418   verb_debug ("[event:%s]: fired", __func__);
419   return send_can_reply (connection, message, can_set_time (state));
420 }
421 
422 static
423 DBusHandlerResult
handle_last_sync_info(DBusConnection * connection,DBusMessage * message,struct state * state)424 handle_last_sync_info (DBusConnection *connection,
425                        DBusMessage *message,
426                        struct state *state)
427 {
428   DBusMessage *reply;
429   DBusMessageIter args;
430   dbus_uint32_t serial = dbus_message_get_serial (message);
431   dbus_bool_t net_synced = !!state->clock_delta;
432   const char *sync = sync_type_str (state->last_sync_type);
433   int64_t t = state->last_time;
434 
435   verb_debug ("[dbus]: handler fired");
436   reply = dbus_message_new_method_return (message);
437   if (!reply)
438     {
439       error ("[dbus] no memory to reply to LastSyncInfo");
440       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
441     }
442 
443   if (!dbus_message_set_reply_serial (reply, serial))
444     {
445      error ("[dbus] no memory to set serial for reply to LastSyncInfo");
446      dbus_message_unref (reply);
447       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
448     }
449 
450   dbus_message_iter_init_append (reply, &args);
451   if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_BOOLEAN, &net_synced))
452     {
453       error ("[dbus] no memory to add reply args to LastSyncInfo");
454       dbus_message_unref (reply);
455       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
456     }
457   if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &sync))
458     {
459       error ("[dbus] no memory to add reply args to LastSyncInfo");
460       dbus_message_unref (reply);
461       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
462     }
463   if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_INT64, &t))
464     {
465       error ("[dbus] no memory to add reply args to LastSyncInfo");
466       dbus_message_unref (reply);
467       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
468     }
469 
470   if (!dbus_connection_send (connection, reply, &serial))
471    {
472       error ("[dbus] unable to send LastSyncInfo reply");
473       dbus_message_unref (reply);
474       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
475    }
476   dbus_connection_flush (connection);
477   dbus_message_unref (reply);
478   return DBUS_HANDLER_RESULT_HANDLED;
479 }
480 
481 static
482 void
unregister_service(DBusConnection * conn,void * data)483 unregister_service (DBusConnection *conn, void *data)
484 {
485   info ("dbus service has been unregistered");
486 }
487 
488 static
489 DBusHandlerResult
service_dispatch(DBusConnection * conn,DBusMessage * msg,void * data)490 service_dispatch (DBusConnection *conn, DBusMessage *msg, void *data)
491 {
492   struct state *state = data;
493   const char *interface;
494   const char *method;
495 
496   verb_debug ("[dbus] service dispatcher called");
497   if (dbus_message_get_type (msg) != DBUS_MESSAGE_TYPE_METHOD_CALL)
498     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
499 
500   interface = dbus_message_get_interface (msg);
501   method = dbus_message_get_member (msg);
502   if (!interface || !method)
503     {
504       verb_debug ("[dbus] service request fired with bogus data");
505       /* Consume it */
506       return DBUS_HANDLER_RESULT_HANDLED;
507     }
508   if (strcmp (interface, kServiceInterface))
509     {
510       verb_debug ("[dbus] invalid interface supplied");
511       return DBUS_HANDLER_RESULT_HANDLED;
512     }
513   if (!strcmp (method, kServiceSetTime))
514     return handle_set_time (conn, msg, state);
515   else if (!strcmp (method, kServiceCanSetTime))
516     return handle_can_set_time (conn, msg, state);
517   else if (!strcmp (method, kServiceLastSyncInfo))
518     return handle_last_sync_info (conn, msg, state);
519   verb_debug ("[dbus] invalid method supplied");
520   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
521 }
522 
523 static DBusObjectPathVTable service_vtable = {
524     .unregister_function = unregister_service,
525     .message_function = service_dispatch,
526 };
527 
528 int
init_dbus(struct state * tlsdate_state)529 init_dbus (struct state *tlsdate_state)
530 {
531   DBusError error;
532   dbus_error_init (&error);
533   struct dbus_state *state = calloc (1, sizeof (struct dbus_state));
534   if (!state)
535     return 1;
536   tlsdate_state->dbus = state;
537   state->conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
538   if (state->conn == NULL || dbus_error_is_set (&error))
539     {
540       error ("[dbus] error when connecting to the bus: %s",
541              error.message);
542       goto err;
543     }
544   if (!dbus_connection_set_timeout_functions (state->conn, add_timeout,
545       remove_timeout, toggle_timeout, tlsdate_state, dbus_free))
546     {
547       error ("[dbus] dbus_connection_set_timeout_functions failed");
548       /* TODO(wad) disconnect from DBus */
549       goto err;
550     }
551   if (!dbus_connection_set_watch_functions (state->conn, add_watch,
552       remove_watch, toggle_watch, tlsdate_state, dbus_free))
553     {
554       error ("[dbus] dbus_connection_set_watch_functions failed");
555       goto err;
556     }
557   if (!dbus_bus_request_name (state->conn, kServiceInterface, 0, &error) ||
558       dbus_error_is_set (&error))
559     {
560       error ("[dbus] failed to get name: %s", error.message);
561       goto err;
562     }
563 
564   /* Setup the vtable for dispatching incoming messages. */
565   if (dbus_connection_register_object_path (
566           state->conn, kServicePath, &service_vtable, tlsdate_state) == FALSE)
567     {
568       error ("[dbus] failed to register object path: %s", kServicePath);
569       goto err;
570     }
571 
572   verb_debug ("[dbus] initialized");
573   return 0;
574 err:
575   tlsdate_state->dbus = NULL;
576   free (state);
577   return 1;
578 }
579