1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* connection.c Client connections 3 * 4 * Copyright (C) 2003 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #include <config.h> 25 #include "connection.h" 26 #include "dispatch.h" 27 #include "policy.h" 28 #include "services.h" 29 #include "utils.h" 30 #include "signals.h" 31 #include "expirelist.h" 32 #include "selinux.h" 33 #include <dbus/dbus-list.h> 34 #include <dbus/dbus-hash.h> 35 #include <dbus/dbus-timeout.h> 36 37 /* Trim executed commands to this length; we want to keep logs readable */ 38 #define MAX_LOG_COMMAND_LEN 50 39 40 static void bus_connection_remove_transactions (DBusConnection *connection); 41 42 typedef struct 43 { 44 BusExpireItem expire_item; 45 46 DBusConnection *will_get_reply; 47 DBusConnection *will_send_reply; 48 49 dbus_uint32_t reply_serial; 50 51 } BusPendingReply; 52 53 struct BusConnections 54 { 55 int refcount; 56 DBusList *completed; /**< List of all completed connections */ 57 int n_completed; /**< Length of completed list */ 58 DBusList *incomplete; /**< List of all not-yet-active connections */ 59 int n_incomplete; /**< Length of incomplete list */ 60 BusContext *context; 61 DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */ 62 DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */ 63 int stamp; /**< Incrementing number */ 64 BusExpireList *pending_replies; /**< List of pending replies */ 65 }; 66 67 static dbus_int32_t connection_data_slot = -1; 68 69 typedef struct 70 { 71 BusConnections *connections; 72 DBusList *link_in_connection_list; 73 DBusConnection *connection; 74 DBusList *services_owned; 75 int n_services_owned; 76 DBusList *match_rules; 77 int n_match_rules; 78 char *name; 79 DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */ 80 DBusMessage *oom_message; 81 DBusPreallocatedSend *oom_preallocated; 82 BusClientPolicy *policy; 83 84 char *cached_loginfo_string; 85 BusSELinuxID *selinux_id; 86 87 long connection_tv_sec; /**< Time when we connected (seconds component) */ 88 long connection_tv_usec; /**< Time when we connected (microsec component) */ 89 int stamp; /**< connections->stamp last time we were traversed */ 90 } BusConnectionData; 91 92 static dbus_bool_t bus_pending_reply_expired (BusExpireList *list, 93 DBusList *link, 94 void *data); 95 96 static void bus_connection_drop_pending_replies (BusConnections *connections, 97 DBusConnection *connection); 98 99 static dbus_bool_t expire_incomplete_timeout (void *data); 100 101 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot)) 102 103 static DBusLoop* 104 connection_get_loop (DBusConnection *connection) 105 { 106 BusConnectionData *d; 107 108 d = BUS_CONNECTION_DATA (connection); 109 110 return bus_context_get_loop (d->connections->context); 111 } 112 113 114 static int 115 get_connections_for_uid (BusConnections *connections, 116 dbus_uid_t uid) 117 { 118 void *val; 119 int current_count; 120 121 /* val is NULL is 0 when it isn't in the hash yet */ 122 123 val = _dbus_hash_table_lookup_uintptr (connections->completed_by_user, 124 uid); 125 126 current_count = _DBUS_POINTER_TO_INT (val); 127 128 return current_count; 129 } 130 131 static dbus_bool_t 132 adjust_connections_for_uid (BusConnections *connections, 133 dbus_uid_t uid, 134 int adjustment) 135 { 136 int current_count; 137 138 current_count = get_connections_for_uid (connections, uid); 139 140 _dbus_verbose ("Adjusting connection count for UID " DBUS_UID_FORMAT 141 ": was %d adjustment %d making %d\n", 142 uid, current_count, adjustment, current_count + adjustment); 143 144 _dbus_assert (current_count >= 0); 145 146 current_count += adjustment; 147 148 _dbus_assert (current_count >= 0); 149 150 if (current_count == 0) 151 { 152 _dbus_hash_table_remove_uintptr (connections->completed_by_user, uid); 153 return TRUE; 154 } 155 else 156 { 157 dbus_bool_t retval; 158 159 retval = _dbus_hash_table_insert_uintptr (connections->completed_by_user, 160 uid, _DBUS_INT_TO_POINTER (current_count)); 161 162 /* only positive adjustment can fail as otherwise 163 * a hash entry should already exist 164 */ 165 _dbus_assert (adjustment > 0 || 166 (adjustment <= 0 && retval)); 167 168 return retval; 169 } 170 } 171 172 void 173 bus_connection_disconnected (DBusConnection *connection) 174 { 175 BusConnectionData *d; 176 BusService *service; 177 BusMatchmaker *matchmaker; 178 179 d = BUS_CONNECTION_DATA (connection); 180 _dbus_assert (d != NULL); 181 182 _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n", 183 d->name ? d->name : "(inactive)"); 184 185 /* Delete our match rules */ 186 if (d->n_match_rules > 0) 187 { 188 matchmaker = bus_context_get_matchmaker (d->connections->context); 189 bus_matchmaker_disconnected (matchmaker, connection); 190 } 191 192 /* Drop any service ownership. Unfortunately, this requires 193 * memory allocation and there doesn't seem to be a good way to 194 * handle it other than sleeping; we can't "fail" the operation of 195 * disconnecting a client, and preallocating a broadcast "service is 196 * now gone" message for every client-service pair seems kind of 197 * involved. 198 */ 199 while ((service = _dbus_list_get_last (&d->services_owned))) 200 { 201 BusTransaction *transaction; 202 DBusError error; 203 204 retry: 205 206 dbus_error_init (&error); 207 208 while ((transaction = bus_transaction_new (d->connections->context)) == NULL) 209 _dbus_wait_for_memory (); 210 211 if (!bus_service_remove_owner (service, connection, 212 transaction, &error)) 213 { 214 _DBUS_ASSERT_ERROR_CONTENT_IS_SET (&error); 215 216 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 217 { 218 dbus_error_free (&error); 219 bus_transaction_cancel_and_free (transaction); 220 _dbus_wait_for_memory (); 221 goto retry; 222 } 223 else 224 { 225 _dbus_verbose ("Failed to remove service owner: %s %s\n", 226 error.name, error.message); 227 _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason"); 228 } 229 } 230 231 bus_transaction_execute_and_free (transaction); 232 } 233 234 bus_dispatch_remove_connection (connection); 235 236 /* no more watching */ 237 if (!dbus_connection_set_watch_functions (connection, 238 NULL, NULL, NULL, 239 connection, 240 NULL)) 241 _dbus_assert_not_reached ("setting watch functions to NULL failed"); 242 243 if (!dbus_connection_set_timeout_functions (connection, 244 NULL, NULL, NULL, 245 connection, 246 NULL)) 247 _dbus_assert_not_reached ("setting timeout functions to NULL failed"); 248 249 dbus_connection_set_unix_user_function (connection, 250 NULL, NULL, NULL); 251 dbus_connection_set_windows_user_function (connection, 252 NULL, NULL, NULL); 253 254 dbus_connection_set_dispatch_status_function (connection, 255 NULL, NULL, NULL); 256 257 bus_connection_remove_transactions (connection); 258 259 if (d->link_in_connection_list != NULL) 260 { 261 if (d->name != NULL) 262 { 263 unsigned long uid; 264 265 _dbus_list_remove_link (&d->connections->completed, d->link_in_connection_list); 266 d->link_in_connection_list = NULL; 267 d->connections->n_completed -= 1; 268 269 if (dbus_connection_get_unix_user (connection, &uid)) 270 { 271 if (!adjust_connections_for_uid (d->connections, 272 uid, -1)) 273 _dbus_assert_not_reached ("adjusting downward should never fail"); 274 } 275 } 276 else 277 { 278 _dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list); 279 d->link_in_connection_list = NULL; 280 d->connections->n_incomplete -= 1; 281 } 282 283 _dbus_assert (d->connections->n_incomplete >= 0); 284 _dbus_assert (d->connections->n_completed >= 0); 285 } 286 287 bus_connection_drop_pending_replies (d->connections, connection); 288 289 /* frees "d" as side effect */ 290 dbus_connection_set_data (connection, 291 connection_data_slot, 292 NULL, NULL); 293 294 dbus_connection_unref (connection); 295 } 296 297 static dbus_bool_t 298 connection_watch_callback (DBusWatch *watch, 299 unsigned int condition, 300 void *data) 301 { 302 /* FIXME this can be done in dbus-mainloop.c 303 * if the code in activation.c for the babysitter 304 * watch handler is fixed. 305 */ 306 307 #if 0 308 _dbus_verbose ("Calling handle_watch\n"); 309 #endif 310 return dbus_watch_handle (watch, condition); 311 } 312 313 static dbus_bool_t 314 add_connection_watch (DBusWatch *watch, 315 void *data) 316 { 317 DBusConnection *connection = data; 318 319 return _dbus_loop_add_watch (connection_get_loop (connection), 320 watch, connection_watch_callback, connection, 321 NULL); 322 } 323 324 static void 325 remove_connection_watch (DBusWatch *watch, 326 void *data) 327 { 328 DBusConnection *connection = data; 329 330 _dbus_loop_remove_watch (connection_get_loop (connection), 331 watch, connection_watch_callback, connection); 332 } 333 334 static void 335 connection_timeout_callback (DBusTimeout *timeout, 336 void *data) 337 { 338 /* DBusConnection *connection = data; */ 339 340 /* can return FALSE on OOM but we just let it fire again later */ 341 dbus_timeout_handle (timeout); 342 } 343 344 static dbus_bool_t 345 add_connection_timeout (DBusTimeout *timeout, 346 void *data) 347 { 348 DBusConnection *connection = data; 349 350 return _dbus_loop_add_timeout (connection_get_loop (connection), 351 timeout, connection_timeout_callback, connection, NULL); 352 } 353 354 static void 355 remove_connection_timeout (DBusTimeout *timeout, 356 void *data) 357 { 358 DBusConnection *connection = data; 359 360 _dbus_loop_remove_timeout (connection_get_loop (connection), 361 timeout, connection_timeout_callback, connection); 362 } 363 364 static void 365 dispatch_status_function (DBusConnection *connection, 366 DBusDispatchStatus new_status, 367 void *data) 368 { 369 DBusLoop *loop = data; 370 371 if (new_status != DBUS_DISPATCH_COMPLETE) 372 { 373 while (!_dbus_loop_queue_dispatch (loop, connection)) 374 _dbus_wait_for_memory (); 375 } 376 } 377 378 static dbus_bool_t 379 allow_unix_user_function (DBusConnection *connection, 380 unsigned long uid, 381 void *data) 382 { 383 BusConnectionData *d; 384 385 d = BUS_CONNECTION_DATA (connection); 386 387 _dbus_assert (d != NULL); 388 389 return bus_context_allow_unix_user (d->connections->context, uid); 390 } 391 392 static void 393 free_connection_data (void *data) 394 { 395 BusConnectionData *d = data; 396 397 /* services_owned should be NULL since we should be disconnected */ 398 _dbus_assert (d->services_owned == NULL); 399 _dbus_assert (d->n_services_owned == 0); 400 /* similarly */ 401 _dbus_assert (d->transaction_messages == NULL); 402 403 if (d->oom_preallocated) 404 dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated); 405 406 if (d->oom_message) 407 dbus_message_unref (d->oom_message); 408 409 if (d->policy) 410 bus_client_policy_unref (d->policy); 411 412 if (d->selinux_id) 413 bus_selinux_id_unref (d->selinux_id); 414 415 dbus_free (d->cached_loginfo_string); 416 417 dbus_free (d->name); 418 419 dbus_free (d); 420 } 421 422 static void 423 call_timeout_callback (DBusTimeout *timeout, 424 void *data) 425 { 426 /* can return FALSE on OOM but we just let it fire again later */ 427 dbus_timeout_handle (timeout); 428 } 429 430 BusConnections* 431 bus_connections_new (BusContext *context) 432 { 433 BusConnections *connections; 434 435 if (!dbus_connection_allocate_data_slot (&connection_data_slot)) 436 goto failed_0; 437 438 connections = dbus_new0 (BusConnections, 1); 439 if (connections == NULL) 440 goto failed_1; 441 442 connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_UINTPTR, 443 NULL, NULL); 444 if (connections->completed_by_user == NULL) 445 goto failed_2; 446 447 connections->expire_timeout = _dbus_timeout_new (100, /* irrelevant */ 448 expire_incomplete_timeout, 449 connections, NULL); 450 if (connections->expire_timeout == NULL) 451 goto failed_3; 452 453 _dbus_timeout_set_enabled (connections->expire_timeout, FALSE); 454 455 connections->pending_replies = bus_expire_list_new (bus_context_get_loop (context), 456 bus_context_get_reply_timeout (context), 457 bus_pending_reply_expired, 458 connections); 459 if (connections->pending_replies == NULL) 460 goto failed_4; 461 462 if (!_dbus_loop_add_timeout (bus_context_get_loop (context), 463 connections->expire_timeout, 464 call_timeout_callback, NULL, NULL)) 465 goto failed_5; 466 467 connections->refcount = 1; 468 connections->context = context; 469 470 return connections; 471 472 failed_5: 473 bus_expire_list_free (connections->pending_replies); 474 failed_4: 475 _dbus_timeout_unref (connections->expire_timeout); 476 failed_3: 477 _dbus_hash_table_unref (connections->completed_by_user); 478 failed_2: 479 dbus_free (connections); 480 failed_1: 481 dbus_connection_free_data_slot (&connection_data_slot); 482 failed_0: 483 return NULL; 484 } 485 486 BusConnections * 487 bus_connections_ref (BusConnections *connections) 488 { 489 _dbus_assert (connections->refcount > 0); 490 connections->refcount += 1; 491 492 return connections; 493 } 494 495 void 496 bus_connections_unref (BusConnections *connections) 497 { 498 _dbus_assert (connections->refcount > 0); 499 connections->refcount -= 1; 500 if (connections->refcount == 0) 501 { 502 /* drop all incomplete */ 503 while (connections->incomplete != NULL) 504 { 505 DBusConnection *connection; 506 507 connection = connections->incomplete->data; 508 509 dbus_connection_ref (connection); 510 dbus_connection_close (connection); 511 bus_connection_disconnected (connection); 512 dbus_connection_unref (connection); 513 } 514 515 _dbus_assert (connections->n_incomplete == 0); 516 517 /* drop all real connections */ 518 while (connections->completed != NULL) 519 { 520 DBusConnection *connection; 521 522 connection = connections->completed->data; 523 524 dbus_connection_ref (connection); 525 dbus_connection_close (connection); 526 bus_connection_disconnected (connection); 527 dbus_connection_unref (connection); 528 } 529 530 _dbus_assert (connections->n_completed == 0); 531 532 bus_expire_list_free (connections->pending_replies); 533 534 _dbus_loop_remove_timeout (bus_context_get_loop (connections->context), 535 connections->expire_timeout, 536 call_timeout_callback, NULL); 537 538 _dbus_timeout_unref (connections->expire_timeout); 539 540 _dbus_hash_table_unref (connections->completed_by_user); 541 542 dbus_free (connections); 543 544 dbus_connection_free_data_slot (&connection_data_slot); 545 } 546 } 547 548 /* Used for logging */ 549 static dbus_bool_t 550 cache_peer_loginfo_string (BusConnectionData *d, 551 DBusConnection *connection) 552 { 553 DBusString loginfo_buf; 554 unsigned long uid; 555 unsigned long pid; 556 char *windows_sid; 557 dbus_bool_t prev_added; 558 559 if (!_dbus_string_init (&loginfo_buf)) 560 return FALSE; 561 562 prev_added = FALSE; 563 if (dbus_connection_get_unix_user (connection, &uid)) 564 { 565 if (!_dbus_string_append_printf (&loginfo_buf, "uid=%ld", uid)) 566 goto oom; 567 else 568 prev_added = TRUE; 569 } 570 571 if (dbus_connection_get_unix_process_id (connection, &pid)) 572 { 573 if (prev_added) 574 { 575 if (!_dbus_string_append_byte (&loginfo_buf, ' ')) 576 goto oom; 577 } 578 if (!_dbus_string_append_printf (&loginfo_buf, "pid=%ld comm=\"", pid)) 579 goto oom; 580 /* Ignore errors here; we may not have permissions to read the 581 * proc file. */ 582 _dbus_command_for_pid (pid, &loginfo_buf, MAX_LOG_COMMAND_LEN, NULL); 583 if (!_dbus_string_append_byte (&loginfo_buf, '"')) 584 goto oom; 585 } 586 587 if (dbus_connection_get_windows_user (connection, &windows_sid)) 588 { 589 if (!_dbus_string_append_printf (&loginfo_buf, "sid=\"%s\" ", windows_sid)) 590 goto oom; 591 dbus_free (windows_sid); 592 } 593 594 if (!_dbus_string_steal_data (&loginfo_buf, &(d->cached_loginfo_string))) 595 goto oom; 596 597 _dbus_string_free (&loginfo_buf); 598 599 return TRUE; 600 oom: 601 _dbus_string_free (&loginfo_buf); 602 return FALSE; 603 } 604 605 dbus_bool_t 606 bus_connections_setup_connection (BusConnections *connections, 607 DBusConnection *connection) 608 { 609 610 BusConnectionData *d; 611 dbus_bool_t retval; 612 DBusError error; 613 614 615 d = dbus_new0 (BusConnectionData, 1); 616 617 if (d == NULL) 618 return FALSE; 619 620 d->connections = connections; 621 d->connection = connection; 622 623 _dbus_get_current_time (&d->connection_tv_sec, 624 &d->connection_tv_usec); 625 626 _dbus_assert (connection_data_slot >= 0); 627 628 if (!dbus_connection_set_data (connection, 629 connection_data_slot, 630 d, free_connection_data)) 631 { 632 dbus_free (d); 633 return FALSE; 634 } 635 636 dbus_connection_set_route_peer_messages (connection, TRUE); 637 638 retval = FALSE; 639 640 dbus_error_init (&error); 641 d->selinux_id = bus_selinux_init_connection_id (connection, 642 &error); 643 if (dbus_error_is_set (&error)) 644 { 645 /* This is a bit bogus because we pretend all errors 646 * are OOM; this is done because we know that in bus.c 647 * an OOM error disconnects the connection, which is 648 * the same thing we want on any other error. 649 */ 650 dbus_error_free (&error); 651 goto out; 652 } 653 654 if (!dbus_connection_set_watch_functions (connection, 655 add_connection_watch, 656 remove_connection_watch, 657 NULL, 658 connection, 659 NULL)) 660 goto out; 661 662 if (!dbus_connection_set_timeout_functions (connection, 663 add_connection_timeout, 664 remove_connection_timeout, 665 NULL, 666 connection, NULL)) 667 goto out; 668 669 /* For now we don't need to set a Windows user function because 670 * there are no policies in the config file controlling what 671 * Windows users can connect. The default 'same user that owns the 672 * bus can connect' behavior of DBusConnection is fine on Windows. 673 */ 674 dbus_connection_set_unix_user_function (connection, 675 allow_unix_user_function, 676 NULL, NULL); 677 678 dbus_connection_set_dispatch_status_function (connection, 679 dispatch_status_function, 680 bus_context_get_loop (connections->context), 681 NULL); 682 683 d->link_in_connection_list = _dbus_list_alloc_link (connection); 684 if (d->link_in_connection_list == NULL) 685 goto out; 686 687 /* Setup the connection with the dispatcher */ 688 if (!bus_dispatch_add_connection (connection)) 689 goto out; 690 691 if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE) 692 { 693 if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection)) 694 { 695 bus_dispatch_remove_connection (connection); 696 goto out; 697 } 698 } 699 700 _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list); 701 connections->n_incomplete += 1; 702 703 dbus_connection_ref (connection); 704 705 /* Note that we might disconnect ourselves here, but it only takes 706 * effect on return to the main loop. We call this to free up 707 * expired connections if possible, and to queue the timeout for our 708 * own expiration. 709 */ 710 bus_connections_expire_incomplete (connections); 711 712 /* And we might also disconnect ourselves here, but again it 713 * only takes effect on return to main loop. 714 */ 715 if (connections->n_incomplete > 716 bus_context_get_max_incomplete_connections (connections->context)) 717 { 718 _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n"); 719 720 _dbus_assert (connections->incomplete != NULL); 721 /* Disconnect the oldest unauthenticated connection. FIXME 722 * would it be more secure to drop a *random* connection? This 723 * algorithm seems to mean that if someone can create new 724 * connections quickly enough, they can keep anyone else from 725 * completing authentication. But random may or may not really 726 * help with that, a more elaborate solution might be required. 727 */ 728 dbus_connection_close (connections->incomplete->data); 729 } 730 731 retval = TRUE; 732 733 out: 734 if (!retval) 735 { 736 if (d->selinux_id) 737 bus_selinux_id_unref (d->selinux_id); 738 d->selinux_id = NULL; 739 740 if (!dbus_connection_set_watch_functions (connection, 741 NULL, NULL, NULL, 742 connection, 743 NULL)) 744 _dbus_assert_not_reached ("setting watch functions to NULL failed"); 745 746 if (!dbus_connection_set_timeout_functions (connection, 747 NULL, NULL, NULL, 748 connection, 749 NULL)) 750 _dbus_assert_not_reached ("setting timeout functions to NULL failed"); 751 752 dbus_connection_set_unix_user_function (connection, 753 NULL, NULL, NULL); 754 755 dbus_connection_set_windows_user_function (connection, 756 NULL, NULL, NULL); 757 758 dbus_connection_set_dispatch_status_function (connection, 759 NULL, NULL, NULL); 760 761 if (d->link_in_connection_list != NULL) 762 { 763 _dbus_assert (d->link_in_connection_list->next == NULL); 764 _dbus_assert (d->link_in_connection_list->prev == NULL); 765 _dbus_list_free_link (d->link_in_connection_list); 766 d->link_in_connection_list = NULL; 767 } 768 769 if (!dbus_connection_set_data (connection, 770 connection_data_slot, 771 NULL, NULL)) 772 _dbus_assert_not_reached ("failed to set connection data to null"); 773 774 /* "d" has now been freed */ 775 } 776 777 return retval; 778 } 779 780 void 781 bus_connections_expire_incomplete (BusConnections *connections) 782 { 783 int next_interval; 784 785 next_interval = -1; 786 787 if (connections->incomplete != NULL) 788 { 789 long tv_sec, tv_usec; 790 DBusList *link; 791 int auth_timeout; 792 793 _dbus_get_current_time (&tv_sec, &tv_usec); 794 auth_timeout = bus_context_get_auth_timeout (connections->context); 795 796 link = _dbus_list_get_first_link (&connections->incomplete); 797 while (link != NULL) 798 { 799 DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link); 800 DBusConnection *connection; 801 BusConnectionData *d; 802 double elapsed; 803 804 connection = link->data; 805 806 d = BUS_CONNECTION_DATA (connection); 807 808 _dbus_assert (d != NULL); 809 810 elapsed = ELAPSED_MILLISECONDS_SINCE (d->connection_tv_sec, 811 d->connection_tv_usec, 812 tv_sec, tv_usec); 813 814 if (elapsed >= (double) auth_timeout) 815 { 816 _dbus_verbose ("Timing out authentication for connection %p\n", connection); 817 dbus_connection_close (connection); 818 } 819 else 820 { 821 /* We can end the loop, since the connections are in oldest-first order */ 822 next_interval = ((double)auth_timeout) - elapsed; 823 _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n", 824 connection, next_interval); 825 826 break; 827 } 828 829 link = next; 830 } 831 } 832 833 bus_expire_timeout_set_interval (connections->expire_timeout, 834 next_interval); 835 } 836 837 static dbus_bool_t 838 expire_incomplete_timeout (void *data) 839 { 840 BusConnections *connections = data; 841 842 _dbus_verbose ("Running\n"); 843 844 /* note that this may remove the timeout */ 845 bus_connections_expire_incomplete (connections); 846 847 return TRUE; 848 } 849 850 dbus_bool_t 851 bus_connection_get_unix_groups (DBusConnection *connection, 852 unsigned long **groups, 853 int *n_groups, 854 DBusError *error) 855 { 856 BusConnectionData *d; 857 unsigned long uid; 858 859 d = BUS_CONNECTION_DATA (connection); 860 861 _dbus_assert (d != NULL); 862 863 *groups = NULL; 864 *n_groups = 0; 865 866 if (dbus_connection_get_unix_user (connection, &uid)) 867 { 868 if (!_dbus_unix_groups_from_uid (uid, groups, n_groups)) 869 { 870 _dbus_verbose ("Did not get any groups for UID %lu\n", 871 uid); 872 return FALSE; 873 } 874 else 875 { 876 _dbus_verbose ("Got %d groups for UID %lu\n", 877 *n_groups, uid); 878 return TRUE; 879 } 880 } 881 else 882 return TRUE; /* successfully got 0 groups */ 883 } 884 885 dbus_bool_t 886 bus_connection_is_in_unix_group (DBusConnection *connection, 887 unsigned long gid) 888 { 889 int i; 890 unsigned long *group_ids; 891 int n_group_ids; 892 893 if (!bus_connection_get_unix_groups (connection, &group_ids, &n_group_ids, 894 NULL)) 895 return FALSE; 896 897 i = 0; 898 while (i < n_group_ids) 899 { 900 if (group_ids[i] == gid) 901 { 902 dbus_free (group_ids); 903 return TRUE; 904 } 905 ++i; 906 } 907 908 dbus_free (group_ids); 909 return FALSE; 910 } 911 912 const char * 913 bus_connection_get_loginfo (DBusConnection *connection) 914 { 915 BusConnectionData *d; 916 917 d = BUS_CONNECTION_DATA (connection); 918 919 if (!bus_connection_is_active (connection)) 920 return "inactive"; 921 return d->cached_loginfo_string; 922 } 923 924 BusClientPolicy* 925 bus_connection_get_policy (DBusConnection *connection) 926 { 927 BusConnectionData *d; 928 929 d = BUS_CONNECTION_DATA (connection); 930 931 _dbus_assert (d != NULL); 932 _dbus_assert (d->policy != NULL); 933 934 return d->policy; 935 } 936 937 static dbus_bool_t 938 foreach_active (BusConnections *connections, 939 BusConnectionForeachFunction function, 940 void *data) 941 { 942 DBusList *link; 943 944 link = _dbus_list_get_first_link (&connections->completed); 945 while (link != NULL) 946 { 947 DBusConnection *connection = link->data; 948 DBusList *next = _dbus_list_get_next_link (&connections->completed, link); 949 950 if (!(* function) (connection, data)) 951 return FALSE; 952 953 link = next; 954 } 955 956 return TRUE; 957 } 958 959 static dbus_bool_t 960 foreach_inactive (BusConnections *connections, 961 BusConnectionForeachFunction function, 962 void *data) 963 { 964 DBusList *link; 965 966 link = _dbus_list_get_first_link (&connections->incomplete); 967 while (link != NULL) 968 { 969 DBusConnection *connection = link->data; 970 DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link); 971 972 if (!(* function) (connection, data)) 973 return FALSE; 974 975 link = next; 976 } 977 978 return TRUE; 979 } 980 981 /** 982 * Calls function on each active connection; if the function returns 983 * #FALSE, stops iterating. Active connections are authenticated 984 * and have sent a Hello message. 985 * 986 * @param connections the connections object 987 * @param function the function 988 * @param data data to pass to it as a second arg 989 */ 990 void 991 bus_connections_foreach_active (BusConnections *connections, 992 BusConnectionForeachFunction function, 993 void *data) 994 { 995 foreach_active (connections, function, data); 996 } 997 998 /** 999 * Calls function on each connection; if the function returns 1000 * #FALSE, stops iterating. 1001 * 1002 * @param connections the connections object 1003 * @param function the function 1004 * @param data data to pass to it as a second arg 1005 */ 1006 void 1007 bus_connections_foreach (BusConnections *connections, 1008 BusConnectionForeachFunction function, 1009 void *data) 1010 { 1011 if (!foreach_active (connections, function, data)) 1012 return; 1013 1014 foreach_inactive (connections, function, data); 1015 } 1016 1017 BusContext* 1018 bus_connections_get_context (BusConnections *connections) 1019 { 1020 return connections->context; 1021 } 1022 1023 /* 1024 * This is used to avoid covering the same connection twice when 1025 * traversing connections. Note that it assumes we will 1026 * bus_connection_mark_stamp() each connection at least once per 1027 * INT_MAX increments of the global stamp, or wraparound would break 1028 * things. 1029 */ 1030 void 1031 bus_connections_increment_stamp (BusConnections *connections) 1032 { 1033 connections->stamp += 1; 1034 } 1035 1036 /* Mark connection with current stamp, return TRUE if it 1037 * didn't already have that stamp 1038 */ 1039 dbus_bool_t 1040 bus_connection_mark_stamp (DBusConnection *connection) 1041 { 1042 BusConnectionData *d; 1043 1044 d = BUS_CONNECTION_DATA (connection); 1045 1046 _dbus_assert (d != NULL); 1047 1048 if (d->stamp == d->connections->stamp) 1049 return FALSE; 1050 else 1051 { 1052 d->stamp = d->connections->stamp; 1053 return TRUE; 1054 } 1055 } 1056 1057 BusContext* 1058 bus_connection_get_context (DBusConnection *connection) 1059 { 1060 BusConnectionData *d; 1061 1062 d = BUS_CONNECTION_DATA (connection); 1063 1064 _dbus_assert (d != NULL); 1065 1066 return d->connections->context; 1067 } 1068 1069 BusConnections* 1070 bus_connection_get_connections (DBusConnection *connection) 1071 { 1072 BusConnectionData *d; 1073 1074 d = BUS_CONNECTION_DATA (connection); 1075 1076 _dbus_assert (d != NULL); 1077 1078 return d->connections; 1079 } 1080 1081 BusRegistry* 1082 bus_connection_get_registry (DBusConnection *connection) 1083 { 1084 BusConnectionData *d; 1085 1086 d = BUS_CONNECTION_DATA (connection); 1087 1088 _dbus_assert (d != NULL); 1089 1090 return bus_context_get_registry (d->connections->context); 1091 } 1092 1093 BusActivation* 1094 bus_connection_get_activation (DBusConnection *connection) 1095 { 1096 BusConnectionData *d; 1097 1098 d = BUS_CONNECTION_DATA (connection); 1099 1100 _dbus_assert (d != NULL); 1101 1102 return bus_context_get_activation (d->connections->context); 1103 } 1104 1105 BusMatchmaker* 1106 bus_connection_get_matchmaker (DBusConnection *connection) 1107 { 1108 BusConnectionData *d; 1109 1110 d = BUS_CONNECTION_DATA (connection); 1111 1112 _dbus_assert (d != NULL); 1113 1114 return bus_context_get_matchmaker (d->connections->context); 1115 } 1116 1117 BusSELinuxID* 1118 bus_connection_get_selinux_id (DBusConnection *connection) 1119 { 1120 BusConnectionData *d; 1121 1122 d = BUS_CONNECTION_DATA (connection); 1123 1124 _dbus_assert (d != NULL); 1125 1126 return d->selinux_id; 1127 } 1128 1129 /** 1130 * Checks whether the connection is registered with the message bus. 1131 * 1132 * @param connection the connection 1133 * @returns #TRUE if we're an active message bus participant 1134 */ 1135 dbus_bool_t 1136 bus_connection_is_active (DBusConnection *connection) 1137 { 1138 BusConnectionData *d; 1139 1140 d = BUS_CONNECTION_DATA (connection); 1141 1142 return d != NULL && d->name != NULL; 1143 } 1144 1145 dbus_bool_t 1146 bus_connection_preallocate_oom_error (DBusConnection *connection) 1147 { 1148 DBusMessage *message; 1149 DBusPreallocatedSend *preallocated; 1150 BusConnectionData *d; 1151 1152 d = BUS_CONNECTION_DATA (connection); 1153 1154 _dbus_assert (d != NULL); 1155 1156 if (d->oom_preallocated != NULL) 1157 return TRUE; 1158 1159 preallocated = dbus_connection_preallocate_send (connection); 1160 if (preallocated == NULL) 1161 return FALSE; 1162 1163 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 1164 1165 if (message == NULL) 1166 { 1167 dbus_connection_free_preallocated_send (connection, preallocated); 1168 return FALSE; 1169 } 1170 1171 /* d->name may be NULL, but that is OK */ 1172 if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) || 1173 !dbus_message_set_destination (message, d->name) || 1174 !dbus_message_set_sender (message, 1175 DBUS_SERVICE_DBUS)) 1176 { 1177 dbus_connection_free_preallocated_send (connection, preallocated); 1178 dbus_message_unref (message); 1179 return FALSE; 1180 } 1181 1182 /* set reply serial to placeholder value just so space is already allocated 1183 * for it. 1184 */ 1185 if (!dbus_message_set_reply_serial (message, 14)) 1186 { 1187 dbus_connection_free_preallocated_send (connection, preallocated); 1188 dbus_message_unref (message); 1189 return FALSE; 1190 } 1191 1192 d->oom_message = message; 1193 d->oom_preallocated = preallocated; 1194 1195 return TRUE; 1196 } 1197 1198 void 1199 bus_connection_send_oom_error (DBusConnection *connection, 1200 DBusMessage *in_reply_to) 1201 { 1202 BusConnectionData *d; 1203 1204 d = BUS_CONNECTION_DATA (connection); 1205 1206 _dbus_assert (d != NULL); 1207 _dbus_assert (d->oom_message != NULL); 1208 1209 /* should always succeed since we set it to a placeholder earlier */ 1210 if (!dbus_message_set_reply_serial (d->oom_message, 1211 dbus_message_get_serial (in_reply_to))) 1212 _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message"); 1213 1214 _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL); 1215 1216 dbus_connection_send_preallocated (connection, d->oom_preallocated, 1217 d->oom_message, NULL); 1218 1219 dbus_message_unref (d->oom_message); 1220 d->oom_message = NULL; 1221 d->oom_preallocated = NULL; 1222 } 1223 1224 void 1225 bus_connection_add_match_rule_link (DBusConnection *connection, 1226 DBusList *link) 1227 { 1228 BusConnectionData *d; 1229 1230 d = BUS_CONNECTION_DATA (connection); 1231 _dbus_assert (d != NULL); 1232 1233 _dbus_list_append_link (&d->match_rules, link); 1234 1235 d->n_match_rules += 1; 1236 } 1237 1238 dbus_bool_t 1239 bus_connection_add_match_rule (DBusConnection *connection, 1240 BusMatchRule *rule) 1241 { 1242 DBusList *link; 1243 1244 link = _dbus_list_alloc_link (rule); 1245 1246 if (link == NULL) 1247 return FALSE; 1248 1249 bus_connection_add_match_rule_link (connection, link); 1250 1251 return TRUE; 1252 } 1253 1254 void 1255 bus_connection_remove_match_rule (DBusConnection *connection, 1256 BusMatchRule *rule) 1257 { 1258 BusConnectionData *d; 1259 1260 d = BUS_CONNECTION_DATA (connection); 1261 _dbus_assert (d != NULL); 1262 1263 _dbus_list_remove_last (&d->match_rules, rule); 1264 1265 d->n_match_rules -= 1; 1266 _dbus_assert (d->n_match_rules >= 0); 1267 } 1268 1269 int 1270 bus_connection_get_n_match_rules (DBusConnection *connection) 1271 { 1272 BusConnectionData *d; 1273 1274 d = BUS_CONNECTION_DATA (connection); 1275 _dbus_assert (d != NULL); 1276 1277 return d->n_match_rules; 1278 } 1279 1280 void 1281 bus_connection_add_owned_service_link (DBusConnection *connection, 1282 DBusList *link) 1283 { 1284 BusConnectionData *d; 1285 1286 d = BUS_CONNECTION_DATA (connection); 1287 _dbus_assert (d != NULL); 1288 1289 _dbus_list_append_link (&d->services_owned, link); 1290 1291 d->n_services_owned += 1; 1292 } 1293 1294 dbus_bool_t 1295 bus_connection_add_owned_service (DBusConnection *connection, 1296 BusService *service) 1297 { 1298 DBusList *link; 1299 1300 link = _dbus_list_alloc_link (service); 1301 1302 if (link == NULL) 1303 return FALSE; 1304 1305 bus_connection_add_owned_service_link (connection, link); 1306 1307 return TRUE; 1308 } 1309 1310 void 1311 bus_connection_remove_owned_service (DBusConnection *connection, 1312 BusService *service) 1313 { 1314 BusConnectionData *d; 1315 1316 d = BUS_CONNECTION_DATA (connection); 1317 _dbus_assert (d != NULL); 1318 1319 _dbus_list_remove_last (&d->services_owned, service); 1320 1321 d->n_services_owned -= 1; 1322 _dbus_assert (d->n_services_owned >= 0); 1323 } 1324 1325 int 1326 bus_connection_get_n_services_owned (DBusConnection *connection) 1327 { 1328 BusConnectionData *d; 1329 1330 d = BUS_CONNECTION_DATA (connection); 1331 _dbus_assert (d != NULL); 1332 1333 return d->n_services_owned; 1334 } 1335 1336 dbus_bool_t 1337 bus_connection_complete (DBusConnection *connection, 1338 const DBusString *name, 1339 DBusError *error) 1340 { 1341 BusConnectionData *d; 1342 unsigned long uid; 1343 1344 d = BUS_CONNECTION_DATA (connection); 1345 _dbus_assert (d != NULL); 1346 _dbus_assert (d->name == NULL); 1347 _dbus_assert (d->policy == NULL); 1348 1349 _dbus_assert (!bus_connection_is_active (connection)); 1350 1351 if (!_dbus_string_copy_data (name, &d->name)) 1352 { 1353 BUS_SET_OOM (error); 1354 return FALSE; 1355 } 1356 1357 _dbus_assert (d->name != NULL); 1358 1359 _dbus_verbose ("Name %s assigned to %p\n", d->name, connection); 1360 1361 d->policy = bus_context_create_client_policy (d->connections->context, 1362 connection, 1363 error); 1364 1365 /* we may have a NULL policy on OOM or error getting list of 1366 * groups for a user. In the latter case we don't handle it so 1367 * well currently, as it will just keep failing over and over. 1368 */ 1369 1370 if (d->policy == NULL) 1371 { 1372 _dbus_verbose ("Failed to create security policy for connection %p\n", 1373 connection); 1374 _DBUS_ASSERT_ERROR_IS_SET (error); 1375 dbus_free (d->name); 1376 d->name = NULL; 1377 return FALSE; 1378 } 1379 1380 if (dbus_connection_get_unix_user (connection, &uid)) 1381 { 1382 if (!adjust_connections_for_uid (d->connections, 1383 uid, 1)) 1384 goto fail; 1385 } 1386 1387 /* Create and cache a string which holds information about the 1388 * peer process; used for logging purposes. 1389 */ 1390 if (!cache_peer_loginfo_string (d, connection)) 1391 goto fail; 1392 1393 /* Now the connection is active, move it between lists */ 1394 _dbus_list_unlink (&d->connections->incomplete, 1395 d->link_in_connection_list); 1396 d->connections->n_incomplete -= 1; 1397 _dbus_list_append_link (&d->connections->completed, 1398 d->link_in_connection_list); 1399 d->connections->n_completed += 1; 1400 1401 _dbus_assert (d->connections->n_incomplete >= 0); 1402 _dbus_assert (d->connections->n_completed > 0); 1403 1404 /* See if we can remove the timeout */ 1405 bus_connections_expire_incomplete (d->connections); 1406 1407 _dbus_assert (bus_connection_is_active (connection)); 1408 1409 return TRUE; 1410 fail: 1411 BUS_SET_OOM (error); 1412 dbus_free (d->name); 1413 d->name = NULL; 1414 if (d->policy) 1415 bus_client_policy_unref (d->policy); 1416 d->policy = NULL; 1417 return FALSE; 1418 } 1419 1420 const char * 1421 bus_connection_get_name (DBusConnection *connection) 1422 { 1423 BusConnectionData *d; 1424 1425 d = BUS_CONNECTION_DATA (connection); 1426 _dbus_assert (d != NULL); 1427 1428 return d->name; 1429 } 1430 1431 /** 1432 * Check whether completing the passed-in connection would 1433 * exceed limits, and if so set error and return #FALSE 1434 */ 1435 dbus_bool_t 1436 bus_connections_check_limits (BusConnections *connections, 1437 DBusConnection *requesting_completion, 1438 DBusError *error) 1439 { 1440 BusConnectionData *d; 1441 unsigned long uid; 1442 1443 d = BUS_CONNECTION_DATA (requesting_completion); 1444 _dbus_assert (d != NULL); 1445 1446 _dbus_assert (d->name == NULL); 1447 1448 if (connections->n_completed >= 1449 bus_context_get_max_completed_connections (connections->context)) 1450 { 1451 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, 1452 "The maximum number of active connections has been reached"); 1453 return FALSE; 1454 } 1455 1456 if (dbus_connection_get_unix_user (requesting_completion, &uid)) 1457 { 1458 if (get_connections_for_uid (connections, uid) >= 1459 bus_context_get_max_connections_per_user (connections->context)) 1460 { 1461 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, 1462 "The maximum number of active connections for UID %lu has been reached", 1463 uid); 1464 return FALSE; 1465 } 1466 } 1467 1468 return TRUE; 1469 } 1470 1471 static void 1472 bus_pending_reply_free (BusPendingReply *pending) 1473 { 1474 _dbus_verbose ("Freeing pending reply %p, replier %p receiver %p serial %u\n", 1475 pending, 1476 pending->will_send_reply, 1477 pending->will_get_reply, 1478 pending->reply_serial); 1479 1480 dbus_free (pending); 1481 } 1482 1483 static dbus_bool_t 1484 bus_pending_reply_send_no_reply (BusConnections *connections, 1485 BusTransaction *transaction, 1486 BusPendingReply *pending) 1487 { 1488 DBusMessage *message; 1489 DBusMessageIter iter; 1490 dbus_bool_t retval; 1491 const char *errmsg; 1492 1493 retval = FALSE; 1494 1495 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 1496 if (message == NULL) 1497 return FALSE; 1498 1499 dbus_message_set_no_reply (message, TRUE); 1500 1501 if (!dbus_message_set_reply_serial (message, 1502 pending->reply_serial)) 1503 goto out; 1504 1505 if (!dbus_message_set_error_name (message, 1506 DBUS_ERROR_NO_REPLY)) 1507 goto out; 1508 1509 errmsg = "Message did not receive a reply (timeout by message bus)"; 1510 dbus_message_iter_init_append (message, &iter); 1511 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &errmsg)) 1512 goto out; 1513 1514 if (!bus_transaction_send_from_driver (transaction, pending->will_get_reply, 1515 message)) 1516 goto out; 1517 1518 retval = TRUE; 1519 1520 out: 1521 dbus_message_unref (message); 1522 return retval; 1523 } 1524 1525 static dbus_bool_t 1526 bus_pending_reply_expired (BusExpireList *list, 1527 DBusList *link, 1528 void *data) 1529 { 1530 BusPendingReply *pending = link->data; 1531 BusConnections *connections = data; 1532 BusTransaction *transaction; 1533 1534 /* No reply is forthcoming. So nuke it if we can. If not, 1535 * leave it in the list to try expiring again later when we 1536 * get more memory. 1537 */ 1538 1539 _dbus_verbose ("Expiring pending reply %p, replier %p receiver %p serial %u\n", 1540 pending, 1541 pending->will_send_reply, 1542 pending->will_get_reply, 1543 pending->reply_serial); 1544 1545 transaction = bus_transaction_new (connections->context); 1546 if (transaction == NULL) 1547 return FALSE; 1548 1549 if (!bus_pending_reply_send_no_reply (connections, 1550 transaction, 1551 pending)) 1552 { 1553 bus_transaction_cancel_and_free (transaction); 1554 return FALSE; 1555 } 1556 1557 bus_expire_list_remove_link (connections->pending_replies, link); 1558 1559 bus_pending_reply_free (pending); 1560 bus_transaction_execute_and_free (transaction); 1561 1562 return TRUE; 1563 } 1564 1565 static void 1566 bus_connection_drop_pending_replies (BusConnections *connections, 1567 DBusConnection *connection) 1568 { 1569 /* The DBusConnection is almost 100% finalized here, so you can't 1570 * do anything with it except check for pointer equality 1571 */ 1572 DBusList *link; 1573 1574 _dbus_verbose ("Dropping pending replies that involve connection %p\n", 1575 connection); 1576 1577 link = bus_expire_list_get_first_link (connections->pending_replies); 1578 while (link != NULL) 1579 { 1580 DBusList *next; 1581 BusPendingReply *pending; 1582 1583 next = bus_expire_list_get_next_link (connections->pending_replies, 1584 link); 1585 pending = link->data; 1586 1587 if (pending->will_get_reply == connection) 1588 { 1589 /* We don't need to track this pending reply anymore */ 1590 1591 _dbus_verbose ("Dropping pending reply %p, replier %p receiver %p serial %u\n", 1592 pending, 1593 pending->will_send_reply, 1594 pending->will_get_reply, 1595 pending->reply_serial); 1596 1597 bus_expire_list_remove_link (connections->pending_replies, 1598 link); 1599 bus_pending_reply_free (pending); 1600 } 1601 else if (pending->will_send_reply == connection) 1602 { 1603 /* The reply isn't going to be sent, so set things 1604 * up so it will be expired right away 1605 */ 1606 _dbus_verbose ("Will expire pending reply %p, replier %p receiver %p serial %u\n", 1607 pending, 1608 pending->will_send_reply, 1609 pending->will_get_reply, 1610 pending->reply_serial); 1611 1612 pending->will_send_reply = NULL; 1613 pending->expire_item.added_tv_sec = 0; 1614 pending->expire_item.added_tv_usec = 0; 1615 1616 bus_expire_list_recheck_immediately (connections->pending_replies); 1617 } 1618 1619 link = next; 1620 } 1621 } 1622 1623 1624 typedef struct 1625 { 1626 BusPendingReply *pending; 1627 BusConnections *connections; 1628 } CancelPendingReplyData; 1629 1630 static void 1631 cancel_pending_reply (void *data) 1632 { 1633 CancelPendingReplyData *d = data; 1634 1635 _dbus_verbose ("d = %p\n", d); 1636 1637 if (!bus_expire_list_remove (d->connections->pending_replies, 1638 &d->pending->expire_item)) 1639 _dbus_assert_not_reached ("pending reply did not exist to be cancelled"); 1640 1641 bus_pending_reply_free (d->pending); /* since it's been cancelled */ 1642 } 1643 1644 static void 1645 cancel_pending_reply_data_free (void *data) 1646 { 1647 CancelPendingReplyData *d = data; 1648 1649 _dbus_verbose ("d = %p\n", d); 1650 1651 /* d->pending should be either freed or still 1652 * in the list of pending replies (owned by someone 1653 * else) 1654 */ 1655 1656 dbus_free (d); 1657 } 1658 1659 /* 1660 * Record that a reply is allowed; return TRUE on success. 1661 */ 1662 dbus_bool_t 1663 bus_connections_expect_reply (BusConnections *connections, 1664 BusTransaction *transaction, 1665 DBusConnection *will_get_reply, 1666 DBusConnection *will_send_reply, 1667 DBusMessage *reply_to_this, 1668 DBusError *error) 1669 { 1670 BusPendingReply *pending; 1671 dbus_uint32_t reply_serial; 1672 DBusList *link; 1673 CancelPendingReplyData *cprd; 1674 int count; 1675 1676 _dbus_assert (will_get_reply != NULL); 1677 _dbus_assert (will_send_reply != NULL); 1678 _dbus_assert (reply_to_this != NULL); 1679 1680 if (dbus_message_get_no_reply (reply_to_this)) 1681 return TRUE; /* we won't allow a reply, since client doesn't care for one. */ 1682 1683 reply_serial = dbus_message_get_serial (reply_to_this); 1684 1685 link = bus_expire_list_get_first_link (connections->pending_replies); 1686 count = 0; 1687 while (link != NULL) 1688 { 1689 pending = link->data; 1690 1691 if (pending->reply_serial == reply_serial && 1692 pending->will_get_reply == will_get_reply && 1693 pending->will_send_reply == will_send_reply) 1694 { 1695 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, 1696 "Message has the same reply serial as a currently-outstanding existing method call"); 1697 return FALSE; 1698 } 1699 1700 link = bus_expire_list_get_next_link (connections->pending_replies, 1701 link); 1702 if (pending->will_get_reply == will_get_reply) 1703 ++count; 1704 } 1705 1706 if (count >= 1707 bus_context_get_max_replies_per_connection (connections->context)) 1708 { 1709 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, 1710 "The maximum number of pending replies per connection has been reached"); 1711 return FALSE; 1712 } 1713 1714 pending = dbus_new0 (BusPendingReply, 1); 1715 if (pending == NULL) 1716 { 1717 BUS_SET_OOM (error); 1718 return FALSE; 1719 } 1720 1721 #ifdef DBUS_ENABLE_VERBOSE_MODE 1722 /* so we can see a not-yet-added pending reply */ 1723 pending->expire_item.added_tv_sec = 1; 1724 pending->expire_item.added_tv_usec = 1; 1725 #endif 1726 1727 pending->will_get_reply = will_get_reply; 1728 pending->will_send_reply = will_send_reply; 1729 pending->reply_serial = reply_serial; 1730 1731 cprd = dbus_new0 (CancelPendingReplyData, 1); 1732 if (cprd == NULL) 1733 { 1734 BUS_SET_OOM (error); 1735 bus_pending_reply_free (pending); 1736 return FALSE; 1737 } 1738 1739 if (!bus_expire_list_add (connections->pending_replies, 1740 &pending->expire_item)) 1741 { 1742 BUS_SET_OOM (error); 1743 dbus_free (cprd); 1744 bus_pending_reply_free (pending); 1745 return FALSE; 1746 } 1747 1748 if (!bus_transaction_add_cancel_hook (transaction, 1749 cancel_pending_reply, 1750 cprd, 1751 cancel_pending_reply_data_free)) 1752 { 1753 BUS_SET_OOM (error); 1754 bus_expire_list_remove (connections->pending_replies, &pending->expire_item); 1755 dbus_free (cprd); 1756 bus_pending_reply_free (pending); 1757 return FALSE; 1758 } 1759 1760 cprd->pending = pending; 1761 cprd->connections = connections; 1762 1763 _dbus_get_current_time (&pending->expire_item.added_tv_sec, 1764 &pending->expire_item.added_tv_usec); 1765 1766 _dbus_verbose ("Added pending reply %p, replier %p receiver %p serial %u\n", 1767 pending, 1768 pending->will_send_reply, 1769 pending->will_get_reply, 1770 pending->reply_serial); 1771 1772 return TRUE; 1773 } 1774 1775 typedef struct 1776 { 1777 DBusList *link; 1778 BusConnections *connections; 1779 } CheckPendingReplyData; 1780 1781 static void 1782 cancel_check_pending_reply (void *data) 1783 { 1784 CheckPendingReplyData *d = data; 1785 1786 _dbus_verbose ("d = %p\n",d); 1787 1788 bus_expire_list_add_link (d->connections->pending_replies, 1789 d->link); 1790 d->link = NULL; 1791 } 1792 1793 static void 1794 check_pending_reply_data_free (void *data) 1795 { 1796 CheckPendingReplyData *d = data; 1797 1798 _dbus_verbose ("d = %p\n",d); 1799 1800 if (d->link != NULL) 1801 { 1802 BusPendingReply *pending = d->link->data; 1803 1804 _dbus_assert (!bus_expire_list_contains_item (d->connections->pending_replies, 1805 &pending->expire_item)); 1806 1807 bus_pending_reply_free (pending); 1808 _dbus_list_free_link (d->link); 1809 } 1810 1811 dbus_free (d); 1812 } 1813 1814 /* 1815 * Check whether a reply is allowed, remove BusPendingReply 1816 * if so, return TRUE if so. 1817 */ 1818 dbus_bool_t 1819 bus_connections_check_reply (BusConnections *connections, 1820 BusTransaction *transaction, 1821 DBusConnection *sending_reply, 1822 DBusConnection *receiving_reply, 1823 DBusMessage *reply, 1824 DBusError *error) 1825 { 1826 CheckPendingReplyData *cprd; 1827 DBusList *link; 1828 dbus_uint32_t reply_serial; 1829 1830 _dbus_assert (sending_reply != NULL); 1831 _dbus_assert (receiving_reply != NULL); 1832 1833 reply_serial = dbus_message_get_reply_serial (reply); 1834 1835 link = bus_expire_list_get_first_link (connections->pending_replies); 1836 while (link != NULL) 1837 { 1838 BusPendingReply *pending = link->data; 1839 1840 if (pending->reply_serial == reply_serial && 1841 pending->will_get_reply == receiving_reply && 1842 pending->will_send_reply == sending_reply) 1843 { 1844 _dbus_verbose ("Found pending reply with serial %u\n", reply_serial); 1845 break; 1846 } 1847 1848 link = bus_expire_list_get_next_link (connections->pending_replies, 1849 link); 1850 } 1851 1852 if (link == NULL) 1853 { 1854 _dbus_verbose ("No pending reply expected\n"); 1855 1856 return FALSE; 1857 } 1858 1859 cprd = dbus_new0 (CheckPendingReplyData, 1); 1860 if (cprd == NULL) 1861 { 1862 BUS_SET_OOM (error); 1863 return FALSE; 1864 } 1865 1866 if (!bus_transaction_add_cancel_hook (transaction, 1867 cancel_check_pending_reply, 1868 cprd, 1869 check_pending_reply_data_free)) 1870 { 1871 BUS_SET_OOM (error); 1872 dbus_free (cprd); 1873 return FALSE; 1874 } 1875 1876 cprd->link = link; 1877 cprd->connections = connections; 1878 1879 bus_expire_list_unlink (connections->pending_replies, 1880 link); 1881 1882 _dbus_assert (!bus_expire_list_contains_item (connections->pending_replies, link->data)); 1883 1884 return TRUE; 1885 } 1886 1887 /* 1888 * Transactions 1889 * 1890 * Note that this is fairly fragile; in particular, don't try to use 1891 * one transaction across any main loop iterations. 1892 */ 1893 1894 typedef struct 1895 { 1896 BusTransaction *transaction; 1897 DBusMessage *message; 1898 DBusPreallocatedSend *preallocated; 1899 } MessageToSend; 1900 1901 typedef struct 1902 { 1903 BusTransactionCancelFunction cancel_function; 1904 DBusFreeFunction free_data_function; 1905 void *data; 1906 } CancelHook; 1907 1908 struct BusTransaction 1909 { 1910 DBusList *connections; 1911 BusContext *context; 1912 DBusList *cancel_hooks; 1913 }; 1914 1915 static void 1916 message_to_send_free (DBusConnection *connection, 1917 MessageToSend *to_send) 1918 { 1919 if (to_send->message) 1920 dbus_message_unref (to_send->message); 1921 1922 if (to_send->preallocated) 1923 dbus_connection_free_preallocated_send (connection, to_send->preallocated); 1924 1925 dbus_free (to_send); 1926 } 1927 1928 static void 1929 cancel_hook_cancel (void *element, 1930 void *data) 1931 { 1932 CancelHook *ch = element; 1933 1934 _dbus_verbose ("Running transaction cancel hook\n"); 1935 1936 if (ch->cancel_function) 1937 (* ch->cancel_function) (ch->data); 1938 } 1939 1940 static void 1941 cancel_hook_free (void *element, 1942 void *data) 1943 { 1944 CancelHook *ch = element; 1945 1946 if (ch->free_data_function) 1947 (* ch->free_data_function) (ch->data); 1948 1949 dbus_free (ch); 1950 } 1951 1952 static void 1953 free_cancel_hooks (BusTransaction *transaction) 1954 { 1955 _dbus_list_foreach (&transaction->cancel_hooks, 1956 cancel_hook_free, NULL); 1957 1958 _dbus_list_clear (&transaction->cancel_hooks); 1959 } 1960 1961 BusTransaction* 1962 bus_transaction_new (BusContext *context) 1963 { 1964 BusTransaction *transaction; 1965 1966 transaction = dbus_new0 (BusTransaction, 1); 1967 if (transaction == NULL) 1968 return NULL; 1969 1970 transaction->context = context; 1971 1972 return transaction; 1973 } 1974 1975 BusContext* 1976 bus_transaction_get_context (BusTransaction *transaction) 1977 { 1978 return transaction->context; 1979 } 1980 1981 BusConnections* 1982 bus_transaction_get_connections (BusTransaction *transaction) 1983 { 1984 return bus_context_get_connections (transaction->context); 1985 } 1986 1987 dbus_bool_t 1988 bus_transaction_send_from_driver (BusTransaction *transaction, 1989 DBusConnection *connection, 1990 DBusMessage *message) 1991 { 1992 /* We have to set the sender to the driver, and have 1993 * to check security policy since it was not done in 1994 * dispatch.c 1995 */ 1996 _dbus_verbose ("Sending %s %s %s from driver\n", 1997 dbus_message_get_interface (message) ? 1998 dbus_message_get_interface (message) : "(no interface)", 1999 dbus_message_get_member (message) ? 2000 dbus_message_get_member (message) : "(no member)", 2001 dbus_message_get_error_name (message) ? 2002 dbus_message_get_error_name (message) : "(no error name)"); 2003 2004 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) 2005 return FALSE; 2006 2007 if (bus_connection_is_active (connection)) 2008 { 2009 if (!dbus_message_set_destination (message, 2010 bus_connection_get_name (connection))) 2011 return FALSE; 2012 } 2013 2014 /* bus driver never wants a reply */ 2015 dbus_message_set_no_reply (message, TRUE); 2016 2017 /* If security policy doesn't allow the message, we silently 2018 * eat it; the driver doesn't care about getting a reply. 2019 */ 2020 if (!bus_context_check_security_policy (bus_transaction_get_context (transaction), 2021 transaction, 2022 NULL, connection, connection, message, NULL)) 2023 return TRUE; 2024 2025 return bus_transaction_send (transaction, connection, message); 2026 } 2027 2028 dbus_bool_t 2029 bus_transaction_send (BusTransaction *transaction, 2030 DBusConnection *connection, 2031 DBusMessage *message) 2032 { 2033 MessageToSend *to_send; 2034 BusConnectionData *d; 2035 DBusList *link; 2036 2037 _dbus_verbose (" trying to add %s interface=%s member=%s error=%s to transaction%s\n", 2038 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" : 2039 dbus_message_get_reply_serial (message) != 0 ? "reply" : 2040 "message", 2041 dbus_message_get_interface (message) ? 2042 dbus_message_get_interface (message) : "(unset)", 2043 dbus_message_get_member (message) ? 2044 dbus_message_get_member (message) : "(unset)", 2045 dbus_message_get_error_name (message) ? 2046 dbus_message_get_error_name (message) : "(unset)", 2047 dbus_connection_get_is_connected (connection) ? 2048 "" : " (disconnected)"); 2049 2050 _dbus_assert (dbus_message_get_sender (message) != NULL); 2051 2052 if (!dbus_connection_get_is_connected (connection)) 2053 return TRUE; /* silently ignore disconnected connections */ 2054 2055 d = BUS_CONNECTION_DATA (connection); 2056 _dbus_assert (d != NULL); 2057 2058 to_send = dbus_new (MessageToSend, 1); 2059 if (to_send == NULL) 2060 { 2061 return FALSE; 2062 } 2063 2064 to_send->preallocated = dbus_connection_preallocate_send (connection); 2065 if (to_send->preallocated == NULL) 2066 { 2067 dbus_free (to_send); 2068 return FALSE; 2069 } 2070 2071 dbus_message_ref (message); 2072 to_send->message = message; 2073 to_send->transaction = transaction; 2074 2075 _dbus_verbose ("about to prepend message\n"); 2076 2077 if (!_dbus_list_prepend (&d->transaction_messages, to_send)) 2078 { 2079 message_to_send_free (connection, to_send); 2080 return FALSE; 2081 } 2082 2083 _dbus_verbose ("prepended message\n"); 2084 2085 /* See if we already had this connection in the list 2086 * for this transaction. If we have a pending message, 2087 * then we should already be in transaction->connections 2088 */ 2089 link = _dbus_list_get_first_link (&d->transaction_messages); 2090 _dbus_assert (link->data == to_send); 2091 link = _dbus_list_get_next_link (&d->transaction_messages, link); 2092 while (link != NULL) 2093 { 2094 MessageToSend *m = link->data; 2095 DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link); 2096 2097 if (m->transaction == transaction) 2098 break; 2099 2100 link = next; 2101 } 2102 2103 if (link == NULL) 2104 { 2105 if (!_dbus_list_prepend (&transaction->connections, connection)) 2106 { 2107 _dbus_list_remove (&d->transaction_messages, to_send); 2108 message_to_send_free (connection, to_send); 2109 return FALSE; 2110 } 2111 } 2112 2113 return TRUE; 2114 } 2115 2116 static void 2117 connection_cancel_transaction (DBusConnection *connection, 2118 BusTransaction *transaction) 2119 { 2120 DBusList *link; 2121 BusConnectionData *d; 2122 2123 d = BUS_CONNECTION_DATA (connection); 2124 _dbus_assert (d != NULL); 2125 2126 link = _dbus_list_get_first_link (&d->transaction_messages); 2127 while (link != NULL) 2128 { 2129 MessageToSend *m = link->data; 2130 DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link); 2131 2132 if (m->transaction == transaction) 2133 { 2134 _dbus_list_remove_link (&d->transaction_messages, 2135 link); 2136 2137 message_to_send_free (connection, m); 2138 } 2139 2140 link = next; 2141 } 2142 } 2143 2144 void 2145 bus_transaction_cancel_and_free (BusTransaction *transaction) 2146 { 2147 DBusConnection *connection; 2148 2149 _dbus_verbose ("TRANSACTION: cancelled\n"); 2150 2151 while ((connection = _dbus_list_pop_first (&transaction->connections))) 2152 connection_cancel_transaction (connection, transaction); 2153 2154 _dbus_assert (transaction->connections == NULL); 2155 2156 _dbus_list_foreach (&transaction->cancel_hooks, 2157 cancel_hook_cancel, NULL); 2158 2159 free_cancel_hooks (transaction); 2160 2161 dbus_free (transaction); 2162 } 2163 2164 static void 2165 connection_execute_transaction (DBusConnection *connection, 2166 BusTransaction *transaction) 2167 { 2168 DBusList *link; 2169 BusConnectionData *d; 2170 2171 d = BUS_CONNECTION_DATA (connection); 2172 _dbus_assert (d != NULL); 2173 2174 /* Send the queue in order (FIFO) */ 2175 link = _dbus_list_get_last_link (&d->transaction_messages); 2176 while (link != NULL) 2177 { 2178 MessageToSend *m = link->data; 2179 DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link); 2180 2181 if (m->transaction == transaction) 2182 { 2183 _dbus_list_remove_link (&d->transaction_messages, 2184 link); 2185 2186 _dbus_assert (dbus_message_get_sender (m->message) != NULL); 2187 2188 dbus_connection_send_preallocated (connection, 2189 m->preallocated, 2190 m->message, 2191 NULL); 2192 2193 m->preallocated = NULL; /* so we don't double-free it */ 2194 2195 message_to_send_free (connection, m); 2196 } 2197 2198 link = prev; 2199 } 2200 } 2201 2202 void 2203 bus_transaction_execute_and_free (BusTransaction *transaction) 2204 { 2205 /* For each connection in transaction->connections 2206 * send the messages 2207 */ 2208 DBusConnection *connection; 2209 2210 _dbus_verbose ("TRANSACTION: executing\n"); 2211 2212 while ((connection = _dbus_list_pop_first (&transaction->connections))) 2213 connection_execute_transaction (connection, transaction); 2214 2215 _dbus_assert (transaction->connections == NULL); 2216 2217 free_cancel_hooks (transaction); 2218 2219 dbus_free (transaction); 2220 } 2221 2222 static void 2223 bus_connection_remove_transactions (DBusConnection *connection) 2224 { 2225 MessageToSend *to_send; 2226 BusConnectionData *d; 2227 2228 d = BUS_CONNECTION_DATA (connection); 2229 _dbus_assert (d != NULL); 2230 2231 while ((to_send = _dbus_list_get_first (&d->transaction_messages))) 2232 { 2233 /* only has an effect for the first MessageToSend listing this transaction */ 2234 _dbus_list_remove (&to_send->transaction->connections, 2235 connection); 2236 2237 _dbus_list_remove (&d->transaction_messages, to_send); 2238 message_to_send_free (connection, to_send); 2239 } 2240 } 2241 2242 /** 2243 * Converts the DBusError to a message reply 2244 */ 2245 dbus_bool_t 2246 bus_transaction_send_error_reply (BusTransaction *transaction, 2247 DBusConnection *connection, 2248 const DBusError *error, 2249 DBusMessage *in_reply_to) 2250 { 2251 DBusMessage *reply; 2252 2253 _dbus_assert (error != NULL); 2254 _DBUS_ASSERT_ERROR_IS_SET (error); 2255 2256 _dbus_verbose ("Sending error reply %s \"%s\"\n", 2257 error->name, error->message); 2258 2259 reply = dbus_message_new_error (in_reply_to, 2260 error->name, 2261 error->message); 2262 if (reply == NULL) 2263 return FALSE; 2264 2265 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 2266 { 2267 dbus_message_unref (reply); 2268 return FALSE; 2269 } 2270 2271 dbus_message_unref (reply); 2272 2273 return TRUE; 2274 } 2275 2276 dbus_bool_t 2277 bus_transaction_add_cancel_hook (BusTransaction *transaction, 2278 BusTransactionCancelFunction cancel_function, 2279 void *data, 2280 DBusFreeFunction free_data_function) 2281 { 2282 CancelHook *ch; 2283 2284 ch = dbus_new (CancelHook, 1); 2285 if (ch == NULL) 2286 return FALSE; 2287 2288 _dbus_verbose (" adding cancel hook function = %p data = %p\n", 2289 cancel_function, data); 2290 2291 ch->cancel_function = cancel_function; 2292 ch->data = data; 2293 ch->free_data_function = free_data_function; 2294 2295 /* It's important that the hooks get run in reverse order that they 2296 * were added 2297 */ 2298 if (!_dbus_list_prepend (&transaction->cancel_hooks, ch)) 2299 { 2300 dbus_free (ch); 2301 return FALSE; 2302 } 2303 2304 return TRUE; 2305 } 2306