D-Bus 1.4.1

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