D-Bus
1.4.16
|
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-private.h" 00035 #include "dbus-marshal-header.h" 00036 #ifdef DBUS_BUILD_TESTS 00037 #include "dbus-server-debug-pipe.h" 00038 #endif 00039 00061 static void 00062 live_messages_notify (DBusCounter *counter, 00063 void *user_data) 00064 { 00065 DBusTransport *transport = user_data; 00066 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 (* transport->vtable->live_messages_changed) (transport); 00081 00082 _dbus_transport_unref (transport); 00083 } 00084 00098 dbus_bool_t 00099 _dbus_transport_init_base (DBusTransport *transport, 00100 const DBusTransportVTable *vtable, 00101 const DBusString *server_guid, 00102 const DBusString *address) 00103 { 00104 DBusMessageLoader *loader; 00105 DBusAuth *auth; 00106 DBusCounter *counter; 00107 char *address_copy; 00108 DBusCredentials *creds; 00109 00110 loader = _dbus_message_loader_new (); 00111 if (loader == NULL) 00112 return FALSE; 00113 00114 if (server_guid) 00115 auth = _dbus_auth_server_new (server_guid); 00116 else 00117 auth = _dbus_auth_client_new (); 00118 if (auth == NULL) 00119 { 00120 _dbus_message_loader_unref (loader); 00121 return FALSE; 00122 } 00123 00124 counter = _dbus_counter_new (); 00125 if (counter == NULL) 00126 { 00127 _dbus_auth_unref (auth); 00128 _dbus_message_loader_unref (loader); 00129 return FALSE; 00130 } 00131 00132 creds = _dbus_credentials_new (); 00133 if (creds == NULL) 00134 { 00135 _dbus_counter_unref (counter); 00136 _dbus_auth_unref (auth); 00137 _dbus_message_loader_unref (loader); 00138 return FALSE; 00139 } 00140 00141 if (server_guid) 00142 { 00143 _dbus_assert (address == NULL); 00144 address_copy = NULL; 00145 } 00146 else 00147 { 00148 _dbus_assert (address != NULL); 00149 00150 if (!_dbus_string_copy_data (address, &address_copy)) 00151 { 00152 _dbus_credentials_unref (creds); 00153 _dbus_counter_unref (counter); 00154 _dbus_auth_unref (auth); 00155 _dbus_message_loader_unref (loader); 00156 return FALSE; 00157 } 00158 } 00159 00160 transport->refcount = 1; 00161 transport->vtable = vtable; 00162 transport->loader = loader; 00163 transport->auth = auth; 00164 transport->live_messages = counter; 00165 transport->authenticated = FALSE; 00166 transport->disconnected = FALSE; 00167 transport->is_server = (server_guid != NULL); 00168 transport->send_credentials_pending = !transport->is_server; 00169 transport->receive_credentials_pending = transport->is_server; 00170 transport->address = address_copy; 00171 00172 transport->unix_user_function = NULL; 00173 transport->unix_user_data = NULL; 00174 transport->free_unix_user_data = NULL; 00175 00176 transport->windows_user_function = NULL; 00177 transport->windows_user_data = NULL; 00178 transport->free_windows_user_data = NULL; 00179 00180 transport->expected_guid = NULL; 00181 00182 /* Try to default to something that won't totally hose the system, 00183 * but doesn't impose too much of a limitation. 00184 */ 00185 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 00186 00187 /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live 00188 should be more than enough */ 00189 transport->max_live_messages_unix_fds = 4096; 00190 00191 /* credentials read from socket if any */ 00192 transport->credentials = creds; 00193 00194 _dbus_counter_set_notify (transport->live_messages, 00195 transport->max_live_messages_size, 00196 transport->max_live_messages_unix_fds, 00197 live_messages_notify, 00198 transport); 00199 00200 if (transport->address) 00201 _dbus_verbose ("Initialized transport on address %s\n", transport->address); 00202 00203 return TRUE; 00204 } 00205 00212 void 00213 _dbus_transport_finalize_base (DBusTransport *transport) 00214 { 00215 if (!transport->disconnected) 00216 _dbus_transport_disconnect (transport); 00217 00218 if (transport->free_unix_user_data != NULL) 00219 (* transport->free_unix_user_data) (transport->unix_user_data); 00220 00221 if (transport->free_windows_user_data != NULL) 00222 (* transport->free_windows_user_data) (transport->windows_user_data); 00223 00224 _dbus_message_loader_unref (transport->loader); 00225 _dbus_auth_unref (transport->auth); 00226 _dbus_counter_set_notify (transport->live_messages, 00227 0, 0, NULL, NULL); 00228 _dbus_counter_unref (transport->live_messages); 00229 dbus_free (transport->address); 00230 dbus_free (transport->expected_guid); 00231 if (transport->credentials) 00232 _dbus_credentials_unref (transport->credentials); 00233 } 00234 00235 00245 static DBusTransport* 00246 check_address (const char *address, DBusError *error) 00247 { 00248 DBusAddressEntry **entries; 00249 DBusTransport *transport = NULL; 00250 int len, i; 00251 00252 _dbus_assert (address != NULL); 00253 _dbus_assert (*address != '\0'); 00254 00255 if (!dbus_parse_address (address, &entries, &len, error)) 00256 return NULL; /* not a valid address */ 00257 00258 for (i = 0; i < len; i++) 00259 { 00260 transport = _dbus_transport_open (entries[i], error); 00261 if (transport != NULL) 00262 break; 00263 } 00264 00265 dbus_address_entries_free (entries); 00266 return transport; 00267 } 00268 00276 static DBusTransport* 00277 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error) 00278 { 00279 DBusString address; 00280 DBusTransport *result = NULL; 00281 00282 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00283 00284 if (!_dbus_string_init (&address)) 00285 { 00286 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00287 return NULL; 00288 } 00289 00290 if (!_dbus_get_autolaunch_address (scope, &address, error)) 00291 { 00292 _DBUS_ASSERT_ERROR_IS_SET (error); 00293 goto out; 00294 } 00295 00296 result = check_address (_dbus_string_get_const_data (&address), error); 00297 if (result == NULL) 00298 _DBUS_ASSERT_ERROR_IS_SET (error); 00299 else 00300 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00301 00302 out: 00303 _dbus_string_free (&address); 00304 return result; 00305 } 00306 00307 static DBusTransportOpenResult 00308 _dbus_transport_open_autolaunch (DBusAddressEntry *entry, 00309 DBusTransport **transport_p, 00310 DBusError *error) 00311 { 00312 const char *method; 00313 00314 method = dbus_address_entry_get_method (entry); 00315 _dbus_assert (method != NULL); 00316 00317 if (strcmp (method, "autolaunch") == 0) 00318 { 00319 const char *scope = dbus_address_entry_get_value (entry, "scope"); 00320 00321 *transport_p = _dbus_transport_new_for_autolaunch (scope, error); 00322 00323 if (*transport_p == NULL) 00324 { 00325 _DBUS_ASSERT_ERROR_IS_SET (error); 00326 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00327 } 00328 else 00329 { 00330 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00331 return DBUS_TRANSPORT_OPEN_OK; 00332 } 00333 } 00334 else 00335 { 00336 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00337 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00338 } 00339 } 00340 00341 static const struct { 00342 DBusTransportOpenResult (* func) (DBusAddressEntry *entry, 00343 DBusTransport **transport_p, 00344 DBusError *error); 00345 } open_funcs[] = { 00346 { _dbus_transport_open_socket }, 00347 { _dbus_transport_open_platform_specific }, 00348 { _dbus_transport_open_autolaunch } 00349 #ifdef DBUS_BUILD_TESTS 00350 , { _dbus_transport_open_debug_pipe } 00351 #endif 00352 }; 00353 00362 DBusTransport* 00363 _dbus_transport_open (DBusAddressEntry *entry, 00364 DBusError *error) 00365 { 00366 DBusTransport *transport; 00367 const char *expected_guid_orig; 00368 char *expected_guid; 00369 int i; 00370 DBusError tmp_error = DBUS_ERROR_INIT; 00371 00372 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00373 00374 transport = NULL; 00375 expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); 00376 expected_guid = _dbus_strdup (expected_guid_orig); 00377 00378 if (expected_guid_orig != NULL && expected_guid == NULL) 00379 { 00380 _DBUS_SET_OOM (error); 00381 return NULL; 00382 } 00383 00384 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i) 00385 { 00386 DBusTransportOpenResult result; 00387 00388 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00389 result = (* open_funcs[i].func) (entry, &transport, &tmp_error); 00390 00391 switch (result) 00392 { 00393 case DBUS_TRANSPORT_OPEN_OK: 00394 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00395 goto out; 00396 break; 00397 case DBUS_TRANSPORT_OPEN_NOT_HANDLED: 00398 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00399 /* keep going through the loop of open funcs */ 00400 break; 00401 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS: 00402 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00403 goto out; 00404 break; 00405 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT: 00406 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00407 goto out; 00408 break; 00409 } 00410 } 00411 00412 out: 00413 00414 if (transport == NULL) 00415 { 00416 if (!dbus_error_is_set (&tmp_error)) 00417 _dbus_set_bad_address (&tmp_error, 00418 NULL, NULL, 00419 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")"); 00420 00421 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00422 dbus_move_error(&tmp_error, error); 00423 dbus_free (expected_guid); 00424 } 00425 else 00426 { 00427 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00428 00429 /* In the case of autostart the initial guid is NULL 00430 * and the autostart transport recursively calls 00431 * _dbus_open_transport wich returns a transport 00432 * with a guid. That guid is the definitive one. 00433 * 00434 * FIXME: if more transports are added they may have 00435 * an effect on the expected_guid semantics (i.e. 00436 * expected_guid and transport->expected_guid may 00437 * both have values). This is very unlikely though 00438 * we should either throw asserts here for those 00439 * corner cases or refactor the code so it is 00440 * clearer on what is expected and what is not 00441 */ 00442 if(expected_guid) 00443 transport->expected_guid = expected_guid; 00444 } 00445 00446 return transport; 00447 } 00448 00455 DBusTransport * 00456 _dbus_transport_ref (DBusTransport *transport) 00457 { 00458 _dbus_assert (transport->refcount > 0); 00459 00460 transport->refcount += 1; 00461 00462 return transport; 00463 } 00464 00472 void 00473 _dbus_transport_unref (DBusTransport *transport) 00474 { 00475 _dbus_assert (transport != NULL); 00476 _dbus_assert (transport->refcount > 0); 00477 00478 transport->refcount -= 1; 00479 if (transport->refcount == 0) 00480 { 00481 _dbus_verbose ("finalizing\n"); 00482 00483 _dbus_assert (transport->vtable->finalize != NULL); 00484 00485 (* transport->vtable->finalize) (transport); 00486 } 00487 } 00488 00497 void 00498 _dbus_transport_disconnect (DBusTransport *transport) 00499 { 00500 _dbus_verbose ("start\n"); 00501 00502 _dbus_assert (transport->vtable->disconnect != NULL); 00503 00504 if (transport->disconnected) 00505 return; 00506 00507 (* transport->vtable->disconnect) (transport); 00508 00509 transport->disconnected = TRUE; 00510 00511 _dbus_verbose ("end\n"); 00512 } 00513 00522 dbus_bool_t 00523 _dbus_transport_get_is_connected (DBusTransport *transport) 00524 { 00525 return !transport->disconnected; 00526 } 00527 00528 static dbus_bool_t 00529 auth_via_unix_user_function (DBusTransport *transport) 00530 { 00531 DBusCredentials *auth_identity; 00532 dbus_bool_t allow; 00533 DBusConnection *connection; 00534 DBusAllowUnixUserFunction unix_user_function; 00535 void *unix_user_data; 00536 dbus_uid_t uid; 00537 00538 /* Dropping the lock here probably isn't that safe. */ 00539 00540 auth_identity = _dbus_auth_get_identity (transport->auth); 00541 _dbus_assert (auth_identity != NULL); 00542 00543 connection = transport->connection; 00544 unix_user_function = transport->unix_user_function; 00545 unix_user_data = transport->unix_user_data; 00546 uid = _dbus_credentials_get_unix_uid (auth_identity); 00547 00548 _dbus_verbose ("unlock\n"); 00549 _dbus_connection_unlock (connection); 00550 00551 allow = (* unix_user_function) (connection, 00552 uid, 00553 unix_user_data); 00554 00555 _dbus_verbose ("lock post unix user function\n"); 00556 _dbus_connection_lock (connection); 00557 00558 if (allow) 00559 { 00560 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); 00561 } 00562 else 00563 { 00564 _dbus_verbose ("Client UID "DBUS_UID_FORMAT 00565 " was rejected, disconnecting\n", 00566 _dbus_credentials_get_unix_uid (auth_identity)); 00567 _dbus_transport_disconnect (transport); 00568 } 00569 00570 return allow; 00571 } 00572 00573 static dbus_bool_t 00574 auth_via_windows_user_function (DBusTransport *transport) 00575 { 00576 DBusCredentials *auth_identity; 00577 dbus_bool_t allow; 00578 DBusConnection *connection; 00579 DBusAllowWindowsUserFunction windows_user_function; 00580 void *windows_user_data; 00581 char *windows_sid; 00582 00583 /* Dropping the lock here probably isn't that safe. */ 00584 00585 auth_identity = _dbus_auth_get_identity (transport->auth); 00586 _dbus_assert (auth_identity != NULL); 00587 00588 connection = transport->connection; 00589 windows_user_function = transport->windows_user_function; 00590 windows_user_data = transport->unix_user_data; 00591 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 00592 00593 if (windows_sid == NULL) 00594 { 00595 /* OOM */ 00596 return FALSE; 00597 } 00598 00599 _dbus_verbose ("unlock\n"); 00600 _dbus_connection_unlock (connection); 00601 00602 allow = (* windows_user_function) (connection, 00603 windows_sid, 00604 windows_user_data); 00605 00606 _dbus_verbose ("lock post windows user function\n"); 00607 _dbus_connection_lock (connection); 00608 00609 if (allow) 00610 { 00611 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); 00612 } 00613 else 00614 { 00615 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", 00616 _dbus_credentials_get_windows_sid (auth_identity)); 00617 _dbus_transport_disconnect (transport); 00618 } 00619 00620 return allow; 00621 } 00622 00623 static dbus_bool_t 00624 auth_via_default_rules (DBusTransport *transport) 00625 { 00626 DBusCredentials *auth_identity; 00627 DBusCredentials *our_identity; 00628 dbus_bool_t allow; 00629 00630 auth_identity = _dbus_auth_get_identity (transport->auth); 00631 _dbus_assert (auth_identity != NULL); 00632 00633 /* By default, connection is allowed if the client is 1) root or 2) 00634 * has the same UID as us or 3) anonymous is allowed. 00635 */ 00636 00637 our_identity = _dbus_credentials_new_from_current_process (); 00638 if (our_identity == NULL) 00639 { 00640 /* OOM */ 00641 return FALSE; 00642 } 00643 00644 if (transport->allow_anonymous || 00645 _dbus_credentials_get_unix_uid (auth_identity) == 0 || 00646 _dbus_credentials_same_user (our_identity, 00647 auth_identity)) 00648 { 00649 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00650 _dbus_verbose ("Client authorized as SID '%s'" 00651 "matching our SID '%s'\n", 00652 _dbus_credentials_get_windows_sid(auth_identity), 00653 _dbus_credentials_get_windows_sid(our_identity)); 00654 else 00655 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00656 " matching our UID "DBUS_UID_FORMAT"\n", 00657 _dbus_credentials_get_unix_uid(auth_identity), 00658 _dbus_credentials_get_unix_uid(our_identity)); 00659 /* We have authenticated! */ 00660 allow = TRUE; 00661 } 00662 else 00663 { 00664 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00665 _dbus_verbose ("Client authorized as SID '%s'" 00666 " but our SID is '%s', disconnecting\n", 00667 (_dbus_credentials_get_windows_sid(auth_identity) ? 00668 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"), 00669 (_dbus_credentials_get_windows_sid(our_identity) ? 00670 _dbus_credentials_get_windows_sid(our_identity) : "<null>")); 00671 else 00672 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00673 " but our UID is "DBUS_UID_FORMAT", disconnecting\n", 00674 _dbus_credentials_get_unix_uid(auth_identity), 00675 _dbus_credentials_get_unix_uid(our_identity)); 00676 _dbus_transport_disconnect (transport); 00677 allow = FALSE; 00678 } 00679 00680 _dbus_credentials_unref (our_identity); 00681 00682 return allow; 00683 } 00684 00685 00696 dbus_bool_t 00697 _dbus_transport_get_is_authenticated (DBusTransport *transport) 00698 { 00699 if (transport->authenticated) 00700 return TRUE; 00701 else 00702 { 00703 dbus_bool_t maybe_authenticated; 00704 00705 if (transport->disconnected) 00706 return FALSE; 00707 00708 /* paranoia ref since we call user callbacks sometimes */ 00709 _dbus_connection_ref_unlocked (transport->connection); 00710 00711 maybe_authenticated = 00712 (!(transport->send_credentials_pending || 00713 transport->receive_credentials_pending)); 00714 00715 if (maybe_authenticated) 00716 { 00717 switch (_dbus_auth_do_work (transport->auth)) 00718 { 00719 case DBUS_AUTH_STATE_AUTHENTICATED: 00720 /* leave as maybe_authenticated */ 00721 break; 00722 default: 00723 maybe_authenticated = FALSE; 00724 } 00725 } 00726 00727 /* If we're the client, verify the GUID 00728 */ 00729 if (maybe_authenticated && !transport->is_server) 00730 { 00731 const char *server_guid; 00732 00733 server_guid = _dbus_auth_get_guid_from_server (transport->auth); 00734 _dbus_assert (server_guid != NULL); 00735 00736 if (transport->expected_guid && 00737 strcmp (transport->expected_guid, server_guid) != 0) 00738 { 00739 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", 00740 transport->expected_guid, server_guid); 00741 _dbus_transport_disconnect (transport); 00742 _dbus_connection_unref_unlocked (transport->connection); 00743 return FALSE; 00744 } 00745 } 00746 00747 /* If we're the server, see if we want to allow this identity to proceed. 00748 */ 00749 if (maybe_authenticated && transport->is_server) 00750 { 00751 dbus_bool_t allow; 00752 DBusCredentials *auth_identity; 00753 00754 auth_identity = _dbus_auth_get_identity (transport->auth); 00755 _dbus_assert (auth_identity != NULL); 00756 00757 /* If we have an auth'd user and a user function, delegate 00758 * deciding whether auth credentials are good enough to the 00759 * app; otherwise, use our default decision process. 00760 */ 00761 if (transport->unix_user_function != NULL && 00762 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) 00763 { 00764 allow = auth_via_unix_user_function (transport); 00765 } 00766 else if (transport->windows_user_function != NULL && 00767 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) 00768 { 00769 allow = auth_via_windows_user_function (transport); 00770 } 00771 else 00772 { 00773 allow = auth_via_default_rules (transport); 00774 } 00775 00776 if (!allow) 00777 maybe_authenticated = FALSE; 00778 } 00779 00780 transport->authenticated = maybe_authenticated; 00781 00782 _dbus_connection_unref_unlocked (transport->connection); 00783 return maybe_authenticated; 00784 } 00785 } 00786 00793 dbus_bool_t 00794 _dbus_transport_get_is_anonymous (DBusTransport *transport) 00795 { 00796 DBusCredentials *auth_identity; 00797 00798 if (!transport->authenticated) 00799 return TRUE; 00800 00801 auth_identity = _dbus_auth_get_identity (transport->auth); 00802 00803 if (_dbus_credentials_are_anonymous (auth_identity)) 00804 return TRUE; 00805 else 00806 return FALSE; 00807 } 00808 00815 dbus_bool_t 00816 _dbus_transport_can_pass_unix_fd(DBusTransport *transport) 00817 { 00818 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport); 00819 } 00820 00828 const char* 00829 _dbus_transport_get_address (DBusTransport *transport) 00830 { 00831 return transport->address; 00832 } 00833 00841 const char* 00842 _dbus_transport_get_server_id (DBusTransport *transport) 00843 { 00844 if (transport->is_server) 00845 return NULL; 00846 else if (transport->authenticated) 00847 return _dbus_auth_get_guid_from_server (transport->auth); 00848 else 00849 return transport->expected_guid; 00850 } 00851 00861 dbus_bool_t 00862 _dbus_transport_handle_watch (DBusTransport *transport, 00863 DBusWatch *watch, 00864 unsigned int condition) 00865 { 00866 dbus_bool_t retval; 00867 00868 _dbus_assert (transport->vtable->handle_watch != NULL); 00869 00870 if (transport->disconnected) 00871 return TRUE; 00872 00873 if (dbus_watch_get_socket (watch) < 0) 00874 { 00875 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n"); 00876 return TRUE; 00877 } 00878 00879 _dbus_watch_sanitize_condition (watch, &condition); 00880 00881 _dbus_transport_ref (transport); 00882 _dbus_watch_ref (watch); 00883 retval = (* transport->vtable->handle_watch) (transport, watch, condition); 00884 _dbus_watch_unref (watch); 00885 _dbus_transport_unref (transport); 00886 00887 return retval; 00888 } 00889 00899 dbus_bool_t 00900 _dbus_transport_set_connection (DBusTransport *transport, 00901 DBusConnection *connection) 00902 { 00903 _dbus_assert (transport->vtable->connection_set != NULL); 00904 _dbus_assert (transport->connection == NULL); 00905 00906 transport->connection = connection; 00907 00908 _dbus_transport_ref (transport); 00909 if (!(* transport->vtable->connection_set) (transport)) 00910 transport->connection = NULL; 00911 _dbus_transport_unref (transport); 00912 00913 return transport->connection != NULL; 00914 } 00915 00923 dbus_bool_t 00924 _dbus_transport_get_socket_fd (DBusTransport *transport, 00925 int *fd_p) 00926 { 00927 dbus_bool_t retval; 00928 00929 if (transport->vtable->get_socket_fd == NULL) 00930 return FALSE; 00931 00932 if (transport->disconnected) 00933 return FALSE; 00934 00935 _dbus_transport_ref (transport); 00936 00937 retval = (* transport->vtable->get_socket_fd) (transport, 00938 fd_p); 00939 00940 _dbus_transport_unref (transport); 00941 00942 return retval; 00943 } 00944 00956 void 00957 _dbus_transport_do_iteration (DBusTransport *transport, 00958 unsigned int flags, 00959 int timeout_milliseconds) 00960 { 00961 _dbus_assert (transport->vtable->do_iteration != NULL); 00962 00963 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n", 00964 flags, timeout_milliseconds, !transport->disconnected); 00965 00966 if ((flags & (DBUS_ITERATION_DO_WRITING | 00967 DBUS_ITERATION_DO_READING)) == 0) 00968 return; /* Nothing to do */ 00969 00970 if (transport->disconnected) 00971 return; 00972 00973 _dbus_transport_ref (transport); 00974 (* transport->vtable->do_iteration) (transport, flags, 00975 timeout_milliseconds); 00976 _dbus_transport_unref (transport); 00977 00978 _dbus_verbose ("end\n"); 00979 } 00980 00981 static dbus_bool_t 00982 recover_unused_bytes (DBusTransport *transport) 00983 { 00984 if (_dbus_auth_needs_decoding (transport->auth)) 00985 { 00986 DBusString plaintext; 00987 const DBusString *encoded; 00988 DBusString *buffer; 00989 int orig_len; 00990 00991 if (!_dbus_string_init (&plaintext)) 00992 goto nomem; 00993 00994 _dbus_auth_get_unused_bytes (transport->auth, 00995 &encoded); 00996 00997 if (!_dbus_auth_decode_data (transport->auth, 00998 encoded, &plaintext)) 00999 { 01000 _dbus_string_free (&plaintext); 01001 goto nomem; 01002 } 01003 01004 _dbus_message_loader_get_buffer (transport->loader, 01005 &buffer); 01006 01007 orig_len = _dbus_string_get_length (buffer); 01008 01009 if (!_dbus_string_move (&plaintext, 0, buffer, 01010 orig_len)) 01011 { 01012 _dbus_string_free (&plaintext); 01013 goto nomem; 01014 } 01015 01016 _dbus_verbose (" %d unused bytes sent to message loader\n", 01017 _dbus_string_get_length (buffer) - 01018 orig_len); 01019 01020 _dbus_message_loader_return_buffer (transport->loader, 01021 buffer, 01022 _dbus_string_get_length (buffer) - 01023 orig_len); 01024 01025 _dbus_auth_delete_unused_bytes (transport->auth); 01026 01027 _dbus_string_free (&plaintext); 01028 } 01029 else 01030 { 01031 const DBusString *bytes; 01032 DBusString *buffer; 01033 int orig_len; 01034 dbus_bool_t succeeded; 01035 01036 _dbus_message_loader_get_buffer (transport->loader, 01037 &buffer); 01038 01039 orig_len = _dbus_string_get_length (buffer); 01040 01041 _dbus_auth_get_unused_bytes (transport->auth, 01042 &bytes); 01043 01044 succeeded = TRUE; 01045 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer))) 01046 succeeded = FALSE; 01047 01048 _dbus_verbose (" %d unused bytes sent to message loader\n", 01049 _dbus_string_get_length (buffer) - 01050 orig_len); 01051 01052 _dbus_message_loader_return_buffer (transport->loader, 01053 buffer, 01054 _dbus_string_get_length (buffer) - 01055 orig_len); 01056 01057 if (succeeded) 01058 _dbus_auth_delete_unused_bytes (transport->auth); 01059 else 01060 goto nomem; 01061 } 01062 01063 return TRUE; 01064 01065 nomem: 01066 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); 01067 return FALSE; 01068 } 01069 01077 DBusDispatchStatus 01078 _dbus_transport_get_dispatch_status (DBusTransport *transport) 01079 { 01080 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size || 01081 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) 01082 return DBUS_DISPATCH_COMPLETE; /* complete for now */ 01083 01084 if (!_dbus_transport_get_is_authenticated (transport)) 01085 { 01086 if (_dbus_auth_do_work (transport->auth) == 01087 DBUS_AUTH_STATE_WAITING_FOR_MEMORY) 01088 return DBUS_DISPATCH_NEED_MEMORY; 01089 else if (!_dbus_transport_get_is_authenticated (transport)) 01090 return DBUS_DISPATCH_COMPLETE; 01091 } 01092 01093 if (!transport->unused_bytes_recovered && 01094 !recover_unused_bytes (transport)) 01095 return DBUS_DISPATCH_NEED_MEMORY; 01096 01097 transport->unused_bytes_recovered = TRUE; 01098 01099 if (!_dbus_message_loader_queue_messages (transport->loader)) 01100 return DBUS_DISPATCH_NEED_MEMORY; 01101 01102 if (_dbus_message_loader_peek_message (transport->loader) != NULL) 01103 return DBUS_DISPATCH_DATA_REMAINS; 01104 else 01105 return DBUS_DISPATCH_COMPLETE; 01106 } 01107 01116 dbus_bool_t 01117 _dbus_transport_queue_messages (DBusTransport *transport) 01118 { 01119 DBusDispatchStatus status; 01120 01121 #if 0 01122 _dbus_verbose ("_dbus_transport_queue_messages()\n"); 01123 #endif 01124 01125 /* Queue any messages */ 01126 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS) 01127 { 01128 DBusMessage *message; 01129 DBusList *link; 01130 01131 link = _dbus_message_loader_pop_message_link (transport->loader); 01132 _dbus_assert (link != NULL); 01133 01134 message = link->data; 01135 01136 _dbus_verbose ("queueing received message %p\n", message); 01137 01138 if (!_dbus_message_add_counter (message, transport->live_messages)) 01139 { 01140 _dbus_message_loader_putback_message_link (transport->loader, 01141 link); 01142 status = DBUS_DISPATCH_NEED_MEMORY; 01143 break; 01144 } 01145 else 01146 { 01147 /* pass ownership of link and message ref to connection */ 01148 _dbus_connection_queue_received_message_link (transport->connection, 01149 link); 01150 } 01151 } 01152 01153 if (_dbus_message_loader_get_is_corrupted (transport->loader)) 01154 { 01155 _dbus_verbose ("Corrupted message stream, disconnecting\n"); 01156 _dbus_transport_disconnect (transport); 01157 } 01158 01159 return status != DBUS_DISPATCH_NEED_MEMORY; 01160 } 01161 01168 void 01169 _dbus_transport_set_max_message_size (DBusTransport *transport, 01170 long size) 01171 { 01172 _dbus_message_loader_set_max_message_size (transport->loader, size); 01173 } 01174 01181 void 01182 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport, 01183 long n) 01184 { 01185 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n); 01186 } 01187 01194 long 01195 _dbus_transport_get_max_message_size (DBusTransport *transport) 01196 { 01197 return _dbus_message_loader_get_max_message_size (transport->loader); 01198 } 01199 01206 long 01207 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport) 01208 { 01209 return _dbus_message_loader_get_max_message_unix_fds (transport->loader); 01210 } 01211 01218 void 01219 _dbus_transport_set_max_received_size (DBusTransport *transport, 01220 long size) 01221 { 01222 transport->max_live_messages_size = size; 01223 _dbus_counter_set_notify (transport->live_messages, 01224 transport->max_live_messages_size, 01225 transport->max_live_messages_unix_fds, 01226 live_messages_notify, 01227 transport); 01228 } 01229 01236 void 01237 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport, 01238 long n) 01239 { 01240 transport->max_live_messages_unix_fds = n; 01241 _dbus_counter_set_notify (transport->live_messages, 01242 transport->max_live_messages_size, 01243 transport->max_live_messages_unix_fds, 01244 live_messages_notify, 01245 transport); 01246 } 01247 01254 long 01255 _dbus_transport_get_max_received_size (DBusTransport *transport) 01256 { 01257 return transport->max_live_messages_size; 01258 } 01259 01266 long 01267 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport) 01268 { 01269 return transport->max_live_messages_unix_fds; 01270 } 01271 01279 dbus_bool_t 01280 _dbus_transport_get_unix_user (DBusTransport *transport, 01281 unsigned long *uid) 01282 { 01283 DBusCredentials *auth_identity; 01284 01285 *uid = _DBUS_INT32_MAX; /* better than some root or system user in 01286 * case of bugs in the caller. Caller should 01287 * never use this value on purpose, however. 01288 */ 01289 01290 if (!transport->authenticated) 01291 return FALSE; 01292 01293 auth_identity = _dbus_auth_get_identity (transport->auth); 01294 01295 if (_dbus_credentials_include (auth_identity, 01296 DBUS_CREDENTIAL_UNIX_USER_ID)) 01297 { 01298 *uid = _dbus_credentials_get_unix_uid (auth_identity); 01299 return TRUE; 01300 } 01301 else 01302 return FALSE; 01303 } 01304 01312 dbus_bool_t 01313 _dbus_transport_get_unix_process_id (DBusTransport *transport, 01314 unsigned long *pid) 01315 { 01316 DBusCredentials *auth_identity; 01317 01318 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose, 01319 * but we set it to a safe number, INT_MAX, 01320 * just to root out possible bugs in bad callers. 01321 */ 01322 01323 if (!transport->authenticated) 01324 return FALSE; 01325 01326 auth_identity = _dbus_auth_get_identity (transport->auth); 01327 01328 if (_dbus_credentials_include (auth_identity, 01329 DBUS_CREDENTIAL_UNIX_PROCESS_ID)) 01330 { 01331 *pid = _dbus_credentials_get_unix_pid (auth_identity); 01332 return TRUE; 01333 } 01334 else 01335 return FALSE; 01336 } 01337 01346 dbus_bool_t 01347 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, 01348 void **data, 01349 int *data_size) 01350 { 01351 DBusCredentials *auth_identity; 01352 01353 *data = NULL; 01354 *data_size = 0; 01355 01356 if (!transport->authenticated) 01357 return FALSE; 01358 01359 auth_identity = _dbus_auth_get_identity (transport->auth); 01360 01361 if (_dbus_credentials_include (auth_identity, 01362 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) 01363 { 01364 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); 01365 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); 01366 return TRUE; 01367 } 01368 else 01369 return FALSE; 01370 } 01371 01382 void 01383 _dbus_transport_set_unix_user_function (DBusTransport *transport, 01384 DBusAllowUnixUserFunction function, 01385 void *data, 01386 DBusFreeFunction free_data_function, 01387 void **old_data, 01388 DBusFreeFunction *old_free_data_function) 01389 { 01390 *old_data = transport->unix_user_data; 01391 *old_free_data_function = transport->free_unix_user_data; 01392 01393 transport->unix_user_function = function; 01394 transport->unix_user_data = data; 01395 transport->free_unix_user_data = free_data_function; 01396 } 01397 01405 dbus_bool_t 01406 _dbus_transport_get_windows_user (DBusTransport *transport, 01407 char **windows_sid_p) 01408 { 01409 DBusCredentials *auth_identity; 01410 01411 *windows_sid_p = NULL; 01412 01413 if (!transport->authenticated) 01414 return FALSE; 01415 01416 auth_identity = _dbus_auth_get_identity (transport->auth); 01417 01418 if (_dbus_credentials_include (auth_identity, 01419 DBUS_CREDENTIAL_WINDOWS_SID)) 01420 { 01421 /* If no memory, we are supposed to return TRUE and set NULL */ 01422 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 01423 01424 return TRUE; 01425 } 01426 else 01427 return FALSE; 01428 } 01429 01441 void 01442 _dbus_transport_set_windows_user_function (DBusTransport *transport, 01443 DBusAllowWindowsUserFunction function, 01444 void *data, 01445 DBusFreeFunction free_data_function, 01446 void **old_data, 01447 DBusFreeFunction *old_free_data_function) 01448 { 01449 *old_data = transport->windows_user_data; 01450 *old_free_data_function = transport->free_windows_user_data; 01451 01452 transport->windows_user_function = function; 01453 transport->windows_user_data = data; 01454 transport->free_windows_user_data = free_data_function; 01455 } 01456 01465 dbus_bool_t 01466 _dbus_transport_set_auth_mechanisms (DBusTransport *transport, 01467 const char **mechanisms) 01468 { 01469 return _dbus_auth_set_mechanisms (transport->auth, mechanisms); 01470 } 01471 01478 void 01479 _dbus_transport_set_allow_anonymous (DBusTransport *transport, 01480 dbus_bool_t value) 01481 { 01482 transport->allow_anonymous = value != FALSE; 01483 } 01484