D-Bus 1.2.24
|
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 "dbus-transport-protected.h" 00025 #include "dbus-transport-unix.h" 00026 #include "dbus-transport-socket.h" 00027 #include "dbus-connection-internal.h" 00028 #include "dbus-watch.h" 00029 #include "dbus-auth.h" 00030 #include "dbus-address.h" 00031 #include "dbus-credentials.h" 00032 #ifdef DBUS_BUILD_TESTS 00033 #include "dbus-server-debug-pipe.h" 00034 #endif 00035 00057 static void 00058 live_messages_size_notify (DBusCounter *counter, 00059 void *user_data) 00060 { 00061 DBusTransport *transport = user_data; 00062 00063 _dbus_transport_ref (transport); 00064 00065 #if 0 00066 _dbus_verbose ("Counter value is now %d\n", 00067 (int) _dbus_counter_get_value (counter)); 00068 #endif 00069 00070 /* disable or re-enable the read watch for the transport if 00071 * required. 00072 */ 00073 if (transport->vtable->live_messages_changed) 00074 (* transport->vtable->live_messages_changed) (transport); 00075 00076 _dbus_transport_unref (transport); 00077 } 00078 00092 dbus_bool_t 00093 _dbus_transport_init_base (DBusTransport *transport, 00094 const DBusTransportVTable *vtable, 00095 const DBusString *server_guid, 00096 const DBusString *address) 00097 { 00098 DBusMessageLoader *loader; 00099 DBusAuth *auth; 00100 DBusCounter *counter; 00101 char *address_copy; 00102 DBusCredentials *creds; 00103 00104 loader = _dbus_message_loader_new (); 00105 if (loader == NULL) 00106 return FALSE; 00107 00108 if (server_guid) 00109 auth = _dbus_auth_server_new (server_guid); 00110 else 00111 auth = _dbus_auth_client_new (); 00112 if (auth == NULL) 00113 { 00114 _dbus_message_loader_unref (loader); 00115 return FALSE; 00116 } 00117 00118 counter = _dbus_counter_new (); 00119 if (counter == NULL) 00120 { 00121 _dbus_auth_unref (auth); 00122 _dbus_message_loader_unref (loader); 00123 return FALSE; 00124 } 00125 00126 creds = _dbus_credentials_new (); 00127 if (creds == NULL) 00128 { 00129 _dbus_counter_unref (counter); 00130 _dbus_auth_unref (auth); 00131 _dbus_message_loader_unref (loader); 00132 return FALSE; 00133 } 00134 00135 if (server_guid) 00136 { 00137 _dbus_assert (address == NULL); 00138 address_copy = NULL; 00139 } 00140 else 00141 { 00142 _dbus_assert (address != NULL); 00143 00144 if (!_dbus_string_copy_data (address, &address_copy)) 00145 { 00146 _dbus_credentials_unref (creds); 00147 _dbus_counter_unref (counter); 00148 _dbus_auth_unref (auth); 00149 _dbus_message_loader_unref (loader); 00150 return FALSE; 00151 } 00152 } 00153 00154 transport->refcount = 1; 00155 transport->vtable = vtable; 00156 transport->loader = loader; 00157 transport->auth = auth; 00158 transport->live_messages_size = counter; 00159 transport->authenticated = FALSE; 00160 transport->disconnected = FALSE; 00161 transport->is_server = (server_guid != NULL); 00162 transport->send_credentials_pending = !transport->is_server; 00163 transport->receive_credentials_pending = transport->is_server; 00164 transport->address = address_copy; 00165 00166 transport->unix_user_function = NULL; 00167 transport->unix_user_data = NULL; 00168 transport->free_unix_user_data = NULL; 00169 00170 transport->windows_user_function = NULL; 00171 transport->windows_user_data = NULL; 00172 transport->free_windows_user_data = NULL; 00173 00174 transport->expected_guid = NULL; 00175 00176 /* Try to default to something that won't totally hose the system, 00177 * but doesn't impose too much of a limitation. 00178 */ 00179 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 00180 00181 /* credentials read from socket if any */ 00182 transport->credentials = creds; 00183 00184 _dbus_counter_set_notify (transport->live_messages_size, 00185 transport->max_live_messages_size, 00186 live_messages_size_notify, 00187 transport); 00188 00189 if (transport->address) 00190 _dbus_verbose ("Initialized transport on address %s\n", transport->address); 00191 00192 return TRUE; 00193 } 00194 00201 void 00202 _dbus_transport_finalize_base (DBusTransport *transport) 00203 { 00204 if (!transport->disconnected) 00205 _dbus_transport_disconnect (transport); 00206 00207 if (transport->free_unix_user_data != NULL) 00208 (* transport->free_unix_user_data) (transport->unix_user_data); 00209 00210 if (transport->free_windows_user_data != NULL) 00211 (* transport->free_windows_user_data) (transport->windows_user_data); 00212 00213 _dbus_message_loader_unref (transport->loader); 00214 _dbus_auth_unref (transport->auth); 00215 _dbus_counter_set_notify (transport->live_messages_size, 00216 0, NULL, NULL); 00217 _dbus_counter_unref (transport->live_messages_size); 00218 dbus_free (transport->address); 00219 dbus_free (transport->expected_guid); 00220 if (transport->credentials) 00221 _dbus_credentials_unref (transport->credentials); 00222 } 00223 00224 00234 static DBusTransport* 00235 check_address (const char *address, DBusError *error) 00236 { 00237 DBusAddressEntry **entries; 00238 DBusTransport *transport = NULL; 00239 int len, i; 00240 00241 _dbus_assert (address != NULL); 00242 _dbus_assert (*address != '\0'); 00243 00244 if (!dbus_parse_address (address, &entries, &len, error)) 00245 return NULL; /* not a valid address */ 00246 00247 for (i = 0; i < len; i++) 00248 { 00249 transport = _dbus_transport_open (entries[i], error); 00250 if (transport != NULL) 00251 break; 00252 } 00253 00254 dbus_address_entries_free (entries); 00255 return transport; 00256 } 00257 00265 static DBusTransport* 00266 _dbus_transport_new_for_autolaunch (DBusError *error) 00267 { 00268 DBusString address; 00269 DBusTransport *result = NULL; 00270 00271 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00272 00273 if (!_dbus_string_init (&address)) 00274 { 00275 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00276 return NULL; 00277 } 00278 00279 if (!_dbus_get_autolaunch_address (&address, error)) 00280 { 00281 _DBUS_ASSERT_ERROR_IS_SET (error); 00282 goto out; 00283 } 00284 00285 result = check_address (_dbus_string_get_const_data (&address), error); 00286 if (result == NULL) 00287 _DBUS_ASSERT_ERROR_IS_SET (error); 00288 else 00289 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00290 00291 out: 00292 _dbus_string_free (&address); 00293 return result; 00294 } 00295 00296 static DBusTransportOpenResult 00297 _dbus_transport_open_autolaunch (DBusAddressEntry *entry, 00298 DBusTransport **transport_p, 00299 DBusError *error) 00300 { 00301 const char *method; 00302 00303 method = dbus_address_entry_get_method (entry); 00304 _dbus_assert (method != NULL); 00305 00306 if (strcmp (method, "autolaunch") == 0) 00307 { 00308 *transport_p = _dbus_transport_new_for_autolaunch (error); 00309 00310 if (*transport_p == NULL) 00311 { 00312 _DBUS_ASSERT_ERROR_IS_SET (error); 00313 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00314 } 00315 else 00316 { 00317 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00318 return DBUS_TRANSPORT_OPEN_OK; 00319 } 00320 } 00321 else 00322 { 00323 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00324 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00325 } 00326 } 00327 00328 static const struct { 00329 DBusTransportOpenResult (* func) (DBusAddressEntry *entry, 00330 DBusTransport **transport_p, 00331 DBusError *error); 00332 } open_funcs[] = { 00333 { _dbus_transport_open_socket }, 00334 { _dbus_transport_open_platform_specific }, 00335 { _dbus_transport_open_autolaunch } 00336 #ifdef DBUS_BUILD_TESTS 00337 , { _dbus_transport_open_debug_pipe } 00338 #endif 00339 }; 00340 00349 DBusTransport* 00350 _dbus_transport_open (DBusAddressEntry *entry, 00351 DBusError *error) 00352 { 00353 DBusTransport *transport; 00354 const char *expected_guid_orig; 00355 char *expected_guid; 00356 int i; 00357 DBusError tmp_error = DBUS_ERROR_INIT; 00358 00359 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00360 00361 transport = NULL; 00362 expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); 00363 expected_guid = _dbus_strdup (expected_guid_orig); 00364 00365 if (expected_guid_orig != NULL && expected_guid == NULL) 00366 { 00367 _DBUS_SET_OOM (error); 00368 return NULL; 00369 } 00370 00371 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i) 00372 { 00373 DBusTransportOpenResult result; 00374 00375 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00376 result = (* open_funcs[i].func) (entry, &transport, &tmp_error); 00377 00378 switch (result) 00379 { 00380 case DBUS_TRANSPORT_OPEN_OK: 00381 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00382 goto out; 00383 break; 00384 case DBUS_TRANSPORT_OPEN_NOT_HANDLED: 00385 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00386 /* keep going through the loop of open funcs */ 00387 break; 00388 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS: 00389 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00390 goto out; 00391 break; 00392 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT: 00393 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00394 goto out; 00395 break; 00396 } 00397 } 00398 00399 out: 00400 00401 if (transport == NULL) 00402 { 00403 if (!dbus_error_is_set (&tmp_error)) 00404 _dbus_set_bad_address (&tmp_error, 00405 NULL, NULL, 00406 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")"); 00407 00408 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00409 dbus_move_error(&tmp_error, error); 00410 dbus_free (expected_guid); 00411 } 00412 else 00413 { 00414 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00415 00416 /* In the case of autostart the initial guid is NULL 00417 * and the autostart transport recursively calls 00418 * _dbus_open_transport wich returns a transport 00419 * with a guid. That guid is the definitive one. 00420 * 00421 * FIXME: if more transports are added they may have 00422 * an effect on the expected_guid semantics (i.e. 00423 * expected_guid and transport->expected_guid may 00424 * both have values). This is very unlikely though 00425 * we should either throw asserts here for those 00426 * corner cases or refactor the code so it is 00427 * clearer on what is expected and what is not 00428 */ 00429 if(expected_guid) 00430 transport->expected_guid = expected_guid; 00431 } 00432 00433 return transport; 00434 } 00435 00442 DBusTransport * 00443 _dbus_transport_ref (DBusTransport *transport) 00444 { 00445 _dbus_assert (transport->refcount > 0); 00446 00447 transport->refcount += 1; 00448 00449 return transport; 00450 } 00451 00459 void 00460 _dbus_transport_unref (DBusTransport *transport) 00461 { 00462 _dbus_assert (transport != NULL); 00463 _dbus_assert (transport->refcount > 0); 00464 00465 transport->refcount -= 1; 00466 if (transport->refcount == 0) 00467 { 00468 _dbus_verbose ("%s: finalizing\n", _DBUS_FUNCTION_NAME); 00469 00470 _dbus_assert (transport->vtable->finalize != NULL); 00471 00472 (* transport->vtable->finalize) (transport); 00473 } 00474 } 00475 00484 void 00485 _dbus_transport_disconnect (DBusTransport *transport) 00486 { 00487 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME); 00488 00489 _dbus_assert (transport->vtable->disconnect != NULL); 00490 00491 if (transport->disconnected) 00492 return; 00493 00494 (* transport->vtable->disconnect) (transport); 00495 00496 transport->disconnected = TRUE; 00497 00498 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME); 00499 } 00500 00509 dbus_bool_t 00510 _dbus_transport_get_is_connected (DBusTransport *transport) 00511 { 00512 return !transport->disconnected; 00513 } 00514 00515 static dbus_bool_t 00516 auth_via_unix_user_function (DBusTransport *transport) 00517 { 00518 DBusCredentials *auth_identity; 00519 dbus_bool_t allow; 00520 DBusConnection *connection; 00521 DBusAllowUnixUserFunction unix_user_function; 00522 void *unix_user_data; 00523 dbus_uid_t uid; 00524 00525 /* Dropping the lock here probably isn't that safe. */ 00526 00527 auth_identity = _dbus_auth_get_identity (transport->auth); 00528 _dbus_assert (auth_identity != NULL); 00529 00530 connection = transport->connection; 00531 unix_user_function = transport->unix_user_function; 00532 unix_user_data = transport->unix_user_data; 00533 uid = _dbus_credentials_get_unix_uid (auth_identity); 00534 00535 _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME); 00536 _dbus_connection_unlock (connection); 00537 00538 allow = (* unix_user_function) (connection, 00539 uid, 00540 unix_user_data); 00541 00542 _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME); 00543 _dbus_connection_lock (connection); 00544 00545 if (allow) 00546 { 00547 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); 00548 } 00549 else 00550 { 00551 _dbus_verbose ("Client UID "DBUS_UID_FORMAT 00552 " was rejected, disconnecting\n", 00553 _dbus_credentials_get_unix_uid (auth_identity)); 00554 _dbus_transport_disconnect (transport); 00555 } 00556 00557 return allow; 00558 } 00559 00560 static dbus_bool_t 00561 auth_via_windows_user_function (DBusTransport *transport) 00562 { 00563 DBusCredentials *auth_identity; 00564 dbus_bool_t allow; 00565 DBusConnection *connection; 00566 DBusAllowWindowsUserFunction windows_user_function; 00567 void *windows_user_data; 00568 char *windows_sid; 00569 00570 /* Dropping the lock here probably isn't that safe. */ 00571 00572 auth_identity = _dbus_auth_get_identity (transport->auth); 00573 _dbus_assert (auth_identity != NULL); 00574 00575 connection = transport->connection; 00576 windows_user_function = transport->windows_user_function; 00577 windows_user_data = transport->unix_user_data; 00578 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 00579 00580 if (windows_sid == NULL) 00581 { 00582 /* OOM */ 00583 return FALSE; 00584 } 00585 00586 _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME); 00587 _dbus_connection_unlock (connection); 00588 00589 allow = (* windows_user_function) (connection, 00590 windows_sid, 00591 windows_user_data); 00592 00593 _dbus_verbose ("lock %s post windows user function\n", _DBUS_FUNCTION_NAME); 00594 _dbus_connection_lock (connection); 00595 00596 if (allow) 00597 { 00598 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); 00599 } 00600 else 00601 { 00602 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", 00603 _dbus_credentials_get_windows_sid (auth_identity)); 00604 _dbus_transport_disconnect (transport); 00605 } 00606 00607 return allow; 00608 } 00609 00610 static dbus_bool_t 00611 auth_via_default_rules (DBusTransport *transport) 00612 { 00613 DBusCredentials *auth_identity; 00614 DBusCredentials *our_identity; 00615 dbus_bool_t allow; 00616 00617 auth_identity = _dbus_auth_get_identity (transport->auth); 00618 _dbus_assert (auth_identity != NULL); 00619 00620 /* By default, connection is allowed if the client is 1) root or 2) 00621 * has the same UID as us or 3) anonymous is allowed. 00622 */ 00623 00624 our_identity = _dbus_credentials_new_from_current_process (); 00625 if (our_identity == NULL) 00626 { 00627 /* OOM */ 00628 return FALSE; 00629 } 00630 00631 if (transport->allow_anonymous || 00632 _dbus_credentials_get_unix_uid (auth_identity) == 0 || 00633 _dbus_credentials_same_user (our_identity, 00634 auth_identity)) 00635 { 00636 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00637 _dbus_verbose ("Client authorized as SID '%s'" 00638 "matching our SID '%s'\n", 00639 _dbus_credentials_get_windows_sid(auth_identity), 00640 _dbus_credentials_get_windows_sid(our_identity)); 00641 else 00642 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00643 " matching our UID "DBUS_UID_FORMAT"\n", 00644 _dbus_credentials_get_unix_uid(auth_identity), 00645 _dbus_credentials_get_unix_uid(our_identity)); 00646 /* We have authenticated! */ 00647 allow = TRUE; 00648 } 00649 else 00650 { 00651 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00652 _dbus_verbose ("Client authorized as SID '%s'" 00653 " but our SID is '%s', disconnecting\n", 00654 _dbus_credentials_get_windows_sid(auth_identity), 00655 _dbus_credentials_get_windows_sid(our_identity)); 00656 else 00657 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00658 " but our UID is "DBUS_UID_FORMAT", disconnecting\n", 00659 _dbus_credentials_get_unix_uid(auth_identity), 00660 _dbus_credentials_get_unix_uid(our_identity)); 00661 _dbus_transport_disconnect (transport); 00662 allow = FALSE; 00663 } 00664 00665 _dbus_credentials_unref (our_identity); 00666 00667 return allow; 00668 } 00669 00670 00681 dbus_bool_t 00682 _dbus_transport_get_is_authenticated (DBusTransport *transport) 00683 { 00684 if (transport->authenticated) 00685 return TRUE; 00686 else 00687 { 00688 dbus_bool_t maybe_authenticated; 00689 00690 if (transport->disconnected) 00691 return FALSE; 00692 00693 /* paranoia ref since we call user callbacks sometimes */ 00694 _dbus_connection_ref_unlocked (transport->connection); 00695 00696 maybe_authenticated = 00697 (!(transport->send_credentials_pending || 00698 transport->receive_credentials_pending)); 00699 00700 if (maybe_authenticated) 00701 { 00702 switch (_dbus_auth_do_work (transport->auth)) 00703 { 00704 case DBUS_AUTH_STATE_AUTHENTICATED: 00705 /* leave as maybe_authenticated */ 00706 break; 00707 default: 00708 maybe_authenticated = FALSE; 00709 } 00710 } 00711 00712 /* If we're the client, verify the GUID 00713 */ 00714 if (maybe_authenticated && !transport->is_server) 00715 { 00716 const char *server_guid; 00717 00718 server_guid = _dbus_auth_get_guid_from_server (transport->auth); 00719 _dbus_assert (server_guid != NULL); 00720 00721 if (transport->expected_guid && 00722 strcmp (transport->expected_guid, server_guid) != 0) 00723 { 00724 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", 00725 transport->expected_guid, server_guid); 00726 _dbus_transport_disconnect (transport); 00727 _dbus_connection_unref_unlocked (transport->connection); 00728 return FALSE; 00729 } 00730 00731 if (transport->expected_guid == NULL) 00732 { 00733 transport->expected_guid = _dbus_strdup (server_guid); 00734 00735 if (transport->expected_guid == NULL) 00736 { 00737 _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME); 00738 return FALSE; 00739 } 00740 } 00741 } 00742 00743 /* If we're the server, see if we want to allow this identity to proceed. 00744 */ 00745 if (maybe_authenticated && transport->is_server) 00746 { 00747 dbus_bool_t allow; 00748 DBusCredentials *auth_identity; 00749 00750 auth_identity = _dbus_auth_get_identity (transport->auth); 00751 _dbus_assert (auth_identity != NULL); 00752 00753 /* If we have an auth'd user and a user function, delegate 00754 * deciding whether auth credentials are good enough to the 00755 * app; otherwise, use our default decision process. 00756 */ 00757 if (transport->unix_user_function != NULL && 00758 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) 00759 { 00760 allow = auth_via_unix_user_function (transport); 00761 } 00762 else if (transport->windows_user_function != NULL && 00763 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) 00764 { 00765 allow = auth_via_windows_user_function (transport); 00766 } 00767 else 00768 { 00769 allow = auth_via_default_rules (transport); 00770 } 00771 00772 if (!allow) 00773 maybe_authenticated = FALSE; 00774 } 00775 00776 transport->authenticated = maybe_authenticated; 00777 00778 _dbus_connection_unref_unlocked (transport->connection); 00779 return maybe_authenticated; 00780 } 00781 } 00782 00789 dbus_bool_t 00790 _dbus_transport_get_is_anonymous (DBusTransport *transport) 00791 { 00792 DBusCredentials *auth_identity; 00793 00794 if (!transport->authenticated) 00795 return TRUE; 00796 00797 auth_identity = _dbus_auth_get_identity (transport->auth); 00798 00799 if (_dbus_credentials_are_anonymous (auth_identity)) 00800 return TRUE; 00801 else 00802 return FALSE; 00803 } 00804 00812 const char* 00813 _dbus_transport_get_address (DBusTransport *transport) 00814 { 00815 return transport->address; 00816 } 00817 00825 const char* 00826 _dbus_transport_get_server_id (DBusTransport *transport) 00827 { 00828 if (transport->is_server) 00829 return NULL; 00830 else 00831 return transport->expected_guid; 00832 } 00833 00843 dbus_bool_t 00844 _dbus_transport_handle_watch (DBusTransport *transport, 00845 DBusWatch *watch, 00846 unsigned int condition) 00847 { 00848 dbus_bool_t retval; 00849 00850 _dbus_assert (transport->vtable->handle_watch != NULL); 00851 00852 if (transport->disconnected) 00853 return TRUE; 00854 00855 if (dbus_watch_get_socket (watch) < 0) 00856 { 00857 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n"); 00858 return TRUE; 00859 } 00860 00861 _dbus_watch_sanitize_condition (watch, &condition); 00862 00863 _dbus_transport_ref (transport); 00864 _dbus_watch_ref (watch); 00865 retval = (* transport->vtable->handle_watch) (transport, watch, condition); 00866 _dbus_watch_unref (watch); 00867 _dbus_transport_unref (transport); 00868 00869 return retval; 00870 } 00871 00881 dbus_bool_t 00882 _dbus_transport_set_connection (DBusTransport *transport, 00883 DBusConnection *connection) 00884 { 00885 _dbus_assert (transport->vtable->connection_set != NULL); 00886 _dbus_assert (transport->connection == NULL); 00887 00888 transport->connection = connection; 00889 00890 _dbus_transport_ref (transport); 00891 if (!(* transport->vtable->connection_set) (transport)) 00892 transport->connection = NULL; 00893 _dbus_transport_unref (transport); 00894 00895 return transport->connection != NULL; 00896 } 00897 00905 dbus_bool_t 00906 _dbus_transport_get_socket_fd (DBusTransport *transport, 00907 int *fd_p) 00908 { 00909 dbus_bool_t retval; 00910 00911 if (transport->vtable->get_socket_fd == NULL) 00912 return FALSE; 00913 00914 if (transport->disconnected) 00915 return FALSE; 00916 00917 _dbus_transport_ref (transport); 00918 00919 retval = (* transport->vtable->get_socket_fd) (transport, 00920 fd_p); 00921 00922 _dbus_transport_unref (transport); 00923 00924 return retval; 00925 } 00926 00938 void 00939 _dbus_transport_do_iteration (DBusTransport *transport, 00940 unsigned int flags, 00941 int timeout_milliseconds) 00942 { 00943 _dbus_assert (transport->vtable->do_iteration != NULL); 00944 00945 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n", 00946 flags, timeout_milliseconds, !transport->disconnected); 00947 00948 if ((flags & (DBUS_ITERATION_DO_WRITING | 00949 DBUS_ITERATION_DO_READING)) == 0) 00950 return; /* Nothing to do */ 00951 00952 if (transport->disconnected) 00953 return; 00954 00955 _dbus_transport_ref (transport); 00956 (* transport->vtable->do_iteration) (transport, flags, 00957 timeout_milliseconds); 00958 _dbus_transport_unref (transport); 00959 00960 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME); 00961 } 00962 00963 static dbus_bool_t 00964 recover_unused_bytes (DBusTransport *transport) 00965 { 00966 if (_dbus_auth_needs_decoding (transport->auth)) 00967 { 00968 DBusString plaintext; 00969 const DBusString *encoded; 00970 DBusString *buffer; 00971 int orig_len; 00972 00973 if (!_dbus_string_init (&plaintext)) 00974 goto nomem; 00975 00976 _dbus_auth_get_unused_bytes (transport->auth, 00977 &encoded); 00978 00979 if (!_dbus_auth_decode_data (transport->auth, 00980 encoded, &plaintext)) 00981 { 00982 _dbus_string_free (&plaintext); 00983 goto nomem; 00984 } 00985 00986 _dbus_message_loader_get_buffer (transport->loader, 00987 &buffer); 00988 00989 orig_len = _dbus_string_get_length (buffer); 00990 00991 if (!_dbus_string_move (&plaintext, 0, buffer, 00992 orig_len)) 00993 { 00994 _dbus_string_free (&plaintext); 00995 goto nomem; 00996 } 00997 00998 _dbus_verbose (" %d unused bytes sent to message loader\n", 00999 _dbus_string_get_length (buffer) - 01000 orig_len); 01001 01002 _dbus_message_loader_return_buffer (transport->loader, 01003 buffer, 01004 _dbus_string_get_length (buffer) - 01005 orig_len); 01006 01007 _dbus_auth_delete_unused_bytes (transport->auth); 01008 01009 _dbus_string_free (&plaintext); 01010 } 01011 else 01012 { 01013 const DBusString *bytes; 01014 DBusString *buffer; 01015 int orig_len; 01016 dbus_bool_t succeeded; 01017 01018 _dbus_message_loader_get_buffer (transport->loader, 01019 &buffer); 01020 01021 orig_len = _dbus_string_get_length (buffer); 01022 01023 _dbus_auth_get_unused_bytes (transport->auth, 01024 &bytes); 01025 01026 succeeded = TRUE; 01027 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer))) 01028 succeeded = FALSE; 01029 01030 _dbus_verbose (" %d unused bytes sent to message loader\n", 01031 _dbus_string_get_length (buffer) - 01032 orig_len); 01033 01034 _dbus_message_loader_return_buffer (transport->loader, 01035 buffer, 01036 _dbus_string_get_length (buffer) - 01037 orig_len); 01038 01039 if (succeeded) 01040 _dbus_auth_delete_unused_bytes (transport->auth); 01041 else 01042 goto nomem; 01043 } 01044 01045 return TRUE; 01046 01047 nomem: 01048 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); 01049 return FALSE; 01050 } 01051 01059 DBusDispatchStatus 01060 _dbus_transport_get_dispatch_status (DBusTransport *transport) 01061 { 01062 if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size) 01063 return DBUS_DISPATCH_COMPLETE; /* complete for now */ 01064 01065 if (!_dbus_transport_get_is_authenticated (transport)) 01066 { 01067 if (_dbus_auth_do_work (transport->auth) == 01068 DBUS_AUTH_STATE_WAITING_FOR_MEMORY) 01069 return DBUS_DISPATCH_NEED_MEMORY; 01070 else if (!_dbus_transport_get_is_authenticated (transport)) 01071 return DBUS_DISPATCH_COMPLETE; 01072 } 01073 01074 if (!transport->unused_bytes_recovered && 01075 !recover_unused_bytes (transport)) 01076 return DBUS_DISPATCH_NEED_MEMORY; 01077 01078 transport->unused_bytes_recovered = TRUE; 01079 01080 if (!_dbus_message_loader_queue_messages (transport->loader)) 01081 return DBUS_DISPATCH_NEED_MEMORY; 01082 01083 if (_dbus_message_loader_peek_message (transport->loader) != NULL) 01084 return DBUS_DISPATCH_DATA_REMAINS; 01085 else 01086 return DBUS_DISPATCH_COMPLETE; 01087 } 01088 01097 dbus_bool_t 01098 _dbus_transport_queue_messages (DBusTransport *transport) 01099 { 01100 DBusDispatchStatus status; 01101 01102 #if 0 01103 _dbus_verbose ("_dbus_transport_queue_messages()\n"); 01104 #endif 01105 01106 /* Queue any messages */ 01107 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS) 01108 { 01109 DBusMessage *message; 01110 DBusList *link; 01111 01112 link = _dbus_message_loader_pop_message_link (transport->loader); 01113 _dbus_assert (link != NULL); 01114 01115 message = link->data; 01116 01117 _dbus_verbose ("queueing received message %p\n", message); 01118 01119 if (!_dbus_message_add_size_counter (message, transport->live_messages_size)) 01120 { 01121 _dbus_message_loader_putback_message_link (transport->loader, 01122 link); 01123 status = DBUS_DISPATCH_NEED_MEMORY; 01124 break; 01125 } 01126 else 01127 { 01128 /* pass ownership of link and message ref to connection */ 01129 _dbus_connection_queue_received_message_link (transport->connection, 01130 link); 01131 } 01132 } 01133 01134 if (_dbus_message_loader_get_is_corrupted (transport->loader)) 01135 { 01136 _dbus_verbose ("Corrupted message stream, disconnecting\n"); 01137 _dbus_transport_disconnect (transport); 01138 } 01139 01140 return status != DBUS_DISPATCH_NEED_MEMORY; 01141 } 01142 01149 void 01150 _dbus_transport_set_max_message_size (DBusTransport *transport, 01151 long size) 01152 { 01153 _dbus_message_loader_set_max_message_size (transport->loader, size); 01154 } 01155 01162 long 01163 _dbus_transport_get_max_message_size (DBusTransport *transport) 01164 { 01165 return _dbus_message_loader_get_max_message_size (transport->loader); 01166 } 01167 01174 void 01175 _dbus_transport_set_max_received_size (DBusTransport *transport, 01176 long size) 01177 { 01178 transport->max_live_messages_size = size; 01179 _dbus_counter_set_notify (transport->live_messages_size, 01180 transport->max_live_messages_size, 01181 live_messages_size_notify, 01182 transport); 01183 } 01184 01185 01192 long 01193 _dbus_transport_get_max_received_size (DBusTransport *transport) 01194 { 01195 return transport->max_live_messages_size; 01196 } 01197 01205 dbus_bool_t 01206 _dbus_transport_get_unix_user (DBusTransport *transport, 01207 unsigned long *uid) 01208 { 01209 DBusCredentials *auth_identity; 01210 01211 *uid = _DBUS_INT32_MAX; /* better than some root or system user in 01212 * case of bugs in the caller. Caller should 01213 * never use this value on purpose, however. 01214 */ 01215 01216 if (!transport->authenticated) 01217 return FALSE; 01218 01219 auth_identity = _dbus_auth_get_identity (transport->auth); 01220 01221 if (_dbus_credentials_include (auth_identity, 01222 DBUS_CREDENTIAL_UNIX_USER_ID)) 01223 { 01224 *uid = _dbus_credentials_get_unix_uid (auth_identity); 01225 return TRUE; 01226 } 01227 else 01228 return FALSE; 01229 } 01230 01238 dbus_bool_t 01239 _dbus_transport_get_unix_process_id (DBusTransport *transport, 01240 unsigned long *pid) 01241 { 01242 DBusCredentials *auth_identity; 01243 01244 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose, 01245 * but we set it to a safe number, INT_MAX, 01246 * just to root out possible bugs in bad callers. 01247 */ 01248 01249 if (!transport->authenticated) 01250 return FALSE; 01251 01252 auth_identity = _dbus_auth_get_identity (transport->auth); 01253 01254 if (_dbus_credentials_include (auth_identity, 01255 DBUS_CREDENTIAL_UNIX_PROCESS_ID)) 01256 { 01257 *pid = _dbus_credentials_get_unix_pid (auth_identity); 01258 return TRUE; 01259 } 01260 else 01261 return FALSE; 01262 } 01263 01272 dbus_bool_t 01273 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, 01274 void **data, 01275 int *data_size) 01276 { 01277 DBusCredentials *auth_identity; 01278 01279 *data = NULL; 01280 *data_size = 0; 01281 01282 if (!transport->authenticated) 01283 return FALSE; 01284 01285 auth_identity = _dbus_auth_get_identity (transport->auth); 01286 01287 if (_dbus_credentials_include (auth_identity, 01288 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) 01289 { 01290 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); 01291 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); 01292 return TRUE; 01293 } 01294 else 01295 return FALSE; 01296 } 01297 01308 void 01309 _dbus_transport_set_unix_user_function (DBusTransport *transport, 01310 DBusAllowUnixUserFunction function, 01311 void *data, 01312 DBusFreeFunction free_data_function, 01313 void **old_data, 01314 DBusFreeFunction *old_free_data_function) 01315 { 01316 *old_data = transport->unix_user_data; 01317 *old_free_data_function = transport->free_unix_user_data; 01318 01319 transport->unix_user_function = function; 01320 transport->unix_user_data = data; 01321 transport->free_unix_user_data = free_data_function; 01322 } 01323 01331 dbus_bool_t 01332 _dbus_transport_get_windows_user (DBusTransport *transport, 01333 char **windows_sid_p) 01334 { 01335 DBusCredentials *auth_identity; 01336 01337 *windows_sid_p = NULL; 01338 01339 if (!transport->authenticated) 01340 return FALSE; 01341 01342 auth_identity = _dbus_auth_get_identity (transport->auth); 01343 01344 if (_dbus_credentials_include (auth_identity, 01345 DBUS_CREDENTIAL_WINDOWS_SID)) 01346 { 01347 /* If no memory, we are supposed to return TRUE and set NULL */ 01348 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 01349 01350 return TRUE; 01351 } 01352 else 01353 return FALSE; 01354 } 01355 01367 void 01368 _dbus_transport_set_windows_user_function (DBusTransport *transport, 01369 DBusAllowWindowsUserFunction function, 01370 void *data, 01371 DBusFreeFunction free_data_function, 01372 void **old_data, 01373 DBusFreeFunction *old_free_data_function) 01374 { 01375 *old_data = transport->windows_user_data; 01376 *old_free_data_function = transport->free_windows_user_data; 01377 01378 transport->windows_user_function = function; 01379 transport->windows_user_data = data; 01380 transport->free_windows_user_data = free_data_function; 01381 } 01382 01391 dbus_bool_t 01392 _dbus_transport_set_auth_mechanisms (DBusTransport *transport, 01393 const char **mechanisms) 01394 { 01395 return _dbus_auth_set_mechanisms (transport->auth, mechanisms); 01396 } 01397 01404 void 01405 _dbus_transport_set_allow_anonymous (DBusTransport *transport, 01406 dbus_bool_t value) 01407 { 01408 transport->allow_anonymous = value != FALSE; 01409 } 01410