1 #include "config.h" 2 3 #include <string.h> 4 #include <stdlib.h> 5 6 #include <gstdio.h> 7 #include <gio/gio.h> 8 #include <gio/gunixsocketaddress.h> 9 #include "gdbusdaemon.h" 10 #include "glibintl.h" 11 12 #include "gdbus-daemon-generated.h" 13 14 #define DBUS_SERVICE_NAME "org.freedesktop.DBus" 15 16 /* Owner flags */ 17 #define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */ 18 #define DBUS_NAME_FLAG_REPLACE_EXISTING 0x2 /**< Request to replace the current primary owner */ 19 #define DBUS_NAME_FLAG_DO_NOT_QUEUE 0x4 /**< If we can not become the primary owner do not place us in the queue */ 20 21 /* Replies to request for a name */ 22 #define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1 /**< Service has become the primary owner of the requested name */ 23 #define DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2 /**< Service could not become the primary owner and has been placed in the queue */ 24 #define DBUS_REQUEST_NAME_REPLY_EXISTS 3 /**< Service is already in the queue */ 25 #define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4 /**< Service is already the primary owner */ 26 27 /* Replies to releasing a name */ 28 #define DBUS_RELEASE_NAME_REPLY_RELEASED 1 /**< Service was released from the given name */ 29 #define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT 2 /**< The given name does not exist on the bus */ 30 #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER 3 /**< Service is not an owner of the given name */ 31 32 /* Replies to service starts */ 33 #define DBUS_START_REPLY_SUCCESS 1 /**< Service was auto started */ 34 #define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */ 35 36 #define IDLE_TIMEOUT_MSEC 3000 37 38 struct _GDBusDaemon 39 { 40 _GFreedesktopDBusSkeleton parent_instance; 41 42 gchar *address; 43 guint timeout; 44 gchar *tmpdir; 45 GDBusServer *server; 46 gchar *guid; 47 GHashTable *clients; 48 GHashTable *names; 49 guint32 next_major_id; 50 guint32 next_minor_id; 51 }; 52 53 struct _GDBusDaemonClass 54 { 55 _GFreedesktopDBusSkeletonClass parent_class; 56 }; 57 58 enum { 59 PROP_0, 60 PROP_ADDRESS, 61 }; 62 63 enum 64 { 65 SIGNAL_IDLE_TIMEOUT, 66 NR_SIGNALS 67 }; 68 69 static guint g_dbus_daemon_signals[NR_SIGNALS]; 70 71 72 static void initable_iface_init (GInitableIface *initable_iface); 73 static void g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface); 74 75 #define g_dbus_daemon_get_type _g_dbus_daemon_get_type 76 G_DEFINE_TYPE_WITH_CODE (GDBusDaemon, g_dbus_daemon, _G_TYPE_FREEDESKTOP_DBUS_SKELETON, 77 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init) 78 G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, g_dbus_daemon_iface_init)) 79 80 typedef struct { 81 GDBusDaemon *daemon; 82 char *id; 83 GDBusConnection *connection; 84 GList *matches; 85 } Client; 86 87 typedef struct { 88 Client *client; 89 guint32 flags; 90 } NameOwner; 91 92 typedef struct { 93 int refcount; 94 95 char *name; 96 GDBusDaemon *daemon; 97 98 NameOwner *owner; 99 GList *queue; 100 } Name; 101 102 enum { 103 MATCH_ELEMENT_TYPE, 104 MATCH_ELEMENT_SENDER, 105 MATCH_ELEMENT_INTERFACE, 106 MATCH_ELEMENT_MEMBER, 107 MATCH_ELEMENT_PATH, 108 MATCH_ELEMENT_PATH_NAMESPACE, 109 MATCH_ELEMENT_DESTINATION, 110 MATCH_ELEMENT_ARG0NAMESPACE, 111 MATCH_ELEMENT_EAVESDROP, 112 MATCH_ELEMENT_ARGN, 113 MATCH_ELEMENT_ARGNPATH, 114 }; 115 116 typedef struct { 117 guint16 type; 118 guint16 arg; 119 char *value; 120 } MatchElement; 121 122 typedef struct { 123 gboolean eavesdrop; 124 GDBusMessageType type; 125 int n_elements; 126 MatchElement *elements; 127 } Match; 128 129 static GDBusMessage *filter_function (GDBusConnection *connection, 130 GDBusMessage *message, 131 gboolean incoming, 132 gpointer user_data); 133 static void connection_closed (GDBusConnection *connection, 134 gboolean remote_peer_vanished, 135 GError *error, 136 Client *client); 137 138 static NameOwner * name_owner_new(Client * client,guint32 flags)139 name_owner_new (Client *client, guint32 flags) 140 { 141 NameOwner *owner; 142 143 owner = g_new0 (NameOwner, 1); 144 owner->client = client; 145 owner->flags = flags; 146 return owner; 147 } 148 149 static void name_owner_free(NameOwner * owner)150 name_owner_free (NameOwner *owner) 151 { 152 g_free (owner); 153 } 154 155 static Name * name_new(GDBusDaemon * daemon,const char * str)156 name_new (GDBusDaemon *daemon, const char *str) 157 { 158 Name *name; 159 160 name = g_new0 (Name, 1); 161 name->refcount = 1; 162 name->daemon = daemon; 163 name->name = g_strdup (str); 164 165 g_hash_table_insert (daemon->names, name->name, name); 166 167 return name; 168 } 169 170 static Name * name_ref(Name * name)171 name_ref (Name *name) 172 { 173 g_assert (name->refcount > 0); 174 name->refcount++; 175 return name; 176 } 177 178 static void name_unref(Name * name)179 name_unref (Name *name) 180 { 181 g_assert (name->refcount > 0); 182 if (--name->refcount == 0) 183 { 184 g_hash_table_remove (name->daemon->names, name->name); 185 g_free (name->name); 186 g_free (name); 187 } 188 } 189 190 static Name * name_ensure(GDBusDaemon * daemon,const char * str)191 name_ensure (GDBusDaemon *daemon, const char *str) 192 { 193 Name *name; 194 195 name = g_hash_table_lookup (daemon->names, str); 196 197 if (name != NULL) 198 return name_ref (name); 199 return name_new (daemon, str); 200 } 201 202 static Name * name_lookup(GDBusDaemon * daemon,const char * str)203 name_lookup (GDBusDaemon *daemon, const char *str) 204 { 205 return g_hash_table_lookup (daemon->names, str); 206 } 207 208 static gboolean is_key(const char * key_start,const char * key_end,const char * value)209 is_key (const char *key_start, const char *key_end, const char *value) 210 { 211 gsize len = strlen (value); 212 213 g_assert (key_end >= key_start); 214 if (len != (gsize) (key_end - key_start)) 215 return FALSE; 216 217 return strncmp (key_start, value, len) == 0; 218 } 219 220 static gboolean parse_key(MatchElement * element,const char * key_start,const char * key_end)221 parse_key (MatchElement *element, const char *key_start, const char *key_end) 222 { 223 gboolean res = TRUE; 224 225 if (is_key (key_start, key_end, "type")) 226 { 227 element->type = MATCH_ELEMENT_TYPE; 228 } 229 else if (is_key (key_start, key_end, "sender")) 230 { 231 element->type = MATCH_ELEMENT_SENDER; 232 } 233 else if (is_key (key_start, key_end, "interface")) 234 { 235 element->type = MATCH_ELEMENT_INTERFACE; 236 } 237 else if (is_key (key_start, key_end, "member")) 238 { 239 element->type = MATCH_ELEMENT_MEMBER; 240 } 241 else if (is_key (key_start, key_end, "path")) 242 { 243 element->type = MATCH_ELEMENT_PATH; 244 } 245 else if (is_key (key_start, key_end, "path_namespace")) 246 { 247 element->type = MATCH_ELEMENT_PATH_NAMESPACE; 248 } 249 else if (is_key (key_start, key_end, "destination")) 250 { 251 element->type = MATCH_ELEMENT_DESTINATION; 252 } 253 else if (is_key (key_start, key_end, "arg0namespace")) 254 { 255 element->type = MATCH_ELEMENT_ARG0NAMESPACE; 256 } 257 else if (is_key (key_start, key_end, "eavesdrop")) 258 { 259 element->type = MATCH_ELEMENT_EAVESDROP; 260 } 261 else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg")) 262 { 263 const char *digits = key_start + 3; 264 const char *end_digits = digits; 265 266 while (end_digits < key_end && g_ascii_isdigit (*end_digits)) 267 end_digits++; 268 269 if (end_digits == key_end) /* argN */ 270 { 271 element->type = MATCH_ELEMENT_ARGN; 272 element->arg = atoi (digits); 273 } 274 else if (is_key (end_digits, key_end, "path")) /* argNpath */ 275 { 276 element->type = MATCH_ELEMENT_ARGNPATH; 277 element->arg = atoi (digits); 278 } 279 else 280 res = FALSE; 281 } 282 else 283 res = FALSE; 284 285 return res; 286 } 287 288 static const char * parse_value(MatchElement * element,const char * s)289 parse_value (MatchElement *element, const char *s) 290 { 291 char quote_char; 292 GString *value; 293 294 value = g_string_new (""); 295 296 quote_char = 0; 297 298 for (;*s; s++) 299 { 300 if (quote_char == 0) 301 { 302 switch (*s) 303 { 304 case '\'': 305 quote_char = '\''; 306 break; 307 308 case ',': 309 s++; 310 goto out; 311 312 case '\\': 313 quote_char = '\\'; 314 break; 315 316 default: 317 g_string_append_c (value, *s); 318 break; 319 } 320 } 321 else if (quote_char == '\\') 322 { 323 /* \ only counts as an escape if escaping a quote mark */ 324 if (*s != '\'') 325 g_string_append_c (value, '\\'); 326 327 g_string_append_c (value, *s); 328 quote_char = 0; 329 } 330 else /* quote_char == ' */ 331 { 332 if (*s == '\'') 333 quote_char = 0; 334 else 335 g_string_append_c (value, *s); 336 } 337 } 338 339 out: 340 341 if (quote_char == '\\') 342 g_string_append_c (value, '\\'); 343 else if (quote_char == '\'') 344 { 345 g_string_free (value, TRUE); 346 return NULL; 347 } 348 349 element->value = g_string_free (value, FALSE); 350 return s; 351 } 352 353 static Match * match_new(const char * str)354 match_new (const char *str) 355 { 356 Match *match; 357 GArray *elements; 358 const char *p; 359 const char *key_start; 360 const char *key_end; 361 MatchElement element; 362 gboolean eavesdrop; 363 GDBusMessageType type; 364 gsize i; 365 366 eavesdrop = FALSE; 367 type = G_DBUS_MESSAGE_TYPE_INVALID; 368 elements = g_array_new (TRUE, TRUE, sizeof (MatchElement)); 369 370 p = str; 371 372 while (*p != 0) 373 { 374 memset (&element, 0, sizeof (element)); 375 376 /* Skip initial whitespace */ 377 while (*p && g_ascii_isspace (*p)) 378 p++; 379 380 key_start = p; 381 382 /* Read non-whitespace non-equals chars */ 383 while (*p && *p != '=' && !g_ascii_isspace (*p)) 384 p++; 385 386 key_end = p; 387 388 /* Skip any whitespace after key */ 389 while (*p && g_ascii_isspace (*p)) 390 p++; 391 392 if (key_start == key_end) 393 continue; /* Allow trailing whitespace */ 394 395 if (*p != '=') 396 goto error; 397 398 ++p; 399 400 if (!parse_key (&element, key_start, key_end)) 401 goto error; 402 403 p = parse_value (&element, p); 404 if (p == NULL) 405 goto error; 406 407 if (element.type == MATCH_ELEMENT_EAVESDROP) 408 { 409 if (strcmp (element.value, "true") == 0) 410 eavesdrop = TRUE; 411 else if (strcmp (element.value, "false") == 0) 412 eavesdrop = FALSE; 413 else 414 { 415 g_free (element.value); 416 goto error; 417 } 418 g_free (element.value); 419 } 420 else if (element.type == MATCH_ELEMENT_TYPE) 421 { 422 if (strcmp (element.value, "signal") == 0) 423 type = G_DBUS_MESSAGE_TYPE_SIGNAL; 424 else if (strcmp (element.value, "method_call") == 0) 425 type = G_DBUS_MESSAGE_TYPE_METHOD_CALL; 426 else if (strcmp (element.value, "method_return") == 0) 427 type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN; 428 else if (strcmp (element.value, "error") == 0) 429 type = G_DBUS_MESSAGE_TYPE_ERROR; 430 else 431 { 432 g_free (element.value); 433 goto error; 434 } 435 g_free (element.value); 436 } 437 else 438 g_array_append_val (elements, element); 439 } 440 441 match = g_new0 (Match, 1); 442 match->n_elements = elements->len; 443 match->elements = (MatchElement *)g_array_free (elements, FALSE); 444 match->eavesdrop = eavesdrop; 445 match->type = type; 446 447 return match; 448 449 error: 450 for (i = 0; i < elements->len; i++) 451 g_free (g_array_index (elements, MatchElement, i).value); 452 g_array_free (elements, TRUE); 453 return NULL; 454 } 455 456 static void match_free(Match * match)457 match_free (Match *match) 458 { 459 int i; 460 for (i = 0; i < match->n_elements; i++) 461 g_free (match->elements[i].value); 462 g_free (match->elements); 463 g_free (match); 464 } 465 466 static gboolean match_equal(Match * a,Match * b)467 match_equal (Match *a, Match *b) 468 { 469 int i; 470 471 if (a->eavesdrop != b->eavesdrop) 472 return FALSE; 473 if (a->type != b->type) 474 return FALSE; 475 if (a->n_elements != b->n_elements) 476 return FALSE; 477 for (i = 0; i < a->n_elements; i++) 478 { 479 if (a->elements[i].type != b->elements[i].type || 480 a->elements[i].arg != b->elements[i].arg || 481 strcmp (a->elements[i].value, b->elements[i].value) != 0) 482 return FALSE; 483 } 484 return TRUE; 485 } 486 487 static const gchar * message_get_argN(GDBusMessage * message,int n,gboolean allow_path)488 message_get_argN (GDBusMessage *message, int n, gboolean allow_path) 489 { 490 const gchar *ret; 491 GVariant *body; 492 493 ret = NULL; 494 495 body = g_dbus_message_get_body (message); 496 497 if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE)) 498 { 499 GVariant *item; 500 item = g_variant_get_child_value (body, n); 501 if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING) || 502 (allow_path && g_variant_is_of_type (item, G_VARIANT_TYPE_OBJECT_PATH))) 503 ret = g_variant_get_string (item, NULL); 504 g_variant_unref (item); 505 } 506 507 return ret; 508 } 509 510 enum { 511 CHECK_TYPE_STRING, 512 CHECK_TYPE_NAME, 513 CHECK_TYPE_PATH_PREFIX, 514 CHECK_TYPE_PATH_RELATED, 515 CHECK_TYPE_NAMESPACE_PREFIX 516 }; 517 518 static gboolean match_matches(GDBusDaemon * daemon,Match * match,GDBusMessage * message,gboolean has_destination)519 match_matches (GDBusDaemon *daemon, 520 Match *match, GDBusMessage *message, 521 gboolean has_destination) 522 { 523 MatchElement *element; 524 Name *name; 525 int i, len, len2; 526 const char *value; 527 int check_type; 528 529 if (has_destination && !match->eavesdrop) 530 return FALSE; 531 532 if (match->type != G_DBUS_MESSAGE_TYPE_INVALID && 533 g_dbus_message_get_message_type (message) != match->type) 534 return FALSE; 535 536 for (i = 0; i < match->n_elements; i++) 537 { 538 element = &match->elements[i]; 539 check_type = CHECK_TYPE_STRING; 540 switch (element->type) 541 { 542 case MATCH_ELEMENT_SENDER: 543 check_type = CHECK_TYPE_NAME; 544 value = g_dbus_message_get_sender (message); 545 if (value == NULL) 546 value = DBUS_SERVICE_NAME; 547 break; 548 case MATCH_ELEMENT_DESTINATION: 549 check_type = CHECK_TYPE_NAME; 550 value = g_dbus_message_get_destination (message); 551 break; 552 case MATCH_ELEMENT_INTERFACE: 553 value = g_dbus_message_get_interface (message); 554 break; 555 case MATCH_ELEMENT_MEMBER: 556 value = g_dbus_message_get_member (message); 557 break; 558 case MATCH_ELEMENT_PATH: 559 value = g_dbus_message_get_path (message); 560 break; 561 case MATCH_ELEMENT_PATH_NAMESPACE: 562 check_type = CHECK_TYPE_PATH_PREFIX; 563 value = g_dbus_message_get_path (message); 564 break; 565 case MATCH_ELEMENT_ARG0NAMESPACE: 566 check_type = CHECK_TYPE_NAMESPACE_PREFIX; 567 value = message_get_argN (message, 0, FALSE); 568 break; 569 case MATCH_ELEMENT_ARGN: 570 value = message_get_argN (message, element->arg, FALSE); 571 break; 572 case MATCH_ELEMENT_ARGNPATH: 573 check_type = CHECK_TYPE_PATH_RELATED; 574 value = message_get_argN (message, element->arg, TRUE); 575 break; 576 default: 577 case MATCH_ELEMENT_TYPE: 578 case MATCH_ELEMENT_EAVESDROP: 579 g_assert_not_reached (); 580 } 581 582 if (value == NULL) 583 return FALSE; 584 585 switch (check_type) 586 { 587 case CHECK_TYPE_STRING: 588 if (strcmp (element->value, value) != 0) 589 return FALSE; 590 break; 591 case CHECK_TYPE_NAME: 592 name = name_lookup (daemon, element->value); 593 if (name != NULL && name->owner != NULL) 594 { 595 if (strcmp (name->owner->client->id, value) != 0) 596 return FALSE; 597 } 598 else if (strcmp (element->value, value) != 0) 599 return FALSE; 600 break; 601 case CHECK_TYPE_PATH_PREFIX: 602 len = strlen (element->value); 603 604 /* Make sure to handle the case of element->value == '/'. */ 605 if (len == 1) 606 break; 607 608 /* Fail if there's no prefix match, or if the prefix match doesn't 609 * finish at the end of or at a separator in the @value. */ 610 if (!g_str_has_prefix (value, element->value)) 611 return FALSE; 612 if (value[len] != 0 && value[len] != '/') 613 return FALSE; 614 615 break; 616 case CHECK_TYPE_PATH_RELATED: 617 len = strlen (element->value); 618 len2 = strlen (value); 619 620 if (!(strcmp (value, element->value) == 0 || 621 (len2 > 0 && value[len2-1] == '/' && g_str_has_prefix (element->value, value)) || 622 (len > 0 && element->value[len-1] == '/' && g_str_has_prefix (value, element->value)))) 623 return FALSE; 624 break; 625 case CHECK_TYPE_NAMESPACE_PREFIX: 626 len = strlen (element->value); 627 if (!(g_str_has_prefix (value, element->value) && 628 (value[len] == 0 || value[len] == '.'))) 629 return FALSE; 630 break; 631 default: 632 g_assert_not_reached (); 633 } 634 } 635 636 return TRUE; 637 } 638 639 static void broadcast_message(GDBusDaemon * daemon,GDBusMessage * message,gboolean has_destination,gboolean preserve_serial,Client * not_to)640 broadcast_message (GDBusDaemon *daemon, 641 GDBusMessage *message, 642 gboolean has_destination, 643 gboolean preserve_serial, 644 Client *not_to) 645 { 646 GList *clients, *l, *ll; 647 GDBusMessage *copy; 648 649 clients = g_hash_table_get_values (daemon->clients); 650 for (l = clients; l != NULL; l = l->next) 651 { 652 Client *client = l->data; 653 654 if (client == not_to) 655 continue; 656 657 for (ll = client->matches; ll != NULL; ll = ll->next) 658 { 659 Match *match = ll->data; 660 661 if (match_matches (daemon, match, message, has_destination)) 662 break; 663 } 664 665 if (ll != NULL) 666 { 667 copy = g_dbus_message_copy (message, NULL); 668 if (copy) 669 { 670 g_dbus_connection_send_message (client->connection, copy, 671 preserve_serial?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL:0, NULL, NULL); 672 g_object_unref (copy); 673 } 674 } 675 } 676 677 g_list_free (clients); 678 } 679 680 static void send_name_owner_changed(GDBusDaemon * daemon,const char * name,const char * old_owner,const char * new_owner)681 send_name_owner_changed (GDBusDaemon *daemon, 682 const char *name, 683 const char *old_owner, 684 const char *new_owner) 685 { 686 GDBusMessage *signal_message; 687 688 signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus", 689 "org.freedesktop.DBus", 690 "NameOwnerChanged"); 691 g_dbus_message_set_body (signal_message, 692 g_variant_new ("(sss)", 693 name, 694 old_owner ? old_owner : "", 695 new_owner ? new_owner : "")); 696 697 broadcast_message (daemon, signal_message, FALSE, FALSE, NULL); 698 g_object_unref (signal_message); 699 700 } 701 702 static gboolean name_unqueue_owner(Name * name,Client * client)703 name_unqueue_owner (Name *name, Client *client) 704 { 705 GList *l; 706 707 for (l = name->queue; l != NULL; l = l->next) 708 { 709 NameOwner *other = l->data; 710 711 if (other->client == client) 712 { 713 name->queue = g_list_delete_link (name->queue, l); 714 name_unref (name); 715 name_owner_free (other); 716 return TRUE; 717 } 718 } 719 720 return FALSE; 721 } 722 723 static void name_replace_owner(Name * name,NameOwner * owner)724 name_replace_owner (Name *name, NameOwner *owner) 725 { 726 GDBusDaemon *daemon = name->daemon; 727 NameOwner *old_owner; 728 char *old_name = NULL, *new_name = NULL; 729 Client *new_client = NULL; 730 731 if (owner) 732 new_client = owner->client; 733 734 name_ref (name); 735 736 old_owner = name->owner; 737 if (old_owner) 738 { 739 Client *old_client = old_owner->client; 740 741 g_assert (old_owner->client != new_client); 742 743 g_dbus_connection_emit_signal (old_client->connection, 744 NULL, "/org/freedesktop/DBus", 745 "org.freedesktop.DBus", "NameLost", 746 g_variant_new ("(s)", 747 name->name), NULL); 748 749 old_name = g_strdup (old_client->id); 750 if (old_owner->flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) 751 { 752 name_unref (name); 753 name_owner_free (old_owner); 754 } 755 else 756 name->queue = g_list_prepend (name->queue, old_owner); 757 } 758 759 name->owner = owner; 760 if (owner) 761 { 762 name_unqueue_owner (name, owner->client); 763 name_ref (name); 764 new_name = new_client->id; 765 766 g_dbus_connection_emit_signal (new_client->connection, 767 NULL, "/org/freedesktop/DBus", 768 "org.freedesktop.DBus", "NameAcquired", 769 g_variant_new ("(s)", 770 name->name), NULL); 771 } 772 773 send_name_owner_changed (daemon, name->name, old_name, new_name); 774 775 g_free (old_name); 776 777 name_unref (name); 778 } 779 780 static void name_release_owner(Name * name)781 name_release_owner (Name *name) 782 { 783 NameOwner *next_owner = NULL; 784 785 name_ref (name); 786 787 /* Will someone else take over? */ 788 if (name->queue) 789 { 790 next_owner = name->queue->data; 791 name_unref (name); 792 name->queue = g_list_delete_link (name->queue, name->queue); 793 } 794 795 name->owner->flags |= DBUS_NAME_FLAG_DO_NOT_QUEUE; 796 name_replace_owner (name, next_owner); 797 798 name_unref (name); 799 } 800 801 static void name_queue_owner(Name * name,NameOwner * owner)802 name_queue_owner (Name *name, NameOwner *owner) 803 { 804 GList *l; 805 806 for (l = name->queue; l != NULL; l = l->next) 807 { 808 NameOwner *other = l->data; 809 810 if (other->client == owner->client) 811 { 812 other->flags = owner->flags; 813 name_owner_free (owner); 814 return; 815 } 816 } 817 818 name->queue = g_list_append (name->queue, owner); 819 name_ref (name); 820 } 821 822 static Client * client_new(GDBusDaemon * daemon,GDBusConnection * connection)823 client_new (GDBusDaemon *daemon, GDBusConnection *connection) 824 { 825 Client *client; 826 GError *error = NULL; 827 828 client = g_new0 (Client, 1); 829 client->daemon = daemon; 830 client->id = g_strdup_printf (":%d.%d", daemon->next_major_id, daemon->next_minor_id); 831 client->connection = g_object_ref (connection); 832 833 if (daemon->next_minor_id == G_MAXUINT32) 834 { 835 daemon->next_minor_id = 0; 836 daemon->next_major_id++; 837 } 838 else 839 daemon->next_minor_id++; 840 841 g_object_set_data (G_OBJECT (connection), "client", client); 842 g_hash_table_insert (daemon->clients, client->id, client); 843 844 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), connection, 845 "/org/freedesktop/DBus", &error); 846 g_assert_no_error (error); 847 848 g_signal_connect (connection, "closed", G_CALLBACK (connection_closed), client); 849 g_dbus_connection_add_filter (connection, 850 filter_function, 851 client, NULL); 852 853 send_name_owner_changed (daemon, client->id, NULL, client->id); 854 855 return client; 856 } 857 858 static void client_free(Client * client)859 client_free (Client *client) 860 { 861 GDBusDaemon *daemon = client->daemon; 862 GList *l, *names; 863 864 g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon), 865 client->connection); 866 867 g_hash_table_remove (daemon->clients, client->id); 868 869 names = g_hash_table_get_values (daemon->names); 870 for (l = names; l != NULL; l = l->next) 871 { 872 Name *name = l->data; 873 874 name_ref (name); 875 876 if (name->owner && name->owner->client == client) 877 name_release_owner (name); 878 879 name_unqueue_owner (name, client); 880 881 name_unref (name); 882 } 883 g_list_free (names); 884 885 send_name_owner_changed (daemon, client->id, client->id, NULL); 886 887 g_object_unref (client->connection); 888 889 for (l = client->matches; l != NULL; l = l->next) 890 match_free (l->data); 891 g_list_free (client->matches); 892 893 g_free (client->id); 894 g_free (client); 895 } 896 897 static gboolean idle_timeout_cb(gpointer user_data)898 idle_timeout_cb (gpointer user_data) 899 { 900 GDBusDaemon *daemon = user_data; 901 902 daemon->timeout = 0; 903 904 g_signal_emit (daemon, 905 g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT], 906 0); 907 908 return G_SOURCE_REMOVE; 909 } 910 911 static void connection_closed(GDBusConnection * connection,gboolean remote_peer_vanished,GError * error,Client * client)912 connection_closed (GDBusConnection *connection, 913 gboolean remote_peer_vanished, 914 GError *error, 915 Client *client) 916 { 917 GDBusDaemon *daemon = client->daemon; 918 919 client_free (client); 920 921 if (g_hash_table_size (daemon->clients) == 0) 922 daemon->timeout = g_timeout_add (IDLE_TIMEOUT_MSEC, 923 idle_timeout_cb, 924 daemon); 925 } 926 927 static gboolean handle_add_match(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_rule)928 handle_add_match (_GFreedesktopDBus *object, 929 GDBusMethodInvocation *invocation, 930 const gchar *arg_rule) 931 { 932 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client"); 933 Match *match; 934 935 match = match_new (arg_rule); 936 937 if (match == NULL) 938 g_dbus_method_invocation_return_error (invocation, 939 G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID, 940 "Invalid rule: %s", arg_rule); 941 else 942 { 943 client->matches = g_list_prepend (client->matches, match); 944 _g_freedesktop_dbus_complete_add_match (object, invocation); 945 } 946 return TRUE; 947 } 948 949 static gboolean handle_get_connection_selinux_security_context(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)950 handle_get_connection_selinux_security_context (_GFreedesktopDBus *object, 951 GDBusMethodInvocation *invocation, 952 const gchar *arg_name) 953 { 954 g_dbus_method_invocation_return_error (invocation, 955 G_DBUS_ERROR, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN, 956 "selinux context not supported"); 957 _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object, invocation, ""); 958 return TRUE; 959 } 960 961 static gboolean handle_get_connection_unix_process_id(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)962 handle_get_connection_unix_process_id (_GFreedesktopDBus *object, 963 GDBusMethodInvocation *invocation, 964 const gchar *arg_name) 965 { 966 g_dbus_method_invocation_return_error (invocation, 967 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, 968 "connection pid not supported"); 969 return TRUE; 970 } 971 972 static gboolean handle_get_connection_unix_user(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)973 handle_get_connection_unix_user (_GFreedesktopDBus *object, 974 GDBusMethodInvocation *invocation, 975 const gchar *arg_name) 976 { 977 g_dbus_method_invocation_return_error (invocation, 978 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, 979 "connection user not supported"); 980 return TRUE; 981 } 982 983 static gboolean handle_get_id(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)984 handle_get_id (_GFreedesktopDBus *object, 985 GDBusMethodInvocation *invocation) 986 { 987 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 988 _g_freedesktop_dbus_complete_get_id (object, invocation, 989 daemon->guid); 990 return TRUE; 991 } 992 993 static gboolean handle_get_name_owner(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)994 handle_get_name_owner (_GFreedesktopDBus *object, 995 GDBusMethodInvocation *invocation, 996 const gchar *arg_name) 997 { 998 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 999 Name *name; 1000 1001 if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0) 1002 { 1003 _g_freedesktop_dbus_complete_get_name_owner (object, invocation, DBUS_SERVICE_NAME); 1004 return TRUE; 1005 } 1006 1007 if (arg_name[0] == ':') 1008 { 1009 if (g_hash_table_lookup (daemon->clients, arg_name) == NULL) 1010 g_dbus_method_invocation_return_error (invocation, 1011 G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER, 1012 "Could not get owner of name '%s': no such name", arg_name); 1013 else 1014 _g_freedesktop_dbus_complete_get_name_owner (object, invocation, arg_name); 1015 return TRUE; 1016 } 1017 1018 name = name_lookup (daemon, arg_name); 1019 if (name == NULL || name->owner == NULL) 1020 { 1021 g_dbus_method_invocation_return_error (invocation, 1022 G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER, 1023 "Could not get owner of name '%s': no such name", arg_name); 1024 return TRUE; 1025 } 1026 1027 _g_freedesktop_dbus_complete_get_name_owner (object, invocation, name->owner->client->id); 1028 return TRUE; 1029 } 1030 1031 static gboolean handle_hello(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1032 handle_hello (_GFreedesktopDBus *object, 1033 GDBusMethodInvocation *invocation) 1034 { 1035 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client"); 1036 _g_freedesktop_dbus_complete_hello (object, invocation, client->id); 1037 1038 g_dbus_connection_emit_signal (client->connection, 1039 NULL, "/org/freedesktop/DBus", 1040 "org.freedesktop.DBus", "NameAcquired", 1041 g_variant_new ("(s)", 1042 client->id), NULL); 1043 1044 return TRUE; 1045 } 1046 1047 static gboolean handle_list_activatable_names(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1048 handle_list_activatable_names (_GFreedesktopDBus *object, 1049 GDBusMethodInvocation *invocation) 1050 { 1051 const char *names[] = { NULL }; 1052 1053 _g_freedesktop_dbus_complete_list_activatable_names (object, 1054 invocation, 1055 names); 1056 return TRUE; 1057 } 1058 1059 static gboolean handle_list_names(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1060 handle_list_names (_GFreedesktopDBus *object, 1061 GDBusMethodInvocation *invocation) 1062 { 1063 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1064 GPtrArray *array; 1065 GList *clients, *names, *l; 1066 1067 array = g_ptr_array_new (); 1068 1069 clients = g_hash_table_get_values (daemon->clients); 1070 for (l = clients; l != NULL; l = l->next) 1071 { 1072 Client *client = l->data; 1073 1074 g_ptr_array_add (array, client->id); 1075 } 1076 1077 g_list_free (clients); 1078 1079 names = g_hash_table_get_values (daemon->names); 1080 for (l = names; l != NULL; l = l->next) 1081 { 1082 Name *name = l->data; 1083 1084 g_ptr_array_add (array, name->name); 1085 } 1086 1087 g_list_free (names); 1088 1089 g_ptr_array_add (array, NULL); 1090 1091 _g_freedesktop_dbus_complete_list_names (object, 1092 invocation, 1093 (const gchar * const*)array->pdata); 1094 g_ptr_array_free (array, TRUE); 1095 return TRUE; 1096 } 1097 1098 static gboolean handle_list_queued_owners(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1099 handle_list_queued_owners (_GFreedesktopDBus *object, 1100 GDBusMethodInvocation *invocation, 1101 const gchar *arg_name) 1102 { 1103 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1104 GPtrArray *array; 1105 Name *name; 1106 GList *l; 1107 1108 array = g_ptr_array_new (); 1109 1110 name = name_lookup (daemon, arg_name); 1111 if (name && name->owner) 1112 { 1113 for (l = name->queue; l != NULL; l = l->next) 1114 { 1115 Client *client = l->data; 1116 1117 g_ptr_array_add (array, client->id); 1118 } 1119 } 1120 1121 g_ptr_array_add (array, NULL); 1122 1123 _g_freedesktop_dbus_complete_list_queued_owners (object, 1124 invocation, 1125 (const gchar * const*)array->pdata); 1126 g_ptr_array_free (array, TRUE); 1127 return TRUE; 1128 } 1129 1130 static gboolean handle_name_has_owner(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1131 handle_name_has_owner (_GFreedesktopDBus *object, 1132 GDBusMethodInvocation *invocation, 1133 const gchar *arg_name) 1134 { 1135 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1136 Name *name; 1137 Client *client; 1138 1139 name = name_lookup (daemon, arg_name); 1140 client = g_hash_table_lookup (daemon->clients, arg_name); 1141 1142 _g_freedesktop_dbus_complete_name_has_owner (object, invocation, 1143 name != NULL || client != NULL); 1144 return TRUE; 1145 } 1146 1147 static gboolean handle_release_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1148 handle_release_name (_GFreedesktopDBus *object, 1149 GDBusMethodInvocation *invocation, 1150 const gchar *arg_name) 1151 { 1152 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client"); 1153 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1154 Name *name; 1155 guint32 result; 1156 1157 if (!g_dbus_is_name (arg_name)) 1158 { 1159 g_dbus_method_invocation_return_error (invocation, 1160 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, 1161 "Given bus name \"%s\" is not valid", arg_name); 1162 return TRUE; 1163 } 1164 1165 if (*arg_name == ':') 1166 { 1167 g_dbus_method_invocation_return_error (invocation, 1168 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, 1169 "Cannot release a service starting with ':' such as \"%s\"", arg_name); 1170 return TRUE; 1171 } 1172 1173 if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0) 1174 { 1175 g_dbus_method_invocation_return_error (invocation, 1176 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, 1177 "Cannot release a service named " DBUS_SERVICE_NAME ", because that is owned by the bus"); 1178 return TRUE; 1179 } 1180 1181 name = name_lookup (daemon, arg_name); 1182 1183 if (name == NULL) 1184 result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT; 1185 else if (name->owner && name->owner->client == client) 1186 { 1187 name_release_owner (name); 1188 result = DBUS_RELEASE_NAME_REPLY_RELEASED; 1189 } 1190 else if (name_unqueue_owner (name, client)) 1191 result = DBUS_RELEASE_NAME_REPLY_RELEASED; 1192 else 1193 result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER; 1194 1195 _g_freedesktop_dbus_complete_release_name (object, invocation, result); 1196 return TRUE; 1197 } 1198 1199 static gboolean handle_reload_config(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1200 handle_reload_config (_GFreedesktopDBus *object, 1201 GDBusMethodInvocation *invocation) 1202 { 1203 _g_freedesktop_dbus_complete_reload_config (object, invocation); 1204 return TRUE; 1205 } 1206 1207 static gboolean handle_update_activation_environment(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,GVariant * arg_environment)1208 handle_update_activation_environment (_GFreedesktopDBus *object, 1209 GDBusMethodInvocation *invocation, 1210 GVariant *arg_environment) 1211 { 1212 g_dbus_method_invocation_return_error (invocation, 1213 G_DBUS_ERROR, G_DBUS_ERROR_FAILED, 1214 "UpdateActivationEnvironment not implemented"); 1215 return TRUE; 1216 } 1217 1218 static gboolean handle_remove_match(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_rule)1219 handle_remove_match (_GFreedesktopDBus *object, 1220 GDBusMethodInvocation *invocation, 1221 const gchar *arg_rule) 1222 { 1223 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client"); 1224 Match *match, *other_match; 1225 GList *l; 1226 1227 match = match_new (arg_rule); 1228 1229 if (match == NULL) 1230 g_dbus_method_invocation_return_error (invocation, 1231 G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID, 1232 "Invalid rule: %s", arg_rule); 1233 else 1234 { 1235 for (l = client->matches; l != NULL; l = l->next) 1236 { 1237 other_match = l->data; 1238 if (match_equal (match, other_match)) 1239 { 1240 match_free (other_match); 1241 client->matches = g_list_delete_link (client->matches, l); 1242 break; 1243 } 1244 } 1245 1246 if (l == NULL) 1247 g_dbus_method_invocation_return_error (invocation, 1248 G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND, 1249 "The given match rule wasn't found and can't be removed"); 1250 else 1251 _g_freedesktop_dbus_complete_remove_match (object, invocation); 1252 } 1253 if (match) 1254 match_free (match); 1255 1256 return TRUE; 1257 } 1258 1259 static gboolean handle_request_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name,guint flags)1260 handle_request_name (_GFreedesktopDBus *object, 1261 GDBusMethodInvocation *invocation, 1262 const gchar *arg_name, 1263 guint flags) 1264 { 1265 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client"); 1266 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1267 Name *name; 1268 NameOwner *owner; 1269 guint32 result; 1270 1271 if (!g_dbus_is_name (arg_name)) 1272 { 1273 g_dbus_method_invocation_return_error (invocation, 1274 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, 1275 "Requested bus name \"%s\" is not valid", arg_name); 1276 return TRUE; 1277 } 1278 1279 if (*arg_name == ':') 1280 { 1281 g_dbus_method_invocation_return_error (invocation, 1282 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, 1283 "Cannot acquire a service starting with ':' such as \"%s\"", arg_name); 1284 return TRUE; 1285 } 1286 1287 if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0) 1288 { 1289 g_dbus_method_invocation_return_error (invocation, 1290 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, 1291 "Cannot acquire a service named " DBUS_SERVICE_NAME ", because that is reserved"); 1292 return TRUE; 1293 } 1294 1295 name = name_ensure (daemon, arg_name); 1296 if (name->owner == NULL) 1297 { 1298 owner = name_owner_new (client, flags); 1299 name_replace_owner (name, owner); 1300 1301 result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; 1302 } 1303 else if (name->owner && name->owner->client == client) 1304 { 1305 name->owner->flags = flags; 1306 result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER; 1307 } 1308 else if ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) && 1309 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || 1310 !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT))) 1311 { 1312 /* Unqueue if queued */ 1313 name_unqueue_owner (name, client); 1314 result = DBUS_REQUEST_NAME_REPLY_EXISTS; 1315 } 1316 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) && 1317 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || 1318 !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT))) 1319 { 1320 /* Queue the connection */ 1321 owner = name_owner_new (client, flags); 1322 name_queue_owner (name, owner); 1323 result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE; 1324 } 1325 else 1326 { 1327 /* Replace the current owner */ 1328 1329 owner = name_owner_new (client, flags); 1330 name_replace_owner (name, owner); 1331 1332 result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; 1333 } 1334 1335 name_unref (name); 1336 1337 _g_freedesktop_dbus_complete_request_name (object, invocation, result); 1338 return TRUE; 1339 } 1340 1341 static gboolean handle_start_service_by_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name,guint arg_flags)1342 handle_start_service_by_name (_GFreedesktopDBus *object, 1343 GDBusMethodInvocation *invocation, 1344 const gchar *arg_name, 1345 guint arg_flags) 1346 { 1347 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1348 Name *name; 1349 1350 name = name_lookup (daemon, arg_name); 1351 if (name) 1352 _g_freedesktop_dbus_complete_start_service_by_name (object, invocation, 1353 DBUS_START_REPLY_ALREADY_RUNNING); 1354 else 1355 g_dbus_method_invocation_return_error (invocation, 1356 G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN, 1357 "No support for activation for name: %s", arg_name); 1358 1359 return TRUE; 1360 } 1361 1362 G_GNUC_PRINTF(5, 6) 1363 static void return_error(Client * client,GDBusMessage * message,GQuark domain,gint code,const gchar * format,...)1364 return_error (Client *client, GDBusMessage *message, 1365 GQuark domain, 1366 gint code, 1367 const gchar *format, 1368 ...) 1369 { 1370 GDBusMessage *reply; 1371 va_list var_args; 1372 char *error_message; 1373 GError *error; 1374 gchar *dbus_error_name; 1375 1376 va_start (var_args, format); 1377 error_message = g_strdup_vprintf (format, var_args); 1378 va_end (var_args); 1379 1380 error = g_error_new_literal (domain, code, ""); 1381 dbus_error_name = g_dbus_error_encode_gerror (error); 1382 1383 reply = g_dbus_message_new_method_error_literal (message, 1384 dbus_error_name, 1385 error_message); 1386 1387 g_error_free (error); 1388 g_free (dbus_error_name); 1389 g_free (error_message); 1390 1391 if (!g_dbus_connection_send_message (client->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL)) 1392 g_warning ("Error sending reply"); 1393 g_object_unref (reply); 1394 } 1395 1396 static GDBusMessage * route_message(Client * source_client,GDBusMessage * message)1397 route_message (Client *source_client, GDBusMessage *message) 1398 { 1399 const char *dest; 1400 Client *dest_client; 1401 GDBusDaemon *daemon; 1402 1403 daemon = source_client->daemon; 1404 1405 dest_client = NULL; 1406 dest = g_dbus_message_get_destination (message); 1407 if (dest != NULL && strcmp (dest, DBUS_SERVICE_NAME) != 0) 1408 { 1409 dest_client = g_hash_table_lookup (daemon->clients, dest); 1410 1411 if (dest_client == NULL) 1412 { 1413 Name *name; 1414 name = name_lookup (daemon, dest); 1415 if (name && name->owner) 1416 dest_client = name->owner->client; 1417 } 1418 1419 if (dest_client == NULL) 1420 { 1421 if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL) 1422 return_error (source_client, message, 1423 G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN, 1424 "The name %s is unknown", dest); 1425 } 1426 else 1427 { 1428 GError *error = NULL; 1429 1430 if (!g_dbus_connection_send_message (dest_client->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, NULL, &error)) 1431 { 1432 g_warning ("Error forwarding message: %s", error->message); 1433 g_error_free (error); 1434 } 1435 } 1436 } 1437 1438 broadcast_message (daemon, message, dest_client != NULL, TRUE, dest_client); 1439 1440 /* Swallow messages not for the bus */ 1441 if (dest == NULL || strcmp (dest, DBUS_SERVICE_NAME) != 0) 1442 { 1443 g_object_unref (message); 1444 message = NULL; 1445 } 1446 1447 return message; 1448 } 1449 1450 static GDBusMessage * copy_if_locked(GDBusMessage * message)1451 copy_if_locked (GDBusMessage *message) 1452 { 1453 if (g_dbus_message_get_locked (message)) 1454 { 1455 GDBusMessage *copy = g_dbus_message_copy (message, NULL); 1456 g_object_unref (message); 1457 message = copy; 1458 } 1459 return message; 1460 } 1461 1462 static GDBusMessage * filter_function(GDBusConnection * connection,GDBusMessage * message,gboolean incoming,gpointer user_data)1463 filter_function (GDBusConnection *connection, 1464 GDBusMessage *message, 1465 gboolean incoming, 1466 gpointer user_data) 1467 { 1468 Client *client = user_data; 1469 1470 if (0) 1471 { 1472 const char *types[] = {"invalid", "method_call", "method_return", "error", "signal" }; 1473 g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n", 1474 client->id, 1475 incoming? "->" : "<-", 1476 types[g_dbus_message_get_message_type (message)], 1477 g_dbus_message_get_serial (message), 1478 g_dbus_message_get_reply_serial (message), 1479 g_dbus_message_get_sender (message), 1480 g_dbus_message_get_destination (message), 1481 g_dbus_message_get_path (message), 1482 g_dbus_message_get_interface (message), 1483 g_dbus_message_get_member (message)); 1484 } 1485 1486 if (incoming) 1487 { 1488 /* Ensure its not locked so we can set the sender */ 1489 message = copy_if_locked (message); 1490 if (message == NULL) 1491 { 1492 g_warning ("Failed to copy incoming message"); 1493 return NULL; 1494 } 1495 g_dbus_message_set_sender (message, client->id); 1496 1497 return route_message (client, message); 1498 } 1499 else 1500 { 1501 if (g_dbus_message_get_sender (message) == NULL || 1502 g_dbus_message_get_destination (message) == NULL) 1503 { 1504 message = copy_if_locked (message); 1505 if (message == NULL) 1506 { 1507 g_warning ("Failed to copy outgoing message"); 1508 return NULL; 1509 } 1510 } 1511 1512 if (g_dbus_message_get_sender (message) == NULL) 1513 g_dbus_message_set_sender (message, DBUS_SERVICE_NAME); 1514 if (g_dbus_message_get_destination (message) == NULL) 1515 g_dbus_message_set_destination (message, client->id); 1516 } 1517 1518 return message; 1519 } 1520 1521 static gboolean on_new_connection(GDBusServer * server,GDBusConnection * connection,gpointer user_data)1522 on_new_connection (GDBusServer *server, 1523 GDBusConnection *connection, 1524 gpointer user_data) 1525 { 1526 GDBusDaemon *daemon = user_data; 1527 1528 g_dbus_connection_set_exit_on_close (connection, FALSE); 1529 1530 if (daemon->timeout) 1531 { 1532 g_source_remove (daemon->timeout); 1533 daemon->timeout = 0; 1534 } 1535 1536 client_new (daemon, connection); 1537 1538 return TRUE; 1539 } 1540 1541 static void g_dbus_daemon_finalize(GObject * object)1542 g_dbus_daemon_finalize (GObject *object) 1543 { 1544 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1545 GList *clients, *l; 1546 1547 if (daemon->timeout) 1548 g_source_remove (daemon->timeout); 1549 1550 clients = g_hash_table_get_values (daemon->clients); 1551 for (l = clients; l != NULL; l = l->next) 1552 client_free (l->data); 1553 g_list_free (clients); 1554 1555 g_assert (g_hash_table_size (daemon->clients) == 0); 1556 g_assert (g_hash_table_size (daemon->names) == 0); 1557 1558 g_hash_table_destroy (daemon->clients); 1559 g_hash_table_destroy (daemon->names); 1560 1561 g_object_unref (daemon->server); 1562 1563 if (daemon->tmpdir) 1564 { 1565 g_rmdir (daemon->tmpdir); 1566 g_free (daemon->tmpdir); 1567 } 1568 1569 g_free (daemon->guid); 1570 g_free (daemon->address); 1571 1572 G_OBJECT_CLASS (g_dbus_daemon_parent_class)->finalize (object); 1573 } 1574 1575 static void g_dbus_daemon_init(GDBusDaemon * daemon)1576 g_dbus_daemon_init (GDBusDaemon *daemon) 1577 { 1578 daemon->next_major_id = 1; 1579 daemon->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); 1580 daemon->names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); 1581 daemon->guid = g_dbus_generate_guid (); 1582 } 1583 1584 static gboolean initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)1585 initable_init (GInitable *initable, 1586 GCancellable *cancellable, 1587 GError **error) 1588 { 1589 GDBusDaemon *daemon = G_DBUS_DAEMON (initable); 1590 GDBusServerFlags flags; 1591 1592 flags = G_DBUS_SERVER_FLAGS_NONE; 1593 if (daemon->address == NULL) 1594 { 1595 #ifdef G_OS_UNIX 1596 if (g_unix_socket_address_abstract_names_supported ()) 1597 daemon->address = g_strdup ("unix:tmpdir=/tmp/gdbus-daemon"); 1598 else 1599 { 1600 daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL); 1601 daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir); 1602 } 1603 flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER; 1604 #else 1605 /* Don’t require authentication on Windows as that hasn’t been 1606 * implemented yet. */ 1607 daemon->address = g_strdup ("nonce-tcp:"); 1608 flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; 1609 #endif 1610 } 1611 1612 daemon->server = g_dbus_server_new_sync (daemon->address, 1613 flags, 1614 daemon->guid, 1615 NULL, 1616 cancellable, 1617 error); 1618 if (daemon->server == NULL) 1619 return FALSE; 1620 1621 1622 g_dbus_server_start (daemon->server); 1623 1624 g_signal_connect (daemon->server, "new-connection", 1625 G_CALLBACK (on_new_connection), 1626 daemon); 1627 1628 return TRUE; 1629 } 1630 1631 static void g_dbus_daemon_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1632 g_dbus_daemon_set_property (GObject *object, 1633 guint prop_id, 1634 const GValue *value, 1635 GParamSpec *pspec) 1636 { 1637 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1638 1639 switch (prop_id) 1640 { 1641 case PROP_ADDRESS: 1642 g_free (daemon->address); 1643 daemon->address = g_value_dup_string (value); 1644 break; 1645 1646 default: 1647 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 1648 } 1649 } 1650 1651 static void g_dbus_daemon_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1652 g_dbus_daemon_get_property (GObject *object, 1653 guint prop_id, 1654 GValue *value, 1655 GParamSpec *pspec) 1656 { 1657 GDBusDaemon *daemon = G_DBUS_DAEMON (object); 1658 1659 switch (prop_id) 1660 { 1661 case PROP_ADDRESS: 1662 g_value_set_string (value, daemon->address); 1663 break; 1664 1665 default: 1666 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 1667 } 1668 } 1669 1670 static void g_dbus_daemon_class_init(GDBusDaemonClass * klass)1671 g_dbus_daemon_class_init (GDBusDaemonClass *klass) 1672 { 1673 GObjectClass *gobject_class; 1674 1675 gobject_class = G_OBJECT_CLASS (klass); 1676 gobject_class->finalize = g_dbus_daemon_finalize; 1677 gobject_class->set_property = g_dbus_daemon_set_property; 1678 gobject_class->get_property = g_dbus_daemon_get_property; 1679 1680 g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT] = 1681 g_signal_new (I_("idle-timeout"), 1682 G_TYPE_DBUS_DAEMON, 1683 G_SIGNAL_RUN_LAST, 1684 0, 1685 NULL, NULL, 1686 NULL, 1687 G_TYPE_NONE, 0); 1688 1689 g_object_class_install_property (gobject_class, 1690 PROP_ADDRESS, 1691 g_param_spec_string ("address", 1692 "Bus Address", 1693 "The address the bus should use", 1694 NULL, 1695 G_PARAM_READWRITE | 1696 G_PARAM_CONSTRUCT_ONLY | 1697 G_PARAM_STATIC_STRINGS)); 1698 } 1699 1700 static void g_dbus_daemon_iface_init(_GFreedesktopDBusIface * iface)1701 g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface) 1702 { 1703 iface->handle_add_match = handle_add_match; 1704 iface->handle_get_connection_selinux_security_context = handle_get_connection_selinux_security_context; 1705 iface->handle_get_connection_unix_process_id = handle_get_connection_unix_process_id; 1706 iface->handle_get_connection_unix_user = handle_get_connection_unix_user; 1707 iface->handle_get_id = handle_get_id; 1708 iface->handle_get_name_owner = handle_get_name_owner; 1709 iface->handle_hello = handle_hello; 1710 iface->handle_list_activatable_names = handle_list_activatable_names; 1711 iface->handle_list_names = handle_list_names; 1712 iface->handle_list_queued_owners = handle_list_queued_owners; 1713 iface->handle_name_has_owner = handle_name_has_owner; 1714 iface->handle_release_name = handle_release_name; 1715 iface->handle_reload_config = handle_reload_config; 1716 iface->handle_update_activation_environment = handle_update_activation_environment; 1717 iface->handle_remove_match = handle_remove_match; 1718 iface->handle_request_name = handle_request_name; 1719 iface->handle_start_service_by_name = handle_start_service_by_name; 1720 } 1721 1722 static void initable_iface_init(GInitableIface * initable_iface)1723 initable_iface_init (GInitableIface *initable_iface) 1724 { 1725 initable_iface->init = initable_init; 1726 } 1727 1728 GDBusDaemon * _g_dbus_daemon_new(const char * address,GCancellable * cancellable,GError ** error)1729 _g_dbus_daemon_new (const char *address, 1730 GCancellable *cancellable, 1731 GError **error) 1732 { 1733 return g_initable_new (G_TYPE_DBUS_DAEMON, 1734 cancellable, 1735 error, 1736 "address", address, 1737 NULL); 1738 } 1739 1740 const char * _g_dbus_daemon_get_address(GDBusDaemon * daemon)1741 _g_dbus_daemon_get_address (GDBusDaemon *daemon) 1742 { 1743 return g_dbus_server_get_client_address (daemon->server); 1744 } 1745