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