D-Bus 1.4.1
|
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-message-private.h" 00034 #include "dbus-marshal-header.h" 00035 #ifdef DBUS_BUILD_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_transport_ref (transport); 00067 00068 #if 0 00069 _dbus_verbose ("Size counter value is now %d\n", 00070 (int) _dbus_counter_get_size_value (counter)); 00071 _dbus_verbose ("Unix FD counter value is now %d\n", 00072 (int) _dbus_counter_get_unix_fd_value (counter)); 00073 #endif 00074 00075 /* disable or re-enable the read watch for the transport if 00076 * required. 00077 */ 00078 if (transport->vtable->live_messages_changed) 00079 (* transport->vtable->live_messages_changed) (transport); 00080 00081 _dbus_transport_unref (transport); 00082 } 00083 00097 dbus_bool_t 00098 _dbus_transport_init_base (DBusTransport *transport, 00099 const DBusTransportVTable *vtable, 00100 const DBusString *server_guid, 00101 const DBusString *address) 00102 { 00103 DBusMessageLoader *loader; 00104 DBusAuth *auth; 00105 DBusCounter *counter; 00106 char *address_copy; 00107 DBusCredentials *creds; 00108 00109 loader = _dbus_message_loader_new (); 00110 if (loader == NULL) 00111 return FALSE; 00112 00113 if (server_guid) 00114 auth = _dbus_auth_server_new (server_guid); 00115 else 00116 auth = _dbus_auth_client_new (); 00117 if (auth == NULL) 00118 { 00119 _dbus_message_loader_unref (loader); 00120 return FALSE; 00121 } 00122 00123 counter = _dbus_counter_new (); 00124 if (counter == NULL) 00125 { 00126 _dbus_auth_unref (auth); 00127 _dbus_message_loader_unref (loader); 00128 return FALSE; 00129 } 00130 00131 creds = _dbus_credentials_new (); 00132 if (creds == NULL) 00133 { 00134 _dbus_counter_unref (counter); 00135 _dbus_auth_unref (auth); 00136 _dbus_message_loader_unref (loader); 00137 return FALSE; 00138 } 00139 00140 if (server_guid) 00141 { 00142 _dbus_assert (address == NULL); 00143 address_copy = NULL; 00144 } 00145 else 00146 { 00147 _dbus_assert (address != NULL); 00148 00149 if (!_dbus_string_copy_data (address, &address_copy)) 00150 { 00151 _dbus_credentials_unref (creds); 00152 _dbus_counter_unref (counter); 00153 _dbus_auth_unref (auth); 00154 _dbus_message_loader_unref (loader); 00155 return FALSE; 00156 } 00157 } 00158 00159 transport->refcount = 1; 00160 transport->vtable = vtable; 00161 transport->loader = loader; 00162 transport->auth = auth; 00163 transport->live_messages = counter; 00164 transport->authenticated = FALSE; 00165 transport->disconnected = FALSE; 00166 transport->is_server = (server_guid != NULL); 00167 transport->send_credentials_pending = !transport->is_server; 00168 transport->receive_credentials_pending = transport->is_server; 00169 transport->address = address_copy; 00170 00171 transport->unix_user_function = NULL; 00172 transport->unix_user_data = NULL; 00173 transport->free_unix_user_data = NULL; 00174 00175 transport->windows_user_function = NULL; 00176 transport->windows_user_data = NULL; 00177 transport->free_windows_user_data = NULL; 00178 00179 transport->expected_guid = NULL; 00180 00181 /* Try to default to something that won't totally hose the system, 00182 * but doesn't impose too much of a limitation. 00183 */ 00184 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 00185 00186 /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live 00187 should be more than enough */ 00188 transport->max_live_messages_unix_fds = 4096; 00189 00190 /* credentials read from socket if any */ 00191 transport->credentials = creds; 00192 00193 _dbus_counter_set_notify (transport->live_messages, 00194 transport->max_live_messages_size, 00195 transport->max_live_messages_unix_fds, 00196 live_messages_notify, 00197 transport); 00198 00199 if (transport->address) 00200 _dbus_verbose ("Initialized transport on address %s\n", transport->address); 00201 00202 return TRUE; 00203 } 00204 00211 void 00212 _dbus_transport_finalize_base (DBusTransport *transport) 00213 { 00214 if (!transport->disconnected) 00215 _dbus_transport_disconnect (transport); 00216 00217 if (transport->free_unix_user_data != NULL) 00218 (* transport->free_unix_user_data) (transport->unix_user_data); 00219 00220 if (transport->free_windows_user_data != NULL) 00221 (* transport->free_windows_user_data) (transport->windows_user_data); 00222 00223 _dbus_message_loader_unref (transport->loader); 00224 _dbus_auth_unref (transport->auth); 00225 _dbus_counter_set_notify (transport->live_messages, 00226 0, 0, NULL, NULL); 00227 _dbus_counter_unref (transport->live_messages); 00228 dbus_free (transport->address); 00229 dbus_free (transport->expected_guid); 00230 if (transport->credentials) 00231 _dbus_credentials_unref (transport->credentials); 00232 } 00233 00234 00244 static DBusTransport* 00245 check_address (const char *address, DBusError *error) 00246 { 00247 DBusAddressEntry **entries; 00248 DBusTransport *transport = NULL; 00249 int len, i; 00250 00251 _dbus_assert (address != NULL); 00252 _dbus_assert (*address != '\0'); 00253 00254 if (!dbus_parse_address (address, &entries, &len, error)) 00255 return NULL; /* not a valid address */ 00256 00257 for (i = 0; i < len; i++) 00258 { 00259 transport = _dbus_transport_open (entries[i], error); 00260 if (transport != NULL) 00261 break; 00262 } 00263 00264 dbus_address_entries_free (entries); 00265 return transport; 00266 } 00267 00275 static DBusTransport* 00276 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error) 00277 { 00278 DBusString address; 00279 DBusTransport *result = NULL; 00280 00281 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00282 00283 if (!_dbus_string_init (&address)) 00284 { 00285 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00286 return NULL; 00287 } 00288 00289 if (!_dbus_get_autolaunch_address (scope, &address, error)) 00290 { 00291 _DBUS_ASSERT_ERROR_IS_SET (error); 00292 goto out; 00293 } 00294 00295 result = check_address (_dbus_string_get_const_data (&address), error); 00296 if (result == NULL) 00297 _DBUS_ASSERT_ERROR_IS_SET (error); 00298 else 00299 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00300 00301 out: 00302 _dbus_string_free (&address); 00303 return result; 00304 } 00305 00306 static DBusTransportOpenResult 00307 _dbus_transport_open_autolaunch (DBusAddressEntry *entry, 00308 DBusTransport **transport_p, 00309 DBusError *error) 00310 { 00311 const char *method; 00312 00313 method = dbus_address_entry_get_method (entry); 00314 _dbus_assert (method != NULL); 00315 00316 if (strcmp (method, "autolaunch") == 0) 00317 { 00318 const char *scope = dbus_address_entry_get_value (entry, "scope"); 00319 00320 *transport_p = _dbus_transport_new_for_autolaunch (scope, error); 00321 00322 if (*transport_p == NULL) 00323 { 00324 _DBUS_ASSERT_ERROR_IS_SET (error); 00325 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00326 } 00327 else 00328 { 00329 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00330 return DBUS_TRANSPORT_OPEN_OK; 00331 } 00332 } 00333 else 00334 { 00335 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00336 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00337 } 00338 } 00339 00340 static const struct { 00341 DBusTransportOpenResult (* func) (DBusAddressEntry *entry, 00342 DBusTransport **transport_p, 00343 DBusError *error); 00344 } open_funcs[] = { 00345 { _dbus_transport_open_socket }, 00346 { _dbus_transport_open_platform_specific }, 00347 { _dbus_transport_open_autolaunch } 00348 #ifdef DBUS_BUILD_TESTS 00349 , { _dbus_transport_open_debug_pipe } 00350 #endif 00351 }; 00352 00361 DBusTransport* 00362 _dbus_transport_open (DBusAddressEntry *entry, 00363 DBusError *error) 00364 { 00365 DBusTransport *transport; 00366 const char *expected_guid_orig; 00367 char *expected_guid; 00368 int i; 00369 DBusError tmp_error = DBUS_ERROR_INIT; 00370 00371 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00372 00373 transport = NULL; 00374 expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); 00375 expected_guid = _dbus_strdup (expected_guid_orig); 00376 00377 if (expected_guid_orig != NULL && expected_guid == NULL) 00378 { 00379 _DBUS_SET_OOM (error); 00380 return NULL; 00381 } 00382 00383 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i) 00384 { 00385 DBusTransportOpenResult result; 00386 00387 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00388 result = (* open_funcs[i].func) (entry, &transport, &tmp_error); 00389 00390 switch (result) 00391 { 00392 case DBUS_TRANSPORT_OPEN_OK: 00393 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00394 goto out; 00395 break; 00396 case DBUS_TRANSPORT_OPEN_NOT_HANDLED: 00397 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00398 /* keep going through the loop of open funcs */ 00399 break; 00400 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS: 00401 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00402 goto out; 00403 break; 00404 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT: 00405 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00406 goto out; 00407 break; 00408 } 00409 } 00410 00411 out: 00412 00413 if (transport == NULL) 00414 { 00415 if (!dbus_error_is_set (&tmp_error)) 00416 _dbus_set_bad_address (&tmp_error, 00417 NULL, NULL, 00418 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")"); 00419 00420 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00421 dbus_move_error(&tmp_error, error); 00422 dbus_free (expected_guid); 00423 } 00424 else 00425 { 00426 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00427 00428 /* In the case of autostart the initial guid is NULL 00429 * and the autostart transport recursively calls 00430 * _dbus_open_transport wich returns a transport 00431 * with a guid. That guid is the definitive one. 00432 * 00433 * FIXME: if more transports are added they may have 00434 * an effect on the expected_guid semantics (i.e. 00435 * expected_guid and transport->expected_guid may 00436 * both have values). This is very unlikely though 00437 * we should either throw asserts here for those 00438 * corner cases or refactor the code so it is 00439 * clearer on what is expected and what is not 00440 */ 00441 if(expected_guid) 00442 transport->expected_guid = expected_guid; 00443 } 00444 00445 return transport; 00446 } 00447 00454 DBusTransport * 00455 _dbus_transport_ref (DBusTransport *transport) 00456 { 00457 _dbus_assert (transport->refcount > 0); 00458 00459 transport->refcount += 1; 00460 00461 return transport; 00462 } 00463 00471 void 00472 _dbus_transport_unref (DBusTransport *transport) 00473 { 00474 _dbus_assert (transport != NULL); 00475 _dbus_assert (transport->refcount > 0); 00476 00477 transport->refcount -= 1; 00478 if (transport->refcount == 0) 00479 { 00480 _dbus_verbose ("finalizing\n"); 00481 00482 _dbus_assert (transport->vtable->finalize != NULL); 00483 00484 (* transport->vtable->finalize) (transport); 00485 } 00486 } 00487 00496 void 00497 _dbus_transport_disconnect (DBusTransport *transport) 00498 { 00499 _dbus_verbose ("start\n"); 00500 00501 _dbus_assert (transport->vtable->disconnect != NULL); 00502 00503 if (transport->disconnected) 00504 return; 00505 00506 (* transport->vtable->disconnect) (transport); 00507 00508 transport->disconnected = TRUE; 00509 00510 _dbus_verbose ("end\n"); 00511 } 00512 00521 dbus_bool_t 00522 _dbus_transport_get_is_connected (DBusTransport *transport) 00523 { 00524 return !transport->disconnected; 00525 } 00526 00527 static dbus_bool_t 00528 auth_via_unix_user_function (DBusTransport *transport) 00529 { 00530 DBusCredentials *auth_identity; 00531 dbus_bool_t allow; 00532 DBusConnection *connection; 00533 DBusAllowUnixUserFunction unix_user_function; 00534 void *unix_user_data; 00535 dbus_uid_t uid; 00536 00537 /* Dropping the lock here probably isn't that safe. */ 00538 00539 auth_identity = _dbus_auth_get_identity (transport->auth); 00540 _dbus_assert (auth_identity != NULL); 00541 00542 connection = transport->connection; 00543 unix_user_function = transport->unix_user_function; 00544 unix_user_data = transport->unix_user_data; 00545 uid = _dbus_credentials_get_unix_uid (auth_identity); 00546 00547 _dbus_verbose ("unlock\n"); 00548 _dbus_connection_unlock (connection); 00549 00550 allow = (* unix_user_function) (connection, 00551 uid, 00552 unix_user_data); 00553 00554 _dbus_verbose ("lock post unix user function\n"); 00555 _dbus_connection_lock (connection); 00556 00557 if (allow) 00558 { 00559 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); 00560 } 00561 else 00562 { 00563 _dbus_verbose ("Client UID "DBUS_UID_FORMAT 00564 " was rejected, disconnecting\n", 00565 _dbus_credentials_get_unix_uid (auth_identity)); 00566 _dbus_transport_disconnect (transport); 00567 } 00568 00569 return allow; 00570 } 00571 00572 static dbus_bool_t 00573 auth_via_windows_user_function (DBusTransport *transport) 00574 { 00575 DBusCredentials *auth_identity; 00576 dbus_bool_t allow; 00577 DBusConnection *connection; 00578 DBusAllowWindowsUserFunction windows_user_function; 00579 void *windows_user_data; 00580 char *windows_sid; 00581 00582 /* Dropping the lock here probably isn't that safe. */ 00583 00584 auth_identity = _dbus_auth_get_identity (transport->auth); 00585 _dbus_assert (auth_identity != NULL); 00586 00587 connection = transport->connection; 00588 windows_user_function = transport->windows_user_function; 00589 windows_user_data = transport->unix_user_data; 00590 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 00591 00592 if (windows_sid == NULL) 00593 { 00594 /* OOM */ 00595 return FALSE; 00596 } 00597 00598 _dbus_verbose ("unlock\n"); 00599 _dbus_connection_unlock (connection); 00600 00601 allow = (* windows_user_function) (connection, 00602 windows_sid, 00603 windows_user_data); 00604 00605 _dbus_verbose ("lock post windows user function\n"); 00606 _dbus_connection_lock (connection); 00607 00608 if (allow) 00609 { 00610 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); 00611 } 00612 else 00613 { 00614 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", 00615 _dbus_credentials_get_windows_sid (auth_identity)); 00616 _dbus_transport_disconnect (transport); 00617 } 00618 00619 return allow; 00620 } 00621 00622 static dbus_bool_t 00623 auth_via_default_rules (DBusTransport *transport) 00624 { 00625 DBusCredentials *auth_identity; 00626 DBusCredentials *our_identity; 00627 dbus_bool_t allow; 00628 00629 auth_identity = _dbus_auth_get_identity (transport->auth); 00630 _dbus_assert (auth_identity != NULL); 00631 00632 /* By default, connection is allowed if the client is 1) root or 2) 00633 * has the same UID as us or 3) anonymous is allowed. 00634 */ 00635 00636 our_identity = _dbus_credentials_new_from_current_process (); 00637 if (our_identity == NULL) 00638 { 00639 /* OOM */ 00640 return FALSE; 00641 } 00642 00643 if (transport->allow_anonymous || 00644 _dbus_credentials_get_unix_uid (auth_identity) == 0 || 00645 _dbus_credentials_same_user (our_identity, 00646 auth_identity)) 00647 { 00648 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00649 _dbus_verbose ("Client authorized as SID '%s'" 00650 "matching our SID '%s'\n", 00651 _dbus_credentials_get_windows_sid(auth_identity), 00652 _dbus_credentials_get_windows_sid(our_identity)); 00653 else 00654 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00655 " matching our UID "DBUS_UID_FORMAT"\n", 00656 _dbus_credentials_get_unix_uid(auth_identity), 00657 _dbus_credentials_get_unix_uid(our_identity)); 00658 /* We have authenticated! */ 00659 allow = TRUE; 00660 } 00661 else 00662 { 00663 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00664 _dbus_verbose ("Client authorized as SID '%s'" 00665 " but our SID is '%s', disconnecting\n", 00666 (_dbus_credentials_get_windows_sid(auth_identity) ? 00667 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"), 00668 (_dbus_credentials_get_windows_sid(our_identity) ? 00669 _dbus_credentials_get_windows_sid(our_identity) : "<null>")); 00670 else 00671 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00672 " but our UID is "DBUS_UID_FORMAT", disconnecting\n", 00673 _dbus_credentials_get_unix_uid(auth_identity), 00674 _dbus_credentials_get_unix_uid(our_identity)); 00675 _dbus_transport_disconnect (transport); 00676 allow = FALSE; 00677 } 00678 00679 _dbus_credentials_unref (our_identity); 00680 00681 return allow; 00682 } 00683 00684 00695 dbus_bool_t 00696 _dbus_transport_get_is_authenticated (DBusTransport *transport) 00697 { 00698 if (transport->authenticated) 00699 return TRUE; 00700 else 00701 { 00702 dbus_bool_t maybe_authenticated; 00703 00704 if (transport->disconnected) 00705 return FALSE; 00706 00707 /* paranoia ref since we call user callbacks sometimes */ 00708 _dbus_connection_ref_unlocked (transport->connection); 00709 00710 maybe_authenticated = 00711 (!(transport->send_credentials_pending || 00712 transport->receive_credentials_pending)); 00713 00714 if (maybe_authenticated) 00715 { 00716 switch (_dbus_auth_do_work (transport->auth)) 00717 { 00718 case DBUS_AUTH_STATE_AUTHENTICATED: 00719 /* leave as maybe_authenticated */ 00720 break; 00721 default: 00722 maybe_authenticated = FALSE; 00723 } 00724 } 00725 00726 /* If we're the client, verify the GUID 00727 */ 00728 if (maybe_authenticated && !transport->is_server) 00729 { 00730 const char *server_guid; 00731 00732 server_guid = _dbus_auth_get_guid_from_server (transport->auth); 00733 _dbus_assert (server_guid != NULL); 00734 00735 if (transport->expected_guid && 00736 strcmp (transport->expected_guid, server_guid) != 0) 00737 { 00738 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", 00739 transport->expected_guid, server_guid); 00740 _dbus_transport_disconnect (transport); 00741 _dbus_connection_unref_unlocked (transport->connection); 00742 return FALSE; 00743 } 00744 00745 if (transport->expected_guid == NULL) 00746 { 00747 transport->expected_guid = _dbus_strdup (server_guid); 00748 00749 if (transport->expected_guid == NULL) 00750 { 00751 _dbus_verbose ("No memory to complete auth\n"); 00752 return FALSE; 00753 } 00754 } 00755 } 00756 00757 /* If we're the server, see if we want to allow this identity to proceed. 00758 */ 00759 if (maybe_authenticated && transport->is_server) 00760 { 00761 dbus_bool_t allow; 00762 DBusCredentials *auth_identity; 00763 00764 auth_identity = _dbus_auth_get_identity (transport->auth); 00765 _dbus_assert (auth_identity != NULL); 00766 00767 /* If we have an auth'd user and a user function, delegate 00768 * deciding whether auth credentials are good enough to the 00769 * app; otherwise, use our default decision process. 00770 */ 00771 if (transport->unix_user_function != NULL && 00772 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) 00773 { 00774 allow = auth_via_unix_user_function (transport); 00775 } 00776 else if (transport->windows_user_function != NULL && 00777 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) 00778 { 00779 allow = auth_via_windows_user_function (transport); 00780 } 00781 else 00782 { 00783 allow = auth_via_default_rules (transport); 00784 } 00785 00786 if (!allow) 00787 maybe_authenticated = FALSE; 00788 } 00789 00790 transport->authenticated = maybe_authenticated; 00791 00792 _dbus_connection_unref_unlocked (transport->connection); 00793 return maybe_authenticated; 00794 } 00795 } 00796 00803 dbus_bool_t 00804 _dbus_transport_get_is_anonymous (DBusTransport *transport) 00805 { 00806 DBusCredentials *auth_identity; 00807 00808 if (!transport->authenticated) 00809 return TRUE; 00810 00811 auth_identity = _dbus_auth_get_identity (transport->auth); 00812 00813 if (_dbus_credentials_are_anonymous (auth_identity)) 00814 return TRUE; 00815 else 00816 return FALSE; 00817 } 00818 00825 dbus_bool_t 00826 _dbus_transport_can_pass_unix_fd(DBusTransport *transport) 00827 { 00828 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport); 00829 } 00830 00838 const char* 00839 _dbus_transport_get_address (DBusTransport *transport) 00840 { 00841 return transport->address; 00842 } 00843 00851 const char* 00852 _dbus_transport_get_server_id (DBusTransport *transport) 00853 { 00854 if (transport->is_server) 00855 return NULL; 00856 else 00857 return transport->expected_guid; 00858 } 00859 00869 dbus_bool_t 00870 _dbus_transport_handle_watch (DBusTransport *transport, 00871 DBusWatch *watch, 00872 unsigned int condition) 00873 { 00874 dbus_bool_t retval; 00875 00876 _dbus_assert (transport->vtable->handle_watch != NULL); 00877 00878 if (transport->disconnected) 00879 return TRUE; 00880 00881 if (dbus_watch_get_socket (watch) < 0) 00882 { 00883 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n"); 00884 return TRUE; 00885 } 00886 00887 _dbus_watch_sanitize_condition (watch, &condition); 00888 00889 _dbus_transport_ref (transport); 00890 _dbus_watch_ref (watch); 00891 retval = (* transport->vtable->handle_watch) (transport, watch, condition); 00892 _dbus_watch_unref (watch); 00893 _dbus_transport_unref (transport); 00894 00895 return retval; 00896 } 00897 00907 dbus_bool_t 00908 _dbus_transport_set_connection (DBusTransport *transport, 00909 DBusConnection *connection) 00910 { 00911 _dbus_assert (transport->vtable->connection_set != NULL); 00912 _dbus_assert (transport->connection == NULL); 00913 00914 transport->connection = connection; 00915 00916 _dbus_transport_ref (transport); 00917 if (!(* transport->vtable->connection_set) (transport)) 00918 transport->connection = NULL; 00919 _dbus_transport_unref (transport); 00920 00921 return transport->connection != NULL; 00922 } 00923 00931 dbus_bool_t 00932 _dbus_transport_get_socket_fd (DBusTransport *transport, 00933 int *fd_p) 00934 { 00935 dbus_bool_t retval; 00936 00937 if (transport->vtable->get_socket_fd == NULL) 00938 return FALSE; 00939 00940 if (transport->disconnected) 00941 return FALSE; 00942 00943 _dbus_transport_ref (transport); 00944 00945 retval = (* transport->vtable->get_socket_fd) (transport, 00946 fd_p); 00947 00948 _dbus_transport_unref (transport); 00949 00950 return retval; 00951 } 00952 00964 void 00965 _dbus_transport_do_iteration (DBusTransport *transport, 00966 unsigned int flags, 00967 int timeout_milliseconds) 00968 { 00969 _dbus_assert (transport->vtable->do_iteration != NULL); 00970 00971 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n", 00972 flags, timeout_milliseconds, !transport->disconnected); 00973 00974 if ((flags & (DBUS_ITERATION_DO_WRITING | 00975 DBUS_ITERATION_DO_READING)) == 0) 00976 return; /* Nothing to do */ 00977 00978 if (transport->disconnected) 00979 return; 00980 00981 _dbus_transport_ref (transport); 00982 (* transport->vtable->do_iteration) (transport, flags, 00983 timeout_milliseconds); 00984 _dbus_transport_unref (transport); 00985 00986 _dbus_verbose ("end\n"); 00987 } 00988 00989 static dbus_bool_t 00990 recover_unused_bytes (DBusTransport *transport) 00991 { 00992 if (_dbus_auth_needs_decoding (transport->auth)) 00993 { 00994 DBusString plaintext; 00995 const DBusString *encoded; 00996 DBusString *buffer; 00997 int orig_len; 00998 00999 if (!_dbus_string_init (&plaintext)) 01000 goto nomem; 01001 01002 _dbus_auth_get_unused_bytes (transport->auth, 01003 &encoded); 01004 01005 if (!_dbus_auth_decode_data (transport->auth, 01006 encoded, &plaintext)) 01007 { 01008 _dbus_string_free (&plaintext); 01009 goto nomem; 01010 } 01011 01012 _dbus_message_loader_get_buffer (transport->loader, 01013 &buffer); 01014 01015 orig_len = _dbus_string_get_length (buffer); 01016 01017 if (!_dbus_string_move (&plaintext, 0, buffer, 01018 orig_len)) 01019 { 01020 _dbus_string_free (&plaintext); 01021 goto nomem; 01022 } 01023 01024 _dbus_verbose (" %d unused bytes sent to message loader\n", 01025 _dbus_string_get_length (buffer) - 01026 orig_len); 01027 01028 _dbus_message_loader_return_buffer (transport->loader, 01029 buffer, 01030 _dbus_string_get_length (buffer) - 01031 orig_len); 01032 01033 _dbus_auth_delete_unused_bytes (transport->auth); 01034 01035 _dbus_string_free (&plaintext); 01036 } 01037 else 01038 { 01039 const DBusString *bytes; 01040 DBusString *buffer; 01041 int orig_len; 01042 dbus_bool_t succeeded; 01043 01044 _dbus_message_loader_get_buffer (transport->loader, 01045 &buffer); 01046 01047 orig_len = _dbus_string_get_length (buffer); 01048 01049 _dbus_auth_get_unused_bytes (transport->auth, 01050 &bytes); 01051 01052 succeeded = TRUE; 01053 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer))) 01054 succeeded = FALSE; 01055 01056 _dbus_verbose (" %d unused bytes sent to message loader\n", 01057 _dbus_string_get_length (buffer) - 01058 orig_len); 01059 01060 _dbus_message_loader_return_buffer (transport->loader, 01061 buffer, 01062 _dbus_string_get_length (buffer) - 01063 orig_len); 01064 01065 if (succeeded) 01066 _dbus_auth_delete_unused_bytes (transport->auth); 01067 else 01068 goto nomem; 01069 } 01070 01071 return TRUE; 01072 01073 nomem: 01074 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); 01075 return FALSE; 01076 } 01077 01085 DBusDispatchStatus 01086 _dbus_transport_get_dispatch_status (DBusTransport *transport) 01087 { 01088 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size || 01089 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) 01090 return DBUS_DISPATCH_COMPLETE; /* complete for now */ 01091 01092 if (!_dbus_transport_get_is_authenticated (transport)) 01093 { 01094 if (_dbus_auth_do_work (transport->auth) == 01095 DBUS_AUTH_STATE_WAITING_FOR_MEMORY) 01096 return DBUS_DISPATCH_NEED_MEMORY; 01097 else if (!_dbus_transport_get_is_authenticated (transport)) 01098 return DBUS_DISPATCH_COMPLETE; 01099 } 01100 01101 if (!transport->unused_bytes_recovered && 01102 !recover_unused_bytes (transport)) 01103 return DBUS_DISPATCH_NEED_MEMORY; 01104 01105 transport->unused_bytes_recovered = TRUE; 01106 01107 if (!_dbus_message_loader_queue_messages (transport->loader)) 01108 return DBUS_DISPATCH_NEED_MEMORY; 01109 01110 if (_dbus_message_loader_peek_message (transport->loader) != NULL) 01111 return DBUS_DISPATCH_DATA_REMAINS; 01112 else 01113 return DBUS_DISPATCH_COMPLETE; 01114 } 01115 01124 dbus_bool_t 01125 _dbus_transport_queue_messages (DBusTransport *transport) 01126 { 01127 DBusDispatchStatus status; 01128 01129 #if 0 01130 _dbus_verbose ("_dbus_transport_queue_messages()\n"); 01131 #endif 01132 01133 /* Queue any messages */ 01134 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS) 01135 { 01136 DBusMessage *message; 01137 DBusList *link; 01138 01139 link = _dbus_message_loader_pop_message_link (transport->loader); 01140 _dbus_assert (link != NULL); 01141 01142 message = link->data; 01143 01144 _dbus_verbose ("queueing received message %p\n", message); 01145 01146 if (!_dbus_message_add_counter (message, transport->live_messages)) 01147 { 01148 _dbus_message_loader_putback_message_link (transport->loader, 01149 link); 01150 status = DBUS_DISPATCH_NEED_MEMORY; 01151 break; 01152 } 01153 else 01154 { 01155 /* pass ownership of link and message ref to connection */ 01156 _dbus_connection_queue_received_message_link (transport->connection, 01157 link); 01158 } 01159 } 01160 01161 if (_dbus_message_loader_get_is_corrupted (transport->loader)) 01162 { 01163 _dbus_verbose ("Corrupted message stream, disconnecting\n"); 01164 _dbus_transport_disconnect (transport); 01165 } 01166 01167 return status != DBUS_DISPATCH_NEED_MEMORY; 01168 } 01169 01176 void 01177 _dbus_transport_set_max_message_size (DBusTransport *transport, 01178 long size) 01179 { 01180 _dbus_message_loader_set_max_message_size (transport->loader, size); 01181 } 01182 01189 void 01190 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport, 01191 long n) 01192 { 01193 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n); 01194 } 01195 01202 long 01203 _dbus_transport_get_max_message_size (DBusTransport *transport) 01204 { 01205 return _dbus_message_loader_get_max_message_size (transport->loader); 01206 } 01207 01214 long 01215 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport) 01216 { 01217 return _dbus_message_loader_get_max_message_unix_fds (transport->loader); 01218 } 01219 01226 void 01227 _dbus_transport_set_max_received_size (DBusTransport *transport, 01228 long size) 01229 { 01230 transport->max_live_messages_size = size; 01231 _dbus_counter_set_notify (transport->live_messages, 01232 transport->max_live_messages_size, 01233 transport->max_live_messages_unix_fds, 01234 live_messages_notify, 01235 transport); 01236 } 01237 01244 void 01245 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport, 01246 long n) 01247 { 01248 transport->max_live_messages_unix_fds = n; 01249 _dbus_counter_set_notify (transport->live_messages, 01250 transport->max_live_messages_size, 01251 transport->max_live_messages_unix_fds, 01252 live_messages_notify, 01253 transport); 01254 } 01255 01262 long 01263 _dbus_transport_get_max_received_size (DBusTransport *transport) 01264 { 01265 return transport->max_live_messages_size; 01266 } 01267 01274 long 01275 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport) 01276 { 01277 return transport->max_live_messages_unix_fds; 01278 } 01279 01287 dbus_bool_t 01288 _dbus_transport_get_unix_user (DBusTransport *transport, 01289 unsigned long *uid) 01290 { 01291 DBusCredentials *auth_identity; 01292 01293 *uid = _DBUS_INT32_MAX; /* better than some root or system user in 01294 * case of bugs in the caller. Caller should 01295 * never use this value on purpose, however. 01296 */ 01297 01298 if (!transport->authenticated) 01299 return FALSE; 01300 01301 auth_identity = _dbus_auth_get_identity (transport->auth); 01302 01303 if (_dbus_credentials_include (auth_identity, 01304 DBUS_CREDENTIAL_UNIX_USER_ID)) 01305 { 01306 *uid = _dbus_credentials_get_unix_uid (auth_identity); 01307 return TRUE; 01308 } 01309 else 01310 return FALSE; 01311 } 01312 01320 dbus_bool_t 01321 _dbus_transport_get_unix_process_id (DBusTransport *transport, 01322 unsigned long *pid) 01323 { 01324 DBusCredentials *auth_identity; 01325 01326 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose, 01327 * but we set it to a safe number, INT_MAX, 01328 * just to root out possible bugs in bad callers. 01329 */ 01330 01331 if (!transport->authenticated) 01332 return FALSE; 01333 01334 auth_identity = _dbus_auth_get_identity (transport->auth); 01335 01336 if (_dbus_credentials_include (auth_identity, 01337 DBUS_CREDENTIAL_UNIX_PROCESS_ID)) 01338 { 01339 *pid = _dbus_credentials_get_unix_pid (auth_identity); 01340 return TRUE; 01341 } 01342 else 01343 return FALSE; 01344 } 01345 01354 dbus_bool_t 01355 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, 01356 void **data, 01357 int *data_size) 01358 { 01359 DBusCredentials *auth_identity; 01360 01361 *data = NULL; 01362 *data_size = 0; 01363 01364 if (!transport->authenticated) 01365 return FALSE; 01366 01367 auth_identity = _dbus_auth_get_identity (transport->auth); 01368 01369 if (_dbus_credentials_include (auth_identity, 01370 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) 01371 { 01372 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); 01373 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); 01374 return TRUE; 01375 } 01376 else 01377 return FALSE; 01378 } 01379 01390 void 01391 _dbus_transport_set_unix_user_function (DBusTransport *transport, 01392 DBusAllowUnixUserFunction function, 01393 void *data, 01394 DBusFreeFunction free_data_function, 01395 void **old_data, 01396 DBusFreeFunction *old_free_data_function) 01397 { 01398 *old_data = transport->unix_user_data; 01399 *old_free_data_function = transport->free_unix_user_data; 01400 01401 transport->unix_user_function = function; 01402 transport->unix_user_data = data; 01403 transport->free_unix_user_data = free_data_function; 01404 } 01405 01413 dbus_bool_t 01414 _dbus_transport_get_windows_user (DBusTransport *transport, 01415 char **windows_sid_p) 01416 { 01417 DBusCredentials *auth_identity; 01418 01419 *windows_sid_p = NULL; 01420 01421 if (!transport->authenticated) 01422 return FALSE; 01423 01424 auth_identity = _dbus_auth_get_identity (transport->auth); 01425 01426 if (_dbus_credentials_include (auth_identity, 01427 DBUS_CREDENTIAL_WINDOWS_SID)) 01428 { 01429 /* If no memory, we are supposed to return TRUE and set NULL */ 01430 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 01431 01432 return TRUE; 01433 } 01434 else 01435 return FALSE; 01436 } 01437 01449 void 01450 _dbus_transport_set_windows_user_function (DBusTransport *transport, 01451 DBusAllowWindowsUserFunction function, 01452 void *data, 01453 DBusFreeFunction free_data_function, 01454 void **old_data, 01455 DBusFreeFunction *old_free_data_function) 01456 { 01457 *old_data = transport->windows_user_data; 01458 *old_free_data_function = transport->free_windows_user_data; 01459 01460 transport->windows_user_function = function; 01461 transport->windows_user_data = data; 01462 transport->free_windows_user_data = free_data_function; 01463 } 01464 01473 dbus_bool_t 01474 _dbus_transport_set_auth_mechanisms (DBusTransport *transport, 01475 const char **mechanisms) 01476 { 01477 return _dbus_auth_set_mechanisms (transport->auth, mechanisms); 01478 } 01479 01486 void 01487 _dbus_transport_set_allow_anonymous (DBusTransport *transport, 01488 dbus_bool_t value) 01489 { 01490 transport->allow_anonymous = value != FALSE; 01491 } 01492