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.h"
00035 #ifdef DBUS_ENABLE_EMBEDDED_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_connection_lock (transport->connection);
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 (* transport->vtable->live_messages_changed) (transport);
00082 }
00083
00084 _dbus_transport_unref (transport);
00085 _dbus_connection_unlock (transport->connection);
00086 }
00087
00101 dbus_bool_t
00102 _dbus_transport_init_base (DBusTransport *transport,
00103 const DBusTransportVTable *vtable,
00104 const DBusString *server_guid,
00105 const DBusString *address)
00106 {
00107 DBusMessageLoader *loader;
00108 DBusAuth *auth;
00109 DBusCounter *counter;
00110 char *address_copy;
00111 DBusCredentials *creds;
00112
00113 loader = _dbus_message_loader_new ();
00114 if (loader == NULL)
00115 return FALSE;
00116
00117 if (server_guid)
00118 auth = _dbus_auth_server_new (server_guid);
00119 else
00120 auth = _dbus_auth_client_new ();
00121 if (auth == NULL)
00122 {
00123 _dbus_message_loader_unref (loader);
00124 return FALSE;
00125 }
00126
00127 counter = _dbus_counter_new ();
00128 if (counter == NULL)
00129 {
00130 _dbus_auth_unref (auth);
00131 _dbus_message_loader_unref (loader);
00132 return FALSE;
00133 }
00134
00135 creds = _dbus_credentials_new ();
00136 if (creds == NULL)
00137 {
00138 _dbus_counter_unref (counter);
00139 _dbus_auth_unref (auth);
00140 _dbus_message_loader_unref (loader);
00141 return FALSE;
00142 }
00143
00144 if (server_guid)
00145 {
00146 _dbus_assert (address == NULL);
00147 address_copy = NULL;
00148 }
00149 else
00150 {
00151 _dbus_assert (address != NULL);
00152
00153 if (!_dbus_string_copy_data (address, &address_copy))
00154 {
00155 _dbus_credentials_unref (creds);
00156 _dbus_counter_unref (counter);
00157 _dbus_auth_unref (auth);
00158 _dbus_message_loader_unref (loader);
00159 return FALSE;
00160 }
00161 }
00162
00163 transport->refcount = 1;
00164 transport->vtable = vtable;
00165 transport->loader = loader;
00166 transport->auth = auth;
00167 transport->live_messages = counter;
00168 transport->authenticated = FALSE;
00169 transport->disconnected = FALSE;
00170 transport->is_server = (server_guid != NULL);
00171 transport->send_credentials_pending = !transport->is_server;
00172 transport->receive_credentials_pending = transport->is_server;
00173 transport->address = address_copy;
00174
00175 transport->unix_user_function = NULL;
00176 transport->unix_user_data = NULL;
00177 transport->free_unix_user_data = NULL;
00178
00179 transport->windows_user_function = NULL;
00180 transport->windows_user_data = NULL;
00181 transport->free_windows_user_data = NULL;
00182
00183 transport->expected_guid = NULL;
00184
00185
00186
00187
00188 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
00189
00190
00191
00192 transport->max_live_messages_unix_fds = 4096;
00193
00194
00195 transport->credentials = creds;
00196
00197 _dbus_counter_set_notify (transport->live_messages,
00198 transport->max_live_messages_size,
00199 transport->max_live_messages_unix_fds,
00200 live_messages_notify,
00201 transport);
00202
00203 if (transport->address)
00204 _dbus_verbose ("Initialized transport on address %s\n", transport->address);
00205
00206 return TRUE;
00207 }
00208
00215 void
00216 _dbus_transport_finalize_base (DBusTransport *transport)
00217 {
00218 if (!transport->disconnected)
00219 _dbus_transport_disconnect (transport);
00220
00221 if (transport->free_unix_user_data != NULL)
00222 (* transport->free_unix_user_data) (transport->unix_user_data);
00223
00224 if (transport->free_windows_user_data != NULL)
00225 (* transport->free_windows_user_data) (transport->windows_user_data);
00226
00227 _dbus_message_loader_unref (transport->loader);
00228 _dbus_auth_unref (transport->auth);
00229 _dbus_counter_set_notify (transport->live_messages,
00230 0, 0, NULL, NULL);
00231 _dbus_counter_unref (transport->live_messages);
00232 dbus_free (transport->address);
00233 dbus_free (transport->expected_guid);
00234 if (transport->credentials)
00235 _dbus_credentials_unref (transport->credentials);
00236 }
00237
00238
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_ERROR_IS_CLEAR (error);
00258
00259 if (!dbus_parse_address (address, &entries, &len, error))
00260 return NULL;
00261
00262 for (i = 0; i < len; i++)
00263 {
00264 dbus_error_free (error);
00265 transport = _dbus_transport_open (entries[i], error);
00266
00267 if (transport != NULL)
00268 break;
00269 }
00270
00271 dbus_address_entries_free (entries);
00272 return transport;
00273 }
00274
00283 static DBusTransport*
00284 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
00285 {
00286 DBusString address;
00287 DBusTransport *result = NULL;
00288
00289 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00290
00291 if (!_dbus_string_init (&address))
00292 {
00293 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00294 return NULL;
00295 }
00296
00297 if (!_dbus_get_autolaunch_address (scope, &address, error))
00298 {
00299 _DBUS_ASSERT_ERROR_IS_SET (error);
00300 goto out;
00301 }
00302
00303 result = check_address (_dbus_string_get_const_data (&address), error);
00304 if (result == NULL)
00305 _DBUS_ASSERT_ERROR_IS_SET (error);
00306 else
00307 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00308
00309 out:
00310 _dbus_string_free (&address);
00311 return result;
00312 }
00313
00314 static DBusTransportOpenResult
00315 _dbus_transport_open_autolaunch (DBusAddressEntry *entry,
00316 DBusTransport **transport_p,
00317 DBusError *error)
00318 {
00319 const char *method;
00320
00321 method = dbus_address_entry_get_method (entry);
00322 _dbus_assert (method != NULL);
00323
00324 if (strcmp (method, "autolaunch") == 0)
00325 {
00326 const char *scope = dbus_address_entry_get_value (entry, "scope");
00327
00328 *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
00329
00330 if (*transport_p == NULL)
00331 {
00332 _DBUS_ASSERT_ERROR_IS_SET (error);
00333 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00334 }
00335 else
00336 {
00337 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00338 return DBUS_TRANSPORT_OPEN_OK;
00339 }
00340 }
00341 else
00342 {
00343 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00344 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
00345 }
00346 }
00347
00348 static const struct {
00349 DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
00350 DBusTransport **transport_p,
00351 DBusError *error);
00352 } open_funcs[] = {
00353 { _dbus_transport_open_socket },
00354 { _dbus_transport_open_platform_specific },
00355 { _dbus_transport_open_autolaunch }
00356 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00357 , { _dbus_transport_open_debug_pipe }
00358 #endif
00359 };
00360
00369 DBusTransport*
00370 _dbus_transport_open (DBusAddressEntry *entry,
00371 DBusError *error)
00372 {
00373 DBusTransport *transport;
00374 const char *expected_guid_orig;
00375 char *expected_guid;
00376 int i;
00377 DBusError tmp_error = DBUS_ERROR_INIT;
00378
00379 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00380
00381 transport = NULL;
00382 expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
00383 expected_guid = _dbus_strdup (expected_guid_orig);
00384
00385 if (expected_guid_orig != NULL && expected_guid == NULL)
00386 {
00387 _DBUS_SET_OOM (error);
00388 return NULL;
00389 }
00390
00391 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
00392 {
00393 DBusTransportOpenResult result;
00394
00395 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00396 result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
00397
00398 switch (result)
00399 {
00400 case DBUS_TRANSPORT_OPEN_OK:
00401 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00402 goto out;
00403 break;
00404 case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
00405 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00406
00407 break;
00408 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
00409 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00410 goto out;
00411 break;
00412 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
00413 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00414 goto out;
00415 break;
00416 }
00417 }
00418
00419 out:
00420
00421 if (transport == NULL)
00422 {
00423 if (!dbus_error_is_set (&tmp_error))
00424 _dbus_set_bad_address (&tmp_error,
00425 NULL, NULL,
00426 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
00427
00428 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00429 dbus_move_error(&tmp_error, error);
00430 dbus_free (expected_guid);
00431 }
00432 else
00433 {
00434 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 if(expected_guid)
00450 transport->expected_guid = expected_guid;
00451 }
00452
00453 return transport;
00454 }
00455
00462 DBusTransport *
00463 _dbus_transport_ref (DBusTransport *transport)
00464 {
00465 _dbus_assert (transport->refcount > 0);
00466
00467 transport->refcount += 1;
00468
00469 return transport;
00470 }
00471
00479 void
00480 _dbus_transport_unref (DBusTransport *transport)
00481 {
00482 _dbus_assert (transport != NULL);
00483 _dbus_assert (transport->refcount > 0);
00484
00485 transport->refcount -= 1;
00486 if (transport->refcount == 0)
00487 {
00488 _dbus_verbose ("finalizing\n");
00489
00490 _dbus_assert (transport->vtable->finalize != NULL);
00491
00492 (* transport->vtable->finalize) (transport);
00493 }
00494 }
00495
00504 void
00505 _dbus_transport_disconnect (DBusTransport *transport)
00506 {
00507 _dbus_verbose ("start\n");
00508
00509 _dbus_assert (transport->vtable->disconnect != NULL);
00510
00511 if (transport->disconnected)
00512 return;
00513
00514 (* transport->vtable->disconnect) (transport);
00515
00516 transport->disconnected = TRUE;
00517
00518 _dbus_verbose ("end\n");
00519 }
00520
00529 dbus_bool_t
00530 _dbus_transport_get_is_connected (DBusTransport *transport)
00531 {
00532 return !transport->disconnected;
00533 }
00534
00535 static dbus_bool_t
00536 auth_via_unix_user_function (DBusTransport *transport)
00537 {
00538 DBusCredentials *auth_identity;
00539 dbus_bool_t allow;
00540 DBusConnection *connection;
00541 DBusAllowUnixUserFunction unix_user_function;
00542 void *unix_user_data;
00543 dbus_uid_t uid;
00544
00545
00546
00547 auth_identity = _dbus_auth_get_identity (transport->auth);
00548 _dbus_assert (auth_identity != NULL);
00549
00550 connection = transport->connection;
00551 unix_user_function = transport->unix_user_function;
00552 unix_user_data = transport->unix_user_data;
00553 uid = _dbus_credentials_get_unix_uid (auth_identity);
00554
00555 _dbus_verbose ("unlock\n");
00556 _dbus_connection_unlock (connection);
00557
00558 allow = (* unix_user_function) (connection,
00559 uid,
00560 unix_user_data);
00561
00562 _dbus_verbose ("lock post unix user function\n");
00563 _dbus_connection_lock (connection);
00564
00565 if (allow)
00566 {
00567 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
00568 }
00569 else
00570 {
00571 _dbus_verbose ("Client UID "DBUS_UID_FORMAT
00572 " was rejected, disconnecting\n",
00573 _dbus_credentials_get_unix_uid (auth_identity));
00574 _dbus_transport_disconnect (transport);
00575 }
00576
00577 return allow;
00578 }
00579
00580 static dbus_bool_t
00581 auth_via_windows_user_function (DBusTransport *transport)
00582 {
00583 DBusCredentials *auth_identity;
00584 dbus_bool_t allow;
00585 DBusConnection *connection;
00586 DBusAllowWindowsUserFunction windows_user_function;
00587 void *windows_user_data;
00588 char *windows_sid;
00589
00590
00591
00592 auth_identity = _dbus_auth_get_identity (transport->auth);
00593 _dbus_assert (auth_identity != NULL);
00594
00595 connection = transport->connection;
00596 windows_user_function = transport->windows_user_function;
00597 windows_user_data = transport->unix_user_data;
00598 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
00599
00600 if (windows_sid == NULL)
00601 {
00602
00603 return FALSE;
00604 }
00605
00606 _dbus_verbose ("unlock\n");
00607 _dbus_connection_unlock (connection);
00608
00609 allow = (* windows_user_function) (connection,
00610 windows_sid,
00611 windows_user_data);
00612
00613 _dbus_verbose ("lock post windows user function\n");
00614 _dbus_connection_lock (connection);
00615
00616 if (allow)
00617 {
00618 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
00619 }
00620 else
00621 {
00622 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
00623 _dbus_credentials_get_windows_sid (auth_identity));
00624 _dbus_transport_disconnect (transport);
00625 }
00626
00627 return allow;
00628 }
00629
00630 static dbus_bool_t
00631 auth_via_default_rules (DBusTransport *transport)
00632 {
00633 DBusCredentials *auth_identity;
00634 DBusCredentials *our_identity;
00635 dbus_bool_t allow;
00636
00637 auth_identity = _dbus_auth_get_identity (transport->auth);
00638 _dbus_assert (auth_identity != NULL);
00639
00640
00641
00642
00643
00644 our_identity = _dbus_credentials_new_from_current_process ();
00645 if (our_identity == NULL)
00646 {
00647
00648 return FALSE;
00649 }
00650
00651 if (transport->allow_anonymous ||
00652 _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
00653 _dbus_credentials_same_user (our_identity,
00654 auth_identity))
00655 {
00656 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00657 _dbus_verbose ("Client authorized as SID '%s'"
00658 "matching our SID '%s'\n",
00659 _dbus_credentials_get_windows_sid(auth_identity),
00660 _dbus_credentials_get_windows_sid(our_identity));
00661 else
00662 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00663 " matching our UID "DBUS_UID_FORMAT"\n",
00664 _dbus_credentials_get_unix_uid(auth_identity),
00665 _dbus_credentials_get_unix_uid(our_identity));
00666
00667 allow = TRUE;
00668 }
00669 else
00670 {
00671 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00672 _dbus_verbose ("Client authorized as SID '%s'"
00673 " but our SID is '%s', disconnecting\n",
00674 (_dbus_credentials_get_windows_sid(auth_identity) ?
00675 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
00676 (_dbus_credentials_get_windows_sid(our_identity) ?
00677 _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
00678 else
00679 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00680 " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
00681 _dbus_credentials_get_unix_uid(auth_identity),
00682 _dbus_credentials_get_unix_uid(our_identity));
00683 _dbus_transport_disconnect (transport);
00684 allow = FALSE;
00685 }
00686
00687 _dbus_credentials_unref (our_identity);
00688
00689 return allow;
00690 }
00691
00703 dbus_bool_t
00704 _dbus_transport_peek_is_authenticated (DBusTransport *transport)
00705 {
00706 return transport->authenticated;
00707 }
00708
00726 dbus_bool_t
00727 _dbus_transport_try_to_authenticate (DBusTransport *transport)
00728 {
00729 if (transport->authenticated)
00730 return TRUE;
00731 else
00732 {
00733 dbus_bool_t maybe_authenticated;
00734
00735 if (transport->disconnected)
00736 return FALSE;
00737
00738
00739 _dbus_connection_ref_unlocked (transport->connection);
00740
00741 maybe_authenticated =
00742 (!(transport->send_credentials_pending ||
00743 transport->receive_credentials_pending));
00744
00745 if (maybe_authenticated)
00746 {
00747 switch (_dbus_auth_do_work (transport->auth))
00748 {
00749 case DBUS_AUTH_STATE_AUTHENTICATED:
00750
00751 break;
00752 default:
00753 maybe_authenticated = FALSE;
00754 }
00755 }
00756
00757
00758
00759 if (maybe_authenticated && !transport->is_server)
00760 {
00761 const char *server_guid;
00762
00763 server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00764 _dbus_assert (server_guid != NULL);
00765
00766 if (transport->expected_guid &&
00767 strcmp (transport->expected_guid, server_guid) != 0)
00768 {
00769 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00770 transport->expected_guid, server_guid);
00771 _dbus_transport_disconnect (transport);
00772 _dbus_connection_unref_unlocked (transport->connection);
00773 return FALSE;
00774 }
00775 }
00776
00777
00778
00779 if (maybe_authenticated && transport->is_server)
00780 {
00781 dbus_bool_t allow;
00782 DBusCredentials *auth_identity;
00783
00784 auth_identity = _dbus_auth_get_identity (transport->auth);
00785 _dbus_assert (auth_identity != NULL);
00786
00787
00788
00789
00790
00791 if (transport->unix_user_function != NULL &&
00792 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00793 {
00794 allow = auth_via_unix_user_function (transport);
00795 }
00796 else if (transport->windows_user_function != NULL &&
00797 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00798 {
00799 allow = auth_via_windows_user_function (transport);
00800 }
00801 else
00802 {
00803 allow = auth_via_default_rules (transport);
00804 }
00805
00806 if (!allow)
00807 maybe_authenticated = FALSE;
00808 }
00809
00810 transport->authenticated = maybe_authenticated;
00811
00812 _dbus_connection_unref_unlocked (transport->connection);
00813 return maybe_authenticated;
00814 }
00815 }
00816
00823 dbus_bool_t
00824 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00825 {
00826 DBusCredentials *auth_identity;
00827
00828 if (!transport->authenticated)
00829 return TRUE;
00830
00831 auth_identity = _dbus_auth_get_identity (transport->auth);
00832
00833 if (_dbus_credentials_are_anonymous (auth_identity))
00834 return TRUE;
00835 else
00836 return FALSE;
00837 }
00838
00845 dbus_bool_t
00846 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
00847 {
00848 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
00849 }
00850
00858 const char*
00859 _dbus_transport_get_address (DBusTransport *transport)
00860 {
00861 return transport->address;
00862 }
00863
00871 const char*
00872 _dbus_transport_get_server_id (DBusTransport *transport)
00873 {
00874 if (transport->is_server)
00875 return NULL;
00876 else if (transport->authenticated)
00877 return _dbus_auth_get_guid_from_server (transport->auth);
00878 else
00879 return transport->expected_guid;
00880 }
00881
00891 dbus_bool_t
00892 _dbus_transport_handle_watch (DBusTransport *transport,
00893 DBusWatch *watch,
00894 unsigned int condition)
00895 {
00896 dbus_bool_t retval;
00897
00898 _dbus_assert (transport->vtable->handle_watch != NULL);
00899
00900 if (transport->disconnected)
00901 return TRUE;
00902
00903 if (dbus_watch_get_socket (watch) < 0)
00904 {
00905 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00906 return TRUE;
00907 }
00908
00909 _dbus_watch_sanitize_condition (watch, &condition);
00910
00911 _dbus_transport_ref (transport);
00912 _dbus_watch_ref (watch);
00913 retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00914 _dbus_watch_unref (watch);
00915 _dbus_transport_unref (transport);
00916
00917 return retval;
00918 }
00919
00929 dbus_bool_t
00930 _dbus_transport_set_connection (DBusTransport *transport,
00931 DBusConnection *connection)
00932 {
00933 _dbus_assert (transport->vtable->connection_set != NULL);
00934 _dbus_assert (transport->connection == NULL);
00935
00936 transport->connection = connection;
00937
00938 _dbus_transport_ref (transport);
00939 if (!(* transport->vtable->connection_set) (transport))
00940 transport->connection = NULL;
00941 _dbus_transport_unref (transport);
00942
00943 return transport->connection != NULL;
00944 }
00945
00953 dbus_bool_t
00954 _dbus_transport_get_socket_fd (DBusTransport *transport,
00955 DBusSocket *fd_p)
00956 {
00957 dbus_bool_t retval;
00958
00959 if (transport->vtable->get_socket_fd == NULL)
00960 return FALSE;
00961
00962 if (transport->disconnected)
00963 return FALSE;
00964
00965 _dbus_transport_ref (transport);
00966
00967 retval = (* transport->vtable->get_socket_fd) (transport,
00968 fd_p);
00969
00970 _dbus_transport_unref (transport);
00971
00972 return retval;
00973 }
00974
00986 void
00987 _dbus_transport_do_iteration (DBusTransport *transport,
00988 unsigned int flags,
00989 int timeout_milliseconds)
00990 {
00991 _dbus_assert (transport->vtable->do_iteration != NULL);
00992
00993 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00994 flags, timeout_milliseconds, !transport->disconnected);
00995
00996 if ((flags & (DBUS_ITERATION_DO_WRITING |
00997 DBUS_ITERATION_DO_READING)) == 0)
00998 return;
00999
01000 if (transport->disconnected)
01001 return;
01002
01003 _dbus_transport_ref (transport);
01004 (* transport->vtable->do_iteration) (transport, flags,
01005 timeout_milliseconds);
01006 _dbus_transport_unref (transport);
01007
01008 _dbus_verbose ("end\n");
01009 }
01010
01011 static dbus_bool_t
01012 recover_unused_bytes (DBusTransport *transport)
01013 {
01014 if (_dbus_auth_needs_decoding (transport->auth))
01015 {
01016 DBusString plaintext;
01017 const DBusString *encoded;
01018 DBusString *buffer;
01019 int orig_len;
01020
01021 if (!_dbus_string_init (&plaintext))
01022 goto nomem;
01023
01024 _dbus_auth_get_unused_bytes (transport->auth,
01025 &encoded);
01026
01027 if (!_dbus_auth_decode_data (transport->auth,
01028 encoded, &plaintext))
01029 {
01030 _dbus_string_free (&plaintext);
01031 goto nomem;
01032 }
01033
01034 _dbus_message_loader_get_buffer (transport->loader,
01035 &buffer);
01036
01037 orig_len = _dbus_string_get_length (buffer);
01038
01039 if (!_dbus_string_move (&plaintext, 0, buffer,
01040 orig_len))
01041 {
01042 _dbus_string_free (&plaintext);
01043 goto nomem;
01044 }
01045
01046 _dbus_verbose (" %d unused bytes sent to message loader\n",
01047 _dbus_string_get_length (buffer) -
01048 orig_len);
01049
01050 _dbus_message_loader_return_buffer (transport->loader,
01051 buffer);
01052
01053 _dbus_auth_delete_unused_bytes (transport->auth);
01054
01055 _dbus_string_free (&plaintext);
01056 }
01057 else
01058 {
01059 const DBusString *bytes;
01060 DBusString *buffer;
01061 int orig_len;
01062 dbus_bool_t succeeded;
01063
01064 _dbus_message_loader_get_buffer (transport->loader,
01065 &buffer);
01066
01067 orig_len = _dbus_string_get_length (buffer);
01068
01069 _dbus_auth_get_unused_bytes (transport->auth,
01070 &bytes);
01071
01072 succeeded = TRUE;
01073 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01074 succeeded = FALSE;
01075
01076 _dbus_verbose (" %d unused bytes sent to message loader\n",
01077 _dbus_string_get_length (buffer) -
01078 orig_len);
01079
01080 _dbus_message_loader_return_buffer (transport->loader,
01081 buffer);
01082
01083 if (succeeded)
01084 _dbus_auth_delete_unused_bytes (transport->auth);
01085 else
01086 goto nomem;
01087 }
01088
01089 return TRUE;
01090
01091 nomem:
01092 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01093 return FALSE;
01094 }
01095
01103 DBusDispatchStatus
01104 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01105 {
01106 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
01107 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
01108 return DBUS_DISPATCH_COMPLETE;
01109
01110 if (!_dbus_transport_try_to_authenticate (transport))
01111 {
01112 if (_dbus_auth_do_work (transport->auth) ==
01113 DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01114 return DBUS_DISPATCH_NEED_MEMORY;
01115 else if (!_dbus_transport_try_to_authenticate (transport))
01116 return DBUS_DISPATCH_COMPLETE;
01117 }
01118
01119 if (!transport->unused_bytes_recovered &&
01120 !recover_unused_bytes (transport))
01121 return DBUS_DISPATCH_NEED_MEMORY;
01122
01123 transport->unused_bytes_recovered = TRUE;
01124
01125 if (!_dbus_message_loader_queue_messages (transport->loader))
01126 return DBUS_DISPATCH_NEED_MEMORY;
01127
01128 if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01129 return DBUS_DISPATCH_DATA_REMAINS;
01130 else
01131 return DBUS_DISPATCH_COMPLETE;
01132 }
01133
01142 dbus_bool_t
01143 _dbus_transport_queue_messages (DBusTransport *transport)
01144 {
01145 DBusDispatchStatus status;
01146
01147 #if 0
01148 _dbus_verbose ("_dbus_transport_queue_messages()\n");
01149 #endif
01150
01151
01152 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01153 {
01154 DBusMessage *message;
01155 DBusList *link;
01156
01157 link = _dbus_message_loader_pop_message_link (transport->loader);
01158 _dbus_assert (link != NULL);
01159
01160 message = link->data;
01161
01162 _dbus_verbose ("queueing received message %p\n", message);
01163
01164 if (!_dbus_message_add_counter (message, transport->live_messages))
01165 {
01166 _dbus_message_loader_putback_message_link (transport->loader,
01167 link);
01168 status = DBUS_DISPATCH_NEED_MEMORY;
01169 break;
01170 }
01171 else
01172 {
01173
01174
01175
01176
01177 if (transport->vtable->live_messages_changed)
01178 (* transport->vtable->live_messages_changed) (transport);
01179
01180
01181 _dbus_connection_queue_received_message_link (transport->connection,
01182 link);
01183 }
01184 }
01185
01186 if (_dbus_message_loader_get_is_corrupted (transport->loader))
01187 {
01188 _dbus_verbose ("Corrupted message stream, disconnecting\n");
01189 _dbus_transport_disconnect (transport);
01190 }
01191
01192 return status != DBUS_DISPATCH_NEED_MEMORY;
01193 }
01194
01201 void
01202 _dbus_transport_set_max_message_size (DBusTransport *transport,
01203 long size)
01204 {
01205 _dbus_message_loader_set_max_message_size (transport->loader, size);
01206 }
01207
01214 void
01215 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport,
01216 long n)
01217 {
01218 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
01219 }
01220
01227 long
01228 _dbus_transport_get_max_message_size (DBusTransport *transport)
01229 {
01230 return _dbus_message_loader_get_max_message_size (transport->loader);
01231 }
01232
01239 long
01240 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport)
01241 {
01242 return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
01243 }
01244
01251 void
01252 _dbus_transport_set_max_received_size (DBusTransport *transport,
01253 long size)
01254 {
01255 transport->max_live_messages_size = size;
01256 _dbus_counter_set_notify (transport->live_messages,
01257 transport->max_live_messages_size,
01258 transport->max_live_messages_unix_fds,
01259 live_messages_notify,
01260 transport);
01261 }
01262
01269 void
01270 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport,
01271 long n)
01272 {
01273 transport->max_live_messages_unix_fds = n;
01274 _dbus_counter_set_notify (transport->live_messages,
01275 transport->max_live_messages_size,
01276 transport->max_live_messages_unix_fds,
01277 live_messages_notify,
01278 transport);
01279 }
01280
01287 long
01288 _dbus_transport_get_max_received_size (DBusTransport *transport)
01289 {
01290 return transport->max_live_messages_size;
01291 }
01292
01299 long
01300 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport)
01301 {
01302 return transport->max_live_messages_unix_fds;
01303 }
01304
01312 dbus_bool_t
01313 _dbus_transport_get_unix_user (DBusTransport *transport,
01314 unsigned long *uid)
01315 {
01316 DBusCredentials *auth_identity;
01317
01318 *uid = _DBUS_INT32_MAX;
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_USER_ID))
01330 {
01331 *uid = _dbus_credentials_get_unix_uid (auth_identity);
01332 return TRUE;
01333 }
01334 else
01335 return FALSE;
01336 }
01337
01345 dbus_bool_t
01346 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01347 unsigned long *pid)
01348 {
01349 DBusCredentials *auth_identity;
01350
01351 *pid = DBUS_PID_UNSET;
01352
01353
01354
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_UNIX_PROCESS_ID))
01363 {
01364 *pid = _dbus_credentials_get_pid (auth_identity);
01365 return TRUE;
01366 }
01367 else
01368 return FALSE;
01369 }
01370
01379 dbus_bool_t
01380 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport,
01381 void **data,
01382 int *data_size)
01383 {
01384 DBusCredentials *auth_identity;
01385
01386 *data = NULL;
01387 *data_size = 0;
01388
01389 if (!transport->authenticated)
01390 return FALSE;
01391
01392 auth_identity = _dbus_auth_get_identity (transport->auth);
01393
01394 if (_dbus_credentials_include (auth_identity,
01395 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
01396 {
01397 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
01398 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
01399 return TRUE;
01400 }
01401 else
01402 return FALSE;
01403 }
01404
01415 void
01416 _dbus_transport_set_unix_user_function (DBusTransport *transport,
01417 DBusAllowUnixUserFunction function,
01418 void *data,
01419 DBusFreeFunction free_data_function,
01420 void **old_data,
01421 DBusFreeFunction *old_free_data_function)
01422 {
01423 *old_data = transport->unix_user_data;
01424 *old_free_data_function = transport->free_unix_user_data;
01425
01426 transport->unix_user_function = function;
01427 transport->unix_user_data = data;
01428 transport->free_unix_user_data = free_data_function;
01429 }
01430
01431 dbus_bool_t
01432 _dbus_transport_get_linux_security_label (DBusTransport *transport,
01433 char **label_p)
01434 {
01435 DBusCredentials *auth_identity;
01436
01437 *label_p = NULL;
01438
01439 if (!transport->authenticated)
01440 return FALSE;
01441
01442 auth_identity = _dbus_auth_get_identity (transport->auth);
01443
01444 if (_dbus_credentials_include (auth_identity,
01445 DBUS_CREDENTIAL_LINUX_SECURITY_LABEL))
01446 {
01447
01448 *label_p = _dbus_strdup (_dbus_credentials_get_linux_security_label (auth_identity));
01449
01450 return TRUE;
01451 }
01452 else
01453 {
01454 return FALSE;
01455 }
01456 }
01457
01465 dbus_bool_t
01466 _dbus_transport_get_windows_user (DBusTransport *transport,
01467 char **windows_sid_p)
01468 {
01469 DBusCredentials *auth_identity;
01470
01471 *windows_sid_p = NULL;
01472
01473 if (!transport->authenticated)
01474 return FALSE;
01475
01476 auth_identity = _dbus_auth_get_identity (transport->auth);
01477
01478 if (_dbus_credentials_include (auth_identity,
01479 DBUS_CREDENTIAL_WINDOWS_SID))
01480 {
01481
01482 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01483
01484 return TRUE;
01485 }
01486 else
01487 return FALSE;
01488 }
01489
01501 void
01502 _dbus_transport_set_windows_user_function (DBusTransport *transport,
01503 DBusAllowWindowsUserFunction function,
01504 void *data,
01505 DBusFreeFunction free_data_function,
01506 void **old_data,
01507 DBusFreeFunction *old_free_data_function)
01508 {
01509 *old_data = transport->windows_user_data;
01510 *old_free_data_function = transport->free_windows_user_data;
01511
01512 transport->windows_user_function = function;
01513 transport->windows_user_data = data;
01514 transport->free_windows_user_data = free_data_function;
01515 }
01516
01525 dbus_bool_t
01526 _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
01527 const char **mechanisms)
01528 {
01529 return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01530 }
01531
01538 void
01539 _dbus_transport_set_allow_anonymous (DBusTransport *transport,
01540 dbus_bool_t value)
01541 {
01542 transport->allow_anonymous = value != FALSE;
01543 }
01544
01550 int
01551 _dbus_transport_get_pending_fds_count (DBusTransport *transport)
01552 {
01553 return _dbus_message_loader_get_pending_fds_count (transport->loader);
01554 }
01555
01563 void
01564 _dbus_transport_set_pending_fds_function (DBusTransport *transport,
01565 void (* callback) (void *),
01566 void *data)
01567 {
01568 _dbus_message_loader_set_pending_fds_function (transport->loader,
01569 callback, data);
01570 }
01571
01572 #ifdef DBUS_ENABLE_STATS
01573 void
01574 _dbus_transport_get_stats (DBusTransport *transport,
01575 dbus_uint32_t *queue_bytes,
01576 dbus_uint32_t *queue_fds,
01577 dbus_uint32_t *peak_queue_bytes,
01578 dbus_uint32_t *peak_queue_fds)
01579 {
01580 if (queue_bytes != NULL)
01581 *queue_bytes = _dbus_counter_get_size_value (transport->live_messages);
01582
01583 if (queue_fds != NULL)
01584 *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages);
01585
01586 if (peak_queue_bytes != NULL)
01587 *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages);
01588
01589 if (peak_queue_fds != NULL)
01590 *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages);
01591 }
01592 #endif
01593