dbus-transport.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
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 = DBUS_ERROR_INIT;
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   for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
00372     {
00373       DBusTransportOpenResult result;
00374 
00375       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00376       result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
00377 
00378       switch (result)
00379         {
00380         case DBUS_TRANSPORT_OPEN_OK:
00381           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00382           goto out;
00383           break;
00384         case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
00385           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00386           /* keep going through the loop of open funcs */
00387           break;
00388         case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
00389           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00390           goto out;
00391           break;
00392         case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
00393           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00394           goto out;
00395           break;
00396         }
00397     }
00398 
00399  out:
00400   
00401   if (transport == NULL)
00402     {
00403       if (!dbus_error_is_set (&tmp_error))
00404         _dbus_set_bad_address (&tmp_error,
00405                                NULL, NULL,
00406                                "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
00407       
00408       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00409       dbus_move_error(&tmp_error, error);
00410       dbus_free (expected_guid);
00411     }
00412   else
00413     {
00414       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00415 
00416       /* In the case of autostart the initial guid is NULL
00417        * and the autostart transport recursively calls
00418        * _dbus_open_transport wich returns a transport
00419        * with a guid.  That guid is the definitive one.
00420        *
00421        * FIXME: if more transports are added they may have
00422        * an effect on the expected_guid semantics (i.e. 
00423        * expected_guid and transport->expected_guid may
00424        * both have values).  This is very unlikely though
00425        * we should either throw asserts here for those 
00426        * corner cases or refactor the code so it is 
00427        * clearer on what is expected and what is not
00428        */
00429       if(expected_guid)
00430         transport->expected_guid = expected_guid;
00431     }
00432 
00433   return transport;
00434 }
00435 
00442 DBusTransport *
00443 _dbus_transport_ref (DBusTransport *transport)
00444 {
00445   _dbus_assert (transport->refcount > 0);
00446   
00447   transport->refcount += 1;
00448 
00449   return transport;
00450 }
00451 
00459 void
00460 _dbus_transport_unref (DBusTransport *transport)
00461 {
00462   _dbus_assert (transport != NULL);
00463   _dbus_assert (transport->refcount > 0);
00464   
00465   transport->refcount -= 1;
00466   if (transport->refcount == 0)
00467     {
00468       _dbus_verbose ("%s: finalizing\n", _DBUS_FUNCTION_NAME);
00469       
00470       _dbus_assert (transport->vtable->finalize != NULL);
00471       
00472       (* transport->vtable->finalize) (transport);
00473     }
00474 }
00475 
00484 void
00485 _dbus_transport_disconnect (DBusTransport *transport)
00486 {
00487   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
00488   
00489   _dbus_assert (transport->vtable->disconnect != NULL);
00490   
00491   if (transport->disconnected)
00492     return;
00493 
00494   (* transport->vtable->disconnect) (transport);
00495   
00496   transport->disconnected = TRUE;
00497 
00498   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
00499 }
00500 
00509 dbus_bool_t
00510 _dbus_transport_get_is_connected (DBusTransport *transport)
00511 {
00512   return !transport->disconnected;
00513 }
00514 
00515 static dbus_bool_t
00516 auth_via_unix_user_function (DBusTransport *transport)
00517 {
00518   DBusCredentials *auth_identity;
00519   dbus_bool_t allow;
00520   DBusConnection *connection;
00521   DBusAllowUnixUserFunction unix_user_function;
00522   void *unix_user_data;
00523   dbus_uid_t uid;
00524 
00525   /* Dropping the lock here probably isn't that safe. */
00526   
00527   auth_identity = _dbus_auth_get_identity (transport->auth);
00528   _dbus_assert (auth_identity != NULL);
00529 
00530   connection = transport->connection;
00531   unix_user_function = transport->unix_user_function;
00532   unix_user_data = transport->unix_user_data;
00533   uid = _dbus_credentials_get_unix_uid (auth_identity);
00534               
00535   _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
00536   _dbus_connection_unlock (connection);
00537 
00538   allow = (* unix_user_function) (connection,
00539                                   uid,
00540                                   unix_user_data);
00541               
00542   _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
00543   _dbus_connection_lock (connection);
00544 
00545   if (allow)
00546     {
00547       _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
00548     }
00549   else
00550     {
00551       _dbus_verbose ("Client UID "DBUS_UID_FORMAT
00552                      " was rejected, disconnecting\n",
00553                      _dbus_credentials_get_unix_uid (auth_identity));
00554       _dbus_transport_disconnect (transport);
00555     }
00556 
00557   return allow;
00558 }
00559 
00560 static dbus_bool_t
00561 auth_via_windows_user_function (DBusTransport *transport)
00562 {
00563   DBusCredentials *auth_identity;  
00564   dbus_bool_t allow;
00565   DBusConnection *connection;
00566   DBusAllowWindowsUserFunction windows_user_function;
00567   void *windows_user_data;
00568   char *windows_sid;
00569 
00570   /* Dropping the lock here probably isn't that safe. */
00571   
00572   auth_identity = _dbus_auth_get_identity (transport->auth);
00573   _dbus_assert (auth_identity != NULL);
00574 
00575   connection = transport->connection;
00576   windows_user_function = transport->windows_user_function;
00577   windows_user_data = transport->unix_user_data;
00578   windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
00579 
00580   if (windows_sid == NULL)
00581     {
00582       /* OOM */
00583       return FALSE;
00584     }
00585                 
00586   _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
00587   _dbus_connection_unlock (connection);
00588 
00589   allow = (* windows_user_function) (connection,
00590                                      windows_sid,
00591                                      windows_user_data);
00592               
00593   _dbus_verbose ("lock %s post windows user function\n", _DBUS_FUNCTION_NAME);
00594   _dbus_connection_lock (connection);
00595 
00596   if (allow)
00597     {
00598       _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
00599     }
00600   else
00601     {
00602       _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
00603                      _dbus_credentials_get_windows_sid (auth_identity));
00604       _dbus_transport_disconnect (transport);
00605     }
00606 
00607   return allow;
00608 }
00609 
00610 static dbus_bool_t
00611 auth_via_default_rules (DBusTransport *transport)
00612 {
00613   DBusCredentials *auth_identity;
00614   DBusCredentials *our_identity;
00615   dbus_bool_t allow;
00616   
00617   auth_identity = _dbus_auth_get_identity (transport->auth);
00618   _dbus_assert (auth_identity != NULL);
00619 
00620   /* By default, connection is allowed if the client is 1) root or 2)
00621    * has the same UID as us or 3) anonymous is allowed.
00622    */
00623   
00624   our_identity = _dbus_credentials_new_from_current_process ();
00625   if (our_identity == NULL)
00626     {
00627       /* OOM */
00628       return FALSE;
00629     }
00630               
00631   if (transport->allow_anonymous ||
00632       _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
00633       _dbus_credentials_same_user (our_identity,
00634                                    auth_identity))
00635     {
00636       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00637           _dbus_verbose ("Client authorized as SID '%s'"
00638                          "matching our SID '%s'\n",
00639                          _dbus_credentials_get_windows_sid(auth_identity),
00640                          _dbus_credentials_get_windows_sid(our_identity));
00641       else
00642           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00643                          " matching our UID "DBUS_UID_FORMAT"\n",
00644                          _dbus_credentials_get_unix_uid(auth_identity),
00645                          _dbus_credentials_get_unix_uid(our_identity));
00646       /* We have authenticated! */
00647       allow = TRUE;
00648     }
00649   else
00650     {
00651       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00652           _dbus_verbose ("Client authorized as SID '%s'"
00653                          " but our SID is '%s', disconnecting\n",
00654                          _dbus_credentials_get_windows_sid(our_identity),
00655                          _dbus_credentials_get_windows_sid(our_identity));
00656       else
00657           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00658                          " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
00659                          _dbus_credentials_get_unix_uid(our_identity),
00660                          _dbus_credentials_get_unix_uid(our_identity));
00661       _dbus_transport_disconnect (transport);
00662       allow = FALSE;
00663     }  
00664 
00665   _dbus_credentials_unref (our_identity);
00666   
00667   return allow;
00668 }
00669 
00670 
00681 dbus_bool_t
00682 _dbus_transport_get_is_authenticated (DBusTransport *transport)
00683 {  
00684   if (transport->authenticated)
00685     return TRUE;
00686   else
00687     {
00688       dbus_bool_t maybe_authenticated;
00689       
00690       if (transport->disconnected)
00691         return FALSE;
00692 
00693       /* paranoia ref since we call user callbacks sometimes */
00694       _dbus_connection_ref_unlocked (transport->connection);
00695       
00696       maybe_authenticated =
00697         (!(transport->send_credentials_pending ||
00698            transport->receive_credentials_pending));
00699 
00700       if (maybe_authenticated)
00701         {
00702           switch (_dbus_auth_do_work (transport->auth))
00703             {
00704             case DBUS_AUTH_STATE_AUTHENTICATED:
00705               /* leave as maybe_authenticated */
00706               break;
00707             default:
00708               maybe_authenticated = FALSE;
00709             }
00710         }
00711 
00712       /* If we're the client, verify the GUID
00713        */
00714       if (maybe_authenticated && !transport->is_server)
00715         {
00716           const char *server_guid;
00717 
00718           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00719           _dbus_assert (server_guid != NULL);
00720 
00721           if (transport->expected_guid &&
00722               strcmp (transport->expected_guid, server_guid) != 0)
00723             {
00724               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00725                              transport->expected_guid, server_guid);
00726               _dbus_transport_disconnect (transport);
00727               _dbus_connection_unref_unlocked (transport->connection);
00728               return FALSE;
00729             }
00730 
00731           if (transport->expected_guid == NULL)
00732             {
00733               transport->expected_guid = _dbus_strdup (server_guid);
00734 
00735               if (transport->expected_guid == NULL)
00736                 {
00737                   _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME);
00738                   return FALSE;
00739                 }
00740             }
00741         }
00742 
00743       /* If we're the server, see if we want to allow this identity to proceed.
00744        */
00745       if (maybe_authenticated && transport->is_server)
00746         {
00747           dbus_bool_t allow;
00748           DBusCredentials *auth_identity;
00749           
00750           auth_identity = _dbus_auth_get_identity (transport->auth);
00751           _dbus_assert (auth_identity != NULL);
00752           
00753           /* If we have an auth'd user and a user function, delegate
00754            * deciding whether auth credentials are good enough to the
00755            * app; otherwise, use our default decision process.
00756            */
00757           if (transport->unix_user_function != NULL &&
00758               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00759             {
00760               allow = auth_via_unix_user_function (transport);
00761             }
00762           else if (transport->windows_user_function != NULL &&
00763                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00764             {
00765               allow = auth_via_windows_user_function (transport);
00766             }      
00767           else
00768             {
00769               allow = auth_via_default_rules (transport);
00770             }
00771           
00772           if (!allow)
00773             maybe_authenticated = FALSE;
00774         }
00775 
00776       transport->authenticated = maybe_authenticated;
00777 
00778       _dbus_connection_unref_unlocked (transport->connection);
00779       return maybe_authenticated;
00780     }
00781 }
00782 
00789 dbus_bool_t
00790 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00791 {
00792   DBusCredentials *auth_identity;
00793   
00794   if (!transport->authenticated)
00795     return TRUE;
00796   
00797   auth_identity = _dbus_auth_get_identity (transport->auth);
00798 
00799   if (_dbus_credentials_are_anonymous (auth_identity))
00800     return TRUE;
00801   else
00802     return FALSE;
00803 }
00804 
00812 const char*
00813 _dbus_transport_get_address (DBusTransport *transport)
00814 {
00815   return transport->address;
00816 }
00817 
00825 const char*
00826 _dbus_transport_get_server_id (DBusTransport *transport)
00827 {
00828   if (transport->is_server)
00829     return NULL;
00830   else
00831     return transport->expected_guid;
00832 }
00833 
00843 dbus_bool_t
00844 _dbus_transport_handle_watch (DBusTransport           *transport,
00845                               DBusWatch               *watch,
00846                               unsigned int             condition)
00847 {
00848   dbus_bool_t retval;
00849   
00850   _dbus_assert (transport->vtable->handle_watch != NULL);
00851 
00852   if (transport->disconnected)
00853     return TRUE;
00854 
00855   if (dbus_watch_get_socket (watch) < 0)
00856     {
00857       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00858       return TRUE;
00859     }
00860   
00861   _dbus_watch_sanitize_condition (watch, &condition);
00862 
00863   _dbus_transport_ref (transport);
00864   _dbus_watch_ref (watch);
00865   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00866   _dbus_watch_unref (watch);
00867   _dbus_transport_unref (transport);
00868 
00869   return retval;
00870 }
00871 
00881 dbus_bool_t
00882 _dbus_transport_set_connection (DBusTransport  *transport,
00883                                 DBusConnection *connection)
00884 {
00885   _dbus_assert (transport->vtable->connection_set != NULL);
00886   _dbus_assert (transport->connection == NULL);
00887   
00888   transport->connection = connection;
00889 
00890   _dbus_transport_ref (transport);
00891   if (!(* transport->vtable->connection_set) (transport))
00892     transport->connection = NULL;
00893   _dbus_transport_unref (transport);
00894 
00895   return transport->connection != NULL;
00896 }
00897 
00905 dbus_bool_t
00906 _dbus_transport_get_socket_fd (DBusTransport *transport,
00907                                int           *fd_p)
00908 {
00909   dbus_bool_t retval;
00910   
00911   if (transport->vtable->get_socket_fd == NULL)
00912     return FALSE;
00913 
00914   if (transport->disconnected)
00915     return FALSE;
00916 
00917   _dbus_transport_ref (transport);
00918 
00919   retval = (* transport->vtable->get_socket_fd) (transport,
00920                                                  fd_p);
00921   
00922   _dbus_transport_unref (transport);
00923 
00924   return retval;
00925 }
00926 
00938 void
00939 _dbus_transport_do_iteration (DBusTransport  *transport,
00940                               unsigned int    flags,
00941                               int             timeout_milliseconds)
00942 {
00943   _dbus_assert (transport->vtable->do_iteration != NULL);
00944 
00945   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00946                  flags, timeout_milliseconds, !transport->disconnected);
00947   
00948   if ((flags & (DBUS_ITERATION_DO_WRITING |
00949                 DBUS_ITERATION_DO_READING)) == 0)
00950     return; /* Nothing to do */
00951 
00952   if (transport->disconnected)
00953     return;
00954 
00955   _dbus_transport_ref (transport);
00956   (* transport->vtable->do_iteration) (transport, flags,
00957                                        timeout_milliseconds);
00958   _dbus_transport_unref (transport);
00959 
00960   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
00961 }
00962 
00963 static dbus_bool_t
00964 recover_unused_bytes (DBusTransport *transport)
00965 {
00966   if (_dbus_auth_needs_decoding (transport->auth))
00967     {
00968       DBusString plaintext;
00969       const DBusString *encoded;
00970       DBusString *buffer;
00971       int orig_len;
00972       
00973       if (!_dbus_string_init (&plaintext))
00974         goto nomem;
00975       
00976       _dbus_auth_get_unused_bytes (transport->auth,
00977                                    &encoded);
00978 
00979       if (!_dbus_auth_decode_data (transport->auth,
00980                                    encoded, &plaintext))
00981         {
00982           _dbus_string_free (&plaintext);
00983           goto nomem;
00984         }
00985       
00986       _dbus_message_loader_get_buffer (transport->loader,
00987                                        &buffer);
00988       
00989       orig_len = _dbus_string_get_length (buffer);
00990       
00991       if (!_dbus_string_move (&plaintext, 0, buffer,
00992                               orig_len))
00993         {
00994           _dbus_string_free (&plaintext);
00995           goto nomem;
00996         }
00997       
00998       _dbus_verbose (" %d unused bytes sent to message loader\n", 
00999                      _dbus_string_get_length (buffer) -
01000                      orig_len);
01001       
01002       _dbus_message_loader_return_buffer (transport->loader,
01003                                           buffer,
01004                                           _dbus_string_get_length (buffer) -
01005                                           orig_len);
01006 
01007       _dbus_auth_delete_unused_bytes (transport->auth);
01008       
01009       _dbus_string_free (&plaintext);
01010     }
01011   else
01012     {
01013       const DBusString *bytes;
01014       DBusString *buffer;
01015       int orig_len;
01016       dbus_bool_t succeeded;
01017 
01018       _dbus_message_loader_get_buffer (transport->loader,
01019                                        &buffer);
01020                 
01021       orig_len = _dbus_string_get_length (buffer);
01022                 
01023       _dbus_auth_get_unused_bytes (transport->auth,
01024                                    &bytes);
01025 
01026       succeeded = TRUE;
01027       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01028         succeeded = FALSE;
01029       
01030       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01031                      _dbus_string_get_length (buffer) -
01032                      orig_len);
01033       
01034       _dbus_message_loader_return_buffer (transport->loader,
01035                                           buffer,
01036                                           _dbus_string_get_length (buffer) -
01037                                           orig_len);
01038 
01039       if (succeeded)
01040         _dbus_auth_delete_unused_bytes (transport->auth);
01041       else
01042         goto nomem;
01043     }
01044 
01045   return TRUE;
01046 
01047  nomem:
01048   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01049   return FALSE;
01050 }
01051 
01059 DBusDispatchStatus
01060 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01061 {
01062   if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
01063     return DBUS_DISPATCH_COMPLETE; /* complete for now */
01064 
01065   if (!_dbus_transport_get_is_authenticated (transport))
01066     {
01067       if (_dbus_auth_do_work (transport->auth) ==
01068           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01069         return DBUS_DISPATCH_NEED_MEMORY;
01070       else if (!_dbus_transport_get_is_authenticated (transport))
01071         return DBUS_DISPATCH_COMPLETE;
01072     }
01073 
01074   if (!transport->unused_bytes_recovered &&
01075       !recover_unused_bytes (transport))
01076     return DBUS_DISPATCH_NEED_MEMORY;
01077 
01078   transport->unused_bytes_recovered = TRUE;
01079   
01080   if (!_dbus_message_loader_queue_messages (transport->loader))
01081     return DBUS_DISPATCH_NEED_MEMORY;
01082 
01083   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01084     return DBUS_DISPATCH_DATA_REMAINS;
01085   else
01086     return DBUS_DISPATCH_COMPLETE;
01087 }
01088 
01097 dbus_bool_t
01098 _dbus_transport_queue_messages (DBusTransport *transport)
01099 {
01100   DBusDispatchStatus status;
01101 
01102 #if 0
01103   _dbus_verbose ("_dbus_transport_queue_messages()\n");
01104 #endif
01105   
01106   /* Queue any messages */
01107   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01108     {
01109       DBusMessage *message;
01110       DBusList *link;
01111 
01112       link = _dbus_message_loader_pop_message_link (transport->loader);
01113       _dbus_assert (link != NULL);
01114       
01115       message = link->data;
01116       
01117       _dbus_verbose ("queueing received message %p\n", message);
01118 
01119       if (!_dbus_message_add_size_counter (message, transport->live_messages_size))
01120         {
01121           _dbus_message_loader_putback_message_link (transport->loader,
01122                                                      link);
01123           status = DBUS_DISPATCH_NEED_MEMORY;
01124           break;
01125         }
01126       else
01127         {
01128           /* pass ownership of link and message ref to connection */
01129           _dbus_connection_queue_received_message_link (transport->connection,
01130                                                         link);
01131         }
01132     }
01133 
01134   if (_dbus_message_loader_get_is_corrupted (transport->loader))
01135     {
01136       _dbus_verbose ("Corrupted message stream, disconnecting\n");
01137       _dbus_transport_disconnect (transport);
01138     }
01139 
01140   return status != DBUS_DISPATCH_NEED_MEMORY;
01141 }
01142 
01149 void
01150 _dbus_transport_set_max_message_size (DBusTransport  *transport,
01151                                       long            size)
01152 {
01153   _dbus_message_loader_set_max_message_size (transport->loader, size);
01154 }
01155 
01162 long
01163 _dbus_transport_get_max_message_size (DBusTransport  *transport)
01164 {
01165   return _dbus_message_loader_get_max_message_size (transport->loader);
01166 }
01167 
01174 void
01175 _dbus_transport_set_max_received_size (DBusTransport  *transport,
01176                                        long            size)
01177 {
01178   transport->max_live_messages_size = size;
01179   _dbus_counter_set_notify (transport->live_messages_size,
01180                             transport->max_live_messages_size,
01181                             live_messages_size_notify,
01182                             transport);
01183 }
01184 
01185 
01192 long
01193 _dbus_transport_get_max_received_size (DBusTransport  *transport)
01194 {
01195   return transport->max_live_messages_size;
01196 }
01197 
01205 dbus_bool_t
01206 _dbus_transport_get_unix_user (DBusTransport *transport,
01207                                unsigned long *uid)
01208 {
01209   DBusCredentials *auth_identity;
01210 
01211   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
01212                            * case of bugs in the caller. Caller should
01213                            * never use this value on purpose, however.
01214                            */
01215   
01216   if (!transport->authenticated)
01217     return FALSE;
01218   
01219   auth_identity = _dbus_auth_get_identity (transport->auth);
01220 
01221   if (_dbus_credentials_include (auth_identity,
01222                                  DBUS_CREDENTIAL_UNIX_USER_ID))
01223     {
01224       *uid = _dbus_credentials_get_unix_uid (auth_identity);
01225       return TRUE;
01226     }
01227   else
01228     return FALSE;
01229 }
01230 
01238 dbus_bool_t
01239 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01240                                      unsigned long *pid)
01241 {
01242   DBusCredentials *auth_identity;
01243 
01244   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
01245                           * but we set it to a safe number, INT_MAX,
01246                           * just to root out possible bugs in bad callers.
01247                           */
01248   
01249   if (!transport->authenticated)
01250     return FALSE;
01251   
01252   auth_identity = _dbus_auth_get_identity (transport->auth);
01253 
01254   if (_dbus_credentials_include (auth_identity,
01255                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
01256     {
01257       *pid = _dbus_credentials_get_unix_pid (auth_identity);
01258       return TRUE;
01259     }
01260   else
01261     return FALSE;
01262 }
01263 
01272 dbus_bool_t
01273 _dbus_transport_get_adt_audit_session_data (DBusTransport      *transport,
01274                                             void              **data,
01275                                             int                *data_size)
01276 {
01277   DBusCredentials *auth_identity;
01278 
01279   *data = NULL;
01280   *data_size = 0;
01281   
01282   if (!transport->authenticated)
01283     return FALSE;
01284   
01285   auth_identity = _dbus_auth_get_identity (transport->auth);
01286 
01287   if (_dbus_credentials_include (auth_identity,
01288                                  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
01289     {
01290       *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
01291       *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
01292       return TRUE;
01293     }
01294   else
01295     return FALSE;
01296 }
01297 
01308 void
01309 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
01310                                         DBusAllowUnixUserFunction  function,
01311                                         void                      *data,
01312                                         DBusFreeFunction           free_data_function,
01313                                         void                     **old_data,
01314                                         DBusFreeFunction          *old_free_data_function)
01315 {  
01316   *old_data = transport->unix_user_data;
01317   *old_free_data_function = transport->free_unix_user_data;
01318 
01319   transport->unix_user_function = function;
01320   transport->unix_user_data = data;
01321   transport->free_unix_user_data = free_data_function;
01322 }
01323 
01331 dbus_bool_t
01332 _dbus_transport_get_windows_user (DBusTransport              *transport,
01333                                   char                      **windows_sid_p)
01334 {
01335   DBusCredentials *auth_identity;
01336 
01337   *windows_sid_p = NULL;
01338   
01339   if (!transport->authenticated)
01340     return FALSE;
01341   
01342   auth_identity = _dbus_auth_get_identity (transport->auth);
01343 
01344   if (_dbus_credentials_include (auth_identity,
01345                                  DBUS_CREDENTIAL_WINDOWS_SID))
01346     {
01347       /* If no memory, we are supposed to return TRUE and set NULL */
01348       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01349 
01350       return TRUE;
01351     }
01352   else
01353     return FALSE;
01354 }
01355 
01367 void
01368 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
01369                                            DBusAllowWindowsUserFunction   function,
01370                                            void                       *data,
01371                                            DBusFreeFunction            free_data_function,
01372                                            void                      **old_data,
01373                                            DBusFreeFunction           *old_free_data_function)
01374 {
01375   *old_data = transport->windows_user_data;
01376   *old_free_data_function = transport->free_windows_user_data;
01377 
01378   transport->windows_user_function = function;
01379   transport->windows_user_data = data;
01380   transport->free_windows_user_data = free_data_function;
01381 }
01382 
01391 dbus_bool_t
01392 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
01393                                      const char    **mechanisms)
01394 {
01395   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01396 }
01397 
01404 void
01405 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
01406                                      dbus_bool_t                 value)
01407 {
01408   transport->allow_anonymous = value != FALSE;
01409 }
01410 

Generated on Thu Jan 22 16:37:06 2009 for D-Bus by  doxygen 1.5.1