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