1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation) 3 * 4 * Copyright (C) 2002, 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 "dbus-transport-protected.h" 26 #include "dbus-transport-unix.h" 27 #include "dbus-transport-socket.h" 28 #include "dbus-connection-internal.h" 29 #include "dbus-watch.h" 30 #include "dbus-auth.h" 31 #include "dbus-address.h" 32 #include "dbus-credentials.h" 33 #include "dbus-mainloop.h" 34 #include "dbus-message.h" 35 #ifdef DBUS_BUILD_TESTS 36 #include "dbus-server-debug-pipe.h" 37 #endif 38 39 /** 40 * @defgroup DBusTransport DBusTransport object 41 * @ingroup DBusInternals 42 * @brief "Backend" for a DBusConnection. 43 * 44 * Types and functions related to DBusTransport. A transport is an 45 * abstraction that can send and receive data via various kinds of 46 * network connections or other IPC mechanisms. 47 * 48 * @{ 49 */ 50 51 /** 52 * @typedef DBusTransport 53 * 54 * Opaque object representing a way message stream. 55 * DBusTransport abstracts various kinds of actual 56 * transport mechanism, such as different network protocols, 57 * or encryption schemes. 58 */ 59 60 static void 61 live_messages_notify (DBusCounter *counter, 62 void *user_data) 63 { 64 DBusTransport *transport = user_data; 65 66 _dbus_transport_ref (transport); 67 68 #if 0 69 _dbus_verbose ("Size counter value is now %d\n", 70 (int) _dbus_counter_get_size_value (counter)); 71 _dbus_verbose ("Unix FD counter value is now %d\n", 72 (int) _dbus_counter_get_unix_fd_value (counter)); 73 #endif 74 75 /* disable or re-enable the read watch for the transport if 76 * required. 77 */ 78 if (transport->vtable->live_messages_changed) 79 { 80 _dbus_connection_lock (transport->connection); 81 (* transport->vtable->live_messages_changed) (transport); 82 _dbus_connection_unlock (transport->connection); 83 } 84 85 _dbus_transport_unref (transport); 86 } 87 88 /** 89 * Initializes the base class members of DBusTransport. Chained up to 90 * by subclasses in their constructor. The server GUID is the 91 * globally unique ID for the server creating this connection 92 * and will be #NULL for the client side of a connection. The GUID 93 * is in hex format. 94 * 95 * @param transport the transport being created. 96 * @param vtable the subclass vtable. 97 * @param server_guid non-#NULL if this transport is on the server side of a connection 98 * @param address the address of the transport 99 * @returns #TRUE on success. 100 */ 101 dbus_bool_t 102 _dbus_transport_init_base (DBusTransport *transport, 103 const DBusTransportVTable *vtable, 104 const DBusString *server_guid, 105 const DBusString *address) 106 { 107 DBusMessageLoader *loader; 108 DBusAuth *auth; 109 DBusCounter *counter; 110 char *address_copy; 111 DBusCredentials *creds; 112 113 loader = _dbus_message_loader_new (); 114 if (loader == NULL) 115 return FALSE; 116 117 if (server_guid) 118 auth = _dbus_auth_server_new (server_guid); 119 else 120 auth = _dbus_auth_client_new (); 121 if (auth == NULL) 122 { 123 _dbus_message_loader_unref (loader); 124 return FALSE; 125 } 126 127 counter = _dbus_counter_new (); 128 if (counter == NULL) 129 { 130 _dbus_auth_unref (auth); 131 _dbus_message_loader_unref (loader); 132 return FALSE; 133 } 134 135 creds = _dbus_credentials_new (); 136 if (creds == NULL) 137 { 138 _dbus_counter_unref (counter); 139 _dbus_auth_unref (auth); 140 _dbus_message_loader_unref (loader); 141 return FALSE; 142 } 143 144 if (server_guid) 145 { 146 _dbus_assert (address == NULL); 147 address_copy = NULL; 148 } 149 else 150 { 151 _dbus_assert (address != NULL); 152 153 if (!_dbus_string_copy_data (address, &address_copy)) 154 { 155 _dbus_credentials_unref (creds); 156 _dbus_counter_unref (counter); 157 _dbus_auth_unref (auth); 158 _dbus_message_loader_unref (loader); 159 return FALSE; 160 } 161 } 162 163 transport->refcount = 1; 164 transport->vtable = vtable; 165 transport->loader = loader; 166 transport->auth = auth; 167 transport->live_messages = counter; 168 transport->authenticated = FALSE; 169 transport->disconnected = FALSE; 170 transport->is_server = (server_guid != NULL); 171 transport->send_credentials_pending = !transport->is_server; 172 transport->receive_credentials_pending = transport->is_server; 173 transport->address = address_copy; 174 175 transport->unix_user_function = NULL; 176 transport->unix_user_data = NULL; 177 transport->free_unix_user_data = NULL; 178 179 transport->windows_user_function = NULL; 180 transport->windows_user_data = NULL; 181 transport->free_windows_user_data = NULL; 182 183 transport->expected_guid = NULL; 184 185 /* Try to default to something that won't totally hose the system, 186 * but doesn't impose too much of a limitation. 187 */ 188 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 189 190 /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live 191 should be more than enough */ 192 transport->max_live_messages_unix_fds = 4096; 193 194 /* credentials read from socket if any */ 195 transport->credentials = creds; 196 197 _dbus_counter_set_notify (transport->live_messages, 198 transport->max_live_messages_size, 199 transport->max_live_messages_unix_fds, 200 live_messages_notify, 201 transport); 202 203 if (transport->address) 204 _dbus_verbose ("Initialized transport on address %s\n", transport->address); 205 206 return TRUE; 207 } 208 209 /** 210 * Finalizes base class members of DBusTransport. 211 * Chained up to from subclass finalizers. 212 * 213 * @param transport the transport. 214 */ 215 void 216 _dbus_transport_finalize_base (DBusTransport *transport) 217 { 218 if (!transport->disconnected) 219 _dbus_transport_disconnect (transport); 220 221 if (transport->free_unix_user_data != NULL) 222 (* transport->free_unix_user_data) (transport->unix_user_data); 223 224 if (transport->free_windows_user_data != NULL) 225 (* transport->free_windows_user_data) (transport->windows_user_data); 226 227 _dbus_message_loader_unref (transport->loader); 228 _dbus_auth_unref (transport->auth); 229 _dbus_counter_set_notify (transport->live_messages, 230 0, 0, NULL, NULL); 231 _dbus_counter_unref (transport->live_messages); 232 dbus_free (transport->address); 233 dbus_free (transport->expected_guid); 234 if (transport->credentials) 235 _dbus_credentials_unref (transport->credentials); 236 } 237 238 239 /** 240 * Verifies if a given D-Bus address is a valid address 241 * by attempting to connect to it. If it is, returns the 242 * opened DBusTransport object. If it isn't, returns #NULL 243 * and sets @p error. 244 * 245 * @param error address where an error can be returned. 246 * @returns a new transport, or #NULL on failure. 247 */ 248 static DBusTransport* 249 check_address (const char *address, DBusError *error) 250 { 251 DBusAddressEntry **entries; 252 DBusTransport *transport = NULL; 253 int len, i; 254 255 _dbus_assert (address != NULL); 256 257 if (!dbus_parse_address (address, &entries, &len, error)) 258 return NULL; /* not a valid address */ 259 260 for (i = 0; i < len; i++) 261 { 262 transport = _dbus_transport_open (entries[i], error); 263 if (transport != NULL) 264 break; 265 } 266 267 dbus_address_entries_free (entries); 268 return transport; 269 } 270 271 /** 272 * Creates a new transport for the "autostart" method. 273 * This creates a client-side of a transport. 274 * 275 * @param error address where an error can be returned. 276 * @returns a new transport, or #NULL on failure. 277 */ 278 static DBusTransport* 279 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error) 280 { 281 DBusString address; 282 DBusTransport *result = NULL; 283 284 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 285 286 if (!_dbus_string_init (&address)) 287 { 288 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 289 return NULL; 290 } 291 292 if (!_dbus_get_autolaunch_address (scope, &address, error)) 293 { 294 _DBUS_ASSERT_ERROR_IS_SET (error); 295 goto out; 296 } 297 298 result = check_address (_dbus_string_get_const_data (&address), error); 299 if (result == NULL) 300 _DBUS_ASSERT_ERROR_IS_SET (error); 301 else 302 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 303 304 out: 305 _dbus_string_free (&address); 306 return result; 307 } 308 309 static DBusTransportOpenResult 310 _dbus_transport_open_autolaunch (DBusAddressEntry *entry, 311 DBusTransport **transport_p, 312 DBusError *error) 313 { 314 const char *method; 315 316 method = dbus_address_entry_get_method (entry); 317 _dbus_assert (method != NULL); 318 319 if (strcmp (method, "autolaunch") == 0) 320 { 321 const char *scope = dbus_address_entry_get_value (entry, "scope"); 322 323 *transport_p = _dbus_transport_new_for_autolaunch (scope, error); 324 325 if (*transport_p == NULL) 326 { 327 _DBUS_ASSERT_ERROR_IS_SET (error); 328 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 329 } 330 else 331 { 332 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 333 return DBUS_TRANSPORT_OPEN_OK; 334 } 335 } 336 else 337 { 338 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 339 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 340 } 341 } 342 343 static const struct { 344 DBusTransportOpenResult (* func) (DBusAddressEntry *entry, 345 DBusTransport **transport_p, 346 DBusError *error); 347 } open_funcs[] = { 348 { _dbus_transport_open_socket }, 349 { _dbus_transport_open_platform_specific }, 350 { _dbus_transport_open_autolaunch } 351 #ifdef DBUS_BUILD_TESTS 352 , { _dbus_transport_open_debug_pipe } 353 #endif 354 }; 355 356 /** 357 * Try to open a new transport for the given address entry. (This 358 * opens a client-side-of-the-connection transport.) 359 * 360 * @param entry the address entry 361 * @param error location to store reason for failure. 362 * @returns new transport of #NULL on failure. 363 */ 364 DBusTransport* 365 _dbus_transport_open (DBusAddressEntry *entry, 366 DBusError *error) 367 { 368 DBusTransport *transport; 369 const char *expected_guid_orig; 370 char *expected_guid; 371 int i; 372 DBusError tmp_error = DBUS_ERROR_INIT; 373 374 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 375 376 transport = NULL; 377 expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); 378 expected_guid = _dbus_strdup (expected_guid_orig); 379 380 if (expected_guid_orig != NULL && expected_guid == NULL) 381 { 382 _DBUS_SET_OOM (error); 383 return NULL; 384 } 385 386 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i) 387 { 388 DBusTransportOpenResult result; 389 390 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 391 result = (* open_funcs[i].func) (entry, &transport, &tmp_error); 392 393 switch (result) 394 { 395 case DBUS_TRANSPORT_OPEN_OK: 396 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 397 goto out; 398 break; 399 case DBUS_TRANSPORT_OPEN_NOT_HANDLED: 400 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 401 /* keep going through the loop of open funcs */ 402 break; 403 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS: 404 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 405 goto out; 406 break; 407 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT: 408 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 409 goto out; 410 break; 411 } 412 } 413 414 out: 415 416 if (transport == NULL) 417 { 418 if (!dbus_error_is_set (&tmp_error)) 419 _dbus_set_bad_address (&tmp_error, 420 NULL, NULL, 421 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")"); 422 423 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 424 dbus_move_error(&tmp_error, error); 425 dbus_free (expected_guid); 426 } 427 else 428 { 429 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 430 431 /* In the case of autostart the initial guid is NULL 432 * and the autostart transport recursively calls 433 * _dbus_open_transport wich returns a transport 434 * with a guid. That guid is the definitive one. 435 * 436 * FIXME: if more transports are added they may have 437 * an effect on the expected_guid semantics (i.e. 438 * expected_guid and transport->expected_guid may 439 * both have values). This is very unlikely though 440 * we should either throw asserts here for those 441 * corner cases or refactor the code so it is 442 * clearer on what is expected and what is not 443 */ 444 if(expected_guid) 445 transport->expected_guid = expected_guid; 446 } 447 448 return transport; 449 } 450 451 /** 452 * Increments the reference count for the transport. 453 * 454 * @param transport the transport. 455 * @returns the transport. 456 */ 457 DBusTransport * 458 _dbus_transport_ref (DBusTransport *transport) 459 { 460 _dbus_assert (transport->refcount > 0); 461 462 transport->refcount += 1; 463 464 return transport; 465 } 466 467 /** 468 * Decrements the reference count for the transport. 469 * Disconnects and finalizes the transport if 470 * the reference count reaches zero. 471 * 472 * @param transport the transport. 473 */ 474 void 475 _dbus_transport_unref (DBusTransport *transport) 476 { 477 _dbus_assert (transport != NULL); 478 _dbus_assert (transport->refcount > 0); 479 480 transport->refcount -= 1; 481 if (transport->refcount == 0) 482 { 483 _dbus_verbose ("finalizing\n"); 484 485 _dbus_assert (transport->vtable->finalize != NULL); 486 487 (* transport->vtable->finalize) (transport); 488 } 489 } 490 491 /** 492 * Closes our end of the connection to a remote application. Further 493 * attempts to use this transport will fail. Only the first call to 494 * _dbus_transport_disconnect() will have an effect. 495 * 496 * @param transport the transport. 497 * 498 */ 499 void 500 _dbus_transport_disconnect (DBusTransport *transport) 501 { 502 _dbus_verbose ("start\n"); 503 504 _dbus_assert (transport->vtable->disconnect != NULL); 505 506 if (transport->disconnected) 507 return; 508 509 (* transport->vtable->disconnect) (transport); 510 511 transport->disconnected = TRUE; 512 513 _dbus_verbose ("end\n"); 514 } 515 516 /** 517 * Returns #TRUE if the transport has not been disconnected. 518 * Disconnection can result from _dbus_transport_disconnect() 519 * or because the server drops its end of the connection. 520 * 521 * @param transport the transport. 522 * @returns whether we're connected 523 */ 524 dbus_bool_t 525 _dbus_transport_get_is_connected (DBusTransport *transport) 526 { 527 return !transport->disconnected; 528 } 529 530 static dbus_bool_t 531 auth_via_unix_user_function (DBusTransport *transport) 532 { 533 DBusCredentials *auth_identity; 534 dbus_bool_t allow; 535 DBusConnection *connection; 536 DBusAllowUnixUserFunction unix_user_function; 537 void *unix_user_data; 538 dbus_uid_t uid; 539 540 /* Dropping the lock here probably isn't that safe. */ 541 542 auth_identity = _dbus_auth_get_identity (transport->auth); 543 _dbus_assert (auth_identity != NULL); 544 545 connection = transport->connection; 546 unix_user_function = transport->unix_user_function; 547 unix_user_data = transport->unix_user_data; 548 uid = _dbus_credentials_get_unix_uid (auth_identity); 549 550 _dbus_verbose ("unlock\n"); 551 _dbus_connection_unlock (connection); 552 553 allow = (* unix_user_function) (connection, 554 uid, 555 unix_user_data); 556 557 _dbus_verbose ("lock post unix user function\n"); 558 _dbus_connection_lock (connection); 559 560 if (allow) 561 { 562 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); 563 } 564 else 565 { 566 _dbus_verbose ("Client UID "DBUS_UID_FORMAT 567 " was rejected, disconnecting\n", 568 _dbus_credentials_get_unix_uid (auth_identity)); 569 _dbus_transport_disconnect (transport); 570 } 571 572 return allow; 573 } 574 575 static dbus_bool_t 576 auth_via_windows_user_function (DBusTransport *transport) 577 { 578 DBusCredentials *auth_identity; 579 dbus_bool_t allow; 580 DBusConnection *connection; 581 DBusAllowWindowsUserFunction windows_user_function; 582 void *windows_user_data; 583 char *windows_sid; 584 585 /* Dropping the lock here probably isn't that safe. */ 586 587 auth_identity = _dbus_auth_get_identity (transport->auth); 588 _dbus_assert (auth_identity != NULL); 589 590 connection = transport->connection; 591 windows_user_function = transport->windows_user_function; 592 windows_user_data = transport->unix_user_data; 593 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 594 595 if (windows_sid == NULL) 596 { 597 /* OOM */ 598 return FALSE; 599 } 600 601 _dbus_verbose ("unlock\n"); 602 _dbus_connection_unlock (connection); 603 604 allow = (* windows_user_function) (connection, 605 windows_sid, 606 windows_user_data); 607 608 _dbus_verbose ("lock post windows user function\n"); 609 _dbus_connection_lock (connection); 610 611 if (allow) 612 { 613 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); 614 } 615 else 616 { 617 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", 618 _dbus_credentials_get_windows_sid (auth_identity)); 619 _dbus_transport_disconnect (transport); 620 } 621 622 return allow; 623 } 624 625 static dbus_bool_t 626 auth_via_default_rules (DBusTransport *transport) 627 { 628 DBusCredentials *auth_identity; 629 DBusCredentials *our_identity; 630 dbus_bool_t allow; 631 632 auth_identity = _dbus_auth_get_identity (transport->auth); 633 _dbus_assert (auth_identity != NULL); 634 635 /* By default, connection is allowed if the client is 1) root or 2) 636 * has the same UID as us or 3) anonymous is allowed. 637 */ 638 639 our_identity = _dbus_credentials_new_from_current_process (); 640 if (our_identity == NULL) 641 { 642 /* OOM */ 643 return FALSE; 644 } 645 646 if (transport->allow_anonymous || 647 _dbus_credentials_get_unix_uid (auth_identity) == 0 || 648 _dbus_credentials_same_user (our_identity, 649 auth_identity)) 650 { 651 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 652 _dbus_verbose ("Client authorized as SID '%s'" 653 "matching our SID '%s'\n", 654 _dbus_credentials_get_windows_sid(auth_identity), 655 _dbus_credentials_get_windows_sid(our_identity)); 656 else 657 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 658 " matching our UID "DBUS_UID_FORMAT"\n", 659 _dbus_credentials_get_unix_uid(auth_identity), 660 _dbus_credentials_get_unix_uid(our_identity)); 661 /* We have authenticated! */ 662 allow = TRUE; 663 } 664 else 665 { 666 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 667 _dbus_verbose ("Client authorized as SID '%s'" 668 " but our SID is '%s', disconnecting\n", 669 (_dbus_credentials_get_windows_sid(auth_identity) ? 670 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"), 671 (_dbus_credentials_get_windows_sid(our_identity) ? 672 _dbus_credentials_get_windows_sid(our_identity) : "<null>")); 673 else 674 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 675 " but our UID is "DBUS_UID_FORMAT", disconnecting\n", 676 _dbus_credentials_get_unix_uid(auth_identity), 677 _dbus_credentials_get_unix_uid(our_identity)); 678 _dbus_transport_disconnect (transport); 679 allow = FALSE; 680 } 681 682 _dbus_credentials_unref (our_identity); 683 684 return allow; 685 } 686 687 688 /** 689 * Returns #TRUE if we have been authenticated. Will return #TRUE 690 * even if the transport is disconnected. 691 * 692 * @todo we drop connection->mutex when calling the unix_user_function, 693 * and windows_user_function, which may not be safe really. 694 * 695 * @param transport the transport 696 * @returns whether we're authenticated 697 */ 698 dbus_bool_t 699 _dbus_transport_get_is_authenticated (DBusTransport *transport) 700 { 701 if (transport->authenticated) 702 return TRUE; 703 else 704 { 705 dbus_bool_t maybe_authenticated; 706 707 if (transport->disconnected) 708 return FALSE; 709 710 /* paranoia ref since we call user callbacks sometimes */ 711 _dbus_connection_ref_unlocked (transport->connection); 712 713 maybe_authenticated = 714 (!(transport->send_credentials_pending || 715 transport->receive_credentials_pending)); 716 717 if (maybe_authenticated) 718 { 719 switch (_dbus_auth_do_work (transport->auth)) 720 { 721 case DBUS_AUTH_STATE_AUTHENTICATED: 722 /* leave as maybe_authenticated */ 723 break; 724 default: 725 maybe_authenticated = FALSE; 726 } 727 } 728 729 /* If we're the client, verify the GUID 730 */ 731 if (maybe_authenticated && !transport->is_server) 732 { 733 const char *server_guid; 734 735 server_guid = _dbus_auth_get_guid_from_server (transport->auth); 736 _dbus_assert (server_guid != NULL); 737 738 if (transport->expected_guid && 739 strcmp (transport->expected_guid, server_guid) != 0) 740 { 741 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", 742 transport->expected_guid, server_guid); 743 _dbus_transport_disconnect (transport); 744 _dbus_connection_unref_unlocked (transport->connection); 745 return FALSE; 746 } 747 } 748 749 /* If we're the server, see if we want to allow this identity to proceed. 750 */ 751 if (maybe_authenticated && transport->is_server) 752 { 753 dbus_bool_t allow; 754 DBusCredentials *auth_identity; 755 756 auth_identity = _dbus_auth_get_identity (transport->auth); 757 _dbus_assert (auth_identity != NULL); 758 759 /* If we have an auth'd user and a user function, delegate 760 * deciding whether auth credentials are good enough to the 761 * app; otherwise, use our default decision process. 762 */ 763 if (transport->unix_user_function != NULL && 764 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) 765 { 766 allow = auth_via_unix_user_function (transport); 767 } 768 else if (transport->windows_user_function != NULL && 769 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) 770 { 771 allow = auth_via_windows_user_function (transport); 772 } 773 else 774 { 775 allow = auth_via_default_rules (transport); 776 } 777 778 if (!allow) 779 maybe_authenticated = FALSE; 780 } 781 782 transport->authenticated = maybe_authenticated; 783 784 _dbus_connection_unref_unlocked (transport->connection); 785 return maybe_authenticated; 786 } 787 } 788 789 /** 790 * See dbus_connection_get_is_anonymous(). 791 * 792 * @param transport the transport 793 * @returns #TRUE if not authenticated or authenticated as anonymous 794 */ 795 dbus_bool_t 796 _dbus_transport_get_is_anonymous (DBusTransport *transport) 797 { 798 DBusCredentials *auth_identity; 799 800 if (!transport->authenticated) 801 return TRUE; 802 803 auth_identity = _dbus_auth_get_identity (transport->auth); 804 805 if (_dbus_credentials_are_anonymous (auth_identity)) 806 return TRUE; 807 else 808 return FALSE; 809 } 810 811 /** 812 * Returns TRUE if the transport supports sending unix fds. 813 * 814 * @param transport the transport 815 * @returns #TRUE if TRUE it is possible to send unix fds across the transport. 816 */ 817 dbus_bool_t 818 _dbus_transport_can_pass_unix_fd(DBusTransport *transport) 819 { 820 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport); 821 } 822 823 /** 824 * Gets the address of a transport. It will be 825 * #NULL for a server-side transport. 826 * 827 * @param transport the transport 828 * @returns transport's address 829 */ 830 const char* 831 _dbus_transport_get_address (DBusTransport *transport) 832 { 833 return transport->address; 834 } 835 836 /** 837 * Gets the id of the server we are connected to (see 838 * dbus_server_get_id()). Only works on client side. 839 * 840 * @param transport the transport 841 * @returns transport's server's id or #NULL if we are the server side 842 */ 843 const char* 844 _dbus_transport_get_server_id (DBusTransport *transport) 845 { 846 if (transport->is_server) 847 return NULL; 848 else if (transport->authenticated) 849 return _dbus_auth_get_guid_from_server (transport->auth); 850 else 851 return transport->expected_guid; 852 } 853 854 /** 855 * Handles a watch by reading data, writing data, or disconnecting 856 * the transport, as appropriate for the given condition. 857 * 858 * @param transport the transport. 859 * @param watch the watch. 860 * @param condition the current state of the watched file descriptor. 861 * @returns #FALSE if not enough memory to fully handle the watch 862 */ 863 dbus_bool_t 864 _dbus_transport_handle_watch (DBusTransport *transport, 865 DBusWatch *watch, 866 unsigned int condition) 867 { 868 dbus_bool_t retval; 869 870 _dbus_assert (transport->vtable->handle_watch != NULL); 871 872 if (transport->disconnected) 873 return TRUE; 874 875 if (dbus_watch_get_socket (watch) < 0) 876 { 877 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n"); 878 return TRUE; 879 } 880 881 _dbus_watch_sanitize_condition (watch, &condition); 882 883 _dbus_transport_ref (transport); 884 _dbus_watch_ref (watch); 885 retval = (* transport->vtable->handle_watch) (transport, watch, condition); 886 _dbus_watch_unref (watch); 887 _dbus_transport_unref (transport); 888 889 return retval; 890 } 891 892 /** 893 * Sets the connection using this transport. Allows the transport 894 * to add watches to the connection, queue incoming messages, 895 * and pull outgoing messages. 896 * 897 * @param transport the transport. 898 * @param connection the connection. 899 * @returns #FALSE if not enough memory 900 */ 901 dbus_bool_t 902 _dbus_transport_set_connection (DBusTransport *transport, 903 DBusConnection *connection) 904 { 905 _dbus_assert (transport->vtable->connection_set != NULL); 906 _dbus_assert (transport->connection == NULL); 907 908 transport->connection = connection; 909 910 _dbus_transport_ref (transport); 911 if (!(* transport->vtable->connection_set) (transport)) 912 transport->connection = NULL; 913 _dbus_transport_unref (transport); 914 915 return transport->connection != NULL; 916 } 917 918 /** 919 * Get the socket file descriptor, if any. 920 * 921 * @param transport the transport 922 * @param fd_p pointer to fill in with the descriptor 923 * @returns #TRUE if a descriptor was available 924 */ 925 dbus_bool_t 926 _dbus_transport_get_socket_fd (DBusTransport *transport, 927 int *fd_p) 928 { 929 dbus_bool_t retval; 930 931 if (transport->vtable->get_socket_fd == NULL) 932 return FALSE; 933 934 if (transport->disconnected) 935 return FALSE; 936 937 _dbus_transport_ref (transport); 938 939 retval = (* transport->vtable->get_socket_fd) (transport, 940 fd_p); 941 942 _dbus_transport_unref (transport); 943 944 return retval; 945 } 946 947 /** 948 * Performs a single poll()/select() on the transport's file 949 * descriptors and then reads/writes data as appropriate, 950 * queueing incoming messages and sending outgoing messages. 951 * This is the backend for _dbus_connection_do_iteration(). 952 * See _dbus_connection_do_iteration() for full details. 953 * 954 * @param transport the transport. 955 * @param flags indicates whether to read or write, and whether to block. 956 * @param timeout_milliseconds if blocking, timeout or -1 for no timeout. 957 */ 958 void 959 _dbus_transport_do_iteration (DBusTransport *transport, 960 unsigned int flags, 961 int timeout_milliseconds) 962 { 963 _dbus_assert (transport->vtable->do_iteration != NULL); 964 965 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n", 966 flags, timeout_milliseconds, !transport->disconnected); 967 968 if ((flags & (DBUS_ITERATION_DO_WRITING | 969 DBUS_ITERATION_DO_READING)) == 0) 970 return; /* Nothing to do */ 971 972 if (transport->disconnected) 973 return; 974 975 _dbus_transport_ref (transport); 976 (* transport->vtable->do_iteration) (transport, flags, 977 timeout_milliseconds); 978 _dbus_transport_unref (transport); 979 980 _dbus_verbose ("end\n"); 981 } 982 983 static dbus_bool_t 984 recover_unused_bytes (DBusTransport *transport) 985 { 986 if (_dbus_auth_needs_decoding (transport->auth)) 987 { 988 DBusString plaintext; 989 const DBusString *encoded; 990 DBusString *buffer; 991 int orig_len; 992 993 if (!_dbus_string_init (&plaintext)) 994 goto nomem; 995 996 _dbus_auth_get_unused_bytes (transport->auth, 997 &encoded); 998 999 if (!_dbus_auth_decode_data (transport->auth, 1000 encoded, &plaintext)) 1001 { 1002 _dbus_string_free (&plaintext); 1003 goto nomem; 1004 } 1005 1006 _dbus_message_loader_get_buffer (transport->loader, 1007 &buffer); 1008 1009 orig_len = _dbus_string_get_length (buffer); 1010 1011 if (!_dbus_string_move (&plaintext, 0, buffer, 1012 orig_len)) 1013 { 1014 _dbus_string_free (&plaintext); 1015 goto nomem; 1016 } 1017 1018 _dbus_verbose (" %d unused bytes sent to message loader\n", 1019 _dbus_string_get_length (buffer) - 1020 orig_len); 1021 1022 _dbus_message_loader_return_buffer (transport->loader, 1023 buffer, 1024 _dbus_string_get_length (buffer) - 1025 orig_len); 1026 1027 _dbus_auth_delete_unused_bytes (transport->auth); 1028 1029 _dbus_string_free (&plaintext); 1030 } 1031 else 1032 { 1033 const DBusString *bytes; 1034 DBusString *buffer; 1035 int orig_len; 1036 dbus_bool_t succeeded; 1037 1038 _dbus_message_loader_get_buffer (transport->loader, 1039 &buffer); 1040 1041 orig_len = _dbus_string_get_length (buffer); 1042 1043 _dbus_auth_get_unused_bytes (transport->auth, 1044 &bytes); 1045 1046 succeeded = TRUE; 1047 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer))) 1048 succeeded = FALSE; 1049 1050 _dbus_verbose (" %d unused bytes sent to message loader\n", 1051 _dbus_string_get_length (buffer) - 1052 orig_len); 1053 1054 _dbus_message_loader_return_buffer (transport->loader, 1055 buffer, 1056 _dbus_string_get_length (buffer) - 1057 orig_len); 1058 1059 if (succeeded) 1060 _dbus_auth_delete_unused_bytes (transport->auth); 1061 else 1062 goto nomem; 1063 } 1064 1065 return TRUE; 1066 1067 nomem: 1068 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); 1069 return FALSE; 1070 } 1071 1072 /** 1073 * Reports our current dispatch status (whether there's buffered 1074 * data to be queued as messages, or not, or we need memory). 1075 * 1076 * @param transport the transport 1077 * @returns current status 1078 */ 1079 DBusDispatchStatus 1080 _dbus_transport_get_dispatch_status (DBusTransport *transport) 1081 { 1082 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size || 1083 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) 1084 return DBUS_DISPATCH_COMPLETE; /* complete for now */ 1085 1086 if (!_dbus_transport_get_is_authenticated (transport)) 1087 { 1088 if (_dbus_auth_do_work (transport->auth) == 1089 DBUS_AUTH_STATE_WAITING_FOR_MEMORY) 1090 return DBUS_DISPATCH_NEED_MEMORY; 1091 else if (!_dbus_transport_get_is_authenticated (transport)) 1092 return DBUS_DISPATCH_COMPLETE; 1093 } 1094 1095 if (!transport->unused_bytes_recovered && 1096 !recover_unused_bytes (transport)) 1097 return DBUS_DISPATCH_NEED_MEMORY; 1098 1099 transport->unused_bytes_recovered = TRUE; 1100 1101 if (!_dbus_message_loader_queue_messages (transport->loader)) 1102 return DBUS_DISPATCH_NEED_MEMORY; 1103 1104 if (_dbus_message_loader_peek_message (transport->loader) != NULL) 1105 return DBUS_DISPATCH_DATA_REMAINS; 1106 else 1107 return DBUS_DISPATCH_COMPLETE; 1108 } 1109 1110 /** 1111 * Processes data we've read while handling a watch, potentially 1112 * converting some of it to messages and queueing those messages on 1113 * the connection. 1114 * 1115 * @param transport the transport 1116 * @returns #TRUE if we had enough memory to queue all messages 1117 */ 1118 dbus_bool_t 1119 _dbus_transport_queue_messages (DBusTransport *transport) 1120 { 1121 DBusDispatchStatus status; 1122 1123 #if 0 1124 _dbus_verbose ("_dbus_transport_queue_messages()\n"); 1125 #endif 1126 1127 /* Queue any messages */ 1128 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS) 1129 { 1130 DBusMessage *message; 1131 DBusList *link; 1132 1133 link = _dbus_message_loader_pop_message_link (transport->loader); 1134 _dbus_assert (link != NULL); 1135 1136 message = link->data; 1137 1138 _dbus_verbose ("queueing received message %p\n", message); 1139 1140 if (!_dbus_message_add_counter (message, transport->live_messages)) 1141 { 1142 _dbus_message_loader_putback_message_link (transport->loader, 1143 link); 1144 status = DBUS_DISPATCH_NEED_MEMORY; 1145 break; 1146 } 1147 else 1148 { 1149 /* We didn't call the notify function when we added the counter, so 1150 * catch up now. Since we have the connection's lock, it's desirable 1151 * that we bypass the notify function and call this virtual method 1152 * directly. */ 1153 if (transport->vtable->live_messages_changed) 1154 (* transport->vtable->live_messages_changed) (transport); 1155 1156 /* pass ownership of link and message ref to connection */ 1157 _dbus_connection_queue_received_message_link (transport->connection, 1158 link); 1159 } 1160 } 1161 1162 if (_dbus_message_loader_get_is_corrupted (transport->loader)) 1163 { 1164 _dbus_verbose ("Corrupted message stream, disconnecting\n"); 1165 _dbus_transport_disconnect (transport); 1166 } 1167 1168 return status != DBUS_DISPATCH_NEED_MEMORY; 1169 } 1170 1171 /** 1172 * See dbus_connection_set_max_message_size(). 1173 * 1174 * @param transport the transport 1175 * @param size the max size of a single message 1176 */ 1177 void 1178 _dbus_transport_set_max_message_size (DBusTransport *transport, 1179 long size) 1180 { 1181 _dbus_message_loader_set_max_message_size (transport->loader, size); 1182 } 1183 1184 /** 1185 * See dbus_connection_set_max_message_unix_fds(). 1186 * 1187 * @param transport the transport 1188 * @param n the max number of unix fds of a single message 1189 */ 1190 void 1191 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport, 1192 long n) 1193 { 1194 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n); 1195 } 1196 1197 /** 1198 * See dbus_connection_get_max_message_size(). 1199 * 1200 * @param transport the transport 1201 * @returns max message size 1202 */ 1203 long 1204 _dbus_transport_get_max_message_size (DBusTransport *transport) 1205 { 1206 return _dbus_message_loader_get_max_message_size (transport->loader); 1207 } 1208 1209 /** 1210 * See dbus_connection_get_max_message_unix_fds(). 1211 * 1212 * @param transport the transport 1213 * @returns max message unix fds 1214 */ 1215 long 1216 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport) 1217 { 1218 return _dbus_message_loader_get_max_message_unix_fds (transport->loader); 1219 } 1220 1221 /** 1222 * See dbus_connection_set_max_received_size(). 1223 * 1224 * @param transport the transport 1225 * @param size the max size of all incoming messages 1226 */ 1227 void 1228 _dbus_transport_set_max_received_size (DBusTransport *transport, 1229 long size) 1230 { 1231 transport->max_live_messages_size = size; 1232 _dbus_counter_set_notify (transport->live_messages, 1233 transport->max_live_messages_size, 1234 transport->max_live_messages_unix_fds, 1235 live_messages_notify, 1236 transport); 1237 } 1238 1239 /** 1240 * See dbus_connection_set_max_received_unix_fds(). 1241 * 1242 * @param transport the transport 1243 * @param n the max unix fds of all incoming messages 1244 */ 1245 void 1246 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport, 1247 long n) 1248 { 1249 transport->max_live_messages_unix_fds = n; 1250 _dbus_counter_set_notify (transport->live_messages, 1251 transport->max_live_messages_size, 1252 transport->max_live_messages_unix_fds, 1253 live_messages_notify, 1254 transport); 1255 } 1256 1257 /** 1258 * See dbus_connection_get_max_received_size(). 1259 * 1260 * @param transport the transport 1261 * @returns max bytes for all live messages 1262 */ 1263 long 1264 _dbus_transport_get_max_received_size (DBusTransport *transport) 1265 { 1266 return transport->max_live_messages_size; 1267 } 1268 1269 /** 1270 * See dbus_connection_set_max_received_unix_fds(). 1271 * 1272 * @param transport the transport 1273 * @returns max unix fds for all live messages 1274 */ 1275 long 1276 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport) 1277 { 1278 return transport->max_live_messages_unix_fds; 1279 } 1280 1281 /** 1282 * See dbus_connection_get_unix_user(). 1283 * 1284 * @param transport the transport 1285 * @param uid return location for the user ID 1286 * @returns #TRUE if uid is filled in with a valid user ID 1287 */ 1288 dbus_bool_t 1289 _dbus_transport_get_unix_user (DBusTransport *transport, 1290 unsigned long *uid) 1291 { 1292 DBusCredentials *auth_identity; 1293 1294 *uid = _DBUS_INT32_MAX; /* better than some root or system user in 1295 * case of bugs in the caller. Caller should 1296 * never use this value on purpose, however. 1297 */ 1298 1299 if (!transport->authenticated) 1300 return FALSE; 1301 1302 auth_identity = _dbus_auth_get_identity (transport->auth); 1303 1304 if (_dbus_credentials_include (auth_identity, 1305 DBUS_CREDENTIAL_UNIX_USER_ID)) 1306 { 1307 *uid = _dbus_credentials_get_unix_uid (auth_identity); 1308 return TRUE; 1309 } 1310 else 1311 return FALSE; 1312 } 1313 1314 /** 1315 * See dbus_connection_get_unix_process_id(). 1316 * 1317 * @param transport the transport 1318 * @param pid return location for the process ID 1319 * @returns #TRUE if uid is filled in with a valid process ID 1320 */ 1321 dbus_bool_t 1322 _dbus_transport_get_unix_process_id (DBusTransport *transport, 1323 unsigned long *pid) 1324 { 1325 DBusCredentials *auth_identity; 1326 1327 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose, 1328 * but we set it to a safe number, INT_MAX, 1329 * just to root out possible bugs in bad callers. 1330 */ 1331 1332 if (!transport->authenticated) 1333 return FALSE; 1334 1335 auth_identity = _dbus_auth_get_identity (transport->auth); 1336 1337 if (_dbus_credentials_include (auth_identity, 1338 DBUS_CREDENTIAL_UNIX_PROCESS_ID)) 1339 { 1340 *pid = _dbus_credentials_get_unix_pid (auth_identity); 1341 return TRUE; 1342 } 1343 else 1344 return FALSE; 1345 } 1346 1347 /** 1348 * See dbus_connection_get_adt_audit_session_data(). 1349 * 1350 * @param transport the transport 1351 * @param data return location for the ADT audit data 1352 * @param data_size return length of audit data 1353 * @returns #TRUE if audit data is filled in with a valid ucred 1354 */ 1355 dbus_bool_t 1356 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, 1357 void **data, 1358 int *data_size) 1359 { 1360 DBusCredentials *auth_identity; 1361 1362 *data = NULL; 1363 *data_size = 0; 1364 1365 if (!transport->authenticated) 1366 return FALSE; 1367 1368 auth_identity = _dbus_auth_get_identity (transport->auth); 1369 1370 if (_dbus_credentials_include (auth_identity, 1371 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) 1372 { 1373 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); 1374 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); 1375 return TRUE; 1376 } 1377 else 1378 return FALSE; 1379 } 1380 1381 /** 1382 * See dbus_connection_set_unix_user_function(). 1383 * 1384 * @param transport the transport 1385 * @param function the predicate 1386 * @param data data to pass to the predicate 1387 * @param free_data_function function to free the data 1388 * @param old_data the old user data to be freed 1389 * @param old_free_data_function old free data function to free it with 1390 */ 1391 void 1392 _dbus_transport_set_unix_user_function (DBusTransport *transport, 1393 DBusAllowUnixUserFunction function, 1394 void *data, 1395 DBusFreeFunction free_data_function, 1396 void **old_data, 1397 DBusFreeFunction *old_free_data_function) 1398 { 1399 *old_data = transport->unix_user_data; 1400 *old_free_data_function = transport->free_unix_user_data; 1401 1402 transport->unix_user_function = function; 1403 transport->unix_user_data = data; 1404 transport->free_unix_user_data = free_data_function; 1405 } 1406 1407 /** 1408 * See dbus_connection_get_windows_user(). 1409 * 1410 * @param transport the transport 1411 * @param windows_sid_p return location for the user ID 1412 * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it 1413 */ 1414 dbus_bool_t 1415 _dbus_transport_get_windows_user (DBusTransport *transport, 1416 char **windows_sid_p) 1417 { 1418 DBusCredentials *auth_identity; 1419 1420 *windows_sid_p = NULL; 1421 1422 if (!transport->authenticated) 1423 return FALSE; 1424 1425 auth_identity = _dbus_auth_get_identity (transport->auth); 1426 1427 if (_dbus_credentials_include (auth_identity, 1428 DBUS_CREDENTIAL_WINDOWS_SID)) 1429 { 1430 /* If no memory, we are supposed to return TRUE and set NULL */ 1431 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 1432 1433 return TRUE; 1434 } 1435 else 1436 return FALSE; 1437 } 1438 1439 /** 1440 * See dbus_connection_set_windows_user_function(). 1441 * 1442 * @param transport the transport 1443 * @param function the predicate 1444 * @param data data to pass to the predicate 1445 * @param free_data_function function to free the data 1446 * @param old_data the old user data to be freed 1447 * @param old_free_data_function old free data function to free it with 1448 */ 1449 1450 void 1451 _dbus_transport_set_windows_user_function (DBusTransport *transport, 1452 DBusAllowWindowsUserFunction function, 1453 void *data, 1454 DBusFreeFunction free_data_function, 1455 void **old_data, 1456 DBusFreeFunction *old_free_data_function) 1457 { 1458 *old_data = transport->windows_user_data; 1459 *old_free_data_function = transport->free_windows_user_data; 1460 1461 transport->windows_user_function = function; 1462 transport->windows_user_data = data; 1463 transport->free_windows_user_data = free_data_function; 1464 } 1465 1466 /** 1467 * Sets the SASL authentication mechanisms supported by this transport. 1468 * 1469 * @param transport the transport 1470 * @param mechanisms the #NULL-terminated array of mechanisms 1471 * 1472 * @returns #FALSE if no memory 1473 */ 1474 dbus_bool_t 1475 _dbus_transport_set_auth_mechanisms (DBusTransport *transport, 1476 const char **mechanisms) 1477 { 1478 return _dbus_auth_set_mechanisms (transport->auth, mechanisms); 1479 } 1480 1481 /** 1482 * See dbus_connection_set_allow_anonymous() 1483 * 1484 * @param transport the transport 1485 * @param value #TRUE to allow anonymous connection 1486 */ 1487 void 1488 _dbus_transport_set_allow_anonymous (DBusTransport *transport, 1489 dbus_bool_t value) 1490 { 1491 transport->allow_anonymous = value != FALSE; 1492 } 1493 1494 #ifdef DBUS_ENABLE_STATS 1495 void 1496 _dbus_transport_get_stats (DBusTransport *transport, 1497 dbus_uint32_t *queue_bytes, 1498 dbus_uint32_t *queue_fds, 1499 dbus_uint32_t *peak_queue_bytes, 1500 dbus_uint32_t *peak_queue_fds) 1501 { 1502 if (queue_bytes != NULL) 1503 *queue_bytes = _dbus_counter_get_size_value (transport->live_messages); 1504 1505 if (queue_fds != NULL) 1506 *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages); 1507 1508 if (peak_queue_bytes != NULL) 1509 *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages); 1510 1511 if (peak_queue_fds != NULL) 1512 *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages); 1513 } 1514 #endif /* DBUS_ENABLE_STATS */ 1515 1516 /** @} */ 1517