D-Bus
1.10.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation) 00003 * 00004 * Copyright (C) 2002, 2003 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-transport-protected.h" 00026 #include "dbus-transport-unix.h" 00027 #include "dbus-transport-socket.h" 00028 #include "dbus-connection-internal.h" 00029 #include "dbus-watch.h" 00030 #include "dbus-auth.h" 00031 #include "dbus-address.h" 00032 #include "dbus-credentials.h" 00033 #include "dbus-mainloop.h" 00034 #include "dbus-message.h" 00035 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00036 #include "dbus-server-debug-pipe.h" 00037 #endif 00038 00060 static void 00061 live_messages_notify (DBusCounter *counter, 00062 void *user_data) 00063 { 00064 DBusTransport *transport = user_data; 00065 00066 _dbus_connection_lock (transport->connection); 00067 _dbus_transport_ref (transport); 00068 00069 #if 0 00070 _dbus_verbose ("Size counter value is now %d\n", 00071 (int) _dbus_counter_get_size_value (counter)); 00072 _dbus_verbose ("Unix FD counter value is now %d\n", 00073 (int) _dbus_counter_get_unix_fd_value (counter)); 00074 #endif 00075 00076 /* disable or re-enable the read watch for the transport if 00077 * required. 00078 */ 00079 if (transport->vtable->live_messages_changed) 00080 { 00081 (* transport->vtable->live_messages_changed) (transport); 00082 } 00083 00084 _dbus_transport_unref (transport); 00085 _dbus_connection_unlock (transport->connection); 00086 } 00087 00101 dbus_bool_t 00102 _dbus_transport_init_base (DBusTransport *transport, 00103 const DBusTransportVTable *vtable, 00104 const DBusString *server_guid, 00105 const DBusString *address) 00106 { 00107 DBusMessageLoader *loader; 00108 DBusAuth *auth; 00109 DBusCounter *counter; 00110 char *address_copy; 00111 DBusCredentials *creds; 00112 00113 loader = _dbus_message_loader_new (); 00114 if (loader == NULL) 00115 return FALSE; 00116 00117 if (server_guid) 00118 auth = _dbus_auth_server_new (server_guid); 00119 else 00120 auth = _dbus_auth_client_new (); 00121 if (auth == NULL) 00122 { 00123 _dbus_message_loader_unref (loader); 00124 return FALSE; 00125 } 00126 00127 counter = _dbus_counter_new (); 00128 if (counter == NULL) 00129 { 00130 _dbus_auth_unref (auth); 00131 _dbus_message_loader_unref (loader); 00132 return FALSE; 00133 } 00134 00135 creds = _dbus_credentials_new (); 00136 if (creds == NULL) 00137 { 00138 _dbus_counter_unref (counter); 00139 _dbus_auth_unref (auth); 00140 _dbus_message_loader_unref (loader); 00141 return FALSE; 00142 } 00143 00144 if (server_guid) 00145 { 00146 _dbus_assert (address == NULL); 00147 address_copy = NULL; 00148 } 00149 else 00150 { 00151 _dbus_assert (address != NULL); 00152 00153 if (!_dbus_string_copy_data (address, &address_copy)) 00154 { 00155 _dbus_credentials_unref (creds); 00156 _dbus_counter_unref (counter); 00157 _dbus_auth_unref (auth); 00158 _dbus_message_loader_unref (loader); 00159 return FALSE; 00160 } 00161 } 00162 00163 transport->refcount = 1; 00164 transport->vtable = vtable; 00165 transport->loader = loader; 00166 transport->auth = auth; 00167 transport->live_messages = counter; 00168 transport->authenticated = FALSE; 00169 transport->disconnected = FALSE; 00170 transport->is_server = (server_guid != NULL); 00171 transport->send_credentials_pending = !transport->is_server; 00172 transport->receive_credentials_pending = transport->is_server; 00173 transport->address = address_copy; 00174 00175 transport->unix_user_function = NULL; 00176 transport->unix_user_data = NULL; 00177 transport->free_unix_user_data = NULL; 00178 00179 transport->windows_user_function = NULL; 00180 transport->windows_user_data = NULL; 00181 transport->free_windows_user_data = NULL; 00182 00183 transport->expected_guid = NULL; 00184 00185 /* Try to default to something that won't totally hose the system, 00186 * but doesn't impose too much of a limitation. 00187 */ 00188 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 00189 00190 /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live 00191 should be more than enough */ 00192 transport->max_live_messages_unix_fds = 4096; 00193 00194 /* credentials read from socket if any */ 00195 transport->credentials = creds; 00196 00197 _dbus_counter_set_notify (transport->live_messages, 00198 transport->max_live_messages_size, 00199 transport->max_live_messages_unix_fds, 00200 live_messages_notify, 00201 transport); 00202 00203 if (transport->address) 00204 _dbus_verbose ("Initialized transport on address %s\n", transport->address); 00205 00206 return TRUE; 00207 } 00208 00215 void 00216 _dbus_transport_finalize_base (DBusTransport *transport) 00217 { 00218 if (!transport->disconnected) 00219 _dbus_transport_disconnect (transport); 00220 00221 if (transport->free_unix_user_data != NULL) 00222 (* transport->free_unix_user_data) (transport->unix_user_data); 00223 00224 if (transport->free_windows_user_data != NULL) 00225 (* transport->free_windows_user_data) (transport->windows_user_data); 00226 00227 _dbus_message_loader_unref (transport->loader); 00228 _dbus_auth_unref (transport->auth); 00229 _dbus_counter_set_notify (transport->live_messages, 00230 0, 0, NULL, NULL); 00231 _dbus_counter_unref (transport->live_messages); 00232 dbus_free (transport->address); 00233 dbus_free (transport->expected_guid); 00234 if (transport->credentials) 00235 _dbus_credentials_unref (transport->credentials); 00236 } 00237 00238 00249 static DBusTransport* 00250 check_address (const char *address, DBusError *error) 00251 { 00252 DBusAddressEntry **entries; 00253 DBusTransport *transport = NULL; 00254 int len, i; 00255 00256 _dbus_assert (address != NULL); 00257 00258 if (!dbus_parse_address (address, &entries, &len, error)) 00259 return NULL; /* not a valid address */ 00260 00261 for (i = 0; i < len; i++) 00262 { 00263 transport = _dbus_transport_open (entries[i], error); 00264 if (transport != NULL) 00265 break; 00266 } 00267 00268 dbus_address_entries_free (entries); 00269 return transport; 00270 } 00271 00280 static DBusTransport* 00281 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error) 00282 { 00283 DBusString address; 00284 DBusTransport *result = NULL; 00285 00286 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00287 00288 if (!_dbus_string_init (&address)) 00289 { 00290 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00291 return NULL; 00292 } 00293 00294 if (!_dbus_get_autolaunch_address (scope, &address, error)) 00295 { 00296 _DBUS_ASSERT_ERROR_IS_SET (error); 00297 goto out; 00298 } 00299 00300 result = check_address (_dbus_string_get_const_data (&address), error); 00301 if (result == NULL) 00302 _DBUS_ASSERT_ERROR_IS_SET (error); 00303 else 00304 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00305 00306 out: 00307 _dbus_string_free (&address); 00308 return result; 00309 } 00310 00311 static DBusTransportOpenResult 00312 _dbus_transport_open_autolaunch (DBusAddressEntry *entry, 00313 DBusTransport **transport_p, 00314 DBusError *error) 00315 { 00316 const char *method; 00317 00318 method = dbus_address_entry_get_method (entry); 00319 _dbus_assert (method != NULL); 00320 00321 if (strcmp (method, "autolaunch") == 0) 00322 { 00323 const char *scope = dbus_address_entry_get_value (entry, "scope"); 00324 00325 *transport_p = _dbus_transport_new_for_autolaunch (scope, error); 00326 00327 if (*transport_p == NULL) 00328 { 00329 _DBUS_ASSERT_ERROR_IS_SET (error); 00330 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00331 } 00332 else 00333 { 00334 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00335 return DBUS_TRANSPORT_OPEN_OK; 00336 } 00337 } 00338 else 00339 { 00340 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00341 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00342 } 00343 } 00344 00345 static const struct { 00346 DBusTransportOpenResult (* func) (DBusAddressEntry *entry, 00347 DBusTransport **transport_p, 00348 DBusError *error); 00349 } open_funcs[] = { 00350 { _dbus_transport_open_socket }, 00351 { _dbus_transport_open_platform_specific }, 00352 { _dbus_transport_open_autolaunch } 00353 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00354 , { _dbus_transport_open_debug_pipe } 00355 #endif 00356 }; 00357 00366 DBusTransport* 00367 _dbus_transport_open (DBusAddressEntry *entry, 00368 DBusError *error) 00369 { 00370 DBusTransport *transport; 00371 const char *expected_guid_orig; 00372 char *expected_guid; 00373 int i; 00374 DBusError tmp_error = DBUS_ERROR_INIT; 00375 00376 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00377 00378 transport = NULL; 00379 expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); 00380 expected_guid = _dbus_strdup (expected_guid_orig); 00381 00382 if (expected_guid_orig != NULL && expected_guid == NULL) 00383 { 00384 _DBUS_SET_OOM (error); 00385 return NULL; 00386 } 00387 00388 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i) 00389 { 00390 DBusTransportOpenResult result; 00391 00392 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00393 result = (* open_funcs[i].func) (entry, &transport, &tmp_error); 00394 00395 switch (result) 00396 { 00397 case DBUS_TRANSPORT_OPEN_OK: 00398 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00399 goto out; 00400 break; 00401 case DBUS_TRANSPORT_OPEN_NOT_HANDLED: 00402 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00403 /* keep going through the loop of open funcs */ 00404 break; 00405 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS: 00406 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00407 goto out; 00408 break; 00409 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT: 00410 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00411 goto out; 00412 break; 00413 } 00414 } 00415 00416 out: 00417 00418 if (transport == NULL) 00419 { 00420 if (!dbus_error_is_set (&tmp_error)) 00421 _dbus_set_bad_address (&tmp_error, 00422 NULL, NULL, 00423 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")"); 00424 00425 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00426 dbus_move_error(&tmp_error, error); 00427 dbus_free (expected_guid); 00428 } 00429 else 00430 { 00431 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00432 00433 /* In the case of autostart the initial guid is NULL 00434 * and the autostart transport recursively calls 00435 * _dbus_open_transport wich returns a transport 00436 * with a guid. That guid is the definitive one. 00437 * 00438 * FIXME: if more transports are added they may have 00439 * an effect on the expected_guid semantics (i.e. 00440 * expected_guid and transport->expected_guid may 00441 * both have values). This is very unlikely though 00442 * we should either throw asserts here for those 00443 * corner cases or refactor the code so it is 00444 * clearer on what is expected and what is not 00445 */ 00446 if(expected_guid) 00447 transport->expected_guid = expected_guid; 00448 } 00449 00450 return transport; 00451 } 00452 00459 DBusTransport * 00460 _dbus_transport_ref (DBusTransport *transport) 00461 { 00462 _dbus_assert (transport->refcount > 0); 00463 00464 transport->refcount += 1; 00465 00466 return transport; 00467 } 00468 00476 void 00477 _dbus_transport_unref (DBusTransport *transport) 00478 { 00479 _dbus_assert (transport != NULL); 00480 _dbus_assert (transport->refcount > 0); 00481 00482 transport->refcount -= 1; 00483 if (transport->refcount == 0) 00484 { 00485 _dbus_verbose ("finalizing\n"); 00486 00487 _dbus_assert (transport->vtable->finalize != NULL); 00488 00489 (* transport->vtable->finalize) (transport); 00490 } 00491 } 00492 00501 void 00502 _dbus_transport_disconnect (DBusTransport *transport) 00503 { 00504 _dbus_verbose ("start\n"); 00505 00506 _dbus_assert (transport->vtable->disconnect != NULL); 00507 00508 if (transport->disconnected) 00509 return; 00510 00511 (* transport->vtable->disconnect) (transport); 00512 00513 transport->disconnected = TRUE; 00514 00515 _dbus_verbose ("end\n"); 00516 } 00517 00526 dbus_bool_t 00527 _dbus_transport_get_is_connected (DBusTransport *transport) 00528 { 00529 return !transport->disconnected; 00530 } 00531 00532 static dbus_bool_t 00533 auth_via_unix_user_function (DBusTransport *transport) 00534 { 00535 DBusCredentials *auth_identity; 00536 dbus_bool_t allow; 00537 DBusConnection *connection; 00538 DBusAllowUnixUserFunction unix_user_function; 00539 void *unix_user_data; 00540 dbus_uid_t uid; 00541 00542 /* Dropping the lock here probably isn't that safe. */ 00543 00544 auth_identity = _dbus_auth_get_identity (transport->auth); 00545 _dbus_assert (auth_identity != NULL); 00546 00547 connection = transport->connection; 00548 unix_user_function = transport->unix_user_function; 00549 unix_user_data = transport->unix_user_data; 00550 uid = _dbus_credentials_get_unix_uid (auth_identity); 00551 00552 _dbus_verbose ("unlock\n"); 00553 _dbus_connection_unlock (connection); 00554 00555 allow = (* unix_user_function) (connection, 00556 uid, 00557 unix_user_data); 00558 00559 _dbus_verbose ("lock post unix user function\n"); 00560 _dbus_connection_lock (connection); 00561 00562 if (allow) 00563 { 00564 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); 00565 } 00566 else 00567 { 00568 _dbus_verbose ("Client UID "DBUS_UID_FORMAT 00569 " was rejected, disconnecting\n", 00570 _dbus_credentials_get_unix_uid (auth_identity)); 00571 _dbus_transport_disconnect (transport); 00572 } 00573 00574 return allow; 00575 } 00576 00577 static dbus_bool_t 00578 auth_via_windows_user_function (DBusTransport *transport) 00579 { 00580 DBusCredentials *auth_identity; 00581 dbus_bool_t allow; 00582 DBusConnection *connection; 00583 DBusAllowWindowsUserFunction windows_user_function; 00584 void *windows_user_data; 00585 char *windows_sid; 00586 00587 /* Dropping the lock here probably isn't that safe. */ 00588 00589 auth_identity = _dbus_auth_get_identity (transport->auth); 00590 _dbus_assert (auth_identity != NULL); 00591 00592 connection = transport->connection; 00593 windows_user_function = transport->windows_user_function; 00594 windows_user_data = transport->unix_user_data; 00595 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 00596 00597 if (windows_sid == NULL) 00598 { 00599 /* OOM */ 00600 return FALSE; 00601 } 00602 00603 _dbus_verbose ("unlock\n"); 00604 _dbus_connection_unlock (connection); 00605 00606 allow = (* windows_user_function) (connection, 00607 windows_sid, 00608 windows_user_data); 00609 00610 _dbus_verbose ("lock post windows user function\n"); 00611 _dbus_connection_lock (connection); 00612 00613 if (allow) 00614 { 00615 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); 00616 } 00617 else 00618 { 00619 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", 00620 _dbus_credentials_get_windows_sid (auth_identity)); 00621 _dbus_transport_disconnect (transport); 00622 } 00623 00624 return allow; 00625 } 00626 00627 static dbus_bool_t 00628 auth_via_default_rules (DBusTransport *transport) 00629 { 00630 DBusCredentials *auth_identity; 00631 DBusCredentials *our_identity; 00632 dbus_bool_t allow; 00633 00634 auth_identity = _dbus_auth_get_identity (transport->auth); 00635 _dbus_assert (auth_identity != NULL); 00636 00637 /* By default, connection is allowed if the client is 1) root or 2) 00638 * has the same UID as us or 3) anonymous is allowed. 00639 */ 00640 00641 our_identity = _dbus_credentials_new_from_current_process (); 00642 if (our_identity == NULL) 00643 { 00644 /* OOM */ 00645 return FALSE; 00646 } 00647 00648 if (transport->allow_anonymous || 00649 _dbus_credentials_get_unix_uid (auth_identity) == 0 || 00650 _dbus_credentials_same_user (our_identity, 00651 auth_identity)) 00652 { 00653 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00654 _dbus_verbose ("Client authorized as SID '%s'" 00655 "matching our SID '%s'\n", 00656 _dbus_credentials_get_windows_sid(auth_identity), 00657 _dbus_credentials_get_windows_sid(our_identity)); 00658 else 00659 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00660 " matching our UID "DBUS_UID_FORMAT"\n", 00661 _dbus_credentials_get_unix_uid(auth_identity), 00662 _dbus_credentials_get_unix_uid(our_identity)); 00663 /* We have authenticated! */ 00664 allow = TRUE; 00665 } 00666 else 00667 { 00668 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00669 _dbus_verbose ("Client authorized as SID '%s'" 00670 " but our SID is '%s', disconnecting\n", 00671 (_dbus_credentials_get_windows_sid(auth_identity) ? 00672 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"), 00673 (_dbus_credentials_get_windows_sid(our_identity) ? 00674 _dbus_credentials_get_windows_sid(our_identity) : "<null>")); 00675 else 00676 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00677 " but our UID is "DBUS_UID_FORMAT", disconnecting\n", 00678 _dbus_credentials_get_unix_uid(auth_identity), 00679 _dbus_credentials_get_unix_uid(our_identity)); 00680 _dbus_transport_disconnect (transport); 00681 allow = FALSE; 00682 } 00683 00684 _dbus_credentials_unref (our_identity); 00685 00686 return allow; 00687 } 00688 00700 dbus_bool_t 00701 _dbus_transport_peek_is_authenticated (DBusTransport *transport) 00702 { 00703 return transport->authenticated; 00704 } 00705 00723 dbus_bool_t 00724 _dbus_transport_try_to_authenticate (DBusTransport *transport) 00725 { 00726 if (transport->authenticated) 00727 return TRUE; 00728 else 00729 { 00730 dbus_bool_t maybe_authenticated; 00731 00732 if (transport->disconnected) 00733 return FALSE; 00734 00735 /* paranoia ref since we call user callbacks sometimes */ 00736 _dbus_connection_ref_unlocked (transport->connection); 00737 00738 maybe_authenticated = 00739 (!(transport->send_credentials_pending || 00740 transport->receive_credentials_pending)); 00741 00742 if (maybe_authenticated) 00743 { 00744 switch (_dbus_auth_do_work (transport->auth)) 00745 { 00746 case DBUS_AUTH_STATE_AUTHENTICATED: 00747 /* leave as maybe_authenticated */ 00748 break; 00749 default: 00750 maybe_authenticated = FALSE; 00751 } 00752 } 00753 00754 /* If we're the client, verify the GUID 00755 */ 00756 if (maybe_authenticated && !transport->is_server) 00757 { 00758 const char *server_guid; 00759 00760 server_guid = _dbus_auth_get_guid_from_server (transport->auth); 00761 _dbus_assert (server_guid != NULL); 00762 00763 if (transport->expected_guid && 00764 strcmp (transport->expected_guid, server_guid) != 0) 00765 { 00766 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", 00767 transport->expected_guid, server_guid); 00768 _dbus_transport_disconnect (transport); 00769 _dbus_connection_unref_unlocked (transport->connection); 00770 return FALSE; 00771 } 00772 } 00773 00774 /* If we're the server, see if we want to allow this identity to proceed. 00775 */ 00776 if (maybe_authenticated && transport->is_server) 00777 { 00778 dbus_bool_t allow; 00779 DBusCredentials *auth_identity; 00780 00781 auth_identity = _dbus_auth_get_identity (transport->auth); 00782 _dbus_assert (auth_identity != NULL); 00783 00784 /* If we have an auth'd user and a user function, delegate 00785 * deciding whether auth credentials are good enough to the 00786 * app; otherwise, use our default decision process. 00787 */ 00788 if (transport->unix_user_function != NULL && 00789 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) 00790 { 00791 allow = auth_via_unix_user_function (transport); 00792 } 00793 else if (transport->windows_user_function != NULL && 00794 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) 00795 { 00796 allow = auth_via_windows_user_function (transport); 00797 } 00798 else 00799 { 00800 allow = auth_via_default_rules (transport); 00801 } 00802 00803 if (!allow) 00804 maybe_authenticated = FALSE; 00805 } 00806 00807 transport->authenticated = maybe_authenticated; 00808 00809 _dbus_connection_unref_unlocked (transport->connection); 00810 return maybe_authenticated; 00811 } 00812 } 00813 00820 dbus_bool_t 00821 _dbus_transport_get_is_anonymous (DBusTransport *transport) 00822 { 00823 DBusCredentials *auth_identity; 00824 00825 if (!transport->authenticated) 00826 return TRUE; 00827 00828 auth_identity = _dbus_auth_get_identity (transport->auth); 00829 00830 if (_dbus_credentials_are_anonymous (auth_identity)) 00831 return TRUE; 00832 else 00833 return FALSE; 00834 } 00835 00842 dbus_bool_t 00843 _dbus_transport_can_pass_unix_fd(DBusTransport *transport) 00844 { 00845 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport); 00846 } 00847 00855 const char* 00856 _dbus_transport_get_address (DBusTransport *transport) 00857 { 00858 return transport->address; 00859 } 00860 00868 const char* 00869 _dbus_transport_get_server_id (DBusTransport *transport) 00870 { 00871 if (transport->is_server) 00872 return NULL; 00873 else if (transport->authenticated) 00874 return _dbus_auth_get_guid_from_server (transport->auth); 00875 else 00876 return transport->expected_guid; 00877 } 00878 00888 dbus_bool_t 00889 _dbus_transport_handle_watch (DBusTransport *transport, 00890 DBusWatch *watch, 00891 unsigned int condition) 00892 { 00893 dbus_bool_t retval; 00894 00895 _dbus_assert (transport->vtable->handle_watch != NULL); 00896 00897 if (transport->disconnected) 00898 return TRUE; 00899 00900 if (dbus_watch_get_socket (watch) < 0) 00901 { 00902 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n"); 00903 return TRUE; 00904 } 00905 00906 _dbus_watch_sanitize_condition (watch, &condition); 00907 00908 _dbus_transport_ref (transport); 00909 _dbus_watch_ref (watch); 00910 retval = (* transport->vtable->handle_watch) (transport, watch, condition); 00911 _dbus_watch_unref (watch); 00912 _dbus_transport_unref (transport); 00913 00914 return retval; 00915 } 00916 00926 dbus_bool_t 00927 _dbus_transport_set_connection (DBusTransport *transport, 00928 DBusConnection *connection) 00929 { 00930 _dbus_assert (transport->vtable->connection_set != NULL); 00931 _dbus_assert (transport->connection == NULL); 00932 00933 transport->connection = connection; 00934 00935 _dbus_transport_ref (transport); 00936 if (!(* transport->vtable->connection_set) (transport)) 00937 transport->connection = NULL; 00938 _dbus_transport_unref (transport); 00939 00940 return transport->connection != NULL; 00941 } 00942 00950 dbus_bool_t 00951 _dbus_transport_get_socket_fd (DBusTransport *transport, 00952 DBusSocket *fd_p) 00953 { 00954 dbus_bool_t retval; 00955 00956 if (transport->vtable->get_socket_fd == NULL) 00957 return FALSE; 00958 00959 if (transport->disconnected) 00960 return FALSE; 00961 00962 _dbus_transport_ref (transport); 00963 00964 retval = (* transport->vtable->get_socket_fd) (transport, 00965 fd_p); 00966 00967 _dbus_transport_unref (transport); 00968 00969 return retval; 00970 } 00971 00983 void 00984 _dbus_transport_do_iteration (DBusTransport *transport, 00985 unsigned int flags, 00986 int timeout_milliseconds) 00987 { 00988 _dbus_assert (transport->vtable->do_iteration != NULL); 00989 00990 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n", 00991 flags, timeout_milliseconds, !transport->disconnected); 00992 00993 if ((flags & (DBUS_ITERATION_DO_WRITING | 00994 DBUS_ITERATION_DO_READING)) == 0) 00995 return; /* Nothing to do */ 00996 00997 if (transport->disconnected) 00998 return; 00999 01000 _dbus_transport_ref (transport); 01001 (* transport->vtable->do_iteration) (transport, flags, 01002 timeout_milliseconds); 01003 _dbus_transport_unref (transport); 01004 01005 _dbus_verbose ("end\n"); 01006 } 01007 01008 static dbus_bool_t 01009 recover_unused_bytes (DBusTransport *transport) 01010 { 01011 if (_dbus_auth_needs_decoding (transport->auth)) 01012 { 01013 DBusString plaintext; 01014 const DBusString *encoded; 01015 DBusString *buffer; 01016 int orig_len; 01017 01018 if (!_dbus_string_init (&plaintext)) 01019 goto nomem; 01020 01021 _dbus_auth_get_unused_bytes (transport->auth, 01022 &encoded); 01023 01024 if (!_dbus_auth_decode_data (transport->auth, 01025 encoded, &plaintext)) 01026 { 01027 _dbus_string_free (&plaintext); 01028 goto nomem; 01029 } 01030 01031 _dbus_message_loader_get_buffer (transport->loader, 01032 &buffer); 01033 01034 orig_len = _dbus_string_get_length (buffer); 01035 01036 if (!_dbus_string_move (&plaintext, 0, buffer, 01037 orig_len)) 01038 { 01039 _dbus_string_free (&plaintext); 01040 goto nomem; 01041 } 01042 01043 _dbus_verbose (" %d unused bytes sent to message loader\n", 01044 _dbus_string_get_length (buffer) - 01045 orig_len); 01046 01047 _dbus_message_loader_return_buffer (transport->loader, 01048 buffer); 01049 01050 _dbus_auth_delete_unused_bytes (transport->auth); 01051 01052 _dbus_string_free (&plaintext); 01053 } 01054 else 01055 { 01056 const DBusString *bytes; 01057 DBusString *buffer; 01058 int orig_len; 01059 dbus_bool_t succeeded; 01060 01061 _dbus_message_loader_get_buffer (transport->loader, 01062 &buffer); 01063 01064 orig_len = _dbus_string_get_length (buffer); 01065 01066 _dbus_auth_get_unused_bytes (transport->auth, 01067 &bytes); 01068 01069 succeeded = TRUE; 01070 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer))) 01071 succeeded = FALSE; 01072 01073 _dbus_verbose (" %d unused bytes sent to message loader\n", 01074 _dbus_string_get_length (buffer) - 01075 orig_len); 01076 01077 _dbus_message_loader_return_buffer (transport->loader, 01078 buffer); 01079 01080 if (succeeded) 01081 _dbus_auth_delete_unused_bytes (transport->auth); 01082 else 01083 goto nomem; 01084 } 01085 01086 return TRUE; 01087 01088 nomem: 01089 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); 01090 return FALSE; 01091 } 01092 01100 DBusDispatchStatus 01101 _dbus_transport_get_dispatch_status (DBusTransport *transport) 01102 { 01103 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size || 01104 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) 01105 return DBUS_DISPATCH_COMPLETE; /* complete for now */ 01106 01107 if (!_dbus_transport_try_to_authenticate (transport)) 01108 { 01109 if (_dbus_auth_do_work (transport->auth) == 01110 DBUS_AUTH_STATE_WAITING_FOR_MEMORY) 01111 return DBUS_DISPATCH_NEED_MEMORY; 01112 else if (!_dbus_transport_try_to_authenticate (transport)) 01113 return DBUS_DISPATCH_COMPLETE; 01114 } 01115 01116 if (!transport->unused_bytes_recovered && 01117 !recover_unused_bytes (transport)) 01118 return DBUS_DISPATCH_NEED_MEMORY; 01119 01120 transport->unused_bytes_recovered = TRUE; 01121 01122 if (!_dbus_message_loader_queue_messages (transport->loader)) 01123 return DBUS_DISPATCH_NEED_MEMORY; 01124 01125 if (_dbus_message_loader_peek_message (transport->loader) != NULL) 01126 return DBUS_DISPATCH_DATA_REMAINS; 01127 else 01128 return DBUS_DISPATCH_COMPLETE; 01129 } 01130 01139 dbus_bool_t 01140 _dbus_transport_queue_messages (DBusTransport *transport) 01141 { 01142 DBusDispatchStatus status; 01143 01144 #if 0 01145 _dbus_verbose ("_dbus_transport_queue_messages()\n"); 01146 #endif 01147 01148 /* Queue any messages */ 01149 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS) 01150 { 01151 DBusMessage *message; 01152 DBusList *link; 01153 01154 link = _dbus_message_loader_pop_message_link (transport->loader); 01155 _dbus_assert (link != NULL); 01156 01157 message = link->data; 01158 01159 _dbus_verbose ("queueing received message %p\n", message); 01160 01161 if (!_dbus_message_add_counter (message, transport->live_messages)) 01162 { 01163 _dbus_message_loader_putback_message_link (transport->loader, 01164 link); 01165 status = DBUS_DISPATCH_NEED_MEMORY; 01166 break; 01167 } 01168 else 01169 { 01170 /* We didn't call the notify function when we added the counter, so 01171 * catch up now. Since we have the connection's lock, it's desirable 01172 * that we bypass the notify function and call this virtual method 01173 * directly. */ 01174 if (transport->vtable->live_messages_changed) 01175 (* transport->vtable->live_messages_changed) (transport); 01176 01177 /* pass ownership of link and message ref to connection */ 01178 _dbus_connection_queue_received_message_link (transport->connection, 01179 link); 01180 } 01181 } 01182 01183 if (_dbus_message_loader_get_is_corrupted (transport->loader)) 01184 { 01185 _dbus_verbose ("Corrupted message stream, disconnecting\n"); 01186 _dbus_transport_disconnect (transport); 01187 } 01188 01189 return status != DBUS_DISPATCH_NEED_MEMORY; 01190 } 01191 01198 void 01199 _dbus_transport_set_max_message_size (DBusTransport *transport, 01200 long size) 01201 { 01202 _dbus_message_loader_set_max_message_size (transport->loader, size); 01203 } 01204 01211 void 01212 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport, 01213 long n) 01214 { 01215 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n); 01216 } 01217 01224 long 01225 _dbus_transport_get_max_message_size (DBusTransport *transport) 01226 { 01227 return _dbus_message_loader_get_max_message_size (transport->loader); 01228 } 01229 01236 long 01237 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport) 01238 { 01239 return _dbus_message_loader_get_max_message_unix_fds (transport->loader); 01240 } 01241 01248 void 01249 _dbus_transport_set_max_received_size (DBusTransport *transport, 01250 long size) 01251 { 01252 transport->max_live_messages_size = size; 01253 _dbus_counter_set_notify (transport->live_messages, 01254 transport->max_live_messages_size, 01255 transport->max_live_messages_unix_fds, 01256 live_messages_notify, 01257 transport); 01258 } 01259 01266 void 01267 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport, 01268 long n) 01269 { 01270 transport->max_live_messages_unix_fds = n; 01271 _dbus_counter_set_notify (transport->live_messages, 01272 transport->max_live_messages_size, 01273 transport->max_live_messages_unix_fds, 01274 live_messages_notify, 01275 transport); 01276 } 01277 01284 long 01285 _dbus_transport_get_max_received_size (DBusTransport *transport) 01286 { 01287 return transport->max_live_messages_size; 01288 } 01289 01296 long 01297 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport) 01298 { 01299 return transport->max_live_messages_unix_fds; 01300 } 01301 01309 dbus_bool_t 01310 _dbus_transport_get_unix_user (DBusTransport *transport, 01311 unsigned long *uid) 01312 { 01313 DBusCredentials *auth_identity; 01314 01315 *uid = _DBUS_INT32_MAX; /* better than some root or system user in 01316 * case of bugs in the caller. Caller should 01317 * never use this value on purpose, however. 01318 */ 01319 01320 if (!transport->authenticated) 01321 return FALSE; 01322 01323 auth_identity = _dbus_auth_get_identity (transport->auth); 01324 01325 if (_dbus_credentials_include (auth_identity, 01326 DBUS_CREDENTIAL_UNIX_USER_ID)) 01327 { 01328 *uid = _dbus_credentials_get_unix_uid (auth_identity); 01329 return TRUE; 01330 } 01331 else 01332 return FALSE; 01333 } 01334 01342 dbus_bool_t 01343 _dbus_transport_get_unix_process_id (DBusTransport *transport, 01344 unsigned long *pid) 01345 { 01346 DBusCredentials *auth_identity; 01347 01348 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose, 01349 * but we set it to a safe number, INT_MAX, 01350 * just to root out possible bugs in bad callers. 01351 */ 01352 01353 if (!transport->authenticated) 01354 return FALSE; 01355 01356 auth_identity = _dbus_auth_get_identity (transport->auth); 01357 01358 if (_dbus_credentials_include (auth_identity, 01359 DBUS_CREDENTIAL_UNIX_PROCESS_ID)) 01360 { 01361 *pid = _dbus_credentials_get_pid (auth_identity); 01362 return TRUE; 01363 } 01364 else 01365 return FALSE; 01366 } 01367 01376 dbus_bool_t 01377 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, 01378 void **data, 01379 int *data_size) 01380 { 01381 DBusCredentials *auth_identity; 01382 01383 *data = NULL; 01384 *data_size = 0; 01385 01386 if (!transport->authenticated) 01387 return FALSE; 01388 01389 auth_identity = _dbus_auth_get_identity (transport->auth); 01390 01391 if (_dbus_credentials_include (auth_identity, 01392 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) 01393 { 01394 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); 01395 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); 01396 return TRUE; 01397 } 01398 else 01399 return FALSE; 01400 } 01401 01412 void 01413 _dbus_transport_set_unix_user_function (DBusTransport *transport, 01414 DBusAllowUnixUserFunction function, 01415 void *data, 01416 DBusFreeFunction free_data_function, 01417 void **old_data, 01418 DBusFreeFunction *old_free_data_function) 01419 { 01420 *old_data = transport->unix_user_data; 01421 *old_free_data_function = transport->free_unix_user_data; 01422 01423 transport->unix_user_function = function; 01424 transport->unix_user_data = data; 01425 transport->free_unix_user_data = free_data_function; 01426 } 01427 01428 dbus_bool_t 01429 _dbus_transport_get_linux_security_label (DBusTransport *transport, 01430 char **label_p) 01431 { 01432 DBusCredentials *auth_identity; 01433 01434 *label_p = NULL; 01435 01436 if (!transport->authenticated) 01437 return FALSE; 01438 01439 auth_identity = _dbus_auth_get_identity (transport->auth); 01440 01441 if (_dbus_credentials_include (auth_identity, 01442 DBUS_CREDENTIAL_LINUX_SECURITY_LABEL)) 01443 { 01444 /* If no memory, we are supposed to return TRUE and set NULL */ 01445 *label_p = _dbus_strdup (_dbus_credentials_get_linux_security_label (auth_identity)); 01446 01447 return TRUE; 01448 } 01449 else 01450 { 01451 return FALSE; 01452 } 01453 } 01454 01462 dbus_bool_t 01463 _dbus_transport_get_windows_user (DBusTransport *transport, 01464 char **windows_sid_p) 01465 { 01466 DBusCredentials *auth_identity; 01467 01468 *windows_sid_p = NULL; 01469 01470 if (!transport->authenticated) 01471 return FALSE; 01472 01473 auth_identity = _dbus_auth_get_identity (transport->auth); 01474 01475 if (_dbus_credentials_include (auth_identity, 01476 DBUS_CREDENTIAL_WINDOWS_SID)) 01477 { 01478 /* If no memory, we are supposed to return TRUE and set NULL */ 01479 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 01480 01481 return TRUE; 01482 } 01483 else 01484 return FALSE; 01485 } 01486 01498 void 01499 _dbus_transport_set_windows_user_function (DBusTransport *transport, 01500 DBusAllowWindowsUserFunction function, 01501 void *data, 01502 DBusFreeFunction free_data_function, 01503 void **old_data, 01504 DBusFreeFunction *old_free_data_function) 01505 { 01506 *old_data = transport->windows_user_data; 01507 *old_free_data_function = transport->free_windows_user_data; 01508 01509 transport->windows_user_function = function; 01510 transport->windows_user_data = data; 01511 transport->free_windows_user_data = free_data_function; 01512 } 01513 01522 dbus_bool_t 01523 _dbus_transport_set_auth_mechanisms (DBusTransport *transport, 01524 const char **mechanisms) 01525 { 01526 return _dbus_auth_set_mechanisms (transport->auth, mechanisms); 01527 } 01528 01535 void 01536 _dbus_transport_set_allow_anonymous (DBusTransport *transport, 01537 dbus_bool_t value) 01538 { 01539 transport->allow_anonymous = value != FALSE; 01540 } 01541 01547 int 01548 _dbus_transport_get_pending_fds_count (DBusTransport *transport) 01549 { 01550 return _dbus_message_loader_get_pending_fds_count (transport->loader); 01551 } 01552 01560 void 01561 _dbus_transport_set_pending_fds_function (DBusTransport *transport, 01562 void (* callback) (void *), 01563 void *data) 01564 { 01565 _dbus_message_loader_set_pending_fds_function (transport->loader, 01566 callback, data); 01567 } 01568 01569 #ifdef DBUS_ENABLE_STATS 01570 void 01571 _dbus_transport_get_stats (DBusTransport *transport, 01572 dbus_uint32_t *queue_bytes, 01573 dbus_uint32_t *queue_fds, 01574 dbus_uint32_t *peak_queue_bytes, 01575 dbus_uint32_t *peak_queue_fds) 01576 { 01577 if (queue_bytes != NULL) 01578 *queue_bytes = _dbus_counter_get_size_value (transport->live_messages); 01579 01580 if (queue_fds != NULL) 01581 *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages); 01582 01583 if (peak_queue_bytes != NULL) 01584 *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages); 01585 01586 if (peak_queue_fds != NULL) 01587 *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages); 01588 } 01589 #endif /* DBUS_ENABLE_STATS */ 01590