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