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;
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       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00623           _dbus_verbose ("Client authorized as SID '%s'"
00624                          "matching our SID '%s'\n",
00625                          _dbus_credentials_get_windows_sid(auth_identity),
00626                          _dbus_credentials_get_windows_sid(our_identity));
00627       else
00628           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00629                          " matching our UID "DBUS_UID_FORMAT"\n",
00630                          _dbus_credentials_get_unix_uid(auth_identity),
00631                          _dbus_credentials_get_unix_uid(our_identity));
00632       /* We have authenticated! */
00633       allow = TRUE;
00634     }
00635   else
00636     {
00637       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00638           _dbus_verbose ("Client authorized as SID '%s'"
00639                          " but our SID is '%s', disconnecting\n",
00640                          _dbus_credentials_get_windows_sid(our_identity),
00641                          _dbus_credentials_get_windows_sid(our_identity));
00642       else
00643           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00644                          " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
00645                          _dbus_credentials_get_unix_uid(our_identity),
00646                          _dbus_credentials_get_unix_uid(our_identity));
00647       _dbus_transport_disconnect (transport);
00648       allow = FALSE;
00649     }  
00650 
00651   _dbus_credentials_unref (our_identity);
00652   
00653   return allow;
00654 }
00655 
00656 
00667 dbus_bool_t
00668 _dbus_transport_get_is_authenticated (DBusTransport *transport)
00669 {  
00670   if (transport->authenticated)
00671     return TRUE;
00672   else
00673     {
00674       dbus_bool_t maybe_authenticated;
00675       
00676       if (transport->disconnected)
00677         return FALSE;
00678 
00679       /* paranoia ref since we call user callbacks sometimes */
00680       _dbus_connection_ref_unlocked (transport->connection);
00681       
00682       maybe_authenticated =
00683         (!(transport->send_credentials_pending ||
00684            transport->receive_credentials_pending));
00685 
00686       if (maybe_authenticated)
00687         {
00688           switch (_dbus_auth_do_work (transport->auth))
00689             {
00690             case DBUS_AUTH_STATE_AUTHENTICATED:
00691               /* leave as maybe_authenticated */
00692               break;
00693             default:
00694               maybe_authenticated = FALSE;
00695             }
00696         }
00697 
00698       /* If we're the client, verify the GUID
00699        */
00700       if (maybe_authenticated && !transport->is_server)
00701         {
00702           const char *server_guid;
00703 
00704           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00705           _dbus_assert (server_guid != NULL);
00706 
00707           if (transport->expected_guid &&
00708               strcmp (transport->expected_guid, server_guid) != 0)
00709             {
00710               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00711                              transport->expected_guid, server_guid);
00712               _dbus_transport_disconnect (transport);
00713               _dbus_connection_unref_unlocked (transport->connection);
00714               return FALSE;
00715             }
00716 
00717           if (transport->expected_guid == NULL)
00718             {
00719               transport->expected_guid = _dbus_strdup (server_guid);
00720 
00721               if (transport->expected_guid == NULL)
00722                 {
00723                   _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME);
00724                   return FALSE;
00725                 }
00726             }
00727         }
00728 
00729       /* If we're the server, see if we want to allow this identity to proceed.
00730        */
00731       if (maybe_authenticated && transport->is_server)
00732         {
00733           dbus_bool_t allow;
00734           DBusCredentials *auth_identity;
00735           
00736           auth_identity = _dbus_auth_get_identity (transport->auth);
00737           _dbus_assert (auth_identity != NULL);
00738           
00739           /* If we have an auth'd user and a user function, delegate
00740            * deciding whether auth credentials are good enough to the
00741            * app; otherwise, use our default decision process.
00742            */
00743           if (transport->unix_user_function != NULL &&
00744               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00745             {
00746               allow = auth_via_unix_user_function (transport);
00747             }
00748           else if (transport->windows_user_function != NULL &&
00749                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00750             {
00751               allow = auth_via_windows_user_function (transport);
00752             }      
00753           else
00754             {
00755               allow = auth_via_default_rules (transport);
00756             }
00757           
00758           if (!allow)
00759             maybe_authenticated = FALSE;
00760         }
00761 
00762       transport->authenticated = maybe_authenticated;
00763 
00764       _dbus_connection_unref_unlocked (transport->connection);
00765       return maybe_authenticated;
00766     }
00767 }
00768 
00775 dbus_bool_t
00776 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00777 {
00778   DBusCredentials *auth_identity;
00779   
00780   if (!transport->authenticated)
00781     return TRUE;
00782   
00783   auth_identity = _dbus_auth_get_identity (transport->auth);
00784 
00785   if (_dbus_credentials_are_anonymous (auth_identity))
00786     return TRUE;
00787   else
00788     return FALSE;
00789 }
00790 
00798 const char*
00799 _dbus_transport_get_address (DBusTransport *transport)
00800 {
00801   return transport->address;
00802 }
00803 
00811 const char*
00812 _dbus_transport_get_server_id (DBusTransport *transport)
00813 {
00814   if (transport->is_server)
00815     return NULL;
00816   else
00817     return transport->expected_guid;
00818 }
00819 
00829 dbus_bool_t
00830 _dbus_transport_handle_watch (DBusTransport           *transport,
00831                               DBusWatch               *watch,
00832                               unsigned int             condition)
00833 {
00834   dbus_bool_t retval;
00835   
00836   _dbus_assert (transport->vtable->handle_watch != NULL);
00837 
00838   if (transport->disconnected)
00839     return TRUE;
00840 
00841   if (dbus_watch_get_socket (watch) < 0)
00842     {
00843       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00844       return TRUE;
00845     }
00846   
00847   _dbus_watch_sanitize_condition (watch, &condition);
00848 
00849   _dbus_transport_ref (transport);
00850   _dbus_watch_ref (watch);
00851   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00852   _dbus_watch_unref (watch);
00853   _dbus_transport_unref (transport);
00854 
00855   return retval;
00856 }
00857 
00867 dbus_bool_t
00868 _dbus_transport_set_connection (DBusTransport  *transport,
00869                                 DBusConnection *connection)
00870 {
00871   _dbus_assert (transport->vtable->connection_set != NULL);
00872   _dbus_assert (transport->connection == NULL);
00873   
00874   transport->connection = connection;
00875 
00876   _dbus_transport_ref (transport);
00877   if (!(* transport->vtable->connection_set) (transport))
00878     transport->connection = NULL;
00879   _dbus_transport_unref (transport);
00880 
00881   return transport->connection != NULL;
00882 }
00883 
00891 dbus_bool_t
00892 _dbus_transport_get_socket_fd (DBusTransport *transport,
00893                                int           *fd_p)
00894 {
00895   dbus_bool_t retval;
00896   
00897   if (transport->vtable->get_socket_fd == NULL)
00898     return FALSE;
00899 
00900   if (transport->disconnected)
00901     return FALSE;
00902 
00903   _dbus_transport_ref (transport);
00904 
00905   retval = (* transport->vtable->get_socket_fd) (transport,
00906                                                  fd_p);
00907   
00908   _dbus_transport_unref (transport);
00909 
00910   return retval;
00911 }
00912 
00924 void
00925 _dbus_transport_do_iteration (DBusTransport  *transport,
00926                               unsigned int    flags,
00927                               int             timeout_milliseconds)
00928 {
00929   _dbus_assert (transport->vtable->do_iteration != NULL);
00930 
00931   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00932                  flags, timeout_milliseconds, !transport->disconnected);
00933   
00934   if ((flags & (DBUS_ITERATION_DO_WRITING |
00935                 DBUS_ITERATION_DO_READING)) == 0)
00936     return; /* Nothing to do */
00937 
00938   if (transport->disconnected)
00939     return;
00940 
00941   _dbus_transport_ref (transport);
00942   (* transport->vtable->do_iteration) (transport, flags,
00943                                        timeout_milliseconds);
00944   _dbus_transport_unref (transport);
00945 
00946   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
00947 }
00948 
00949 static dbus_bool_t
00950 recover_unused_bytes (DBusTransport *transport)
00951 {
00952   if (_dbus_auth_needs_decoding (transport->auth))
00953     {
00954       DBusString plaintext;
00955       const DBusString *encoded;
00956       DBusString *buffer;
00957       int orig_len;
00958       
00959       if (!_dbus_string_init (&plaintext))
00960         goto nomem;
00961       
00962       _dbus_auth_get_unused_bytes (transport->auth,
00963                                    &encoded);
00964 
00965       if (!_dbus_auth_decode_data (transport->auth,
00966                                    encoded, &plaintext))
00967         {
00968           _dbus_string_free (&plaintext);
00969           goto nomem;
00970         }
00971       
00972       _dbus_message_loader_get_buffer (transport->loader,
00973                                        &buffer);
00974       
00975       orig_len = _dbus_string_get_length (buffer);
00976       
00977       if (!_dbus_string_move (&plaintext, 0, buffer,
00978                               orig_len))
00979         {
00980           _dbus_string_free (&plaintext);
00981           goto nomem;
00982         }
00983       
00984       _dbus_verbose (" %d unused bytes sent to message loader\n", 
00985                      _dbus_string_get_length (buffer) -
00986                      orig_len);
00987       
00988       _dbus_message_loader_return_buffer (transport->loader,
00989                                           buffer,
00990                                           _dbus_string_get_length (buffer) -
00991                                           orig_len);
00992 
00993       _dbus_auth_delete_unused_bytes (transport->auth);
00994       
00995       _dbus_string_free (&plaintext);
00996     }
00997   else
00998     {
00999       const DBusString *bytes;
01000       DBusString *buffer;
01001       int orig_len;
01002       dbus_bool_t succeeded;
01003 
01004       _dbus_message_loader_get_buffer (transport->loader,
01005                                        &buffer);
01006                 
01007       orig_len = _dbus_string_get_length (buffer);
01008                 
01009       _dbus_auth_get_unused_bytes (transport->auth,
01010                                    &bytes);
01011 
01012       succeeded = TRUE;
01013       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01014         succeeded = FALSE;
01015       
01016       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01017                      _dbus_string_get_length (buffer) -
01018                      orig_len);
01019       
01020       _dbus_message_loader_return_buffer (transport->loader,
01021                                           buffer,
01022                                           _dbus_string_get_length (buffer) -
01023                                           orig_len);
01024 
01025       if (succeeded)
01026         _dbus_auth_delete_unused_bytes (transport->auth);
01027       else
01028         goto nomem;
01029     }
01030 
01031   return TRUE;
01032 
01033  nomem:
01034   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01035   return FALSE;
01036 }
01037 
01045 DBusDispatchStatus
01046 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01047 {
01048   if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
01049     return DBUS_DISPATCH_COMPLETE; /* complete for now */
01050 
01051   if (!_dbus_transport_get_is_authenticated (transport))
01052     {
01053       if (_dbus_auth_do_work (transport->auth) ==
01054           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01055         return DBUS_DISPATCH_NEED_MEMORY;
01056       else if (!_dbus_transport_get_is_authenticated (transport))
01057         return DBUS_DISPATCH_COMPLETE;
01058     }
01059 
01060   if (!transport->unused_bytes_recovered &&
01061       !recover_unused_bytes (transport))
01062     return DBUS_DISPATCH_NEED_MEMORY;
01063 
01064   transport->unused_bytes_recovered = TRUE;
01065   
01066   if (!_dbus_message_loader_queue_messages (transport->loader))
01067     return DBUS_DISPATCH_NEED_MEMORY;
01068 
01069   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01070     return DBUS_DISPATCH_DATA_REMAINS;
01071   else
01072     return DBUS_DISPATCH_COMPLETE;
01073 }
01074 
01083 dbus_bool_t
01084 _dbus_transport_queue_messages (DBusTransport *transport)
01085 {
01086   DBusDispatchStatus status;
01087 
01088 #if 0
01089   _dbus_verbose ("_dbus_transport_queue_messages()\n");
01090 #endif
01091   
01092   /* Queue any messages */
01093   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01094     {
01095       DBusMessage *message;
01096       DBusList *link;
01097 
01098       link = _dbus_message_loader_pop_message_link (transport->loader);
01099       _dbus_assert (link != NULL);
01100       
01101       message = link->data;
01102       
01103       _dbus_verbose ("queueing received message %p\n", message);
01104 
01105       if (!_dbus_message_add_size_counter (message, transport->live_messages_size))
01106         {
01107           _dbus_message_loader_putback_message_link (transport->loader,
01108                                                      link);
01109           status = DBUS_DISPATCH_NEED_MEMORY;
01110           break;
01111         }
01112       else
01113         {
01114           /* pass ownership of link and message ref to connection */
01115           _dbus_connection_queue_received_message_link (transport->connection,
01116                                                         link);
01117         }
01118     }
01119 
01120   if (_dbus_message_loader_get_is_corrupted (transport->loader))
01121     {
01122       _dbus_verbose ("Corrupted message stream, disconnecting\n");
01123       _dbus_transport_disconnect (transport);
01124     }
01125 
01126   return status != DBUS_DISPATCH_NEED_MEMORY;
01127 }
01128 
01135 void
01136 _dbus_transport_set_max_message_size (DBusTransport  *transport,
01137                                       long            size)
01138 {
01139   _dbus_message_loader_set_max_message_size (transport->loader, size);
01140 }
01141 
01148 long
01149 _dbus_transport_get_max_message_size (DBusTransport  *transport)
01150 {
01151   return _dbus_message_loader_get_max_message_size (transport->loader);
01152 }
01153 
01160 void
01161 _dbus_transport_set_max_received_size (DBusTransport  *transport,
01162                                        long            size)
01163 {
01164   transport->max_live_messages_size = size;
01165   _dbus_counter_set_notify (transport->live_messages_size,
01166                             transport->max_live_messages_size,
01167                             live_messages_size_notify,
01168                             transport);
01169 }
01170 
01171 
01178 long
01179 _dbus_transport_get_max_received_size (DBusTransport  *transport)
01180 {
01181   return transport->max_live_messages_size;
01182 }
01183 
01191 dbus_bool_t
01192 _dbus_transport_get_unix_user (DBusTransport *transport,
01193                                unsigned long *uid)
01194 {
01195   DBusCredentials *auth_identity;
01196 
01197   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
01198                            * case of bugs in the caller. Caller should
01199                            * never use this value on purpose, however.
01200                            */
01201   
01202   if (!transport->authenticated)
01203     return FALSE;
01204   
01205   auth_identity = _dbus_auth_get_identity (transport->auth);
01206 
01207   if (_dbus_credentials_include (auth_identity,
01208                                  DBUS_CREDENTIAL_UNIX_USER_ID))
01209     {
01210       *uid = _dbus_credentials_get_unix_uid (auth_identity);
01211       return TRUE;
01212     }
01213   else
01214     return FALSE;
01215 }
01216 
01224 dbus_bool_t
01225 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01226                                      unsigned long *pid)
01227 {
01228   DBusCredentials *auth_identity;
01229 
01230   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
01231                           * but we set it to a safe number, INT_MAX,
01232                           * just to root out possible bugs in bad callers.
01233                           */
01234   
01235   if (!transport->authenticated)
01236     return FALSE;
01237   
01238   auth_identity = _dbus_auth_get_identity (transport->auth);
01239 
01240   if (_dbus_credentials_include (auth_identity,
01241                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
01242     {
01243       *pid = _dbus_credentials_get_unix_pid (auth_identity);
01244       return TRUE;
01245     }
01246   else
01247     return FALSE;
01248 }
01249 
01260 void
01261 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
01262                                         DBusAllowUnixUserFunction  function,
01263                                         void                      *data,
01264                                         DBusFreeFunction           free_data_function,
01265                                         void                     **old_data,
01266                                         DBusFreeFunction          *old_free_data_function)
01267 {  
01268   *old_data = transport->unix_user_data;
01269   *old_free_data_function = transport->free_unix_user_data;
01270 
01271   transport->unix_user_function = function;
01272   transport->unix_user_data = data;
01273   transport->free_unix_user_data = free_data_function;
01274 }
01275 
01283 dbus_bool_t
01284 _dbus_transport_get_windows_user (DBusTransport              *transport,
01285                                   char                      **windows_sid_p)
01286 {
01287   DBusCredentials *auth_identity;
01288 
01289   *windows_sid_p = NULL;
01290   
01291   if (!transport->authenticated)
01292     return FALSE;
01293   
01294   auth_identity = _dbus_auth_get_identity (transport->auth);
01295 
01296   if (_dbus_credentials_include (auth_identity,
01297                                  DBUS_CREDENTIAL_WINDOWS_SID))
01298     {
01299       /* If no memory, we are supposed to return TRUE and set NULL */
01300       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01301 
01302       return TRUE;
01303     }
01304   else
01305     return FALSE;
01306 }
01307 
01319 void
01320 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
01321                                            DBusAllowWindowsUserFunction   function,
01322                                            void                       *data,
01323                                            DBusFreeFunction            free_data_function,
01324                                            void                      **old_data,
01325                                            DBusFreeFunction           *old_free_data_function)
01326 {
01327   *old_data = transport->windows_user_data;
01328   *old_free_data_function = transport->free_windows_user_data;
01329 
01330   transport->windows_user_function = function;
01331   transport->windows_user_data = data;
01332   transport->free_windows_user_data = free_data_function;
01333 }
01334 
01343 dbus_bool_t
01344 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
01345                                      const char    **mechanisms)
01346 {
01347   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01348 }
01349 
01356 void
01357 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
01358                                      dbus_bool_t                 value)
01359 {
01360   transport->allow_anonymous = value != FALSE;
01361 }
01362 

Generated on Mon Feb 1 19:15:26 2010 for D-Bus by  doxygen 1.4.7