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