D-Bus 1.6.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation) 00003 * 00004 * Copyright (C) 2002, 2003 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-transport-protected.h" 00026 #include "dbus-transport-unix.h" 00027 #include "dbus-transport-socket.h" 00028 #include "dbus-connection-internal.h" 00029 #include "dbus-watch.h" 00030 #include "dbus-auth.h" 00031 #include "dbus-address.h" 00032 #include "dbus-credentials.h" 00033 #include "dbus-mainloop.h" 00034 #include "dbus-message.h" 00035 #ifdef DBUS_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 { 00080 _dbus_connection_lock (transport->connection); 00081 (* transport->vtable->live_messages_changed) (transport); 00082 _dbus_connection_unlock (transport->connection); 00083 } 00084 00085 _dbus_transport_unref (transport); 00086 } 00087 00101 dbus_bool_t 00102 _dbus_transport_init_base (DBusTransport *transport, 00103 const DBusTransportVTable *vtable, 00104 const DBusString *server_guid, 00105 const DBusString *address) 00106 { 00107 DBusMessageLoader *loader; 00108 DBusAuth *auth; 00109 DBusCounter *counter; 00110 char *address_copy; 00111 DBusCredentials *creds; 00112 00113 loader = _dbus_message_loader_new (); 00114 if (loader == NULL) 00115 return FALSE; 00116 00117 if (server_guid) 00118 auth = _dbus_auth_server_new (server_guid); 00119 else 00120 auth = _dbus_auth_client_new (); 00121 if (auth == NULL) 00122 { 00123 _dbus_message_loader_unref (loader); 00124 return FALSE; 00125 } 00126 00127 counter = _dbus_counter_new (); 00128 if (counter == NULL) 00129 { 00130 _dbus_auth_unref (auth); 00131 _dbus_message_loader_unref (loader); 00132 return FALSE; 00133 } 00134 00135 creds = _dbus_credentials_new (); 00136 if (creds == NULL) 00137 { 00138 _dbus_counter_unref (counter); 00139 _dbus_auth_unref (auth); 00140 _dbus_message_loader_unref (loader); 00141 return FALSE; 00142 } 00143 00144 if (server_guid) 00145 { 00146 _dbus_assert (address == NULL); 00147 address_copy = NULL; 00148 } 00149 else 00150 { 00151 _dbus_assert (address != NULL); 00152 00153 if (!_dbus_string_copy_data (address, &address_copy)) 00154 { 00155 _dbus_credentials_unref (creds); 00156 _dbus_counter_unref (counter); 00157 _dbus_auth_unref (auth); 00158 _dbus_message_loader_unref (loader); 00159 return FALSE; 00160 } 00161 } 00162 00163 transport->refcount = 1; 00164 transport->vtable = vtable; 00165 transport->loader = loader; 00166 transport->auth = auth; 00167 transport->live_messages = counter; 00168 transport->authenticated = FALSE; 00169 transport->disconnected = FALSE; 00170 transport->is_server = (server_guid != NULL); 00171 transport->send_credentials_pending = !transport->is_server; 00172 transport->receive_credentials_pending = transport->is_server; 00173 transport->address = address_copy; 00174 00175 transport->unix_user_function = NULL; 00176 transport->unix_user_data = NULL; 00177 transport->free_unix_user_data = NULL; 00178 00179 transport->windows_user_function = NULL; 00180 transport->windows_user_data = NULL; 00181 transport->free_windows_user_data = NULL; 00182 00183 transport->expected_guid = NULL; 00184 00185 /* Try to default to something that won't totally hose the system, 00186 * but doesn't impose too much of a limitation. 00187 */ 00188 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 00189 00190 /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live 00191 should be more than enough */ 00192 transport->max_live_messages_unix_fds = 4096; 00193 00194 /* credentials read from socket if any */ 00195 transport->credentials = creds; 00196 00197 _dbus_counter_set_notify (transport->live_messages, 00198 transport->max_live_messages_size, 00199 transport->max_live_messages_unix_fds, 00200 live_messages_notify, 00201 transport); 00202 00203 if (transport->address) 00204 _dbus_verbose ("Initialized transport on address %s\n", transport->address); 00205 00206 return TRUE; 00207 } 00208 00215 void 00216 _dbus_transport_finalize_base (DBusTransport *transport) 00217 { 00218 if (!transport->disconnected) 00219 _dbus_transport_disconnect (transport); 00220 00221 if (transport->free_unix_user_data != NULL) 00222 (* transport->free_unix_user_data) (transport->unix_user_data); 00223 00224 if (transport->free_windows_user_data != NULL) 00225 (* transport->free_windows_user_data) (transport->windows_user_data); 00226 00227 _dbus_message_loader_unref (transport->loader); 00228 _dbus_auth_unref (transport->auth); 00229 _dbus_counter_set_notify (transport->live_messages, 00230 0, 0, NULL, NULL); 00231 _dbus_counter_unref (transport->live_messages); 00232 dbus_free (transport->address); 00233 dbus_free (transport->expected_guid); 00234 if (transport->credentials) 00235 _dbus_credentials_unref (transport->credentials); 00236 } 00237 00238 00248 static DBusTransport* 00249 check_address (const char *address, DBusError *error) 00250 { 00251 DBusAddressEntry **entries; 00252 DBusTransport *transport = NULL; 00253 int len, i; 00254 00255 _dbus_assert (address != NULL); 00256 00257 if (!dbus_parse_address (address, &entries, &len, error)) 00258 return NULL; /* not a valid address */ 00259 00260 for (i = 0; i < len; i++) 00261 { 00262 transport = _dbus_transport_open (entries[i], error); 00263 if (transport != NULL) 00264 break; 00265 } 00266 00267 dbus_address_entries_free (entries); 00268 return transport; 00269 } 00270 00278 static DBusTransport* 00279 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error) 00280 { 00281 DBusString address; 00282 DBusTransport *result = NULL; 00283 00284 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00285 00286 if (!_dbus_string_init (&address)) 00287 { 00288 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00289 return NULL; 00290 } 00291 00292 if (!_dbus_get_autolaunch_address (scope, &address, error)) 00293 { 00294 _DBUS_ASSERT_ERROR_IS_SET (error); 00295 goto out; 00296 } 00297 00298 result = check_address (_dbus_string_get_const_data (&address), error); 00299 if (result == NULL) 00300 _DBUS_ASSERT_ERROR_IS_SET (error); 00301 else 00302 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00303 00304 out: 00305 _dbus_string_free (&address); 00306 return result; 00307 } 00308 00309 static DBusTransportOpenResult 00310 _dbus_transport_open_autolaunch (DBusAddressEntry *entry, 00311 DBusTransport **transport_p, 00312 DBusError *error) 00313 { 00314 const char *method; 00315 00316 method = dbus_address_entry_get_method (entry); 00317 _dbus_assert (method != NULL); 00318 00319 if (strcmp (method, "autolaunch") == 0) 00320 { 00321 const char *scope = dbus_address_entry_get_value (entry, "scope"); 00322 00323 *transport_p = _dbus_transport_new_for_autolaunch (scope, error); 00324 00325 if (*transport_p == NULL) 00326 { 00327 _DBUS_ASSERT_ERROR_IS_SET (error); 00328 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00329 } 00330 else 00331 { 00332 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00333 return DBUS_TRANSPORT_OPEN_OK; 00334 } 00335 } 00336 else 00337 { 00338 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00339 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00340 } 00341 } 00342 00343 static const struct { 00344 DBusTransportOpenResult (* func) (DBusAddressEntry *entry, 00345 DBusTransport **transport_p, 00346 DBusError *error); 00347 } open_funcs[] = { 00348 { _dbus_transport_open_socket }, 00349 { _dbus_transport_open_platform_specific }, 00350 { _dbus_transport_open_autolaunch } 00351 #ifdef DBUS_BUILD_TESTS 00352 , { _dbus_transport_open_debug_pipe } 00353 #endif 00354 }; 00355 00364 DBusTransport* 00365 _dbus_transport_open (DBusAddressEntry *entry, 00366 DBusError *error) 00367 { 00368 DBusTransport *transport; 00369 const char *expected_guid_orig; 00370 char *expected_guid; 00371 int i; 00372 DBusError tmp_error = DBUS_ERROR_INIT; 00373 00374 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00375 00376 transport = NULL; 00377 expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); 00378 expected_guid = _dbus_strdup (expected_guid_orig); 00379 00380 if (expected_guid_orig != NULL && expected_guid == NULL) 00381 { 00382 _DBUS_SET_OOM (error); 00383 return NULL; 00384 } 00385 00386 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i) 00387 { 00388 DBusTransportOpenResult result; 00389 00390 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00391 result = (* open_funcs[i].func) (entry, &transport, &tmp_error); 00392 00393 switch (result) 00394 { 00395 case DBUS_TRANSPORT_OPEN_OK: 00396 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00397 goto out; 00398 break; 00399 case DBUS_TRANSPORT_OPEN_NOT_HANDLED: 00400 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00401 /* keep going through the loop of open funcs */ 00402 break; 00403 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS: 00404 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00405 goto out; 00406 break; 00407 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT: 00408 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00409 goto out; 00410 break; 00411 } 00412 } 00413 00414 out: 00415 00416 if (transport == NULL) 00417 { 00418 if (!dbus_error_is_set (&tmp_error)) 00419 _dbus_set_bad_address (&tmp_error, 00420 NULL, NULL, 00421 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")"); 00422 00423 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00424 dbus_move_error(&tmp_error, error); 00425 dbus_free (expected_guid); 00426 } 00427 else 00428 { 00429 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00430 00431 /* In the case of autostart the initial guid is NULL 00432 * and the autostart transport recursively calls 00433 * _dbus_open_transport wich returns a transport 00434 * with a guid. That guid is the definitive one. 00435 * 00436 * FIXME: if more transports are added they may have 00437 * an effect on the expected_guid semantics (i.e. 00438 * expected_guid and transport->expected_guid may 00439 * both have values). This is very unlikely though 00440 * we should either throw asserts here for those 00441 * corner cases or refactor the code so it is 00442 * clearer on what is expected and what is not 00443 */ 00444 if(expected_guid) 00445 transport->expected_guid = expected_guid; 00446 } 00447 00448 return transport; 00449 } 00450 00457 DBusTransport * 00458 _dbus_transport_ref (DBusTransport *transport) 00459 { 00460 _dbus_assert (transport->refcount > 0); 00461 00462 transport->refcount += 1; 00463 00464 return transport; 00465 } 00466 00474 void 00475 _dbus_transport_unref (DBusTransport *transport) 00476 { 00477 _dbus_assert (transport != NULL); 00478 _dbus_assert (transport->refcount > 0); 00479 00480 transport->refcount -= 1; 00481 if (transport->refcount == 0) 00482 { 00483 _dbus_verbose ("finalizing\n"); 00484 00485 _dbus_assert (transport->vtable->finalize != NULL); 00486 00487 (* transport->vtable->finalize) (transport); 00488 } 00489 } 00490 00499 void 00500 _dbus_transport_disconnect (DBusTransport *transport) 00501 { 00502 _dbus_verbose ("start\n"); 00503 00504 _dbus_assert (transport->vtable->disconnect != NULL); 00505 00506 if (transport->disconnected) 00507 return; 00508 00509 (* transport->vtable->disconnect) (transport); 00510 00511 transport->disconnected = TRUE; 00512 00513 _dbus_verbose ("end\n"); 00514 } 00515 00524 dbus_bool_t 00525 _dbus_transport_get_is_connected (DBusTransport *transport) 00526 { 00527 return !transport->disconnected; 00528 } 00529 00530 static dbus_bool_t 00531 auth_via_unix_user_function (DBusTransport *transport) 00532 { 00533 DBusCredentials *auth_identity; 00534 dbus_bool_t allow; 00535 DBusConnection *connection; 00536 DBusAllowUnixUserFunction unix_user_function; 00537 void *unix_user_data; 00538 dbus_uid_t uid; 00539 00540 /* Dropping the lock here probably isn't that safe. */ 00541 00542 auth_identity = _dbus_auth_get_identity (transport->auth); 00543 _dbus_assert (auth_identity != NULL); 00544 00545 connection = transport->connection; 00546 unix_user_function = transport->unix_user_function; 00547 unix_user_data = transport->unix_user_data; 00548 uid = _dbus_credentials_get_unix_uid (auth_identity); 00549 00550 _dbus_verbose ("unlock\n"); 00551 _dbus_connection_unlock (connection); 00552 00553 allow = (* unix_user_function) (connection, 00554 uid, 00555 unix_user_data); 00556 00557 _dbus_verbose ("lock post unix user function\n"); 00558 _dbus_connection_lock (connection); 00559 00560 if (allow) 00561 { 00562 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); 00563 } 00564 else 00565 { 00566 _dbus_verbose ("Client UID "DBUS_UID_FORMAT 00567 " was rejected, disconnecting\n", 00568 _dbus_credentials_get_unix_uid (auth_identity)); 00569 _dbus_transport_disconnect (transport); 00570 } 00571 00572 return allow; 00573 } 00574 00575 static dbus_bool_t 00576 auth_via_windows_user_function (DBusTransport *transport) 00577 { 00578 DBusCredentials *auth_identity; 00579 dbus_bool_t allow; 00580 DBusConnection *connection; 00581 DBusAllowWindowsUserFunction windows_user_function; 00582 void *windows_user_data; 00583 char *windows_sid; 00584 00585 /* Dropping the lock here probably isn't that safe. */ 00586 00587 auth_identity = _dbus_auth_get_identity (transport->auth); 00588 _dbus_assert (auth_identity != NULL); 00589 00590 connection = transport->connection; 00591 windows_user_function = transport->windows_user_function; 00592 windows_user_data = transport->unix_user_data; 00593 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 00594 00595 if (windows_sid == NULL) 00596 { 00597 /* OOM */ 00598 return FALSE; 00599 } 00600 00601 _dbus_verbose ("unlock\n"); 00602 _dbus_connection_unlock (connection); 00603 00604 allow = (* windows_user_function) (connection, 00605 windows_sid, 00606 windows_user_data); 00607 00608 _dbus_verbose ("lock post windows user function\n"); 00609 _dbus_connection_lock (connection); 00610 00611 if (allow) 00612 { 00613 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); 00614 } 00615 else 00616 { 00617 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", 00618 _dbus_credentials_get_windows_sid (auth_identity)); 00619 _dbus_transport_disconnect (transport); 00620 } 00621 00622 return allow; 00623 } 00624 00625 static dbus_bool_t 00626 auth_via_default_rules (DBusTransport *transport) 00627 { 00628 DBusCredentials *auth_identity; 00629 DBusCredentials *our_identity; 00630 dbus_bool_t allow; 00631 00632 auth_identity = _dbus_auth_get_identity (transport->auth); 00633 _dbus_assert (auth_identity != NULL); 00634 00635 /* By default, connection is allowed if the client is 1) root or 2) 00636 * has the same UID as us or 3) anonymous is allowed. 00637 */ 00638 00639 our_identity = _dbus_credentials_new_from_current_process (); 00640 if (our_identity == NULL) 00641 { 00642 /* OOM */ 00643 return FALSE; 00644 } 00645 00646 if (transport->allow_anonymous || 00647 _dbus_credentials_get_unix_uid (auth_identity) == 0 || 00648 _dbus_credentials_same_user (our_identity, 00649 auth_identity)) 00650 { 00651 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00652 _dbus_verbose ("Client authorized as SID '%s'" 00653 "matching our SID '%s'\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 " matching our UID "DBUS_UID_FORMAT"\n", 00659 _dbus_credentials_get_unix_uid(auth_identity), 00660 _dbus_credentials_get_unix_uid(our_identity)); 00661 /* We have authenticated! */ 00662 allow = TRUE; 00663 } 00664 else 00665 { 00666 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00667 _dbus_verbose ("Client authorized as SID '%s'" 00668 " but our SID is '%s', disconnecting\n", 00669 (_dbus_credentials_get_windows_sid(auth_identity) ? 00670 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"), 00671 (_dbus_credentials_get_windows_sid(our_identity) ? 00672 _dbus_credentials_get_windows_sid(our_identity) : "<null>")); 00673 else 00674 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00675 " but our UID is "DBUS_UID_FORMAT", disconnecting\n", 00676 _dbus_credentials_get_unix_uid(auth_identity), 00677 _dbus_credentials_get_unix_uid(our_identity)); 00678 _dbus_transport_disconnect (transport); 00679 allow = FALSE; 00680 } 00681 00682 _dbus_credentials_unref (our_identity); 00683 00684 return allow; 00685 } 00686 00687 00698 dbus_bool_t 00699 _dbus_transport_get_is_authenticated (DBusTransport *transport) 00700 { 00701 if (transport->authenticated) 00702 return TRUE; 00703 else 00704 { 00705 dbus_bool_t maybe_authenticated; 00706 00707 if (transport->disconnected) 00708 return FALSE; 00709 00710 /* paranoia ref since we call user callbacks sometimes */ 00711 _dbus_connection_ref_unlocked (transport->connection); 00712 00713 maybe_authenticated = 00714 (!(transport->send_credentials_pending || 00715 transport->receive_credentials_pending)); 00716 00717 if (maybe_authenticated) 00718 { 00719 switch (_dbus_auth_do_work (transport->auth)) 00720 { 00721 case DBUS_AUTH_STATE_AUTHENTICATED: 00722 /* leave as maybe_authenticated */ 00723 break; 00724 default: 00725 maybe_authenticated = FALSE; 00726 } 00727 } 00728 00729 /* If we're the client, verify the GUID 00730 */ 00731 if (maybe_authenticated && !transport->is_server) 00732 { 00733 const char *server_guid; 00734 00735 server_guid = _dbus_auth_get_guid_from_server (transport->auth); 00736 _dbus_assert (server_guid != NULL); 00737 00738 if (transport->expected_guid && 00739 strcmp (transport->expected_guid, server_guid) != 0) 00740 { 00741 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", 00742 transport->expected_guid, server_guid); 00743 _dbus_transport_disconnect (transport); 00744 _dbus_connection_unref_unlocked (transport->connection); 00745 return FALSE; 00746 } 00747 } 00748 00749 /* If we're the server, see if we want to allow this identity to proceed. 00750 */ 00751 if (maybe_authenticated && transport->is_server) 00752 { 00753 dbus_bool_t allow; 00754 DBusCredentials *auth_identity; 00755 00756 auth_identity = _dbus_auth_get_identity (transport->auth); 00757 _dbus_assert (auth_identity != NULL); 00758 00759 /* If we have an auth'd user and a user function, delegate 00760 * deciding whether auth credentials are good enough to the 00761 * app; otherwise, use our default decision process. 00762 */ 00763 if (transport->unix_user_function != NULL && 00764 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) 00765 { 00766 allow = auth_via_unix_user_function (transport); 00767 } 00768 else if (transport->windows_user_function != NULL && 00769 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) 00770 { 00771 allow = auth_via_windows_user_function (transport); 00772 } 00773 else 00774 { 00775 allow = auth_via_default_rules (transport); 00776 } 00777 00778 if (!allow) 00779 maybe_authenticated = FALSE; 00780 } 00781 00782 transport->authenticated = maybe_authenticated; 00783 00784 _dbus_connection_unref_unlocked (transport->connection); 00785 return maybe_authenticated; 00786 } 00787 } 00788 00795 dbus_bool_t 00796 _dbus_transport_get_is_anonymous (DBusTransport *transport) 00797 { 00798 DBusCredentials *auth_identity; 00799 00800 if (!transport->authenticated) 00801 return TRUE; 00802 00803 auth_identity = _dbus_auth_get_identity (transport->auth); 00804 00805 if (_dbus_credentials_are_anonymous (auth_identity)) 00806 return TRUE; 00807 else 00808 return FALSE; 00809 } 00810 00817 dbus_bool_t 00818 _dbus_transport_can_pass_unix_fd(DBusTransport *transport) 00819 { 00820 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport); 00821 } 00822 00830 const char* 00831 _dbus_transport_get_address (DBusTransport *transport) 00832 { 00833 return transport->address; 00834 } 00835 00843 const char* 00844 _dbus_transport_get_server_id (DBusTransport *transport) 00845 { 00846 if (transport->is_server) 00847 return NULL; 00848 else if (transport->authenticated) 00849 return _dbus_auth_get_guid_from_server (transport->auth); 00850 else 00851 return transport->expected_guid; 00852 } 00853 00863 dbus_bool_t 00864 _dbus_transport_handle_watch (DBusTransport *transport, 00865 DBusWatch *watch, 00866 unsigned int condition) 00867 { 00868 dbus_bool_t retval; 00869 00870 _dbus_assert (transport->vtable->handle_watch != NULL); 00871 00872 if (transport->disconnected) 00873 return TRUE; 00874 00875 if (dbus_watch_get_socket (watch) < 0) 00876 { 00877 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n"); 00878 return TRUE; 00879 } 00880 00881 _dbus_watch_sanitize_condition (watch, &condition); 00882 00883 _dbus_transport_ref (transport); 00884 _dbus_watch_ref (watch); 00885 retval = (* transport->vtable->handle_watch) (transport, watch, condition); 00886 _dbus_watch_unref (watch); 00887 _dbus_transport_unref (transport); 00888 00889 return retval; 00890 } 00891 00901 dbus_bool_t 00902 _dbus_transport_set_connection (DBusTransport *transport, 00903 DBusConnection *connection) 00904 { 00905 _dbus_assert (transport->vtable->connection_set != NULL); 00906 _dbus_assert (transport->connection == NULL); 00907 00908 transport->connection = connection; 00909 00910 _dbus_transport_ref (transport); 00911 if (!(* transport->vtable->connection_set) (transport)) 00912 transport->connection = NULL; 00913 _dbus_transport_unref (transport); 00914 00915 return transport->connection != NULL; 00916 } 00917 00925 dbus_bool_t 00926 _dbus_transport_get_socket_fd (DBusTransport *transport, 00927 int *fd_p) 00928 { 00929 dbus_bool_t retval; 00930 00931 if (transport->vtable->get_socket_fd == NULL) 00932 return FALSE; 00933 00934 if (transport->disconnected) 00935 return FALSE; 00936 00937 _dbus_transport_ref (transport); 00938 00939 retval = (* transport->vtable->get_socket_fd) (transport, 00940 fd_p); 00941 00942 _dbus_transport_unref (transport); 00943 00944 return retval; 00945 } 00946 00958 void 00959 _dbus_transport_do_iteration (DBusTransport *transport, 00960 unsigned int flags, 00961 int timeout_milliseconds) 00962 { 00963 _dbus_assert (transport->vtable->do_iteration != NULL); 00964 00965 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n", 00966 flags, timeout_milliseconds, !transport->disconnected); 00967 00968 if ((flags & (DBUS_ITERATION_DO_WRITING | 00969 DBUS_ITERATION_DO_READING)) == 0) 00970 return; /* Nothing to do */ 00971 00972 if (transport->disconnected) 00973 return; 00974 00975 _dbus_transport_ref (transport); 00976 (* transport->vtable->do_iteration) (transport, flags, 00977 timeout_milliseconds); 00978 _dbus_transport_unref (transport); 00979 00980 _dbus_verbose ("end\n"); 00981 } 00982 00983 static dbus_bool_t 00984 recover_unused_bytes (DBusTransport *transport) 00985 { 00986 if (_dbus_auth_needs_decoding (transport->auth)) 00987 { 00988 DBusString plaintext; 00989 const DBusString *encoded; 00990 DBusString *buffer; 00991 int orig_len; 00992 00993 if (!_dbus_string_init (&plaintext)) 00994 goto nomem; 00995 00996 _dbus_auth_get_unused_bytes (transport->auth, 00997 &encoded); 00998 00999 if (!_dbus_auth_decode_data (transport->auth, 01000 encoded, &plaintext)) 01001 { 01002 _dbus_string_free (&plaintext); 01003 goto nomem; 01004 } 01005 01006 _dbus_message_loader_get_buffer (transport->loader, 01007 &buffer); 01008 01009 orig_len = _dbus_string_get_length (buffer); 01010 01011 if (!_dbus_string_move (&plaintext, 0, buffer, 01012 orig_len)) 01013 { 01014 _dbus_string_free (&plaintext); 01015 goto nomem; 01016 } 01017 01018 _dbus_verbose (" %d unused bytes sent to message loader\n", 01019 _dbus_string_get_length (buffer) - 01020 orig_len); 01021 01022 _dbus_message_loader_return_buffer (transport->loader, 01023 buffer, 01024 _dbus_string_get_length (buffer) - 01025 orig_len); 01026 01027 _dbus_auth_delete_unused_bytes (transport->auth); 01028 01029 _dbus_string_free (&plaintext); 01030 } 01031 else 01032 { 01033 const DBusString *bytes; 01034 DBusString *buffer; 01035 int orig_len; 01036 dbus_bool_t succeeded; 01037 01038 _dbus_message_loader_get_buffer (transport->loader, 01039 &buffer); 01040 01041 orig_len = _dbus_string_get_length (buffer); 01042 01043 _dbus_auth_get_unused_bytes (transport->auth, 01044 &bytes); 01045 01046 succeeded = TRUE; 01047 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer))) 01048 succeeded = FALSE; 01049 01050 _dbus_verbose (" %d unused bytes sent to message loader\n", 01051 _dbus_string_get_length (buffer) - 01052 orig_len); 01053 01054 _dbus_message_loader_return_buffer (transport->loader, 01055 buffer, 01056 _dbus_string_get_length (buffer) - 01057 orig_len); 01058 01059 if (succeeded) 01060 _dbus_auth_delete_unused_bytes (transport->auth); 01061 else 01062 goto nomem; 01063 } 01064 01065 return TRUE; 01066 01067 nomem: 01068 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); 01069 return FALSE; 01070 } 01071 01079 DBusDispatchStatus 01080 _dbus_transport_get_dispatch_status (DBusTransport *transport) 01081 { 01082 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size || 01083 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) 01084 return DBUS_DISPATCH_COMPLETE; /* complete for now */ 01085 01086 if (!_dbus_transport_get_is_authenticated (transport)) 01087 { 01088 if (_dbus_auth_do_work (transport->auth) == 01089 DBUS_AUTH_STATE_WAITING_FOR_MEMORY) 01090 return DBUS_DISPATCH_NEED_MEMORY; 01091 else if (!_dbus_transport_get_is_authenticated (transport)) 01092 return DBUS_DISPATCH_COMPLETE; 01093 } 01094 01095 if (!transport->unused_bytes_recovered && 01096 !recover_unused_bytes (transport)) 01097 return DBUS_DISPATCH_NEED_MEMORY; 01098 01099 transport->unused_bytes_recovered = TRUE; 01100 01101 if (!_dbus_message_loader_queue_messages (transport->loader)) 01102 return DBUS_DISPATCH_NEED_MEMORY; 01103 01104 if (_dbus_message_loader_peek_message (transport->loader) != NULL) 01105 return DBUS_DISPATCH_DATA_REMAINS; 01106 else 01107 return DBUS_DISPATCH_COMPLETE; 01108 } 01109 01118 dbus_bool_t 01119 _dbus_transport_queue_messages (DBusTransport *transport) 01120 { 01121 DBusDispatchStatus status; 01122 01123 #if 0 01124 _dbus_verbose ("_dbus_transport_queue_messages()\n"); 01125 #endif 01126 01127 /* Queue any messages */ 01128 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS) 01129 { 01130 DBusMessage *message; 01131 DBusList *link; 01132 01133 link = _dbus_message_loader_pop_message_link (transport->loader); 01134 _dbus_assert (link != NULL); 01135 01136 message = link->data; 01137 01138 _dbus_verbose ("queueing received message %p\n", message); 01139 01140 if (!_dbus_message_add_counter (message, transport->live_messages)) 01141 { 01142 _dbus_message_loader_putback_message_link (transport->loader, 01143 link); 01144 status = DBUS_DISPATCH_NEED_MEMORY; 01145 break; 01146 } 01147 else 01148 { 01149 /* We didn't call the notify function when we added the counter, so 01150 * catch up now. Since we have the connection's lock, it's desirable 01151 * that we bypass the notify function and call this virtual method 01152 * directly. */ 01153 if (transport->vtable->live_messages_changed) 01154 (* transport->vtable->live_messages_changed) (transport); 01155 01156 /* pass ownership of link and message ref to connection */ 01157 _dbus_connection_queue_received_message_link (transport->connection, 01158 link); 01159 } 01160 } 01161 01162 if (_dbus_message_loader_get_is_corrupted (transport->loader)) 01163 { 01164 _dbus_verbose ("Corrupted message stream, disconnecting\n"); 01165 _dbus_transport_disconnect (transport); 01166 } 01167 01168 return status != DBUS_DISPATCH_NEED_MEMORY; 01169 } 01170 01177 void 01178 _dbus_transport_set_max_message_size (DBusTransport *transport, 01179 long size) 01180 { 01181 _dbus_message_loader_set_max_message_size (transport->loader, size); 01182 } 01183 01190 void 01191 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport, 01192 long n) 01193 { 01194 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n); 01195 } 01196 01203 long 01204 _dbus_transport_get_max_message_size (DBusTransport *transport) 01205 { 01206 return _dbus_message_loader_get_max_message_size (transport->loader); 01207 } 01208 01215 long 01216 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport) 01217 { 01218 return _dbus_message_loader_get_max_message_unix_fds (transport->loader); 01219 } 01220 01227 void 01228 _dbus_transport_set_max_received_size (DBusTransport *transport, 01229 long size) 01230 { 01231 transport->max_live_messages_size = size; 01232 _dbus_counter_set_notify (transport->live_messages, 01233 transport->max_live_messages_size, 01234 transport->max_live_messages_unix_fds, 01235 live_messages_notify, 01236 transport); 01237 } 01238 01245 void 01246 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport, 01247 long n) 01248 { 01249 transport->max_live_messages_unix_fds = n; 01250 _dbus_counter_set_notify (transport->live_messages, 01251 transport->max_live_messages_size, 01252 transport->max_live_messages_unix_fds, 01253 live_messages_notify, 01254 transport); 01255 } 01256 01263 long 01264 _dbus_transport_get_max_received_size (DBusTransport *transport) 01265 { 01266 return transport->max_live_messages_size; 01267 } 01268 01275 long 01276 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport) 01277 { 01278 return transport->max_live_messages_unix_fds; 01279 } 01280 01288 dbus_bool_t 01289 _dbus_transport_get_unix_user (DBusTransport *transport, 01290 unsigned long *uid) 01291 { 01292 DBusCredentials *auth_identity; 01293 01294 *uid = _DBUS_INT32_MAX; /* better than some root or system user in 01295 * case of bugs in the caller. Caller should 01296 * never use this value on purpose, however. 01297 */ 01298 01299 if (!transport->authenticated) 01300 return FALSE; 01301 01302 auth_identity = _dbus_auth_get_identity (transport->auth); 01303 01304 if (_dbus_credentials_include (auth_identity, 01305 DBUS_CREDENTIAL_UNIX_USER_ID)) 01306 { 01307 *uid = _dbus_credentials_get_unix_uid (auth_identity); 01308 return TRUE; 01309 } 01310 else 01311 return FALSE; 01312 } 01313 01321 dbus_bool_t 01322 _dbus_transport_get_unix_process_id (DBusTransport *transport, 01323 unsigned long *pid) 01324 { 01325 DBusCredentials *auth_identity; 01326 01327 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose, 01328 * but we set it to a safe number, INT_MAX, 01329 * just to root out possible bugs in bad callers. 01330 */ 01331 01332 if (!transport->authenticated) 01333 return FALSE; 01334 01335 auth_identity = _dbus_auth_get_identity (transport->auth); 01336 01337 if (_dbus_credentials_include (auth_identity, 01338 DBUS_CREDENTIAL_UNIX_PROCESS_ID)) 01339 { 01340 *pid = _dbus_credentials_get_unix_pid (auth_identity); 01341 return TRUE; 01342 } 01343 else 01344 return FALSE; 01345 } 01346 01355 dbus_bool_t 01356 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, 01357 void **data, 01358 int *data_size) 01359 { 01360 DBusCredentials *auth_identity; 01361 01362 *data = NULL; 01363 *data_size = 0; 01364 01365 if (!transport->authenticated) 01366 return FALSE; 01367 01368 auth_identity = _dbus_auth_get_identity (transport->auth); 01369 01370 if (_dbus_credentials_include (auth_identity, 01371 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) 01372 { 01373 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); 01374 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); 01375 return TRUE; 01376 } 01377 else 01378 return FALSE; 01379 } 01380 01391 void 01392 _dbus_transport_set_unix_user_function (DBusTransport *transport, 01393 DBusAllowUnixUserFunction function, 01394 void *data, 01395 DBusFreeFunction free_data_function, 01396 void **old_data, 01397 DBusFreeFunction *old_free_data_function) 01398 { 01399 *old_data = transport->unix_user_data; 01400 *old_free_data_function = transport->free_unix_user_data; 01401 01402 transport->unix_user_function = function; 01403 transport->unix_user_data = data; 01404 transport->free_unix_user_data = free_data_function; 01405 } 01406 01414 dbus_bool_t 01415 _dbus_transport_get_windows_user (DBusTransport *transport, 01416 char **windows_sid_p) 01417 { 01418 DBusCredentials *auth_identity; 01419 01420 *windows_sid_p = NULL; 01421 01422 if (!transport->authenticated) 01423 return FALSE; 01424 01425 auth_identity = _dbus_auth_get_identity (transport->auth); 01426 01427 if (_dbus_credentials_include (auth_identity, 01428 DBUS_CREDENTIAL_WINDOWS_SID)) 01429 { 01430 /* If no memory, we are supposed to return TRUE and set NULL */ 01431 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 01432 01433 return TRUE; 01434 } 01435 else 01436 return FALSE; 01437 } 01438 01450 void 01451 _dbus_transport_set_windows_user_function (DBusTransport *transport, 01452 DBusAllowWindowsUserFunction function, 01453 void *data, 01454 DBusFreeFunction free_data_function, 01455 void **old_data, 01456 DBusFreeFunction *old_free_data_function) 01457 { 01458 *old_data = transport->windows_user_data; 01459 *old_free_data_function = transport->free_windows_user_data; 01460 01461 transport->windows_user_function = function; 01462 transport->windows_user_data = data; 01463 transport->free_windows_user_data = free_data_function; 01464 } 01465 01474 dbus_bool_t 01475 _dbus_transport_set_auth_mechanisms (DBusTransport *transport, 01476 const char **mechanisms) 01477 { 01478 return _dbus_auth_set_mechanisms (transport->auth, mechanisms); 01479 } 01480 01487 void 01488 _dbus_transport_set_allow_anonymous (DBusTransport *transport, 01489 dbus_bool_t value) 01490 { 01491 transport->allow_anonymous = value != FALSE; 01492 } 01493 01494 #ifdef DBUS_ENABLE_STATS 01495 void 01496 _dbus_transport_get_stats (DBusTransport *transport, 01497 dbus_uint32_t *queue_bytes, 01498 dbus_uint32_t *queue_fds, 01499 dbus_uint32_t *peak_queue_bytes, 01500 dbus_uint32_t *peak_queue_fds) 01501 { 01502 if (queue_bytes != NULL) 01503 *queue_bytes = _dbus_counter_get_size_value (transport->live_messages); 01504 01505 if (queue_fds != NULL) 01506 *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages); 01507 01508 if (peak_queue_bytes != NULL) 01509 *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages); 01510 01511 if (peak_queue_fds != NULL) 01512 *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages); 01513 } 01514 #endif /* DBUS_ENABLE_STATS */ 01515