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