00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00077
00078
00079 if (transport->vtable->live_messages_changed)
00080 (* transport->vtable->live_messages_changed) (transport);
00081
00082 _dbus_transport_unref (transport);
00083 }
00084
00098 dbus_bool_t
00099 _dbus_transport_init_base (DBusTransport *transport,
00100 const DBusTransportVTable *vtable,
00101 const DBusString *server_guid,
00102 const DBusString *address)
00103 {
00104 DBusMessageLoader *loader;
00105 DBusAuth *auth;
00106 DBusCounter *counter;
00107 char *address_copy;
00108 DBusCredentials *creds;
00109
00110 loader = _dbus_message_loader_new ();
00111 if (loader == NULL)
00112 return FALSE;
00113
00114 if (server_guid)
00115 auth = _dbus_auth_server_new (server_guid);
00116 else
00117 auth = _dbus_auth_client_new ();
00118 if (auth == NULL)
00119 {
00120 _dbus_message_loader_unref (loader);
00121 return FALSE;
00122 }
00123
00124 counter = _dbus_counter_new ();
00125 if (counter == NULL)
00126 {
00127 _dbus_auth_unref (auth);
00128 _dbus_message_loader_unref (loader);
00129 return FALSE;
00130 }
00131
00132 creds = _dbus_credentials_new ();
00133 if (creds == NULL)
00134 {
00135 _dbus_counter_unref (counter);
00136 _dbus_auth_unref (auth);
00137 _dbus_message_loader_unref (loader);
00138 return FALSE;
00139 }
00140
00141 if (server_guid)
00142 {
00143 _dbus_assert (address == NULL);
00144 address_copy = NULL;
00145 }
00146 else
00147 {
00148 _dbus_assert (address != NULL);
00149
00150 if (!_dbus_string_copy_data (address, &address_copy))
00151 {
00152 _dbus_credentials_unref (creds);
00153 _dbus_counter_unref (counter);
00154 _dbus_auth_unref (auth);
00155 _dbus_message_loader_unref (loader);
00156 return FALSE;
00157 }
00158 }
00159
00160 transport->refcount = 1;
00161 transport->vtable = vtable;
00162 transport->loader = loader;
00163 transport->auth = auth;
00164 transport->live_messages = counter;
00165 transport->authenticated = FALSE;
00166 transport->disconnected = FALSE;
00167 transport->is_server = (server_guid != NULL);
00168 transport->send_credentials_pending = !transport->is_server;
00169 transport->receive_credentials_pending = transport->is_server;
00170 transport->address = address_copy;
00171
00172 transport->unix_user_function = NULL;
00173 transport->unix_user_data = NULL;
00174 transport->free_unix_user_data = NULL;
00175
00176 transport->windows_user_function = NULL;
00177 transport->windows_user_data = NULL;
00178 transport->free_windows_user_data = NULL;
00179
00180 transport->expected_guid = NULL;
00181
00182
00183
00184
00185 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
00186
00187
00188
00189 transport->max_live_messages_unix_fds = 4096;
00190
00191
00192 transport->credentials = creds;
00193
00194 _dbus_counter_set_notify (transport->live_messages,
00195 transport->max_live_messages_size,
00196 transport->max_live_messages_unix_fds,
00197 live_messages_notify,
00198 transport);
00199
00200 if (transport->address)
00201 _dbus_verbose ("Initialized transport on address %s\n", transport->address);
00202
00203 return TRUE;
00204 }
00205
00212 void
00213 _dbus_transport_finalize_base (DBusTransport *transport)
00214 {
00215 if (!transport->disconnected)
00216 _dbus_transport_disconnect (transport);
00217
00218 if (transport->free_unix_user_data != NULL)
00219 (* transport->free_unix_user_data) (transport->unix_user_data);
00220
00221 if (transport->free_windows_user_data != NULL)
00222 (* transport->free_windows_user_data) (transport->windows_user_data);
00223
00224 _dbus_message_loader_unref (transport->loader);
00225 _dbus_auth_unref (transport->auth);
00226 _dbus_counter_set_notify (transport->live_messages,
00227 0, 0, NULL, NULL);
00228 _dbus_counter_unref (transport->live_messages);
00229 dbus_free (transport->address);
00230 dbus_free (transport->expected_guid);
00231 if (transport->credentials)
00232 _dbus_credentials_unref (transport->credentials);
00233 }
00234
00235
00245 static DBusTransport*
00246 check_address (const char *address, DBusError *error)
00247 {
00248 DBusAddressEntry **entries;
00249 DBusTransport *transport = NULL;
00250 int len, i;
00251
00252 _dbus_assert (address != NULL);
00253 _dbus_assert (*address != '\0');
00254
00255 if (!dbus_parse_address (address, &entries, &len, error))
00256 return NULL;
00257
00258 for (i = 0; i < len; i++)
00259 {
00260 transport = _dbus_transport_open (entries[i], error);
00261 if (transport != NULL)
00262 break;
00263 }
00264
00265 dbus_address_entries_free (entries);
00266 return transport;
00267 }
00268
00276 static DBusTransport*
00277 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
00278 {
00279 DBusString address;
00280 DBusTransport *result = NULL;
00281
00282 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00283
00284 if (!_dbus_string_init (&address))
00285 {
00286 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00287 return NULL;
00288 }
00289
00290 if (!_dbus_get_autolaunch_address (scope, &address, error))
00291 {
00292 _DBUS_ASSERT_ERROR_IS_SET (error);
00293 goto out;
00294 }
00295
00296 result = check_address (_dbus_string_get_const_data (&address), error);
00297 if (result == NULL)
00298 _DBUS_ASSERT_ERROR_IS_SET (error);
00299 else
00300 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00301
00302 out:
00303 _dbus_string_free (&address);
00304 return result;
00305 }
00306
00307 static DBusTransportOpenResult
00308 _dbus_transport_open_autolaunch (DBusAddressEntry *entry,
00309 DBusTransport **transport_p,
00310 DBusError *error)
00311 {
00312 const char *method;
00313
00314 method = dbus_address_entry_get_method (entry);
00315 _dbus_assert (method != NULL);
00316
00317 if (strcmp (method, "autolaunch") == 0)
00318 {
00319 const char *scope = dbus_address_entry_get_value (entry, "scope");
00320
00321 *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
00322
00323 if (*transport_p == NULL)
00324 {
00325 _DBUS_ASSERT_ERROR_IS_SET (error);
00326 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00327 }
00328 else
00329 {
00330 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00331 return DBUS_TRANSPORT_OPEN_OK;
00332 }
00333 }
00334 else
00335 {
00336 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00337 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
00338 }
00339 }
00340
00341 static const struct {
00342 DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
00343 DBusTransport **transport_p,
00344 DBusError *error);
00345 } open_funcs[] = {
00346 { _dbus_transport_open_socket },
00347 { _dbus_transport_open_platform_specific },
00348 { _dbus_transport_open_autolaunch }
00349 #ifdef DBUS_BUILD_TESTS
00350 , { _dbus_transport_open_debug_pipe }
00351 #endif
00352 };
00353
00362 DBusTransport*
00363 _dbus_transport_open (DBusAddressEntry *entry,
00364 DBusError *error)
00365 {
00366 DBusTransport *transport;
00367 const char *expected_guid_orig;
00368 char *expected_guid;
00369 int i;
00370 DBusError tmp_error = DBUS_ERROR_INIT;
00371
00372 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00373
00374 transport = NULL;
00375 expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
00376 expected_guid = _dbus_strdup (expected_guid_orig);
00377
00378 if (expected_guid_orig != NULL && expected_guid == NULL)
00379 {
00380 _DBUS_SET_OOM (error);
00381 return NULL;
00382 }
00383
00384 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
00385 {
00386 DBusTransportOpenResult result;
00387
00388 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00389 result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
00390
00391 switch (result)
00392 {
00393 case DBUS_TRANSPORT_OPEN_OK:
00394 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00395 goto out;
00396 break;
00397 case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
00398 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00399
00400 break;
00401 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
00402 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00403 goto out;
00404 break;
00405 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
00406 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00407 goto out;
00408 break;
00409 }
00410 }
00411
00412 out:
00413
00414 if (transport == NULL)
00415 {
00416 if (!dbus_error_is_set (&tmp_error))
00417 _dbus_set_bad_address (&tmp_error,
00418 NULL, NULL,
00419 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
00420
00421 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00422 dbus_move_error(&tmp_error, error);
00423 dbus_free (expected_guid);
00424 }
00425 else
00426 {
00427 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 if(expected_guid)
00443 transport->expected_guid = expected_guid;
00444 }
00445
00446 return transport;
00447 }
00448
00455 DBusTransport *
00456 _dbus_transport_ref (DBusTransport *transport)
00457 {
00458 _dbus_assert (transport->refcount > 0);
00459
00460 transport->refcount += 1;
00461
00462 return transport;
00463 }
00464
00472 void
00473 _dbus_transport_unref (DBusTransport *transport)
00474 {
00475 _dbus_assert (transport != NULL);
00476 _dbus_assert (transport->refcount > 0);
00477
00478 transport->refcount -= 1;
00479 if (transport->refcount == 0)
00480 {
00481 _dbus_verbose ("finalizing\n");
00482
00483 _dbus_assert (transport->vtable->finalize != NULL);
00484
00485 (* transport->vtable->finalize) (transport);
00486 }
00487 }
00488
00497 void
00498 _dbus_transport_disconnect (DBusTransport *transport)
00499 {
00500 _dbus_verbose ("start\n");
00501
00502 _dbus_assert (transport->vtable->disconnect != NULL);
00503
00504 if (transport->disconnected)
00505 return;
00506
00507 (* transport->vtable->disconnect) (transport);
00508
00509 transport->disconnected = TRUE;
00510
00511 _dbus_verbose ("end\n");
00512 }
00513
00522 dbus_bool_t
00523 _dbus_transport_get_is_connected (DBusTransport *transport)
00524 {
00525 return !transport->disconnected;
00526 }
00527
00528 static dbus_bool_t
00529 auth_via_unix_user_function (DBusTransport *transport)
00530 {
00531 DBusCredentials *auth_identity;
00532 dbus_bool_t allow;
00533 DBusConnection *connection;
00534 DBusAllowUnixUserFunction unix_user_function;
00535 void *unix_user_data;
00536 dbus_uid_t uid;
00537
00538
00539
00540 auth_identity = _dbus_auth_get_identity (transport->auth);
00541 _dbus_assert (auth_identity != NULL);
00542
00543 connection = transport->connection;
00544 unix_user_function = transport->unix_user_function;
00545 unix_user_data = transport->unix_user_data;
00546 uid = _dbus_credentials_get_unix_uid (auth_identity);
00547
00548 _dbus_verbose ("unlock\n");
00549 _dbus_connection_unlock (connection);
00550
00551 allow = (* unix_user_function) (connection,
00552 uid,
00553 unix_user_data);
00554
00555 _dbus_verbose ("lock post unix user function\n");
00556 _dbus_connection_lock (connection);
00557
00558 if (allow)
00559 {
00560 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
00561 }
00562 else
00563 {
00564 _dbus_verbose ("Client UID "DBUS_UID_FORMAT
00565 " was rejected, disconnecting\n",
00566 _dbus_credentials_get_unix_uid (auth_identity));
00567 _dbus_transport_disconnect (transport);
00568 }
00569
00570 return allow;
00571 }
00572
00573 static dbus_bool_t
00574 auth_via_windows_user_function (DBusTransport *transport)
00575 {
00576 DBusCredentials *auth_identity;
00577 dbus_bool_t allow;
00578 DBusConnection *connection;
00579 DBusAllowWindowsUserFunction windows_user_function;
00580 void *windows_user_data;
00581 char *windows_sid;
00582
00583
00584
00585 auth_identity = _dbus_auth_get_identity (transport->auth);
00586 _dbus_assert (auth_identity != NULL);
00587
00588 connection = transport->connection;
00589 windows_user_function = transport->windows_user_function;
00590 windows_user_data = transport->unix_user_data;
00591 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
00592
00593 if (windows_sid == NULL)
00594 {
00595
00596 return FALSE;
00597 }
00598
00599 _dbus_verbose ("unlock\n");
00600 _dbus_connection_unlock (connection);
00601
00602 allow = (* windows_user_function) (connection,
00603 windows_sid,
00604 windows_user_data);
00605
00606 _dbus_verbose ("lock post windows user function\n");
00607 _dbus_connection_lock (connection);
00608
00609 if (allow)
00610 {
00611 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
00612 }
00613 else
00614 {
00615 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
00616 _dbus_credentials_get_windows_sid (auth_identity));
00617 _dbus_transport_disconnect (transport);
00618 }
00619
00620 return allow;
00621 }
00622
00623 static dbus_bool_t
00624 auth_via_default_rules (DBusTransport *transport)
00625 {
00626 DBusCredentials *auth_identity;
00627 DBusCredentials *our_identity;
00628 dbus_bool_t allow;
00629
00630 auth_identity = _dbus_auth_get_identity (transport->auth);
00631 _dbus_assert (auth_identity != NULL);
00632
00633
00634
00635
00636
00637 our_identity = _dbus_credentials_new_from_current_process ();
00638 if (our_identity == NULL)
00639 {
00640
00641 return FALSE;
00642 }
00643
00644 if (transport->allow_anonymous ||
00645 _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
00646 _dbus_credentials_same_user (our_identity,
00647 auth_identity))
00648 {
00649 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00650 _dbus_verbose ("Client authorized as SID '%s'"
00651 "matching our SID '%s'\n",
00652 _dbus_credentials_get_windows_sid(auth_identity),
00653 _dbus_credentials_get_windows_sid(our_identity));
00654 else
00655 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00656 " matching our UID "DBUS_UID_FORMAT"\n",
00657 _dbus_credentials_get_unix_uid(auth_identity),
00658 _dbus_credentials_get_unix_uid(our_identity));
00659
00660 allow = TRUE;
00661 }
00662 else
00663 {
00664 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00665 _dbus_verbose ("Client authorized as SID '%s'"
00666 " but our SID is '%s', disconnecting\n",
00667 (_dbus_credentials_get_windows_sid(auth_identity) ?
00668 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
00669 (_dbus_credentials_get_windows_sid(our_identity) ?
00670 _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
00671 else
00672 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00673 " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
00674 _dbus_credentials_get_unix_uid(auth_identity),
00675 _dbus_credentials_get_unix_uid(our_identity));
00676 _dbus_transport_disconnect (transport);
00677 allow = FALSE;
00678 }
00679
00680 _dbus_credentials_unref (our_identity);
00681
00682 return allow;
00683 }
00684
00685
00696 dbus_bool_t
00697 _dbus_transport_get_is_authenticated (DBusTransport *transport)
00698 {
00699 if (transport->authenticated)
00700 return TRUE;
00701 else
00702 {
00703 dbus_bool_t maybe_authenticated;
00704
00705 if (transport->disconnected)
00706 return FALSE;
00707
00708
00709 _dbus_connection_ref_unlocked (transport->connection);
00710
00711 maybe_authenticated =
00712 (!(transport->send_credentials_pending ||
00713 transport->receive_credentials_pending));
00714
00715 if (maybe_authenticated)
00716 {
00717 switch (_dbus_auth_do_work (transport->auth))
00718 {
00719 case DBUS_AUTH_STATE_AUTHENTICATED:
00720
00721 break;
00722 default:
00723 maybe_authenticated = FALSE;
00724 }
00725 }
00726
00727
00728
00729 if (maybe_authenticated && !transport->is_server)
00730 {
00731 const char *server_guid;
00732
00733 server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00734 _dbus_assert (server_guid != NULL);
00735
00736 if (transport->expected_guid &&
00737 strcmp (transport->expected_guid, server_guid) != 0)
00738 {
00739 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00740 transport->expected_guid, server_guid);
00741 _dbus_transport_disconnect (transport);
00742 _dbus_connection_unref_unlocked (transport->connection);
00743 return FALSE;
00744 }
00745 }
00746
00747
00748
00749 if (maybe_authenticated && transport->is_server)
00750 {
00751 dbus_bool_t allow;
00752 DBusCredentials *auth_identity;
00753
00754 auth_identity = _dbus_auth_get_identity (transport->auth);
00755 _dbus_assert (auth_identity != NULL);
00756
00757
00758
00759
00760
00761 if (transport->unix_user_function != NULL &&
00762 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00763 {
00764 allow = auth_via_unix_user_function (transport);
00765 }
00766 else if (transport->windows_user_function != NULL &&
00767 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00768 {
00769 allow = auth_via_windows_user_function (transport);
00770 }
00771 else
00772 {
00773 allow = auth_via_default_rules (transport);
00774 }
00775
00776 if (!allow)
00777 maybe_authenticated = FALSE;
00778 }
00779
00780 transport->authenticated = maybe_authenticated;
00781
00782 _dbus_connection_unref_unlocked (transport->connection);
00783 return maybe_authenticated;
00784 }
00785 }
00786
00793 dbus_bool_t
00794 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00795 {
00796 DBusCredentials *auth_identity;
00797
00798 if (!transport->authenticated)
00799 return TRUE;
00800
00801 auth_identity = _dbus_auth_get_identity (transport->auth);
00802
00803 if (_dbus_credentials_are_anonymous (auth_identity))
00804 return TRUE;
00805 else
00806 return FALSE;
00807 }
00808
00815 dbus_bool_t
00816 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
00817 {
00818 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
00819 }
00820
00828 const char*
00829 _dbus_transport_get_address (DBusTransport *transport)
00830 {
00831 return transport->address;
00832 }
00833
00841 const char*
00842 _dbus_transport_get_server_id (DBusTransport *transport)
00843 {
00844 if (transport->is_server)
00845 return NULL;
00846 else if (transport->authenticated)
00847 return _dbus_auth_get_guid_from_server (transport->auth);
00848 else
00849 return transport->expected_guid;
00850 }
00851
00861 dbus_bool_t
00862 _dbus_transport_handle_watch (DBusTransport *transport,
00863 DBusWatch *watch,
00864 unsigned int condition)
00865 {
00866 dbus_bool_t retval;
00867
00868 _dbus_assert (transport->vtable->handle_watch != NULL);
00869
00870 if (transport->disconnected)
00871 return TRUE;
00872
00873 if (dbus_watch_get_socket (watch) < 0)
00874 {
00875 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00876 return TRUE;
00877 }
00878
00879 _dbus_watch_sanitize_condition (watch, &condition);
00880
00881 _dbus_transport_ref (transport);
00882 _dbus_watch_ref (watch);
00883 retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00884 _dbus_watch_unref (watch);
00885 _dbus_transport_unref (transport);
00886
00887 return retval;
00888 }
00889
00899 dbus_bool_t
00900 _dbus_transport_set_connection (DBusTransport *transport,
00901 DBusConnection *connection)
00902 {
00903 _dbus_assert (transport->vtable->connection_set != NULL);
00904 _dbus_assert (transport->connection == NULL);
00905
00906 transport->connection = connection;
00907
00908 _dbus_transport_ref (transport);
00909 if (!(* transport->vtable->connection_set) (transport))
00910 transport->connection = NULL;
00911 _dbus_transport_unref (transport);
00912
00913 return transport->connection != NULL;
00914 }
00915
00923 dbus_bool_t
00924 _dbus_transport_get_socket_fd (DBusTransport *transport,
00925 int *fd_p)
00926 {
00927 dbus_bool_t retval;
00928
00929 if (transport->vtable->get_socket_fd == NULL)
00930 return FALSE;
00931
00932 if (transport->disconnected)
00933 return FALSE;
00934
00935 _dbus_transport_ref (transport);
00936
00937 retval = (* transport->vtable->get_socket_fd) (transport,
00938 fd_p);
00939
00940 _dbus_transport_unref (transport);
00941
00942 return retval;
00943 }
00944
00956 void
00957 _dbus_transport_do_iteration (DBusTransport *transport,
00958 unsigned int flags,
00959 int timeout_milliseconds)
00960 {
00961 _dbus_assert (transport->vtable->do_iteration != NULL);
00962
00963 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00964 flags, timeout_milliseconds, !transport->disconnected);
00965
00966 if ((flags & (DBUS_ITERATION_DO_WRITING |
00967 DBUS_ITERATION_DO_READING)) == 0)
00968 return;
00969
00970 if (transport->disconnected)
00971 return;
00972
00973 _dbus_transport_ref (transport);
00974 (* transport->vtable->do_iteration) (transport, flags,
00975 timeout_milliseconds);
00976 _dbus_transport_unref (transport);
00977
00978 _dbus_verbose ("end\n");
00979 }
00980
00981 static dbus_bool_t
00982 recover_unused_bytes (DBusTransport *transport)
00983 {
00984 if (_dbus_auth_needs_decoding (transport->auth))
00985 {
00986 DBusString plaintext;
00987 const DBusString *encoded;
00988 DBusString *buffer;
00989 int orig_len;
00990
00991 if (!_dbus_string_init (&plaintext))
00992 goto nomem;
00993
00994 _dbus_auth_get_unused_bytes (transport->auth,
00995 &encoded);
00996
00997 if (!_dbus_auth_decode_data (transport->auth,
00998 encoded, &plaintext))
00999 {
01000 _dbus_string_free (&plaintext);
01001 goto nomem;
01002 }
01003
01004 _dbus_message_loader_get_buffer (transport->loader,
01005 &buffer);
01006
01007 orig_len = _dbus_string_get_length (buffer);
01008
01009 if (!_dbus_string_move (&plaintext, 0, buffer,
01010 orig_len))
01011 {
01012 _dbus_string_free (&plaintext);
01013 goto nomem;
01014 }
01015
01016 _dbus_verbose (" %d unused bytes sent to message loader\n",
01017 _dbus_string_get_length (buffer) -
01018 orig_len);
01019
01020 _dbus_message_loader_return_buffer (transport->loader,
01021 buffer,
01022 _dbus_string_get_length (buffer) -
01023 orig_len);
01024
01025 _dbus_auth_delete_unused_bytes (transport->auth);
01026
01027 _dbus_string_free (&plaintext);
01028 }
01029 else
01030 {
01031 const DBusString *bytes;
01032 DBusString *buffer;
01033 int orig_len;
01034 dbus_bool_t succeeded;
01035
01036 _dbus_message_loader_get_buffer (transport->loader,
01037 &buffer);
01038
01039 orig_len = _dbus_string_get_length (buffer);
01040
01041 _dbus_auth_get_unused_bytes (transport->auth,
01042 &bytes);
01043
01044 succeeded = TRUE;
01045 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01046 succeeded = FALSE;
01047
01048 _dbus_verbose (" %d unused bytes sent to message loader\n",
01049 _dbus_string_get_length (buffer) -
01050 orig_len);
01051
01052 _dbus_message_loader_return_buffer (transport->loader,
01053 buffer,
01054 _dbus_string_get_length (buffer) -
01055 orig_len);
01056
01057 if (succeeded)
01058 _dbus_auth_delete_unused_bytes (transport->auth);
01059 else
01060 goto nomem;
01061 }
01062
01063 return TRUE;
01064
01065 nomem:
01066 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01067 return FALSE;
01068 }
01069
01077 DBusDispatchStatus
01078 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01079 {
01080 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
01081 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
01082 return DBUS_DISPATCH_COMPLETE;
01083
01084 if (!_dbus_transport_get_is_authenticated (transport))
01085 {
01086 if (_dbus_auth_do_work (transport->auth) ==
01087 DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01088 return DBUS_DISPATCH_NEED_MEMORY;
01089 else if (!_dbus_transport_get_is_authenticated (transport))
01090 return DBUS_DISPATCH_COMPLETE;
01091 }
01092
01093 if (!transport->unused_bytes_recovered &&
01094 !recover_unused_bytes (transport))
01095 return DBUS_DISPATCH_NEED_MEMORY;
01096
01097 transport->unused_bytes_recovered = TRUE;
01098
01099 if (!_dbus_message_loader_queue_messages (transport->loader))
01100 return DBUS_DISPATCH_NEED_MEMORY;
01101
01102 if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01103 return DBUS_DISPATCH_DATA_REMAINS;
01104 else
01105 return DBUS_DISPATCH_COMPLETE;
01106 }
01107
01116 dbus_bool_t
01117 _dbus_transport_queue_messages (DBusTransport *transport)
01118 {
01119 DBusDispatchStatus status;
01120
01121 #if 0
01122 _dbus_verbose ("_dbus_transport_queue_messages()\n");
01123 #endif
01124
01125
01126 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01127 {
01128 DBusMessage *message;
01129 DBusList *link;
01130
01131 link = _dbus_message_loader_pop_message_link (transport->loader);
01132 _dbus_assert (link != NULL);
01133
01134 message = link->data;
01135
01136 _dbus_verbose ("queueing received message %p\n", message);
01137
01138 if (!_dbus_message_add_counter (message, transport->live_messages))
01139 {
01140 _dbus_message_loader_putback_message_link (transport->loader,
01141 link);
01142 status = DBUS_DISPATCH_NEED_MEMORY;
01143 break;
01144 }
01145 else
01146 {
01147
01148 _dbus_connection_queue_received_message_link (transport->connection,
01149 link);
01150 }
01151 }
01152
01153 if (_dbus_message_loader_get_is_corrupted (transport->loader))
01154 {
01155 _dbus_verbose ("Corrupted message stream, disconnecting\n");
01156 _dbus_transport_disconnect (transport);
01157 }
01158
01159 return status != DBUS_DISPATCH_NEED_MEMORY;
01160 }
01161
01168 void
01169 _dbus_transport_set_max_message_size (DBusTransport *transport,
01170 long size)
01171 {
01172 _dbus_message_loader_set_max_message_size (transport->loader, size);
01173 }
01174
01181 void
01182 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport,
01183 long n)
01184 {
01185 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
01186 }
01187
01194 long
01195 _dbus_transport_get_max_message_size (DBusTransport *transport)
01196 {
01197 return _dbus_message_loader_get_max_message_size (transport->loader);
01198 }
01199
01206 long
01207 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport)
01208 {
01209 return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
01210 }
01211
01218 void
01219 _dbus_transport_set_max_received_size (DBusTransport *transport,
01220 long size)
01221 {
01222 transport->max_live_messages_size = size;
01223 _dbus_counter_set_notify (transport->live_messages,
01224 transport->max_live_messages_size,
01225 transport->max_live_messages_unix_fds,
01226 live_messages_notify,
01227 transport);
01228 }
01229
01236 void
01237 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport,
01238 long n)
01239 {
01240 transport->max_live_messages_unix_fds = n;
01241 _dbus_counter_set_notify (transport->live_messages,
01242 transport->max_live_messages_size,
01243 transport->max_live_messages_unix_fds,
01244 live_messages_notify,
01245 transport);
01246 }
01247
01254 long
01255 _dbus_transport_get_max_received_size (DBusTransport *transport)
01256 {
01257 return transport->max_live_messages_size;
01258 }
01259
01266 long
01267 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport)
01268 {
01269 return transport->max_live_messages_unix_fds;
01270 }
01271
01279 dbus_bool_t
01280 _dbus_transport_get_unix_user (DBusTransport *transport,
01281 unsigned long *uid)
01282 {
01283 DBusCredentials *auth_identity;
01284
01285 *uid = _DBUS_INT32_MAX;
01286
01287
01288
01289
01290 if (!transport->authenticated)
01291 return FALSE;
01292
01293 auth_identity = _dbus_auth_get_identity (transport->auth);
01294
01295 if (_dbus_credentials_include (auth_identity,
01296 DBUS_CREDENTIAL_UNIX_USER_ID))
01297 {
01298 *uid = _dbus_credentials_get_unix_uid (auth_identity);
01299 return TRUE;
01300 }
01301 else
01302 return FALSE;
01303 }
01304
01312 dbus_bool_t
01313 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01314 unsigned long *pid)
01315 {
01316 DBusCredentials *auth_identity;
01317
01318 *pid = DBUS_PID_UNSET;
01319
01320
01321
01322
01323 if (!transport->authenticated)
01324 return FALSE;
01325
01326 auth_identity = _dbus_auth_get_identity (transport->auth);
01327
01328 if (_dbus_credentials_include (auth_identity,
01329 DBUS_CREDENTIAL_UNIX_PROCESS_ID))
01330 {
01331 *pid = _dbus_credentials_get_unix_pid (auth_identity);
01332 return TRUE;
01333 }
01334 else
01335 return FALSE;
01336 }
01337
01346 dbus_bool_t
01347 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport,
01348 void **data,
01349 int *data_size)
01350 {
01351 DBusCredentials *auth_identity;
01352
01353 *data = NULL;
01354 *data_size = 0;
01355
01356 if (!transport->authenticated)
01357 return FALSE;
01358
01359 auth_identity = _dbus_auth_get_identity (transport->auth);
01360
01361 if (_dbus_credentials_include (auth_identity,
01362 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
01363 {
01364 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
01365 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
01366 return TRUE;
01367 }
01368 else
01369 return FALSE;
01370 }
01371
01382 void
01383 _dbus_transport_set_unix_user_function (DBusTransport *transport,
01384 DBusAllowUnixUserFunction function,
01385 void *data,
01386 DBusFreeFunction free_data_function,
01387 void **old_data,
01388 DBusFreeFunction *old_free_data_function)
01389 {
01390 *old_data = transport->unix_user_data;
01391 *old_free_data_function = transport->free_unix_user_data;
01392
01393 transport->unix_user_function = function;
01394 transport->unix_user_data = data;
01395 transport->free_unix_user_data = free_data_function;
01396 }
01397
01405 dbus_bool_t
01406 _dbus_transport_get_windows_user (DBusTransport *transport,
01407 char **windows_sid_p)
01408 {
01409 DBusCredentials *auth_identity;
01410
01411 *windows_sid_p = NULL;
01412
01413 if (!transport->authenticated)
01414 return FALSE;
01415
01416 auth_identity = _dbus_auth_get_identity (transport->auth);
01417
01418 if (_dbus_credentials_include (auth_identity,
01419 DBUS_CREDENTIAL_WINDOWS_SID))
01420 {
01421
01422 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01423
01424 return TRUE;
01425 }
01426 else
01427 return FALSE;
01428 }
01429
01441 void
01442 _dbus_transport_set_windows_user_function (DBusTransport *transport,
01443 DBusAllowWindowsUserFunction function,
01444 void *data,
01445 DBusFreeFunction free_data_function,
01446 void **old_data,
01447 DBusFreeFunction *old_free_data_function)
01448 {
01449 *old_data = transport->windows_user_data;
01450 *old_free_data_function = transport->free_windows_user_data;
01451
01452 transport->windows_user_function = function;
01453 transport->windows_user_data = data;
01454 transport->free_windows_user_data = free_data_function;
01455 }
01456
01465 dbus_bool_t
01466 _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
01467 const char **mechanisms)
01468 {
01469 return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01470 }
01471
01478 void
01479 _dbus_transport_set_allow_anonymous (DBusTransport *transport,
01480 dbus_bool_t value)
01481 {
01482 transport->allow_anonymous = value != FALSE;
01483 }
01484