D-Bus 1.4.0
|
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-message-private.h" 00034 #include "dbus-marshal-header.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 (* transport->vtable->live_messages_changed) (transport); 00080 00081 _dbus_transport_unref (transport); 00082 } 00083 00097 dbus_bool_t 00098 _dbus_transport_init_base (DBusTransport *transport, 00099 const DBusTransportVTable *vtable, 00100 const DBusString *server_guid, 00101 const DBusString *address) 00102 { 00103 DBusMessageLoader *loader; 00104 DBusAuth *auth; 00105 DBusCounter *counter; 00106 char *address_copy; 00107 DBusCredentials *creds; 00108 00109 loader = _dbus_message_loader_new (); 00110 if (loader == NULL) 00111 return FALSE; 00112 00113 if (server_guid) 00114 auth = _dbus_auth_server_new (server_guid); 00115 else 00116 auth = _dbus_auth_client_new (); 00117 if (auth == NULL) 00118 { 00119 _dbus_message_loader_unref (loader); 00120 return FALSE; 00121 } 00122 00123 counter = _dbus_counter_new (); 00124 if (counter == NULL) 00125 { 00126 _dbus_auth_unref (auth); 00127 _dbus_message_loader_unref (loader); 00128 return FALSE; 00129 } 00130 00131 creds = _dbus_credentials_new (); 00132 if (creds == NULL) 00133 { 00134 _dbus_counter_unref (counter); 00135 _dbus_auth_unref (auth); 00136 _dbus_message_loader_unref (loader); 00137 return FALSE; 00138 } 00139 00140 if (server_guid) 00141 { 00142 _dbus_assert (address == NULL); 00143 address_copy = NULL; 00144 } 00145 else 00146 { 00147 _dbus_assert (address != NULL); 00148 00149 if (!_dbus_string_copy_data (address, &address_copy)) 00150 { 00151 _dbus_credentials_unref (creds); 00152 _dbus_counter_unref (counter); 00153 _dbus_auth_unref (auth); 00154 _dbus_message_loader_unref (loader); 00155 return FALSE; 00156 } 00157 } 00158 00159 transport->refcount = 1; 00160 transport->vtable = vtable; 00161 transport->loader = loader; 00162 transport->auth = auth; 00163 transport->live_messages = counter; 00164 transport->authenticated = FALSE; 00165 transport->disconnected = FALSE; 00166 transport->is_server = (server_guid != NULL); 00167 transport->send_credentials_pending = !transport->is_server; 00168 transport->receive_credentials_pending = transport->is_server; 00169 transport->address = address_copy; 00170 00171 transport->unix_user_function = NULL; 00172 transport->unix_user_data = NULL; 00173 transport->free_unix_user_data = NULL; 00174 00175 transport->windows_user_function = NULL; 00176 transport->windows_user_data = NULL; 00177 transport->free_windows_user_data = NULL; 00178 00179 transport->expected_guid = NULL; 00180 00181 /* Try to default to something that won't totally hose the system, 00182 * but doesn't impose too much of a limitation. 00183 */ 00184 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; 00185 00186 /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live 00187 should be more than enough */ 00188 transport->max_live_messages_unix_fds = 4096; 00189 00190 /* credentials read from socket if any */ 00191 transport->credentials = creds; 00192 00193 _dbus_counter_set_notify (transport->live_messages, 00194 transport->max_live_messages_size, 00195 transport->max_live_messages_unix_fds, 00196 live_messages_notify, 00197 transport); 00198 00199 if (transport->address) 00200 _dbus_verbose ("Initialized transport on address %s\n", transport->address); 00201 00202 return TRUE; 00203 } 00204 00211 void 00212 _dbus_transport_finalize_base (DBusTransport *transport) 00213 { 00214 if (!transport->disconnected) 00215 _dbus_transport_disconnect (transport); 00216 00217 if (transport->free_unix_user_data != NULL) 00218 (* transport->free_unix_user_data) (transport->unix_user_data); 00219 00220 if (transport->free_windows_user_data != NULL) 00221 (* transport->free_windows_user_data) (transport->windows_user_data); 00222 00223 _dbus_message_loader_unref (transport->loader); 00224 _dbus_auth_unref (transport->auth); 00225 _dbus_counter_set_notify (transport->live_messages, 00226 0, 0, NULL, NULL); 00227 _dbus_counter_unref (transport->live_messages); 00228 dbus_free (transport->address); 00229 dbus_free (transport->expected_guid); 00230 if (transport->credentials) 00231 _dbus_credentials_unref (transport->credentials); 00232 } 00233 00234 00244 static DBusTransport* 00245 check_address (const char *address, DBusError *error) 00246 { 00247 DBusAddressEntry **entries; 00248 DBusTransport *transport = NULL; 00249 int len, i; 00250 00251 _dbus_assert (address != NULL); 00252 _dbus_assert (*address != '\0'); 00253 00254 if (!dbus_parse_address (address, &entries, &len, error)) 00255 return NULL; /* not a valid address */ 00256 00257 for (i = 0; i < len; i++) 00258 { 00259 transport = _dbus_transport_open (entries[i], error); 00260 if (transport != NULL) 00261 break; 00262 } 00263 00264 dbus_address_entries_free (entries); 00265 return transport; 00266 } 00267 00275 static DBusTransport* 00276 _dbus_transport_new_for_autolaunch (DBusError *error) 00277 { 00278 DBusString address; 00279 DBusTransport *result = NULL; 00280 00281 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00282 00283 if (!_dbus_string_init (&address)) 00284 { 00285 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00286 return NULL; 00287 } 00288 00289 if (!_dbus_get_autolaunch_address (&address, error)) 00290 { 00291 _DBUS_ASSERT_ERROR_IS_SET (error); 00292 goto out; 00293 } 00294 00295 result = check_address (_dbus_string_get_const_data (&address), error); 00296 if (result == NULL) 00297 _DBUS_ASSERT_ERROR_IS_SET (error); 00298 else 00299 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00300 00301 out: 00302 _dbus_string_free (&address); 00303 return result; 00304 } 00305 00306 static DBusTransportOpenResult 00307 _dbus_transport_open_autolaunch (DBusAddressEntry *entry, 00308 DBusTransport **transport_p, 00309 DBusError *error) 00310 { 00311 const char *method; 00312 00313 method = dbus_address_entry_get_method (entry); 00314 _dbus_assert (method != NULL); 00315 00316 if (strcmp (method, "autolaunch") == 0) 00317 { 00318 *transport_p = _dbus_transport_new_for_autolaunch (error); 00319 00320 if (*transport_p == NULL) 00321 { 00322 _DBUS_ASSERT_ERROR_IS_SET (error); 00323 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00324 } 00325 else 00326 { 00327 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00328 return DBUS_TRANSPORT_OPEN_OK; 00329 } 00330 } 00331 else 00332 { 00333 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00334 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00335 } 00336 } 00337 00338 static const struct { 00339 DBusTransportOpenResult (* func) (DBusAddressEntry *entry, 00340 DBusTransport **transport_p, 00341 DBusError *error); 00342 } open_funcs[] = { 00343 { _dbus_transport_open_socket }, 00344 { _dbus_transport_open_platform_specific }, 00345 { _dbus_transport_open_autolaunch } 00346 #ifdef DBUS_BUILD_TESTS 00347 , { _dbus_transport_open_debug_pipe } 00348 #endif 00349 }; 00350 00359 DBusTransport* 00360 _dbus_transport_open (DBusAddressEntry *entry, 00361 DBusError *error) 00362 { 00363 DBusTransport *transport; 00364 const char *expected_guid_orig; 00365 char *expected_guid; 00366 int i; 00367 DBusError tmp_error = DBUS_ERROR_INIT; 00368 00369 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00370 00371 transport = NULL; 00372 expected_guid_orig = dbus_address_entry_get_value (entry, "guid"); 00373 expected_guid = _dbus_strdup (expected_guid_orig); 00374 00375 if (expected_guid_orig != NULL && expected_guid == NULL) 00376 { 00377 _DBUS_SET_OOM (error); 00378 return NULL; 00379 } 00380 00381 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i) 00382 { 00383 DBusTransportOpenResult result; 00384 00385 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00386 result = (* open_funcs[i].func) (entry, &transport, &tmp_error); 00387 00388 switch (result) 00389 { 00390 case DBUS_TRANSPORT_OPEN_OK: 00391 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00392 goto out; 00393 break; 00394 case DBUS_TRANSPORT_OPEN_NOT_HANDLED: 00395 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00396 /* keep going through the loop of open funcs */ 00397 break; 00398 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS: 00399 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00400 goto out; 00401 break; 00402 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT: 00403 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00404 goto out; 00405 break; 00406 } 00407 } 00408 00409 out: 00410 00411 if (transport == NULL) 00412 { 00413 if (!dbus_error_is_set (&tmp_error)) 00414 _dbus_set_bad_address (&tmp_error, 00415 NULL, NULL, 00416 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")"); 00417 00418 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00419 dbus_move_error(&tmp_error, error); 00420 dbus_free (expected_guid); 00421 } 00422 else 00423 { 00424 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00425 00426 /* In the case of autostart the initial guid is NULL 00427 * and the autostart transport recursively calls 00428 * _dbus_open_transport wich returns a transport 00429 * with a guid. That guid is the definitive one. 00430 * 00431 * FIXME: if more transports are added they may have 00432 * an effect on the expected_guid semantics (i.e. 00433 * expected_guid and transport->expected_guid may 00434 * both have values). This is very unlikely though 00435 * we should either throw asserts here for those 00436 * corner cases or refactor the code so it is 00437 * clearer on what is expected and what is not 00438 */ 00439 if(expected_guid) 00440 transport->expected_guid = expected_guid; 00441 } 00442 00443 return transport; 00444 } 00445 00452 DBusTransport * 00453 _dbus_transport_ref (DBusTransport *transport) 00454 { 00455 _dbus_assert (transport->refcount > 0); 00456 00457 transport->refcount += 1; 00458 00459 return transport; 00460 } 00461 00469 void 00470 _dbus_transport_unref (DBusTransport *transport) 00471 { 00472 _dbus_assert (transport != NULL); 00473 _dbus_assert (transport->refcount > 0); 00474 00475 transport->refcount -= 1; 00476 if (transport->refcount == 0) 00477 { 00478 _dbus_verbose ("finalizing\n"); 00479 00480 _dbus_assert (transport->vtable->finalize != NULL); 00481 00482 (* transport->vtable->finalize) (transport); 00483 } 00484 } 00485 00494 void 00495 _dbus_transport_disconnect (DBusTransport *transport) 00496 { 00497 _dbus_verbose ("start\n"); 00498 00499 _dbus_assert (transport->vtable->disconnect != NULL); 00500 00501 if (transport->disconnected) 00502 return; 00503 00504 (* transport->vtable->disconnect) (transport); 00505 00506 transport->disconnected = TRUE; 00507 00508 _dbus_verbose ("end\n"); 00509 } 00510 00519 dbus_bool_t 00520 _dbus_transport_get_is_connected (DBusTransport *transport) 00521 { 00522 return !transport->disconnected; 00523 } 00524 00525 static dbus_bool_t 00526 auth_via_unix_user_function (DBusTransport *transport) 00527 { 00528 DBusCredentials *auth_identity; 00529 dbus_bool_t allow; 00530 DBusConnection *connection; 00531 DBusAllowUnixUserFunction unix_user_function; 00532 void *unix_user_data; 00533 dbus_uid_t uid; 00534 00535 /* Dropping the lock here probably isn't that safe. */ 00536 00537 auth_identity = _dbus_auth_get_identity (transport->auth); 00538 _dbus_assert (auth_identity != NULL); 00539 00540 connection = transport->connection; 00541 unix_user_function = transport->unix_user_function; 00542 unix_user_data = transport->unix_user_data; 00543 uid = _dbus_credentials_get_unix_uid (auth_identity); 00544 00545 _dbus_verbose ("unlock\n"); 00546 _dbus_connection_unlock (connection); 00547 00548 allow = (* unix_user_function) (connection, 00549 uid, 00550 unix_user_data); 00551 00552 _dbus_verbose ("lock post unix user function\n"); 00553 _dbus_connection_lock (connection); 00554 00555 if (allow) 00556 { 00557 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); 00558 } 00559 else 00560 { 00561 _dbus_verbose ("Client UID "DBUS_UID_FORMAT 00562 " was rejected, disconnecting\n", 00563 _dbus_credentials_get_unix_uid (auth_identity)); 00564 _dbus_transport_disconnect (transport); 00565 } 00566 00567 return allow; 00568 } 00569 00570 static dbus_bool_t 00571 auth_via_windows_user_function (DBusTransport *transport) 00572 { 00573 DBusCredentials *auth_identity; 00574 dbus_bool_t allow; 00575 DBusConnection *connection; 00576 DBusAllowWindowsUserFunction windows_user_function; 00577 void *windows_user_data; 00578 char *windows_sid; 00579 00580 /* Dropping the lock here probably isn't that safe. */ 00581 00582 auth_identity = _dbus_auth_get_identity (transport->auth); 00583 _dbus_assert (auth_identity != NULL); 00584 00585 connection = transport->connection; 00586 windows_user_function = transport->windows_user_function; 00587 windows_user_data = transport->unix_user_data; 00588 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 00589 00590 if (windows_sid == NULL) 00591 { 00592 /* OOM */ 00593 return FALSE; 00594 } 00595 00596 _dbus_verbose ("unlock\n"); 00597 _dbus_connection_unlock (connection); 00598 00599 allow = (* windows_user_function) (connection, 00600 windows_sid, 00601 windows_user_data); 00602 00603 _dbus_verbose ("lock post windows user function\n"); 00604 _dbus_connection_lock (connection); 00605 00606 if (allow) 00607 { 00608 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); 00609 } 00610 else 00611 { 00612 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", 00613 _dbus_credentials_get_windows_sid (auth_identity)); 00614 _dbus_transport_disconnect (transport); 00615 } 00616 00617 return allow; 00618 } 00619 00620 static dbus_bool_t 00621 auth_via_default_rules (DBusTransport *transport) 00622 { 00623 DBusCredentials *auth_identity; 00624 DBusCredentials *our_identity; 00625 dbus_bool_t allow; 00626 00627 auth_identity = _dbus_auth_get_identity (transport->auth); 00628 _dbus_assert (auth_identity != NULL); 00629 00630 /* By default, connection is allowed if the client is 1) root or 2) 00631 * has the same UID as us or 3) anonymous is allowed. 00632 */ 00633 00634 our_identity = _dbus_credentials_new_from_current_process (); 00635 if (our_identity == NULL) 00636 { 00637 /* OOM */ 00638 return FALSE; 00639 } 00640 00641 if (transport->allow_anonymous || 00642 _dbus_credentials_get_unix_uid (auth_identity) == 0 || 00643 _dbus_credentials_same_user (our_identity, 00644 auth_identity)) 00645 { 00646 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00647 _dbus_verbose ("Client authorized as SID '%s'" 00648 "matching our SID '%s'\n", 00649 _dbus_credentials_get_windows_sid(auth_identity), 00650 _dbus_credentials_get_windows_sid(our_identity)); 00651 else 00652 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00653 " matching our UID "DBUS_UID_FORMAT"\n", 00654 _dbus_credentials_get_unix_uid(auth_identity), 00655 _dbus_credentials_get_unix_uid(our_identity)); 00656 /* We have authenticated! */ 00657 allow = TRUE; 00658 } 00659 else 00660 { 00661 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID)) 00662 _dbus_verbose ("Client authorized as SID '%s'" 00663 " but our SID is '%s', disconnecting\n", 00664 (_dbus_credentials_get_windows_sid(auth_identity) ? 00665 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"), 00666 (_dbus_credentials_get_windows_sid(our_identity) ? 00667 _dbus_credentials_get_windows_sid(our_identity) : "<null>")); 00668 else 00669 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT 00670 " but our UID is "DBUS_UID_FORMAT", disconnecting\n", 00671 _dbus_credentials_get_unix_uid(auth_identity), 00672 _dbus_credentials_get_unix_uid(our_identity)); 00673 _dbus_transport_disconnect (transport); 00674 allow = FALSE; 00675 } 00676 00677 _dbus_credentials_unref (our_identity); 00678 00679 return allow; 00680 } 00681 00682 00693 dbus_bool_t 00694 _dbus_transport_get_is_authenticated (DBusTransport *transport) 00695 { 00696 if (transport->authenticated) 00697 return TRUE; 00698 else 00699 { 00700 dbus_bool_t maybe_authenticated; 00701 00702 if (transport->disconnected) 00703 return FALSE; 00704 00705 /* paranoia ref since we call user callbacks sometimes */ 00706 _dbus_connection_ref_unlocked (transport->connection); 00707 00708 maybe_authenticated = 00709 (!(transport->send_credentials_pending || 00710 transport->receive_credentials_pending)); 00711 00712 if (maybe_authenticated) 00713 { 00714 switch (_dbus_auth_do_work (transport->auth)) 00715 { 00716 case DBUS_AUTH_STATE_AUTHENTICATED: 00717 /* leave as maybe_authenticated */ 00718 break; 00719 default: 00720 maybe_authenticated = FALSE; 00721 } 00722 } 00723 00724 /* If we're the client, verify the GUID 00725 */ 00726 if (maybe_authenticated && !transport->is_server) 00727 { 00728 const char *server_guid; 00729 00730 server_guid = _dbus_auth_get_guid_from_server (transport->auth); 00731 _dbus_assert (server_guid != NULL); 00732 00733 if (transport->expected_guid && 00734 strcmp (transport->expected_guid, server_guid) != 0) 00735 { 00736 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n", 00737 transport->expected_guid, server_guid); 00738 _dbus_transport_disconnect (transport); 00739 _dbus_connection_unref_unlocked (transport->connection); 00740 return FALSE; 00741 } 00742 00743 if (transport->expected_guid == NULL) 00744 { 00745 transport->expected_guid = _dbus_strdup (server_guid); 00746 00747 if (transport->expected_guid == NULL) 00748 { 00749 _dbus_verbose ("No memory to complete auth\n"); 00750 return FALSE; 00751 } 00752 } 00753 } 00754 00755 /* If we're the server, see if we want to allow this identity to proceed. 00756 */ 00757 if (maybe_authenticated && transport->is_server) 00758 { 00759 dbus_bool_t allow; 00760 DBusCredentials *auth_identity; 00761 00762 auth_identity = _dbus_auth_get_identity (transport->auth); 00763 _dbus_assert (auth_identity != NULL); 00764 00765 /* If we have an auth'd user and a user function, delegate 00766 * deciding whether auth credentials are good enough to the 00767 * app; otherwise, use our default decision process. 00768 */ 00769 if (transport->unix_user_function != NULL && 00770 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) 00771 { 00772 allow = auth_via_unix_user_function (transport); 00773 } 00774 else if (transport->windows_user_function != NULL && 00775 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) 00776 { 00777 allow = auth_via_windows_user_function (transport); 00778 } 00779 else 00780 { 00781 allow = auth_via_default_rules (transport); 00782 } 00783 00784 if (!allow) 00785 maybe_authenticated = FALSE; 00786 } 00787 00788 transport->authenticated = maybe_authenticated; 00789 00790 _dbus_connection_unref_unlocked (transport->connection); 00791 return maybe_authenticated; 00792 } 00793 } 00794 00801 dbus_bool_t 00802 _dbus_transport_get_is_anonymous (DBusTransport *transport) 00803 { 00804 DBusCredentials *auth_identity; 00805 00806 if (!transport->authenticated) 00807 return TRUE; 00808 00809 auth_identity = _dbus_auth_get_identity (transport->auth); 00810 00811 if (_dbus_credentials_are_anonymous (auth_identity)) 00812 return TRUE; 00813 else 00814 return FALSE; 00815 } 00816 00823 dbus_bool_t 00824 _dbus_transport_can_pass_unix_fd(DBusTransport *transport) 00825 { 00826 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport); 00827 } 00828 00836 const char* 00837 _dbus_transport_get_address (DBusTransport *transport) 00838 { 00839 return transport->address; 00840 } 00841 00849 const char* 00850 _dbus_transport_get_server_id (DBusTransport *transport) 00851 { 00852 if (transport->is_server) 00853 return NULL; 00854 else 00855 return transport->expected_guid; 00856 } 00857 00867 dbus_bool_t 00868 _dbus_transport_handle_watch (DBusTransport *transport, 00869 DBusWatch *watch, 00870 unsigned int condition) 00871 { 00872 dbus_bool_t retval; 00873 00874 _dbus_assert (transport->vtable->handle_watch != NULL); 00875 00876 if (transport->disconnected) 00877 return TRUE; 00878 00879 if (dbus_watch_get_socket (watch) < 0) 00880 { 00881 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n"); 00882 return TRUE; 00883 } 00884 00885 _dbus_watch_sanitize_condition (watch, &condition); 00886 00887 _dbus_transport_ref (transport); 00888 _dbus_watch_ref (watch); 00889 retval = (* transport->vtable->handle_watch) (transport, watch, condition); 00890 _dbus_watch_unref (watch); 00891 _dbus_transport_unref (transport); 00892 00893 return retval; 00894 } 00895 00905 dbus_bool_t 00906 _dbus_transport_set_connection (DBusTransport *transport, 00907 DBusConnection *connection) 00908 { 00909 _dbus_assert (transport->vtable->connection_set != NULL); 00910 _dbus_assert (transport->connection == NULL); 00911 00912 transport->connection = connection; 00913 00914 _dbus_transport_ref (transport); 00915 if (!(* transport->vtable->connection_set) (transport)) 00916 transport->connection = NULL; 00917 _dbus_transport_unref (transport); 00918 00919 return transport->connection != NULL; 00920 } 00921 00929 dbus_bool_t 00930 _dbus_transport_get_socket_fd (DBusTransport *transport, 00931 int *fd_p) 00932 { 00933 dbus_bool_t retval; 00934 00935 if (transport->vtable->get_socket_fd == NULL) 00936 return FALSE; 00937 00938 if (transport->disconnected) 00939 return FALSE; 00940 00941 _dbus_transport_ref (transport); 00942 00943 retval = (* transport->vtable->get_socket_fd) (transport, 00944 fd_p); 00945 00946 _dbus_transport_unref (transport); 00947 00948 return retval; 00949 } 00950 00962 void 00963 _dbus_transport_do_iteration (DBusTransport *transport, 00964 unsigned int flags, 00965 int timeout_milliseconds) 00966 { 00967 _dbus_assert (transport->vtable->do_iteration != NULL); 00968 00969 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n", 00970 flags, timeout_milliseconds, !transport->disconnected); 00971 00972 if ((flags & (DBUS_ITERATION_DO_WRITING | 00973 DBUS_ITERATION_DO_READING)) == 0) 00974 return; /* Nothing to do */ 00975 00976 if (transport->disconnected) 00977 return; 00978 00979 _dbus_transport_ref (transport); 00980 (* transport->vtable->do_iteration) (transport, flags, 00981 timeout_milliseconds); 00982 _dbus_transport_unref (transport); 00983 00984 _dbus_verbose ("end\n"); 00985 } 00986 00987 static dbus_bool_t 00988 recover_unused_bytes (DBusTransport *transport) 00989 { 00990 if (_dbus_auth_needs_decoding (transport->auth)) 00991 { 00992 DBusString plaintext; 00993 const DBusString *encoded; 00994 DBusString *buffer; 00995 int orig_len; 00996 00997 if (!_dbus_string_init (&plaintext)) 00998 goto nomem; 00999 01000 _dbus_auth_get_unused_bytes (transport->auth, 01001 &encoded); 01002 01003 if (!_dbus_auth_decode_data (transport->auth, 01004 encoded, &plaintext)) 01005 { 01006 _dbus_string_free (&plaintext); 01007 goto nomem; 01008 } 01009 01010 _dbus_message_loader_get_buffer (transport->loader, 01011 &buffer); 01012 01013 orig_len = _dbus_string_get_length (buffer); 01014 01015 if (!_dbus_string_move (&plaintext, 0, buffer, 01016 orig_len)) 01017 { 01018 _dbus_string_free (&plaintext); 01019 goto nomem; 01020 } 01021 01022 _dbus_verbose (" %d unused bytes sent to message loader\n", 01023 _dbus_string_get_length (buffer) - 01024 orig_len); 01025 01026 _dbus_message_loader_return_buffer (transport->loader, 01027 buffer, 01028 _dbus_string_get_length (buffer) - 01029 orig_len); 01030 01031 _dbus_auth_delete_unused_bytes (transport->auth); 01032 01033 _dbus_string_free (&plaintext); 01034 } 01035 else 01036 { 01037 const DBusString *bytes; 01038 DBusString *buffer; 01039 int orig_len; 01040 dbus_bool_t succeeded; 01041 01042 _dbus_message_loader_get_buffer (transport->loader, 01043 &buffer); 01044 01045 orig_len = _dbus_string_get_length (buffer); 01046 01047 _dbus_auth_get_unused_bytes (transport->auth, 01048 &bytes); 01049 01050 succeeded = TRUE; 01051 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer))) 01052 succeeded = FALSE; 01053 01054 _dbus_verbose (" %d unused bytes sent to message loader\n", 01055 _dbus_string_get_length (buffer) - 01056 orig_len); 01057 01058 _dbus_message_loader_return_buffer (transport->loader, 01059 buffer, 01060 _dbus_string_get_length (buffer) - 01061 orig_len); 01062 01063 if (succeeded) 01064 _dbus_auth_delete_unused_bytes (transport->auth); 01065 else 01066 goto nomem; 01067 } 01068 01069 return TRUE; 01070 01071 nomem: 01072 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n"); 01073 return FALSE; 01074 } 01075 01083 DBusDispatchStatus 01084 _dbus_transport_get_dispatch_status (DBusTransport *transport) 01085 { 01086 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size || 01087 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) 01088 return DBUS_DISPATCH_COMPLETE; /* complete for now */ 01089 01090 if (!_dbus_transport_get_is_authenticated (transport)) 01091 { 01092 if (_dbus_auth_do_work (transport->auth) == 01093 DBUS_AUTH_STATE_WAITING_FOR_MEMORY) 01094 return DBUS_DISPATCH_NEED_MEMORY; 01095 else if (!_dbus_transport_get_is_authenticated (transport)) 01096 return DBUS_DISPATCH_COMPLETE; 01097 } 01098 01099 if (!transport->unused_bytes_recovered && 01100 !recover_unused_bytes (transport)) 01101 return DBUS_DISPATCH_NEED_MEMORY; 01102 01103 transport->unused_bytes_recovered = TRUE; 01104 01105 if (!_dbus_message_loader_queue_messages (transport->loader)) 01106 return DBUS_DISPATCH_NEED_MEMORY; 01107 01108 if (_dbus_message_loader_peek_message (transport->loader) != NULL) 01109 return DBUS_DISPATCH_DATA_REMAINS; 01110 else 01111 return DBUS_DISPATCH_COMPLETE; 01112 } 01113 01122 dbus_bool_t 01123 _dbus_transport_queue_messages (DBusTransport *transport) 01124 { 01125 DBusDispatchStatus status; 01126 01127 #if 0 01128 _dbus_verbose ("_dbus_transport_queue_messages()\n"); 01129 #endif 01130 01131 /* Queue any messages */ 01132 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS) 01133 { 01134 DBusMessage *message; 01135 DBusList *link; 01136 01137 link = _dbus_message_loader_pop_message_link (transport->loader); 01138 _dbus_assert (link != NULL); 01139 01140 message = link->data; 01141 01142 _dbus_verbose ("queueing received message %p\n", message); 01143 01144 if (!_dbus_message_add_counter (message, transport->live_messages)) 01145 { 01146 _dbus_message_loader_putback_message_link (transport->loader, 01147 link); 01148 status = DBUS_DISPATCH_NEED_MEMORY; 01149 break; 01150 } 01151 else 01152 { 01153 /* pass ownership of link and message ref to connection */ 01154 _dbus_connection_queue_received_message_link (transport->connection, 01155 link); 01156 } 01157 } 01158 01159 if (_dbus_message_loader_get_is_corrupted (transport->loader)) 01160 { 01161 _dbus_verbose ("Corrupted message stream, disconnecting\n"); 01162 _dbus_transport_disconnect (transport); 01163 } 01164 01165 return status != DBUS_DISPATCH_NEED_MEMORY; 01166 } 01167 01174 void 01175 _dbus_transport_set_max_message_size (DBusTransport *transport, 01176 long size) 01177 { 01178 _dbus_message_loader_set_max_message_size (transport->loader, size); 01179 } 01180 01187 void 01188 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport, 01189 long n) 01190 { 01191 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n); 01192 } 01193 01200 long 01201 _dbus_transport_get_max_message_size (DBusTransport *transport) 01202 { 01203 return _dbus_message_loader_get_max_message_size (transport->loader); 01204 } 01205 01212 long 01213 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport) 01214 { 01215 return _dbus_message_loader_get_max_message_unix_fds (transport->loader); 01216 } 01217 01224 void 01225 _dbus_transport_set_max_received_size (DBusTransport *transport, 01226 long size) 01227 { 01228 transport->max_live_messages_size = size; 01229 _dbus_counter_set_notify (transport->live_messages, 01230 transport->max_live_messages_size, 01231 transport->max_live_messages_unix_fds, 01232 live_messages_notify, 01233 transport); 01234 } 01235 01242 void 01243 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport, 01244 long n) 01245 { 01246 transport->max_live_messages_unix_fds = n; 01247 _dbus_counter_set_notify (transport->live_messages, 01248 transport->max_live_messages_size, 01249 transport->max_live_messages_unix_fds, 01250 live_messages_notify, 01251 transport); 01252 } 01253 01260 long 01261 _dbus_transport_get_max_received_size (DBusTransport *transport) 01262 { 01263 return transport->max_live_messages_size; 01264 } 01265 01272 long 01273 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport) 01274 { 01275 return transport->max_live_messages_unix_fds; 01276 } 01277 01285 dbus_bool_t 01286 _dbus_transport_get_unix_user (DBusTransport *transport, 01287 unsigned long *uid) 01288 { 01289 DBusCredentials *auth_identity; 01290 01291 *uid = _DBUS_INT32_MAX; /* better than some root or system user in 01292 * case of bugs in the caller. Caller should 01293 * never use this value on purpose, however. 01294 */ 01295 01296 if (!transport->authenticated) 01297 return FALSE; 01298 01299 auth_identity = _dbus_auth_get_identity (transport->auth); 01300 01301 if (_dbus_credentials_include (auth_identity, 01302 DBUS_CREDENTIAL_UNIX_USER_ID)) 01303 { 01304 *uid = _dbus_credentials_get_unix_uid (auth_identity); 01305 return TRUE; 01306 } 01307 else 01308 return FALSE; 01309 } 01310 01318 dbus_bool_t 01319 _dbus_transport_get_unix_process_id (DBusTransport *transport, 01320 unsigned long *pid) 01321 { 01322 DBusCredentials *auth_identity; 01323 01324 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose, 01325 * but we set it to a safe number, INT_MAX, 01326 * just to root out possible bugs in bad callers. 01327 */ 01328 01329 if (!transport->authenticated) 01330 return FALSE; 01331 01332 auth_identity = _dbus_auth_get_identity (transport->auth); 01333 01334 if (_dbus_credentials_include (auth_identity, 01335 DBUS_CREDENTIAL_UNIX_PROCESS_ID)) 01336 { 01337 *pid = _dbus_credentials_get_unix_pid (auth_identity); 01338 return TRUE; 01339 } 01340 else 01341 return FALSE; 01342 } 01343 01352 dbus_bool_t 01353 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, 01354 void **data, 01355 int *data_size) 01356 { 01357 DBusCredentials *auth_identity; 01358 01359 *data = NULL; 01360 *data_size = 0; 01361 01362 if (!transport->authenticated) 01363 return FALSE; 01364 01365 auth_identity = _dbus_auth_get_identity (transport->auth); 01366 01367 if (_dbus_credentials_include (auth_identity, 01368 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) 01369 { 01370 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); 01371 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); 01372 return TRUE; 01373 } 01374 else 01375 return FALSE; 01376 } 01377 01388 void 01389 _dbus_transport_set_unix_user_function (DBusTransport *transport, 01390 DBusAllowUnixUserFunction function, 01391 void *data, 01392 DBusFreeFunction free_data_function, 01393 void **old_data, 01394 DBusFreeFunction *old_free_data_function) 01395 { 01396 *old_data = transport->unix_user_data; 01397 *old_free_data_function = transport->free_unix_user_data; 01398 01399 transport->unix_user_function = function; 01400 transport->unix_user_data = data; 01401 transport->free_unix_user_data = free_data_function; 01402 } 01403 01411 dbus_bool_t 01412 _dbus_transport_get_windows_user (DBusTransport *transport, 01413 char **windows_sid_p) 01414 { 01415 DBusCredentials *auth_identity; 01416 01417 *windows_sid_p = NULL; 01418 01419 if (!transport->authenticated) 01420 return FALSE; 01421 01422 auth_identity = _dbus_auth_get_identity (transport->auth); 01423 01424 if (_dbus_credentials_include (auth_identity, 01425 DBUS_CREDENTIAL_WINDOWS_SID)) 01426 { 01427 /* If no memory, we are supposed to return TRUE and set NULL */ 01428 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); 01429 01430 return TRUE; 01431 } 01432 else 01433 return FALSE; 01434 } 01435 01447 void 01448 _dbus_transport_set_windows_user_function (DBusTransport *transport, 01449 DBusAllowWindowsUserFunction function, 01450 void *data, 01451 DBusFreeFunction free_data_function, 01452 void **old_data, 01453 DBusFreeFunction *old_free_data_function) 01454 { 01455 *old_data = transport->windows_user_data; 01456 *old_free_data_function = transport->free_windows_user_data; 01457 01458 transport->windows_user_function = function; 01459 transport->windows_user_data = data; 01460 transport->free_windows_user_data = free_data_function; 01461 } 01462 01471 dbus_bool_t 01472 _dbus_transport_set_auth_mechanisms (DBusTransport *transport, 01473 const char **mechanisms) 01474 { 01475 return _dbus_auth_set_mechanisms (transport->auth, mechanisms); 01476 } 01477 01484 void 01485 _dbus_transport_set_allow_anonymous (DBusTransport *transport, 01486 dbus_bool_t value) 01487 { 01488 transport->allow_anonymous = value != FALSE; 01489 } 01490