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