dbus-transport.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation)
00003  *
00004  * Copyright (C) 2002, 2003  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include "dbus-transport-protected.h"
00025 #include "dbus-transport-unix.h"
00026 #include "dbus-transport-socket.h"
00027 #include "dbus-connection-internal.h"
00028 #include "dbus-watch.h"
00029 #include "dbus-auth.h"
00030 #include "dbus-address.h"
00031 #include "dbus-credentials.h"
00032 #ifdef DBUS_BUILD_TESTS
00033 #include "dbus-server-debug-pipe.h"
00034 #endif
00035 
00057 static void
00058 live_messages_size_notify (DBusCounter *counter,
00059                            void        *user_data)
00060 {
00061   DBusTransport *transport = user_data;
00062 
00063   _dbus_transport_ref (transport);
00064 
00065 #if 0
00066   _dbus_verbose ("Counter value is now %d\n",
00067                  (int) _dbus_counter_get_value (counter));
00068 #endif
00069   
00070   /* disable or re-enable the read watch for the transport if
00071    * required.
00072    */
00073   if (transport->vtable->live_messages_changed)
00074     (* transport->vtable->live_messages_changed) (transport);
00075 
00076   _dbus_transport_unref (transport);
00077 }
00078 
00092 dbus_bool_t
00093 _dbus_transport_init_base (DBusTransport             *transport,
00094                            const DBusTransportVTable *vtable,
00095                            const DBusString          *server_guid,
00096                            const DBusString          *address)
00097 {
00098   DBusMessageLoader *loader;
00099   DBusAuth *auth;
00100   DBusCounter *counter;
00101   char *address_copy;
00102   DBusCredentials *creds;
00103   
00104   loader = _dbus_message_loader_new ();
00105   if (loader == NULL)
00106     return FALSE;
00107   
00108   if (server_guid)
00109     auth = _dbus_auth_server_new (server_guid);
00110   else
00111     auth = _dbus_auth_client_new ();
00112   if (auth == NULL)
00113     {
00114       _dbus_message_loader_unref (loader);
00115       return FALSE;
00116     }
00117 
00118   counter = _dbus_counter_new ();
00119   if (counter == NULL)
00120     {
00121       _dbus_auth_unref (auth);
00122       _dbus_message_loader_unref (loader);
00123       return FALSE;
00124     }  
00125 
00126   creds = _dbus_credentials_new ();
00127   if (creds == NULL)
00128     {
00129       _dbus_counter_unref (counter);
00130       _dbus_auth_unref (auth);
00131       _dbus_message_loader_unref (loader);
00132       return FALSE;
00133     }
00134   
00135   if (server_guid)
00136     {
00137       _dbus_assert (address == NULL);
00138       address_copy = NULL;
00139     }
00140   else
00141     {
00142       _dbus_assert (address != NULL);
00143 
00144       if (!_dbus_string_copy_data (address, &address_copy))
00145         {
00146           _dbus_credentials_unref (creds);
00147           _dbus_counter_unref (counter);
00148           _dbus_auth_unref (auth);
00149           _dbus_message_loader_unref (loader);
00150           return FALSE;
00151         }
00152     }
00153   
00154   transport->refcount = 1;
00155   transport->vtable = vtable;
00156   transport->loader = loader;
00157   transport->auth = auth;
00158   transport->live_messages_size = counter;
00159   transport->authenticated = FALSE;
00160   transport->disconnected = FALSE;
00161   transport->is_server = (server_guid != NULL);
00162   transport->send_credentials_pending = !transport->is_server;
00163   transport->receive_credentials_pending = transport->is_server;
00164   transport->address = address_copy;
00165   
00166   transport->unix_user_function = NULL;
00167   transport->unix_user_data = NULL;
00168   transport->free_unix_user_data = NULL;
00169 
00170   transport->windows_user_function = NULL;
00171   transport->windows_user_data = NULL;
00172   transport->free_windows_user_data = NULL;
00173   
00174   transport->expected_guid = NULL;
00175   
00176   /* Try to default to something that won't totally hose the system,
00177    * but doesn't impose too much of a limitation.
00178    */
00179   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
00180 
00181   /* credentials read from socket if any */
00182   transport->credentials = creds;
00183   
00184   _dbus_counter_set_notify (transport->live_messages_size,
00185                             transport->max_live_messages_size,
00186                             live_messages_size_notify,
00187                             transport);
00188 
00189   if (transport->address)
00190     _dbus_verbose ("Initialized transport on address %s\n", transport->address);
00191   
00192   return TRUE;
00193 }
00194 
00201 void
00202 _dbus_transport_finalize_base (DBusTransport *transport)
00203 {
00204   if (!transport->disconnected)
00205     _dbus_transport_disconnect (transport);
00206 
00207   if (transport->free_unix_user_data != NULL)
00208     (* transport->free_unix_user_data) (transport->unix_user_data);
00209 
00210   if (transport->free_windows_user_data != NULL)
00211     (* transport->free_windows_user_data) (transport->windows_user_data);
00212   
00213   _dbus_message_loader_unref (transport->loader);
00214   _dbus_auth_unref (transport->auth);
00215   _dbus_counter_set_notify (transport->live_messages_size,
00216                             0, NULL, NULL);
00217   _dbus_counter_unref (transport->live_messages_size);
00218   dbus_free (transport->address);
00219   dbus_free (transport->expected_guid);
00220   if (transport->credentials)
00221     _dbus_credentials_unref (transport->credentials);
00222 }
00223 
00224 
00234 static DBusTransport*
00235 check_address (const char *address, DBusError *error)
00236 {
00237   DBusAddressEntry **entries;
00238   DBusTransport *transport = NULL;
00239   int len, i;
00240 
00241   _dbus_assert (address != NULL);
00242   _dbus_assert (*address != '\0');
00243 
00244   if (!dbus_parse_address (address, &entries, &len, error))
00245     return FALSE;              /* not a valid address */
00246 
00247   for (i = 0; i < len; i++)
00248     {
00249       transport = _dbus_transport_open (entries[i], error);
00250       if (transport != NULL)
00251         break;
00252     }
00253 
00254   dbus_address_entries_free (entries);
00255   return transport;
00256 }
00257 
00265 static DBusTransport*
00266 _dbus_transport_new_for_autolaunch (DBusError      *error)
00267 {
00268   DBusString address;
00269   DBusTransport *result = NULL;
00270 
00271   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00272 
00273   if (!_dbus_string_init (&address))
00274     {
00275       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00276       return NULL;
00277     }
00278 
00279   if (!_dbus_get_autolaunch_address (&address, error))
00280     {
00281       _DBUS_ASSERT_ERROR_IS_SET (error);
00282       goto out;
00283     }
00284 
00285   result = check_address (_dbus_string_get_const_data (&address), error);
00286   if (result == NULL)
00287     _DBUS_ASSERT_ERROR_IS_SET (error);
00288   else
00289     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00290 
00291  out:
00292   _dbus_string_free (&address);
00293   return result;
00294 }
00295 
00296 static DBusTransportOpenResult
00297 _dbus_transport_open_autolaunch (DBusAddressEntry  *entry,
00298                                  DBusTransport    **transport_p,
00299                                  DBusError         *error)
00300 {
00301   const char *method;
00302   
00303   method = dbus_address_entry_get_method (entry);
00304   _dbus_assert (method != NULL);
00305 
00306   if (strcmp (method, "autolaunch") == 0)
00307     {
00308       *transport_p = _dbus_transport_new_for_autolaunch (error);
00309 
00310       if (*transport_p == NULL)
00311         {
00312           _DBUS_ASSERT_ERROR_IS_SET (error);
00313           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00314         }
00315       else
00316         {
00317           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00318           return DBUS_TRANSPORT_OPEN_OK;
00319         }      
00320     }
00321   else
00322     {
00323       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00324       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
00325     }
00326 }
00327 
00328 static const struct {
00329   DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
00330                                     DBusTransport   **transport_p,
00331                                     DBusError        *error);
00332 } open_funcs[] = {
00333   { _dbus_transport_open_socket },
00334   { _dbus_transport_open_platform_specific },
00335   { _dbus_transport_open_autolaunch }
00336 #ifdef DBUS_BUILD_TESTS
00337   , { _dbus_transport_open_debug_pipe }
00338 #endif
00339 };
00340 
00349 DBusTransport*
00350 _dbus_transport_open (DBusAddressEntry *entry,
00351                       DBusError        *error)
00352 {
00353   DBusTransport *transport;
00354   const char *expected_guid_orig;
00355   char *expected_guid;
00356   int i;
00357   DBusError tmp_error;
00358   
00359   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00360   
00361   transport = NULL;
00362   expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
00363   expected_guid = _dbus_strdup (expected_guid_orig);
00364 
00365   if (expected_guid_orig != NULL && expected_guid == NULL)
00366     {
00367       _DBUS_SET_OOM (error);
00368       return NULL;
00369     }
00370 
00371   dbus_error_init (&tmp_error);
00372   for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
00373     {
00374       DBusTransportOpenResult result;
00375 
00376       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00377       result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
00378 
00379       switch (result)
00380         {
00381         case DBUS_TRANSPORT_OPEN_OK:
00382           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00383           goto out;
00384           break;
00385         case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
00386           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00387           /* keep going through the loop of open funcs */
00388           break;
00389         case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
00390           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00391           goto out;
00392           break;
00393         case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
00394           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00395           goto out;
00396           break;
00397         }
00398     }
00399 
00400  out:
00401   
00402   if (transport == NULL)
00403     {
00404       if (!dbus_error_is_set (&tmp_error))
00405         _dbus_set_bad_address (&tmp_error,
00406                                NULL, NULL,
00407                                "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
00408       
00409       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00410       dbus_move_error(&tmp_error, error);
00411       dbus_free (expected_guid);
00412     }
00413   else
00414     {
00415       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00416       transport->expected_guid = expected_guid;
00417     }
00418 
00419   return transport;
00420 }
00421 
00428 DBusTransport *
00429 _dbus_transport_ref (DBusTransport *transport)
00430 {
00431   _dbus_assert (transport->refcount > 0);
00432   
00433   transport->refcount += 1;
00434 
00435   return transport;
00436 }
00437 
00445 void
00446 _dbus_transport_unref (DBusTransport *transport)
00447 {
00448   _dbus_assert (transport != NULL);
00449   _dbus_assert (transport->refcount > 0);
00450   
00451   transport->refcount -= 1;
00452   if (transport->refcount == 0)
00453     {
00454       _dbus_verbose ("%s: finalizing\n", _DBUS_FUNCTION_NAME);
00455       
00456       _dbus_assert (transport->vtable->finalize != NULL);
00457       
00458       (* transport->vtable->finalize) (transport);
00459     }
00460 }
00461 
00470 void
00471 _dbus_transport_disconnect (DBusTransport *transport)
00472 {
00473   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
00474   
00475   _dbus_assert (transport->vtable->disconnect != NULL);
00476   
00477   if (transport->disconnected)
00478     return;
00479 
00480   (* transport->vtable->disconnect) (transport);
00481   
00482   transport->disconnected = TRUE;
00483 
00484   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
00485 }
00486 
00495 dbus_bool_t
00496 _dbus_transport_get_is_connected (DBusTransport *transport)
00497 {
00498   return !transport->disconnected;
00499 }
00500 
00501 static dbus_bool_t
00502 auth_via_unix_user_function (DBusTransport *transport)
00503 {
00504   DBusCredentials *auth_identity;
00505   dbus_bool_t allow;
00506   DBusConnection *connection;
00507   DBusAllowUnixUserFunction unix_user_function;
00508   void *unix_user_data;
00509   dbus_uid_t uid;
00510 
00511   /* Dropping the lock here probably isn't that safe. */
00512   
00513   auth_identity = _dbus_auth_get_identity (transport->auth);
00514   _dbus_assert (auth_identity != NULL);
00515 
00516   connection = transport->connection;
00517   unix_user_function = transport->unix_user_function;
00518   unix_user_data = transport->unix_user_data;
00519   uid = _dbus_credentials_get_unix_uid (auth_identity);
00520               
00521   _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
00522   _dbus_connection_unlock (connection);
00523 
00524   allow = (* unix_user_function) (connection,
00525                                   uid,
00526                                   unix_user_data);
00527               
00528   _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
00529   _dbus_connection_lock (connection);
00530 
00531   if (allow)
00532     {
00533       _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
00534     }
00535   else
00536     {
00537       _dbus_verbose ("Client UID "DBUS_UID_FORMAT
00538                      " was rejected, disconnecting\n",
00539                      _dbus_credentials_get_unix_uid (auth_identity));
00540       _dbus_transport_disconnect (transport);
00541     }
00542 
00543   return allow;
00544 }
00545 
00546 static dbus_bool_t
00547 auth_via_windows_user_function (DBusTransport *transport)
00548 {
00549   DBusCredentials *auth_identity;  
00550   dbus_bool_t allow;
00551   DBusConnection *connection;
00552   DBusAllowWindowsUserFunction windows_user_function;
00553   void *windows_user_data;
00554   char *windows_sid;
00555 
00556   /* Dropping the lock here probably isn't that safe. */
00557   
00558   auth_identity = _dbus_auth_get_identity (transport->auth);
00559   _dbus_assert (auth_identity != NULL);
00560 
00561   connection = transport->connection;
00562   windows_user_function = transport->windows_user_function;
00563   windows_user_data = transport->unix_user_data;
00564   windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
00565 
00566   if (windows_sid == NULL)
00567     {
00568       /* OOM */
00569       return FALSE;
00570     }
00571                 
00572   _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
00573   _dbus_connection_unlock (connection);
00574 
00575   allow = (* windows_user_function) (connection,
00576                                      windows_sid,
00577                                      windows_user_data);
00578               
00579   _dbus_verbose ("lock %s post windows user function\n", _DBUS_FUNCTION_NAME);
00580   _dbus_connection_lock (connection);
00581 
00582   if (allow)
00583     {
00584       _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
00585     }
00586   else
00587     {
00588       _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
00589                      _dbus_credentials_get_windows_sid (auth_identity));
00590       _dbus_transport_disconnect (transport);
00591     }
00592 
00593   return allow;
00594 }
00595 
00596 static dbus_bool_t
00597 auth_via_default_rules (DBusTransport *transport)
00598 {
00599   DBusCredentials *auth_identity;
00600   DBusCredentials *our_identity;
00601   dbus_bool_t allow;
00602   
00603   auth_identity = _dbus_auth_get_identity (transport->auth);
00604   _dbus_assert (auth_identity != NULL);
00605 
00606   /* By default, connection is allowed if the client is 1) root or 2)
00607    * has the same UID as us or 3) anonymous is allowed.
00608    */
00609   
00610   our_identity = _dbus_credentials_new_from_current_process ();
00611   if (our_identity == NULL)
00612     {
00613       /* OOM */
00614       return FALSE;
00615     }
00616               
00617   if (transport->allow_anonymous ||
00618       _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
00619       _dbus_credentials_same_user (our_identity,
00620                                    auth_identity))
00621     {
00622       /* FIXME the verbose spam here is unix-specific */                  
00623       _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00624                      " matching our UID "DBUS_UID_FORMAT"\n",
00625                      _dbus_credentials_get_unix_uid(auth_identity),
00626                      _dbus_credentials_get_unix_uid(our_identity));
00627       /* We have authenticated! */
00628       allow = TRUE;
00629     }
00630   else
00631     {
00632       /* FIXME the verbose spam here is unix-specific */
00633       _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00634                      " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
00635                      _dbus_credentials_get_unix_uid(our_identity),
00636                      _dbus_credentials_get_unix_uid(our_identity));
00637       _dbus_transport_disconnect (transport);
00638       allow = FALSE;
00639     }  
00640 
00641   _dbus_credentials_unref (our_identity);
00642   
00643   return allow;
00644 }
00645 
00646 
00657 dbus_bool_t
00658 _dbus_transport_get_is_authenticated (DBusTransport *transport)
00659 {  
00660   if (transport->authenticated)
00661     return TRUE;
00662   else
00663     {
00664       dbus_bool_t maybe_authenticated;
00665       
00666       if (transport->disconnected)
00667         return FALSE;
00668 
00669       /* paranoia ref since we call user callbacks sometimes */
00670       _dbus_connection_ref_unlocked (transport->connection);
00671       
00672       maybe_authenticated =
00673         (!(transport->send_credentials_pending ||
00674            transport->receive_credentials_pending));
00675 
00676       if (maybe_authenticated)
00677         {
00678           switch (_dbus_auth_do_work (transport->auth))
00679             {
00680             case DBUS_AUTH_STATE_AUTHENTICATED:
00681               /* leave as maybe_authenticated */
00682               break;
00683             default:
00684               maybe_authenticated = FALSE;
00685             }
00686         }
00687 
00688       /* If we're the client, verify the GUID
00689        */
00690       if (maybe_authenticated && !transport->is_server)
00691         {
00692           const char *server_guid;
00693 
00694           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00695           _dbus_assert (server_guid != NULL);
00696 
00697           if (transport->expected_guid &&
00698               strcmp (transport->expected_guid, server_guid) != 0)
00699             {
00700               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00701                              transport->expected_guid, server_guid);
00702               _dbus_transport_disconnect (transport);
00703               _dbus_connection_unref_unlocked (transport->connection);
00704               return FALSE;
00705             }
00706 
00707           if (transport->expected_guid == NULL)
00708             {
00709               transport->expected_guid = _dbus_strdup (server_guid);
00710 
00711               if (transport->expected_guid == NULL)
00712                 {
00713                   _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME);
00714                   return FALSE;
00715                 }
00716             }
00717         }
00718 
00719       /* If we're the server, see if we want to allow this identity to proceed.
00720        */
00721       if (maybe_authenticated && transport->is_server)
00722         {
00723           dbus_bool_t allow;
00724           DBusCredentials *auth_identity;
00725           
00726           auth_identity = _dbus_auth_get_identity (transport->auth);
00727           _dbus_assert (auth_identity != NULL);
00728           
00729           /* If we have an auth'd user and a user function, delegate
00730            * deciding whether auth credentials are good enough to the
00731            * app; otherwise, use our default decision process.
00732            */
00733           if (transport->unix_user_function != NULL &&
00734               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00735             {
00736               allow = auth_via_unix_user_function (transport);
00737             }
00738           else if (transport->windows_user_function != NULL &&
00739                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00740             {
00741               allow = auth_via_windows_user_function (transport);
00742             }      
00743           else
00744             {
00745               allow = auth_via_default_rules (transport);
00746             }
00747           
00748           if (!allow)
00749             maybe_authenticated = FALSE;
00750         }
00751 
00752       transport->authenticated = maybe_authenticated;
00753 
00754       _dbus_connection_unref_unlocked (transport->connection);
00755       return maybe_authenticated;
00756     }
00757 }
00758 
00765 dbus_bool_t
00766 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00767 {
00768   DBusCredentials *auth_identity;
00769   
00770   if (!transport->authenticated)
00771     return TRUE;
00772   
00773   auth_identity = _dbus_auth_get_identity (transport->auth);
00774 
00775   if (_dbus_credentials_are_anonymous (auth_identity))
00776     return TRUE;
00777   else
00778     return FALSE;
00779 }
00780 
00788 const char*
00789 _dbus_transport_get_address (DBusTransport *transport)
00790 {
00791   return transport->address;
00792 }
00793 
00801 const char*
00802 _dbus_transport_get_server_id (DBusTransport *transport)
00803 {
00804   if (transport->is_server)
00805     return NULL;
00806   else
00807     return transport->expected_guid;
00808 }
00809 
00819 dbus_bool_t
00820 _dbus_transport_handle_watch (DBusTransport           *transport,
00821                               DBusWatch               *watch,
00822                               unsigned int             condition)
00823 {
00824   dbus_bool_t retval;
00825   
00826   _dbus_assert (transport->vtable->handle_watch != NULL);
00827 
00828   if (transport->disconnected)
00829     return TRUE;
00830 
00831   if (dbus_watch_get_socket (watch) < 0)
00832     {
00833       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00834       return TRUE;
00835     }
00836   
00837   _dbus_watch_sanitize_condition (watch, &condition);
00838 
00839   _dbus_transport_ref (transport);
00840   _dbus_watch_ref (watch);
00841   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00842   _dbus_watch_unref (watch);
00843   _dbus_transport_unref (transport);
00844 
00845   return retval;
00846 }
00847 
00857 dbus_bool_t
00858 _dbus_transport_set_connection (DBusTransport  *transport,
00859                                 DBusConnection *connection)
00860 {
00861   _dbus_assert (transport->vtable->connection_set != NULL);
00862   _dbus_assert (transport->connection == NULL);
00863   
00864   transport->connection = connection;
00865 
00866   _dbus_transport_ref (transport);
00867   if (!(* transport->vtable->connection_set) (transport))
00868     transport->connection = NULL;
00869   _dbus_transport_unref (transport);
00870 
00871   return transport->connection != NULL;
00872 }
00873 
00881 dbus_bool_t
00882 _dbus_transport_get_socket_fd (DBusTransport *transport,
00883                                int           *fd_p)
00884 {
00885   dbus_bool_t retval;
00886   
00887   if (transport->vtable->get_socket_fd == NULL)
00888     return FALSE;
00889 
00890   if (transport->disconnected)
00891     return FALSE;
00892 
00893   _dbus_transport_ref (transport);
00894 
00895   retval = (* transport->vtable->get_socket_fd) (transport,
00896                                                  fd_p);
00897   
00898   _dbus_transport_unref (transport);
00899 
00900   return retval;
00901 }
00902 
00914 void
00915 _dbus_transport_do_iteration (DBusTransport  *transport,
00916                               unsigned int    flags,
00917                               int             timeout_milliseconds)
00918 {
00919   _dbus_assert (transport->vtable->do_iteration != NULL);
00920 
00921   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00922                  flags, timeout_milliseconds, !transport->disconnected);
00923   
00924   if ((flags & (DBUS_ITERATION_DO_WRITING |
00925                 DBUS_ITERATION_DO_READING)) == 0)
00926     return; /* Nothing to do */
00927 
00928   if (transport->disconnected)
00929     return;
00930 
00931   _dbus_transport_ref (transport);
00932   (* transport->vtable->do_iteration) (transport, flags,
00933                                        timeout_milliseconds);
00934   _dbus_transport_unref (transport);
00935 
00936   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
00937 }
00938 
00939 static dbus_bool_t
00940 recover_unused_bytes (DBusTransport *transport)
00941 {
00942   if (_dbus_auth_needs_decoding (transport->auth))
00943     {
00944       DBusString plaintext;
00945       const DBusString *encoded;
00946       DBusString *buffer;
00947       int orig_len;
00948       
00949       if (!_dbus_string_init (&plaintext))
00950         goto nomem;
00951       
00952       _dbus_auth_get_unused_bytes (transport->auth,
00953                                    &encoded);
00954 
00955       if (!_dbus_auth_decode_data (transport->auth,
00956                                    encoded, &plaintext))
00957         {
00958           _dbus_string_free (&plaintext);
00959           goto nomem;
00960         }
00961       
00962       _dbus_message_loader_get_buffer (transport->loader,
00963                                        &buffer);
00964       
00965       orig_len = _dbus_string_get_length (buffer);
00966       
00967       if (!_dbus_string_move (&plaintext, 0, buffer,
00968                               orig_len))
00969         {
00970           _dbus_string_free (&plaintext);
00971           goto nomem;
00972         }
00973       
00974       _dbus_verbose (" %d unused bytes sent to message loader\n", 
00975                      _dbus_string_get_length (buffer) -
00976                      orig_len);
00977       
00978       _dbus_message_loader_return_buffer (transport->loader,
00979                                           buffer,
00980                                           _dbus_string_get_length (buffer) -
00981                                           orig_len);
00982 
00983       _dbus_auth_delete_unused_bytes (transport->auth);
00984       
00985       _dbus_string_free (&plaintext);
00986     }
00987   else
00988     {
00989       const DBusString *bytes;
00990       DBusString *buffer;
00991       int orig_len;
00992       dbus_bool_t succeeded;
00993 
00994       _dbus_message_loader_get_buffer (transport->loader,
00995                                        &buffer);
00996                 
00997       orig_len = _dbus_string_get_length (buffer);
00998                 
00999       _dbus_auth_get_unused_bytes (transport->auth,
01000                                    &bytes);
01001 
01002       succeeded = TRUE;
01003       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01004         succeeded = FALSE;
01005       
01006       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01007                      _dbus_string_get_length (buffer) -
01008                      orig_len);
01009       
01010       _dbus_message_loader_return_buffer (transport->loader,
01011                                           buffer,
01012                                           _dbus_string_get_length (buffer) -
01013                                           orig_len);
01014 
01015       if (succeeded)
01016         _dbus_auth_delete_unused_bytes (transport->auth);
01017       else
01018         goto nomem;
01019     }
01020 
01021   return TRUE;
01022 
01023  nomem:
01024   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01025   return FALSE;
01026 }
01027 
01035 DBusDispatchStatus
01036 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01037 {
01038   if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
01039     return DBUS_DISPATCH_COMPLETE; /* complete for now */
01040 
01041   if (!_dbus_transport_get_is_authenticated (transport))
01042     {
01043       if (_dbus_auth_do_work (transport->auth) ==
01044           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01045         return DBUS_DISPATCH_NEED_MEMORY;
01046       else if (!_dbus_transport_get_is_authenticated (transport))
01047         return DBUS_DISPATCH_COMPLETE;
01048     }
01049 
01050   if (!transport->unused_bytes_recovered &&
01051       !recover_unused_bytes (transport))
01052     return DBUS_DISPATCH_NEED_MEMORY;
01053 
01054   transport->unused_bytes_recovered = TRUE;
01055   
01056   if (!_dbus_message_loader_queue_messages (transport->loader))
01057     return DBUS_DISPATCH_NEED_MEMORY;
01058 
01059   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01060     return DBUS_DISPATCH_DATA_REMAINS;
01061   else
01062     return DBUS_DISPATCH_COMPLETE;
01063 }
01064 
01073 dbus_bool_t
01074 _dbus_transport_queue_messages (DBusTransport *transport)
01075 {
01076   DBusDispatchStatus status;
01077 
01078 #if 0
01079   _dbus_verbose ("_dbus_transport_queue_messages()\n");
01080 #endif
01081   
01082   /* Queue any messages */
01083   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01084     {
01085       DBusMessage *message;
01086       DBusList *link;
01087 
01088       link = _dbus_message_loader_pop_message_link (transport->loader);
01089       _dbus_assert (link != NULL);
01090       
01091       message = link->data;
01092       
01093       _dbus_verbose ("queueing received message %p\n", message);
01094 
01095       if (!_dbus_message_add_size_counter (message, transport->live_messages_size))
01096         {
01097           _dbus_message_loader_putback_message_link (transport->loader,
01098                                                      link);
01099           status = DBUS_DISPATCH_NEED_MEMORY;
01100           break;
01101         }
01102       else
01103         {
01104           /* pass ownership of link and message ref to connection */
01105           _dbus_connection_queue_received_message_link (transport->connection,
01106                                                         link);
01107         }
01108     }
01109 
01110   if (_dbus_message_loader_get_is_corrupted (transport->loader))
01111     {
01112       _dbus_verbose ("Corrupted message stream, disconnecting\n");
01113       _dbus_transport_disconnect (transport);
01114     }
01115 
01116   return status != DBUS_DISPATCH_NEED_MEMORY;
01117 }
01118 
01125 void
01126 _dbus_transport_set_max_message_size (DBusTransport  *transport,
01127                                       long            size)
01128 {
01129   _dbus_message_loader_set_max_message_size (transport->loader, size);
01130 }
01131 
01138 long
01139 _dbus_transport_get_max_message_size (DBusTransport  *transport)
01140 {
01141   return _dbus_message_loader_get_max_message_size (transport->loader);
01142 }
01143 
01150 void
01151 _dbus_transport_set_max_received_size (DBusTransport  *transport,
01152                                        long            size)
01153 {
01154   transport->max_live_messages_size = size;
01155   _dbus_counter_set_notify (transport->live_messages_size,
01156                             transport->max_live_messages_size,
01157                             live_messages_size_notify,
01158                             transport);
01159 }
01160 
01161 
01168 long
01169 _dbus_transport_get_max_received_size (DBusTransport  *transport)
01170 {
01171   return transport->max_live_messages_size;
01172 }
01173 
01181 dbus_bool_t
01182 _dbus_transport_get_unix_user (DBusTransport *transport,
01183                                unsigned long *uid)
01184 {
01185   DBusCredentials *auth_identity;
01186 
01187   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
01188                            * case of bugs in the caller. Caller should
01189                            * never use this value on purpose, however.
01190                            */
01191   
01192   if (!transport->authenticated)
01193     return FALSE;
01194   
01195   auth_identity = _dbus_auth_get_identity (transport->auth);
01196 
01197   if (_dbus_credentials_include (auth_identity,
01198                                  DBUS_CREDENTIAL_UNIX_USER_ID))
01199     {
01200       *uid = _dbus_credentials_get_unix_uid (auth_identity);
01201       return TRUE;
01202     }
01203   else
01204     return FALSE;
01205 }
01206 
01214 dbus_bool_t
01215 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01216                                      unsigned long *pid)
01217 {
01218   DBusCredentials *auth_identity;
01219 
01220   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
01221                           * but we set it to a safe number, INT_MAX,
01222                           * just to root out possible bugs in bad callers.
01223                           */
01224   
01225   if (!transport->authenticated)
01226     return FALSE;
01227   
01228   auth_identity = _dbus_auth_get_identity (transport->auth);
01229 
01230   if (_dbus_credentials_include (auth_identity,
01231                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
01232     {
01233       *pid = _dbus_credentials_get_unix_pid (auth_identity);
01234       return TRUE;
01235     }
01236   else
01237     return FALSE;
01238 }
01239 
01250 void
01251 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
01252                                         DBusAllowUnixUserFunction  function,
01253                                         void                      *data,
01254                                         DBusFreeFunction           free_data_function,
01255                                         void                     **old_data,
01256                                         DBusFreeFunction          *old_free_data_function)
01257 {  
01258   *old_data = transport->unix_user_data;
01259   *old_free_data_function = transport->free_unix_user_data;
01260 
01261   transport->unix_user_function = function;
01262   transport->unix_user_data = data;
01263   transport->free_unix_user_data = free_data_function;
01264 }
01265 
01273 dbus_bool_t
01274 _dbus_transport_get_windows_user (DBusTransport              *transport,
01275                                   char                      **windows_sid_p)
01276 {
01277   DBusCredentials *auth_identity;
01278 
01279   *windows_sid_p = NULL;
01280   
01281   if (!transport->authenticated)
01282     return FALSE;
01283   
01284   auth_identity = _dbus_auth_get_identity (transport->auth);
01285 
01286   if (_dbus_credentials_include (auth_identity,
01287                                  DBUS_CREDENTIAL_WINDOWS_SID))
01288     {
01289       /* If no memory, we are supposed to return TRUE and set NULL */
01290       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01291 
01292       return TRUE;
01293     }
01294   else
01295     return FALSE;
01296 }
01297 
01309 void
01310 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
01311                                            DBusAllowWindowsUserFunction   function,
01312                                            void                       *data,
01313                                            DBusFreeFunction            free_data_function,
01314                                            void                      **old_data,
01315                                            DBusFreeFunction           *old_free_data_function)
01316 {
01317   *old_data = transport->windows_user_data;
01318   *old_free_data_function = transport->free_windows_user_data;
01319 
01320   transport->windows_user_function = function;
01321   transport->windows_user_data = data;
01322   transport->free_windows_user_data = free_data_function;
01323 }
01324 
01333 dbus_bool_t
01334 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
01335                                      const char    **mechanisms)
01336 {
01337   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01338 }
01339 
01346 void
01347 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
01348                                      dbus_bool_t                 value)
01349 {
01350   transport->allow_anonymous = value != FALSE;
01351 }
01352 

Generated on Tue Oct 14 03:28:55 2008 for D-Bus by  doxygen 1.5.3