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       transport->expected_guid = expected_guid;
00416     }
00417 
00418   return transport;
00419 }
00420 
00427 DBusTransport *
00428 _dbus_transport_ref (DBusTransport *transport)
00429 {
00430   _dbus_assert (transport->refcount > 0);
00431   
00432   transport->refcount += 1;
00433 
00434   return transport;
00435 }
00436 
00444 void
00445 _dbus_transport_unref (DBusTransport *transport)
00446 {
00447   _dbus_assert (transport != NULL);
00448   _dbus_assert (transport->refcount > 0);
00449   
00450   transport->refcount -= 1;
00451   if (transport->refcount == 0)
00452     {
00453       _dbus_verbose ("%s: finalizing\n", _DBUS_FUNCTION_NAME);
00454       
00455       _dbus_assert (transport->vtable->finalize != NULL);
00456       
00457       (* transport->vtable->finalize) (transport);
00458     }
00459 }
00460 
00469 void
00470 _dbus_transport_disconnect (DBusTransport *transport)
00471 {
00472   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
00473   
00474   _dbus_assert (transport->vtable->disconnect != NULL);
00475   
00476   if (transport->disconnected)
00477     return;
00478 
00479   (* transport->vtable->disconnect) (transport);
00480   
00481   transport->disconnected = TRUE;
00482 
00483   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
00484 }
00485 
00494 dbus_bool_t
00495 _dbus_transport_get_is_connected (DBusTransport *transport)
00496 {
00497   return !transport->disconnected;
00498 }
00499 
00500 static dbus_bool_t
00501 auth_via_unix_user_function (DBusTransport *transport)
00502 {
00503   DBusCredentials *auth_identity;
00504   dbus_bool_t allow;
00505   DBusConnection *connection;
00506   DBusAllowUnixUserFunction unix_user_function;
00507   void *unix_user_data;
00508   dbus_uid_t uid;
00509 
00510   /* Dropping the lock here probably isn't that safe. */
00511   
00512   auth_identity = _dbus_auth_get_identity (transport->auth);
00513   _dbus_assert (auth_identity != NULL);
00514 
00515   connection = transport->connection;
00516   unix_user_function = transport->unix_user_function;
00517   unix_user_data = transport->unix_user_data;
00518   uid = _dbus_credentials_get_unix_uid (auth_identity);
00519               
00520   _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
00521   _dbus_connection_unlock (connection);
00522 
00523   allow = (* unix_user_function) (connection,
00524                                   uid,
00525                                   unix_user_data);
00526               
00527   _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
00528   _dbus_connection_lock (connection);
00529 
00530   if (allow)
00531     {
00532       _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
00533     }
00534   else
00535     {
00536       _dbus_verbose ("Client UID "DBUS_UID_FORMAT
00537                      " was rejected, disconnecting\n",
00538                      _dbus_credentials_get_unix_uid (auth_identity));
00539       _dbus_transport_disconnect (transport);
00540     }
00541 
00542   return allow;
00543 }
00544 
00545 static dbus_bool_t
00546 auth_via_windows_user_function (DBusTransport *transport)
00547 {
00548   DBusCredentials *auth_identity;  
00549   dbus_bool_t allow;
00550   DBusConnection *connection;
00551   DBusAllowWindowsUserFunction windows_user_function;
00552   void *windows_user_data;
00553   char *windows_sid;
00554 
00555   /* Dropping the lock here probably isn't that safe. */
00556   
00557   auth_identity = _dbus_auth_get_identity (transport->auth);
00558   _dbus_assert (auth_identity != NULL);
00559 
00560   connection = transport->connection;
00561   windows_user_function = transport->windows_user_function;
00562   windows_user_data = transport->unix_user_data;
00563   windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
00564 
00565   if (windows_sid == NULL)
00566     {
00567       /* OOM */
00568       return FALSE;
00569     }
00570                 
00571   _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
00572   _dbus_connection_unlock (connection);
00573 
00574   allow = (* windows_user_function) (connection,
00575                                      windows_sid,
00576                                      windows_user_data);
00577               
00578   _dbus_verbose ("lock %s post windows user function\n", _DBUS_FUNCTION_NAME);
00579   _dbus_connection_lock (connection);
00580 
00581   if (allow)
00582     {
00583       _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
00584     }
00585   else
00586     {
00587       _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
00588                      _dbus_credentials_get_windows_sid (auth_identity));
00589       _dbus_transport_disconnect (transport);
00590     }
00591 
00592   return allow;
00593 }
00594 
00595 static dbus_bool_t
00596 auth_via_default_rules (DBusTransport *transport)
00597 {
00598   DBusCredentials *auth_identity;
00599   DBusCredentials *our_identity;
00600   dbus_bool_t allow;
00601   
00602   auth_identity = _dbus_auth_get_identity (transport->auth);
00603   _dbus_assert (auth_identity != NULL);
00604 
00605   /* By default, connection is allowed if the client is 1) root or 2)
00606    * has the same UID as us or 3) anonymous is allowed.
00607    */
00608   
00609   our_identity = _dbus_credentials_new_from_current_process ();
00610   if (our_identity == NULL)
00611     {
00612       /* OOM */
00613       return FALSE;
00614     }
00615               
00616   if (transport->allow_anonymous ||
00617       _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
00618       _dbus_credentials_same_user (our_identity,
00619                                    auth_identity))
00620     {
00621       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00622           _dbus_verbose ("Client authorized as SID '%s'"
00623                          "matching our SID '%s'\n",
00624                          _dbus_credentials_get_windows_sid(auth_identity),
00625                          _dbus_credentials_get_windows_sid(our_identity));
00626       else
00627           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00628                          " matching our UID "DBUS_UID_FORMAT"\n",
00629                          _dbus_credentials_get_unix_uid(auth_identity),
00630                          _dbus_credentials_get_unix_uid(our_identity));
00631       /* We have authenticated! */
00632       allow = TRUE;
00633     }
00634   else
00635     {
00636       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00637           _dbus_verbose ("Client authorized as SID '%s'"
00638                          " but our SID is '%s', disconnecting\n",
00639                          _dbus_credentials_get_windows_sid(our_identity),
00640                          _dbus_credentials_get_windows_sid(our_identity));
00641       else
00642           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00643                          " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
00644                          _dbus_credentials_get_unix_uid(our_identity),
00645                          _dbus_credentials_get_unix_uid(our_identity));
00646       _dbus_transport_disconnect (transport);
00647       allow = FALSE;
00648     }  
00649 
00650   _dbus_credentials_unref (our_identity);
00651   
00652   return allow;
00653 }
00654 
00655 
00666 dbus_bool_t
00667 _dbus_transport_get_is_authenticated (DBusTransport *transport)
00668 {  
00669   if (transport->authenticated)
00670     return TRUE;
00671   else
00672     {
00673       dbus_bool_t maybe_authenticated;
00674       
00675       if (transport->disconnected)
00676         return FALSE;
00677 
00678       /* paranoia ref since we call user callbacks sometimes */
00679       _dbus_connection_ref_unlocked (transport->connection);
00680       
00681       maybe_authenticated =
00682         (!(transport->send_credentials_pending ||
00683            transport->receive_credentials_pending));
00684 
00685       if (maybe_authenticated)
00686         {
00687           switch (_dbus_auth_do_work (transport->auth))
00688             {
00689             case DBUS_AUTH_STATE_AUTHENTICATED:
00690               /* leave as maybe_authenticated */
00691               break;
00692             default:
00693               maybe_authenticated = FALSE;
00694             }
00695         }
00696 
00697       /* If we're the client, verify the GUID
00698        */
00699       if (maybe_authenticated && !transport->is_server)
00700         {
00701           const char *server_guid;
00702 
00703           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00704           _dbus_assert (server_guid != NULL);
00705 
00706           if (transport->expected_guid &&
00707               strcmp (transport->expected_guid, server_guid) != 0)
00708             {
00709               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00710                              transport->expected_guid, server_guid);
00711               _dbus_transport_disconnect (transport);
00712               _dbus_connection_unref_unlocked (transport->connection);
00713               return FALSE;
00714             }
00715 
00716           if (transport->expected_guid == NULL)
00717             {
00718               transport->expected_guid = _dbus_strdup (server_guid);
00719 
00720               if (transport->expected_guid == NULL)
00721                 {
00722                   _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME);
00723                   return FALSE;
00724                 }
00725             }
00726         }
00727 
00728       /* If we're the server, see if we want to allow this identity to proceed.
00729        */
00730       if (maybe_authenticated && transport->is_server)
00731         {
00732           dbus_bool_t allow;
00733           DBusCredentials *auth_identity;
00734           
00735           auth_identity = _dbus_auth_get_identity (transport->auth);
00736           _dbus_assert (auth_identity != NULL);
00737           
00738           /* If we have an auth'd user and a user function, delegate
00739            * deciding whether auth credentials are good enough to the
00740            * app; otherwise, use our default decision process.
00741            */
00742           if (transport->unix_user_function != NULL &&
00743               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00744             {
00745               allow = auth_via_unix_user_function (transport);
00746             }
00747           else if (transport->windows_user_function != NULL &&
00748                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00749             {
00750               allow = auth_via_windows_user_function (transport);
00751             }      
00752           else
00753             {
00754               allow = auth_via_default_rules (transport);
00755             }
00756           
00757           if (!allow)
00758             maybe_authenticated = FALSE;
00759         }
00760 
00761       transport->authenticated = maybe_authenticated;
00762 
00763       _dbus_connection_unref_unlocked (transport->connection);
00764       return maybe_authenticated;
00765     }
00766 }
00767 
00774 dbus_bool_t
00775 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00776 {
00777   DBusCredentials *auth_identity;
00778   
00779   if (!transport->authenticated)
00780     return TRUE;
00781   
00782   auth_identity = _dbus_auth_get_identity (transport->auth);
00783 
00784   if (_dbus_credentials_are_anonymous (auth_identity))
00785     return TRUE;
00786   else
00787     return FALSE;
00788 }
00789 
00797 const char*
00798 _dbus_transport_get_address (DBusTransport *transport)
00799 {
00800   return transport->address;
00801 }
00802 
00810 const char*
00811 _dbus_transport_get_server_id (DBusTransport *transport)
00812 {
00813   if (transport->is_server)
00814     return NULL;
00815   else
00816     return transport->expected_guid;
00817 }
00818 
00828 dbus_bool_t
00829 _dbus_transport_handle_watch (DBusTransport           *transport,
00830                               DBusWatch               *watch,
00831                               unsigned int             condition)
00832 {
00833   dbus_bool_t retval;
00834   
00835   _dbus_assert (transport->vtable->handle_watch != NULL);
00836 
00837   if (transport->disconnected)
00838     return TRUE;
00839 
00840   if (dbus_watch_get_socket (watch) < 0)
00841     {
00842       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00843       return TRUE;
00844     }
00845   
00846   _dbus_watch_sanitize_condition (watch, &condition);
00847 
00848   _dbus_transport_ref (transport);
00849   _dbus_watch_ref (watch);
00850   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00851   _dbus_watch_unref (watch);
00852   _dbus_transport_unref (transport);
00853 
00854   return retval;
00855 }
00856 
00866 dbus_bool_t
00867 _dbus_transport_set_connection (DBusTransport  *transport,
00868                                 DBusConnection *connection)
00869 {
00870   _dbus_assert (transport->vtable->connection_set != NULL);
00871   _dbus_assert (transport->connection == NULL);
00872   
00873   transport->connection = connection;
00874 
00875   _dbus_transport_ref (transport);
00876   if (!(* transport->vtable->connection_set) (transport))
00877     transport->connection = NULL;
00878   _dbus_transport_unref (transport);
00879 
00880   return transport->connection != NULL;
00881 }
00882 
00890 dbus_bool_t
00891 _dbus_transport_get_socket_fd (DBusTransport *transport,
00892                                int           *fd_p)
00893 {
00894   dbus_bool_t retval;
00895   
00896   if (transport->vtable->get_socket_fd == NULL)
00897     return FALSE;
00898 
00899   if (transport->disconnected)
00900     return FALSE;
00901 
00902   _dbus_transport_ref (transport);
00903 
00904   retval = (* transport->vtable->get_socket_fd) (transport,
00905                                                  fd_p);
00906   
00907   _dbus_transport_unref (transport);
00908 
00909   return retval;
00910 }
00911 
00923 void
00924 _dbus_transport_do_iteration (DBusTransport  *transport,
00925                               unsigned int    flags,
00926                               int             timeout_milliseconds)
00927 {
00928   _dbus_assert (transport->vtable->do_iteration != NULL);
00929 
00930   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00931                  flags, timeout_milliseconds, !transport->disconnected);
00932   
00933   if ((flags & (DBUS_ITERATION_DO_WRITING |
00934                 DBUS_ITERATION_DO_READING)) == 0)
00935     return; /* Nothing to do */
00936 
00937   if (transport->disconnected)
00938     return;
00939 
00940   _dbus_transport_ref (transport);
00941   (* transport->vtable->do_iteration) (transport, flags,
00942                                        timeout_milliseconds);
00943   _dbus_transport_unref (transport);
00944 
00945   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
00946 }
00947 
00948 static dbus_bool_t
00949 recover_unused_bytes (DBusTransport *transport)
00950 {
00951   if (_dbus_auth_needs_decoding (transport->auth))
00952     {
00953       DBusString plaintext;
00954       const DBusString *encoded;
00955       DBusString *buffer;
00956       int orig_len;
00957       
00958       if (!_dbus_string_init (&plaintext))
00959         goto nomem;
00960       
00961       _dbus_auth_get_unused_bytes (transport->auth,
00962                                    &encoded);
00963 
00964       if (!_dbus_auth_decode_data (transport->auth,
00965                                    encoded, &plaintext))
00966         {
00967           _dbus_string_free (&plaintext);
00968           goto nomem;
00969         }
00970       
00971       _dbus_message_loader_get_buffer (transport->loader,
00972                                        &buffer);
00973       
00974       orig_len = _dbus_string_get_length (buffer);
00975       
00976       if (!_dbus_string_move (&plaintext, 0, buffer,
00977                               orig_len))
00978         {
00979           _dbus_string_free (&plaintext);
00980           goto nomem;
00981         }
00982       
00983       _dbus_verbose (" %d unused bytes sent to message loader\n", 
00984                      _dbus_string_get_length (buffer) -
00985                      orig_len);
00986       
00987       _dbus_message_loader_return_buffer (transport->loader,
00988                                           buffer,
00989                                           _dbus_string_get_length (buffer) -
00990                                           orig_len);
00991 
00992       _dbus_auth_delete_unused_bytes (transport->auth);
00993       
00994       _dbus_string_free (&plaintext);
00995     }
00996   else
00997     {
00998       const DBusString *bytes;
00999       DBusString *buffer;
01000       int orig_len;
01001       dbus_bool_t succeeded;
01002 
01003       _dbus_message_loader_get_buffer (transport->loader,
01004                                        &buffer);
01005                 
01006       orig_len = _dbus_string_get_length (buffer);
01007                 
01008       _dbus_auth_get_unused_bytes (transport->auth,
01009                                    &bytes);
01010 
01011       succeeded = TRUE;
01012       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01013         succeeded = FALSE;
01014       
01015       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01016                      _dbus_string_get_length (buffer) -
01017                      orig_len);
01018       
01019       _dbus_message_loader_return_buffer (transport->loader,
01020                                           buffer,
01021                                           _dbus_string_get_length (buffer) -
01022                                           orig_len);
01023 
01024       if (succeeded)
01025         _dbus_auth_delete_unused_bytes (transport->auth);
01026       else
01027         goto nomem;
01028     }
01029 
01030   return TRUE;
01031 
01032  nomem:
01033   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01034   return FALSE;
01035 }
01036 
01044 DBusDispatchStatus
01045 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01046 {
01047   if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
01048     return DBUS_DISPATCH_COMPLETE; /* complete for now */
01049 
01050   if (!_dbus_transport_get_is_authenticated (transport))
01051     {
01052       if (_dbus_auth_do_work (transport->auth) ==
01053           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01054         return DBUS_DISPATCH_NEED_MEMORY;
01055       else if (!_dbus_transport_get_is_authenticated (transport))
01056         return DBUS_DISPATCH_COMPLETE;
01057     }
01058 
01059   if (!transport->unused_bytes_recovered &&
01060       !recover_unused_bytes (transport))
01061     return DBUS_DISPATCH_NEED_MEMORY;
01062 
01063   transport->unused_bytes_recovered = TRUE;
01064   
01065   if (!_dbus_message_loader_queue_messages (transport->loader))
01066     return DBUS_DISPATCH_NEED_MEMORY;
01067 
01068   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01069     return DBUS_DISPATCH_DATA_REMAINS;
01070   else
01071     return DBUS_DISPATCH_COMPLETE;
01072 }
01073 
01082 dbus_bool_t
01083 _dbus_transport_queue_messages (DBusTransport *transport)
01084 {
01085   DBusDispatchStatus status;
01086 
01087 #if 0
01088   _dbus_verbose ("_dbus_transport_queue_messages()\n");
01089 #endif
01090   
01091   /* Queue any messages */
01092   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01093     {
01094       DBusMessage *message;
01095       DBusList *link;
01096 
01097       link = _dbus_message_loader_pop_message_link (transport->loader);
01098       _dbus_assert (link != NULL);
01099       
01100       message = link->data;
01101       
01102       _dbus_verbose ("queueing received message %p\n", message);
01103 
01104       if (!_dbus_message_add_size_counter (message, transport->live_messages_size))
01105         {
01106           _dbus_message_loader_putback_message_link (transport->loader,
01107                                                      link);
01108           status = DBUS_DISPATCH_NEED_MEMORY;
01109           break;
01110         }
01111       else
01112         {
01113           /* pass ownership of link and message ref to connection */
01114           _dbus_connection_queue_received_message_link (transport->connection,
01115                                                         link);
01116         }
01117     }
01118 
01119   if (_dbus_message_loader_get_is_corrupted (transport->loader))
01120     {
01121       _dbus_verbose ("Corrupted message stream, disconnecting\n");
01122       _dbus_transport_disconnect (transport);
01123     }
01124 
01125   return status != DBUS_DISPATCH_NEED_MEMORY;
01126 }
01127 
01134 void
01135 _dbus_transport_set_max_message_size (DBusTransport  *transport,
01136                                       long            size)
01137 {
01138   _dbus_message_loader_set_max_message_size (transport->loader, size);
01139 }
01140 
01147 long
01148 _dbus_transport_get_max_message_size (DBusTransport  *transport)
01149 {
01150   return _dbus_message_loader_get_max_message_size (transport->loader);
01151 }
01152 
01159 void
01160 _dbus_transport_set_max_received_size (DBusTransport  *transport,
01161                                        long            size)
01162 {
01163   transport->max_live_messages_size = size;
01164   _dbus_counter_set_notify (transport->live_messages_size,
01165                             transport->max_live_messages_size,
01166                             live_messages_size_notify,
01167                             transport);
01168 }
01169 
01170 
01177 long
01178 _dbus_transport_get_max_received_size (DBusTransport  *transport)
01179 {
01180   return transport->max_live_messages_size;
01181 }
01182 
01190 dbus_bool_t
01191 _dbus_transport_get_unix_user (DBusTransport *transport,
01192                                unsigned long *uid)
01193 {
01194   DBusCredentials *auth_identity;
01195 
01196   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
01197                            * case of bugs in the caller. Caller should
01198                            * never use this value on purpose, however.
01199                            */
01200   
01201   if (!transport->authenticated)
01202     return FALSE;
01203   
01204   auth_identity = _dbus_auth_get_identity (transport->auth);
01205 
01206   if (_dbus_credentials_include (auth_identity,
01207                                  DBUS_CREDENTIAL_UNIX_USER_ID))
01208     {
01209       *uid = _dbus_credentials_get_unix_uid (auth_identity);
01210       return TRUE;
01211     }
01212   else
01213     return FALSE;
01214 }
01215 
01223 dbus_bool_t
01224 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01225                                      unsigned long *pid)
01226 {
01227   DBusCredentials *auth_identity;
01228 
01229   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
01230                           * but we set it to a safe number, INT_MAX,
01231                           * just to root out possible bugs in bad callers.
01232                           */
01233   
01234   if (!transport->authenticated)
01235     return FALSE;
01236   
01237   auth_identity = _dbus_auth_get_identity (transport->auth);
01238 
01239   if (_dbus_credentials_include (auth_identity,
01240                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
01241     {
01242       *pid = _dbus_credentials_get_unix_pid (auth_identity);
01243       return TRUE;
01244     }
01245   else
01246     return FALSE;
01247 }
01248 
01259 void
01260 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
01261                                         DBusAllowUnixUserFunction  function,
01262                                         void                      *data,
01263                                         DBusFreeFunction           free_data_function,
01264                                         void                     **old_data,
01265                                         DBusFreeFunction          *old_free_data_function)
01266 {  
01267   *old_data = transport->unix_user_data;
01268   *old_free_data_function = transport->free_unix_user_data;
01269 
01270   transport->unix_user_function = function;
01271   transport->unix_user_data = data;
01272   transport->free_unix_user_data = free_data_function;
01273 }
01274 
01282 dbus_bool_t
01283 _dbus_transport_get_windows_user (DBusTransport              *transport,
01284                                   char                      **windows_sid_p)
01285 {
01286   DBusCredentials *auth_identity;
01287 
01288   *windows_sid_p = NULL;
01289   
01290   if (!transport->authenticated)
01291     return FALSE;
01292   
01293   auth_identity = _dbus_auth_get_identity (transport->auth);
01294 
01295   if (_dbus_credentials_include (auth_identity,
01296                                  DBUS_CREDENTIAL_WINDOWS_SID))
01297     {
01298       /* If no memory, we are supposed to return TRUE and set NULL */
01299       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01300 
01301       return TRUE;
01302     }
01303   else
01304     return FALSE;
01305 }
01306 
01318 void
01319 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
01320                                            DBusAllowWindowsUserFunction   function,
01321                                            void                       *data,
01322                                            DBusFreeFunction            free_data_function,
01323                                            void                      **old_data,
01324                                            DBusFreeFunction           *old_free_data_function)
01325 {
01326   *old_data = transport->windows_user_data;
01327   *old_free_data_function = transport->free_windows_user_data;
01328 
01329   transport->windows_user_function = function;
01330   transport->windows_user_data = data;
01331   transport->free_windows_user_data = free_data_function;
01332 }
01333 
01342 dbus_bool_t
01343 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
01344                                      const char    **mechanisms)
01345 {
01346   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01347 }
01348 
01355 void
01356 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
01357                                      dbus_bool_t                 value)
01358 {
01359   transport->allow_anonymous = value != FALSE;
01360 }
01361 

Generated on Sat Jun 14 22:43:04 2008 for D-Bus by  doxygen 1.4.6