Home | History | Annotate | Download | only in src
      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
     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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    483 unregister_service (DBusConnection *conn, void *data)
    484 {
    485   info ("dbus service has been unregistered");
    486 }
    487 
    488 static
    489 DBusHandlerResult
    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
    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