D-Bus  1.10.12
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-mainloop.h"
00034 #include "dbus-message.h"
00035 #ifdef DBUS_ENABLE_EMBEDDED_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_connection_lock (transport->connection);
00067   _dbus_transport_ref (transport);
00068 
00069 #if 0
00070   _dbus_verbose ("Size counter value is now %d\n",
00071                  (int) _dbus_counter_get_size_value (counter));
00072   _dbus_verbose ("Unix FD counter value is now %d\n",
00073                  (int) _dbus_counter_get_unix_fd_value (counter));
00074 #endif
00075 
00076   /* disable or re-enable the read watch for the transport if
00077    * required.
00078    */
00079   if (transport->vtable->live_messages_changed)
00080     {
00081       (* transport->vtable->live_messages_changed) (transport);
00082     }
00083 
00084   _dbus_transport_unref (transport);
00085   _dbus_connection_unlock (transport->connection);
00086 }
00087 
00101 dbus_bool_t
00102 _dbus_transport_init_base (DBusTransport             *transport,
00103                            const DBusTransportVTable *vtable,
00104                            const DBusString          *server_guid,
00105                            const DBusString          *address)
00106 {
00107   DBusMessageLoader *loader;
00108   DBusAuth *auth;
00109   DBusCounter *counter;
00110   char *address_copy;
00111   DBusCredentials *creds;
00112   
00113   loader = _dbus_message_loader_new ();
00114   if (loader == NULL)
00115     return FALSE;
00116   
00117   if (server_guid)
00118     auth = _dbus_auth_server_new (server_guid);
00119   else
00120     auth = _dbus_auth_client_new ();
00121   if (auth == NULL)
00122     {
00123       _dbus_message_loader_unref (loader);
00124       return FALSE;
00125     }
00126 
00127   counter = _dbus_counter_new ();
00128   if (counter == NULL)
00129     {
00130       _dbus_auth_unref (auth);
00131       _dbus_message_loader_unref (loader);
00132       return FALSE;
00133     }  
00134 
00135   creds = _dbus_credentials_new ();
00136   if (creds == NULL)
00137     {
00138       _dbus_counter_unref (counter);
00139       _dbus_auth_unref (auth);
00140       _dbus_message_loader_unref (loader);
00141       return FALSE;
00142     }
00143   
00144   if (server_guid)
00145     {
00146       _dbus_assert (address == NULL);
00147       address_copy = NULL;
00148     }
00149   else
00150     {
00151       _dbus_assert (address != NULL);
00152 
00153       if (!_dbus_string_copy_data (address, &address_copy))
00154         {
00155           _dbus_credentials_unref (creds);
00156           _dbus_counter_unref (counter);
00157           _dbus_auth_unref (auth);
00158           _dbus_message_loader_unref (loader);
00159           return FALSE;
00160         }
00161     }
00162   
00163   transport->refcount = 1;
00164   transport->vtable = vtable;
00165   transport->loader = loader;
00166   transport->auth = auth;
00167   transport->live_messages = counter;
00168   transport->authenticated = FALSE;
00169   transport->disconnected = FALSE;
00170   transport->is_server = (server_guid != NULL);
00171   transport->send_credentials_pending = !transport->is_server;
00172   transport->receive_credentials_pending = transport->is_server;
00173   transport->address = address_copy;
00174   
00175   transport->unix_user_function = NULL;
00176   transport->unix_user_data = NULL;
00177   transport->free_unix_user_data = NULL;
00178 
00179   transport->windows_user_function = NULL;
00180   transport->windows_user_data = NULL;
00181   transport->free_windows_user_data = NULL;
00182   
00183   transport->expected_guid = NULL;
00184   
00185   /* Try to default to something that won't totally hose the system,
00186    * but doesn't impose too much of a limitation.
00187    */
00188   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
00189 
00190   /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
00191      should be more than enough */
00192   transport->max_live_messages_unix_fds = 4096;
00193 
00194   /* credentials read from socket if any */
00195   transport->credentials = creds;
00196 
00197   _dbus_counter_set_notify (transport->live_messages,
00198                             transport->max_live_messages_size,
00199                             transport->max_live_messages_unix_fds,
00200                             live_messages_notify,
00201                             transport);
00202 
00203   if (transport->address)
00204     _dbus_verbose ("Initialized transport on address %s\n", transport->address);
00205 
00206   return TRUE;
00207 }
00208 
00215 void
00216 _dbus_transport_finalize_base (DBusTransport *transport)
00217 {
00218   if (!transport->disconnected)
00219     _dbus_transport_disconnect (transport);
00220 
00221   if (transport->free_unix_user_data != NULL)
00222     (* transport->free_unix_user_data) (transport->unix_user_data);
00223 
00224   if (transport->free_windows_user_data != NULL)
00225     (* transport->free_windows_user_data) (transport->windows_user_data);
00226   
00227   _dbus_message_loader_unref (transport->loader);
00228   _dbus_auth_unref (transport->auth);
00229   _dbus_counter_set_notify (transport->live_messages,
00230                             0, 0, NULL, NULL);
00231   _dbus_counter_unref (transport->live_messages);
00232   dbus_free (transport->address);
00233   dbus_free (transport->expected_guid);
00234   if (transport->credentials)
00235     _dbus_credentials_unref (transport->credentials);
00236 }
00237 
00238 
00249 static DBusTransport*
00250 check_address (const char *address, DBusError *error)
00251 {
00252   DBusAddressEntry **entries;
00253   DBusTransport *transport = NULL;
00254   int len, i;
00255 
00256   _dbus_assert (address != NULL);
00257 
00258   if (!dbus_parse_address (address, &entries, &len, error))
00259     return NULL;              /* not a valid address */
00260 
00261   for (i = 0; i < len; i++)
00262     {
00263       transport = _dbus_transport_open (entries[i], error);
00264       if (transport != NULL)
00265         break;
00266     }
00267 
00268   dbus_address_entries_free (entries);
00269   return transport;
00270 }
00271 
00280 static DBusTransport*
00281 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
00282 {
00283   DBusString address;
00284   DBusTransport *result = NULL;
00285 
00286   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00287 
00288   if (!_dbus_string_init (&address))
00289     {
00290       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00291       return NULL;
00292     }
00293 
00294   if (!_dbus_get_autolaunch_address (scope, &address, error))
00295     {
00296       _DBUS_ASSERT_ERROR_IS_SET (error);
00297       goto out;
00298     }
00299 
00300   result = check_address (_dbus_string_get_const_data (&address), error);
00301   if (result == NULL)
00302     _DBUS_ASSERT_ERROR_IS_SET (error);
00303   else
00304     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00305 
00306  out:
00307   _dbus_string_free (&address);
00308   return result;
00309 }
00310 
00311 static DBusTransportOpenResult
00312 _dbus_transport_open_autolaunch (DBusAddressEntry  *entry,
00313                                  DBusTransport    **transport_p,
00314                                  DBusError         *error)
00315 {
00316   const char *method;
00317   
00318   method = dbus_address_entry_get_method (entry);
00319   _dbus_assert (method != NULL);
00320 
00321   if (strcmp (method, "autolaunch") == 0)
00322     {
00323       const char *scope = dbus_address_entry_get_value (entry, "scope");
00324 
00325       *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
00326 
00327       if (*transport_p == NULL)
00328         {
00329           _DBUS_ASSERT_ERROR_IS_SET (error);
00330           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00331         }
00332       else
00333         {
00334           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00335           return DBUS_TRANSPORT_OPEN_OK;
00336         }      
00337     }
00338   else
00339     {
00340       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00341       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
00342     }
00343 }
00344 
00345 static const struct {
00346   DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
00347                                     DBusTransport   **transport_p,
00348                                     DBusError        *error);
00349 } open_funcs[] = {
00350   { _dbus_transport_open_socket },
00351   { _dbus_transport_open_platform_specific },
00352   { _dbus_transport_open_autolaunch }
00353 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00354   , { _dbus_transport_open_debug_pipe }
00355 #endif
00356 };
00357 
00366 DBusTransport*
00367 _dbus_transport_open (DBusAddressEntry *entry,
00368                       DBusError        *error)
00369 {
00370   DBusTransport *transport;
00371   const char *expected_guid_orig;
00372   char *expected_guid;
00373   int i;
00374   DBusError tmp_error = DBUS_ERROR_INIT;
00375 
00376   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00377   
00378   transport = NULL;
00379   expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
00380   expected_guid = _dbus_strdup (expected_guid_orig);
00381 
00382   if (expected_guid_orig != NULL && expected_guid == NULL)
00383     {
00384       _DBUS_SET_OOM (error);
00385       return NULL;
00386     }
00387 
00388   for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
00389     {
00390       DBusTransportOpenResult result;
00391 
00392       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00393       result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
00394 
00395       switch (result)
00396         {
00397         case DBUS_TRANSPORT_OPEN_OK:
00398           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00399           goto out;
00400           break;
00401         case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
00402           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00403           /* keep going through the loop of open funcs */
00404           break;
00405         case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
00406           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00407           goto out;
00408           break;
00409         case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
00410           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00411           goto out;
00412           break;
00413         }
00414     }
00415 
00416  out:
00417   
00418   if (transport == NULL)
00419     {
00420       if (!dbus_error_is_set (&tmp_error))
00421         _dbus_set_bad_address (&tmp_error,
00422                                NULL, NULL,
00423                                "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
00424       
00425       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00426       dbus_move_error(&tmp_error, error);
00427       dbus_free (expected_guid);
00428     }
00429   else
00430     {
00431       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00432 
00433       /* In the case of autostart the initial guid is NULL
00434        * and the autostart transport recursively calls
00435        * _dbus_open_transport wich returns a transport
00436        * with a guid.  That guid is the definitive one.
00437        *
00438        * FIXME: if more transports are added they may have
00439        * an effect on the expected_guid semantics (i.e. 
00440        * expected_guid and transport->expected_guid may
00441        * both have values).  This is very unlikely though
00442        * we should either throw asserts here for those 
00443        * corner cases or refactor the code so it is 
00444        * clearer on what is expected and what is not
00445        */
00446       if(expected_guid)
00447         transport->expected_guid = expected_guid;
00448     }
00449 
00450   return transport;
00451 }
00452 
00459 DBusTransport *
00460 _dbus_transport_ref (DBusTransport *transport)
00461 {
00462   _dbus_assert (transport->refcount > 0);
00463   
00464   transport->refcount += 1;
00465 
00466   return transport;
00467 }
00468 
00476 void
00477 _dbus_transport_unref (DBusTransport *transport)
00478 {
00479   _dbus_assert (transport != NULL);
00480   _dbus_assert (transport->refcount > 0);
00481   
00482   transport->refcount -= 1;
00483   if (transport->refcount == 0)
00484     {
00485       _dbus_verbose ("finalizing\n");
00486       
00487       _dbus_assert (transport->vtable->finalize != NULL);
00488       
00489       (* transport->vtable->finalize) (transport);
00490     }
00491 }
00492 
00501 void
00502 _dbus_transport_disconnect (DBusTransport *transport)
00503 {
00504   _dbus_verbose ("start\n");
00505   
00506   _dbus_assert (transport->vtable->disconnect != NULL);
00507   
00508   if (transport->disconnected)
00509     return;
00510 
00511   (* transport->vtable->disconnect) (transport);
00512   
00513   transport->disconnected = TRUE;
00514 
00515   _dbus_verbose ("end\n");
00516 }
00517 
00526 dbus_bool_t
00527 _dbus_transport_get_is_connected (DBusTransport *transport)
00528 {
00529   return !transport->disconnected;
00530 }
00531 
00532 static dbus_bool_t
00533 auth_via_unix_user_function (DBusTransport *transport)
00534 {
00535   DBusCredentials *auth_identity;
00536   dbus_bool_t allow;
00537   DBusConnection *connection;
00538   DBusAllowUnixUserFunction unix_user_function;
00539   void *unix_user_data;
00540   dbus_uid_t uid;
00541 
00542   /* Dropping the lock here probably isn't that safe. */
00543   
00544   auth_identity = _dbus_auth_get_identity (transport->auth);
00545   _dbus_assert (auth_identity != NULL);
00546 
00547   connection = transport->connection;
00548   unix_user_function = transport->unix_user_function;
00549   unix_user_data = transport->unix_user_data;
00550   uid = _dbus_credentials_get_unix_uid (auth_identity);
00551               
00552   _dbus_verbose ("unlock\n");
00553   _dbus_connection_unlock (connection);
00554 
00555   allow = (* unix_user_function) (connection,
00556                                   uid,
00557                                   unix_user_data);
00558               
00559   _dbus_verbose ("lock post unix user function\n");
00560   _dbus_connection_lock (connection);
00561 
00562   if (allow)
00563     {
00564       _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
00565     }
00566   else
00567     {
00568       _dbus_verbose ("Client UID "DBUS_UID_FORMAT
00569                      " was rejected, disconnecting\n",
00570                      _dbus_credentials_get_unix_uid (auth_identity));
00571       _dbus_transport_disconnect (transport);
00572     }
00573 
00574   return allow;
00575 }
00576 
00577 static dbus_bool_t
00578 auth_via_windows_user_function (DBusTransport *transport)
00579 {
00580   DBusCredentials *auth_identity;  
00581   dbus_bool_t allow;
00582   DBusConnection *connection;
00583   DBusAllowWindowsUserFunction windows_user_function;
00584   void *windows_user_data;
00585   char *windows_sid;
00586 
00587   /* Dropping the lock here probably isn't that safe. */
00588   
00589   auth_identity = _dbus_auth_get_identity (transport->auth);
00590   _dbus_assert (auth_identity != NULL);
00591 
00592   connection = transport->connection;
00593   windows_user_function = transport->windows_user_function;
00594   windows_user_data = transport->unix_user_data;
00595   windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
00596 
00597   if (windows_sid == NULL)
00598     {
00599       /* OOM */
00600       return FALSE;
00601     }
00602                 
00603   _dbus_verbose ("unlock\n");
00604   _dbus_connection_unlock (connection);
00605 
00606   allow = (* windows_user_function) (connection,
00607                                      windows_sid,
00608                                      windows_user_data);
00609               
00610   _dbus_verbose ("lock post windows user function\n");
00611   _dbus_connection_lock (connection);
00612 
00613   if (allow)
00614     {
00615       _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
00616     }
00617   else
00618     {
00619       _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
00620                      _dbus_credentials_get_windows_sid (auth_identity));
00621       _dbus_transport_disconnect (transport);
00622     }
00623 
00624   return allow;
00625 }
00626 
00627 static dbus_bool_t
00628 auth_via_default_rules (DBusTransport *transport)
00629 {
00630   DBusCredentials *auth_identity;
00631   DBusCredentials *our_identity;
00632   dbus_bool_t allow;
00633   
00634   auth_identity = _dbus_auth_get_identity (transport->auth);
00635   _dbus_assert (auth_identity != NULL);
00636 
00637   /* By default, connection is allowed if the client is 1) root or 2)
00638    * has the same UID as us or 3) anonymous is allowed.
00639    */
00640   
00641   our_identity = _dbus_credentials_new_from_current_process ();
00642   if (our_identity == NULL)
00643     {
00644       /* OOM */
00645       return FALSE;
00646     }
00647               
00648   if (transport->allow_anonymous ||
00649       _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
00650       _dbus_credentials_same_user (our_identity,
00651                                    auth_identity))
00652     {
00653       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00654           _dbus_verbose ("Client authorized as SID '%s'"
00655                          "matching our SID '%s'\n",
00656                          _dbus_credentials_get_windows_sid(auth_identity),
00657                          _dbus_credentials_get_windows_sid(our_identity));
00658       else
00659           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00660                          " matching our UID "DBUS_UID_FORMAT"\n",
00661                          _dbus_credentials_get_unix_uid(auth_identity),
00662                          _dbus_credentials_get_unix_uid(our_identity));
00663       /* We have authenticated! */
00664       allow = TRUE;
00665     }
00666   else
00667     {
00668       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00669           _dbus_verbose ("Client authorized as SID '%s'"
00670                          " but our SID is '%s', disconnecting\n",
00671                          (_dbus_credentials_get_windows_sid(auth_identity) ?
00672                           _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
00673                          (_dbus_credentials_get_windows_sid(our_identity) ?
00674                           _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
00675       else
00676           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00677                          " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
00678                          _dbus_credentials_get_unix_uid(auth_identity),
00679                          _dbus_credentials_get_unix_uid(our_identity));
00680       _dbus_transport_disconnect (transport);
00681       allow = FALSE;
00682     }  
00683 
00684   _dbus_credentials_unref (our_identity);
00685   
00686   return allow;
00687 }
00688 
00700 dbus_bool_t
00701 _dbus_transport_peek_is_authenticated (DBusTransport *transport)
00702 {
00703   return transport->authenticated;
00704 }
00705 
00723 dbus_bool_t
00724 _dbus_transport_try_to_authenticate (DBusTransport *transport)
00725 {  
00726   if (transport->authenticated)
00727     return TRUE;
00728   else
00729     {
00730       dbus_bool_t maybe_authenticated;
00731       
00732       if (transport->disconnected)
00733         return FALSE;
00734 
00735       /* paranoia ref since we call user callbacks sometimes */
00736       _dbus_connection_ref_unlocked (transport->connection);
00737       
00738       maybe_authenticated =
00739         (!(transport->send_credentials_pending ||
00740            transport->receive_credentials_pending));
00741 
00742       if (maybe_authenticated)
00743         {
00744           switch (_dbus_auth_do_work (transport->auth))
00745             {
00746             case DBUS_AUTH_STATE_AUTHENTICATED:
00747               /* leave as maybe_authenticated */
00748               break;
00749             default:
00750               maybe_authenticated = FALSE;
00751             }
00752         }
00753 
00754       /* If we're the client, verify the GUID
00755        */
00756       if (maybe_authenticated && !transport->is_server)
00757         {
00758           const char *server_guid;
00759 
00760           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00761           _dbus_assert (server_guid != NULL);
00762 
00763           if (transport->expected_guid &&
00764               strcmp (transport->expected_guid, server_guid) != 0)
00765             {
00766               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00767                              transport->expected_guid, server_guid);
00768               _dbus_transport_disconnect (transport);
00769               _dbus_connection_unref_unlocked (transport->connection);
00770               return FALSE;
00771             }
00772         }
00773 
00774       /* If we're the server, see if we want to allow this identity to proceed.
00775        */
00776       if (maybe_authenticated && transport->is_server)
00777         {
00778           dbus_bool_t allow;
00779           DBusCredentials *auth_identity;
00780           
00781           auth_identity = _dbus_auth_get_identity (transport->auth);
00782           _dbus_assert (auth_identity != NULL);
00783           
00784           /* If we have an auth'd user and a user function, delegate
00785            * deciding whether auth credentials are good enough to the
00786            * app; otherwise, use our default decision process.
00787            */
00788           if (transport->unix_user_function != NULL &&
00789               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00790             {
00791               allow = auth_via_unix_user_function (transport);
00792             }
00793           else if (transport->windows_user_function != NULL &&
00794                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00795             {
00796               allow = auth_via_windows_user_function (transport);
00797             }      
00798           else
00799             {
00800               allow = auth_via_default_rules (transport);
00801             }
00802           
00803           if (!allow)
00804             maybe_authenticated = FALSE;
00805         }
00806 
00807       transport->authenticated = maybe_authenticated;
00808 
00809       _dbus_connection_unref_unlocked (transport->connection);
00810       return maybe_authenticated;
00811     }
00812 }
00813 
00820 dbus_bool_t
00821 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00822 {
00823   DBusCredentials *auth_identity;
00824   
00825   if (!transport->authenticated)
00826     return TRUE;
00827   
00828   auth_identity = _dbus_auth_get_identity (transport->auth);
00829 
00830   if (_dbus_credentials_are_anonymous (auth_identity))
00831     return TRUE;
00832   else
00833     return FALSE;
00834 }
00835 
00842 dbus_bool_t
00843 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
00844 {
00845   return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
00846 }
00847 
00855 const char*
00856 _dbus_transport_get_address (DBusTransport *transport)
00857 {
00858   return transport->address;
00859 }
00860 
00868 const char*
00869 _dbus_transport_get_server_id (DBusTransport *transport)
00870 {
00871   if (transport->is_server)
00872     return NULL;
00873   else if (transport->authenticated)
00874     return _dbus_auth_get_guid_from_server (transport->auth);
00875   else
00876     return transport->expected_guid;
00877 }
00878 
00888 dbus_bool_t
00889 _dbus_transport_handle_watch (DBusTransport           *transport,
00890                               DBusWatch               *watch,
00891                               unsigned int             condition)
00892 {
00893   dbus_bool_t retval;
00894   
00895   _dbus_assert (transport->vtable->handle_watch != NULL);
00896 
00897   if (transport->disconnected)
00898     return TRUE;
00899 
00900   if (dbus_watch_get_socket (watch) < 0)
00901     {
00902       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00903       return TRUE;
00904     }
00905   
00906   _dbus_watch_sanitize_condition (watch, &condition);
00907 
00908   _dbus_transport_ref (transport);
00909   _dbus_watch_ref (watch);
00910   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00911   _dbus_watch_unref (watch);
00912   _dbus_transport_unref (transport);
00913 
00914   return retval;
00915 }
00916 
00926 dbus_bool_t
00927 _dbus_transport_set_connection (DBusTransport  *transport,
00928                                 DBusConnection *connection)
00929 {
00930   _dbus_assert (transport->vtable->connection_set != NULL);
00931   _dbus_assert (transport->connection == NULL);
00932   
00933   transport->connection = connection;
00934 
00935   _dbus_transport_ref (transport);
00936   if (!(* transport->vtable->connection_set) (transport))
00937     transport->connection = NULL;
00938   _dbus_transport_unref (transport);
00939 
00940   return transport->connection != NULL;
00941 }
00942 
00950 dbus_bool_t
00951 _dbus_transport_get_socket_fd (DBusTransport *transport,
00952                                DBusSocket    *fd_p)
00953 {
00954   dbus_bool_t retval;
00955   
00956   if (transport->vtable->get_socket_fd == NULL)
00957     return FALSE;
00958 
00959   if (transport->disconnected)
00960     return FALSE;
00961 
00962   _dbus_transport_ref (transport);
00963 
00964   retval = (* transport->vtable->get_socket_fd) (transport,
00965                                                  fd_p);
00966   
00967   _dbus_transport_unref (transport);
00968 
00969   return retval;
00970 }
00971 
00983 void
00984 _dbus_transport_do_iteration (DBusTransport  *transport,
00985                               unsigned int    flags,
00986                               int             timeout_milliseconds)
00987 {
00988   _dbus_assert (transport->vtable->do_iteration != NULL);
00989 
00990   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00991                  flags, timeout_milliseconds, !transport->disconnected);
00992   
00993   if ((flags & (DBUS_ITERATION_DO_WRITING |
00994                 DBUS_ITERATION_DO_READING)) == 0)
00995     return; /* Nothing to do */
00996 
00997   if (transport->disconnected)
00998     return;
00999 
01000   _dbus_transport_ref (transport);
01001   (* transport->vtable->do_iteration) (transport, flags,
01002                                        timeout_milliseconds);
01003   _dbus_transport_unref (transport);
01004 
01005   _dbus_verbose ("end\n");
01006 }
01007 
01008 static dbus_bool_t
01009 recover_unused_bytes (DBusTransport *transport)
01010 {
01011   if (_dbus_auth_needs_decoding (transport->auth))
01012     {
01013       DBusString plaintext;
01014       const DBusString *encoded;
01015       DBusString *buffer;
01016       int orig_len;
01017       
01018       if (!_dbus_string_init (&plaintext))
01019         goto nomem;
01020       
01021       _dbus_auth_get_unused_bytes (transport->auth,
01022                                    &encoded);
01023 
01024       if (!_dbus_auth_decode_data (transport->auth,
01025                                    encoded, &plaintext))
01026         {
01027           _dbus_string_free (&plaintext);
01028           goto nomem;
01029         }
01030       
01031       _dbus_message_loader_get_buffer (transport->loader,
01032                                        &buffer);
01033       
01034       orig_len = _dbus_string_get_length (buffer);
01035       
01036       if (!_dbus_string_move (&plaintext, 0, buffer,
01037                               orig_len))
01038         {
01039           _dbus_string_free (&plaintext);
01040           goto nomem;
01041         }
01042       
01043       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01044                      _dbus_string_get_length (buffer) -
01045                      orig_len);
01046       
01047       _dbus_message_loader_return_buffer (transport->loader,
01048                                           buffer);
01049 
01050       _dbus_auth_delete_unused_bytes (transport->auth);
01051       
01052       _dbus_string_free (&plaintext);
01053     }
01054   else
01055     {
01056       const DBusString *bytes;
01057       DBusString *buffer;
01058       int orig_len;
01059       dbus_bool_t succeeded;
01060 
01061       _dbus_message_loader_get_buffer (transport->loader,
01062                                        &buffer);
01063                 
01064       orig_len = _dbus_string_get_length (buffer);
01065                 
01066       _dbus_auth_get_unused_bytes (transport->auth,
01067                                    &bytes);
01068 
01069       succeeded = TRUE;
01070       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01071         succeeded = FALSE;
01072       
01073       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01074                      _dbus_string_get_length (buffer) -
01075                      orig_len);
01076       
01077       _dbus_message_loader_return_buffer (transport->loader,
01078                                           buffer);
01079 
01080       if (succeeded)
01081         _dbus_auth_delete_unused_bytes (transport->auth);
01082       else
01083         goto nomem;
01084     }
01085 
01086   return TRUE;
01087 
01088  nomem:
01089   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01090   return FALSE;
01091 }
01092 
01100 DBusDispatchStatus
01101 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01102 {
01103   if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
01104       _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
01105     return DBUS_DISPATCH_COMPLETE; /* complete for now */
01106 
01107   if (!_dbus_transport_try_to_authenticate (transport))
01108     {
01109       if (_dbus_auth_do_work (transport->auth) ==
01110           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01111         return DBUS_DISPATCH_NEED_MEMORY;
01112       else if (!_dbus_transport_try_to_authenticate (transport))
01113         return DBUS_DISPATCH_COMPLETE;
01114     }
01115 
01116   if (!transport->unused_bytes_recovered &&
01117       !recover_unused_bytes (transport))
01118     return DBUS_DISPATCH_NEED_MEMORY;
01119 
01120   transport->unused_bytes_recovered = TRUE;
01121   
01122   if (!_dbus_message_loader_queue_messages (transport->loader))
01123     return DBUS_DISPATCH_NEED_MEMORY;
01124 
01125   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01126     return DBUS_DISPATCH_DATA_REMAINS;
01127   else
01128     return DBUS_DISPATCH_COMPLETE;
01129 }
01130 
01139 dbus_bool_t
01140 _dbus_transport_queue_messages (DBusTransport *transport)
01141 {
01142   DBusDispatchStatus status;
01143 
01144 #if 0
01145   _dbus_verbose ("_dbus_transport_queue_messages()\n");
01146 #endif
01147   
01148   /* Queue any messages */
01149   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01150     {
01151       DBusMessage *message;
01152       DBusList *link;
01153 
01154       link = _dbus_message_loader_pop_message_link (transport->loader);
01155       _dbus_assert (link != NULL);
01156       
01157       message = link->data;
01158       
01159       _dbus_verbose ("queueing received message %p\n", message);
01160 
01161       if (!_dbus_message_add_counter (message, transport->live_messages))
01162         {
01163           _dbus_message_loader_putback_message_link (transport->loader,
01164                                                      link);
01165           status = DBUS_DISPATCH_NEED_MEMORY;
01166           break;
01167         }
01168       else
01169         {
01170           /* We didn't call the notify function when we added the counter, so
01171            * catch up now. Since we have the connection's lock, it's desirable
01172            * that we bypass the notify function and call this virtual method
01173            * directly. */
01174           if (transport->vtable->live_messages_changed)
01175             (* transport->vtable->live_messages_changed) (transport);
01176 
01177           /* pass ownership of link and message ref to connection */
01178           _dbus_connection_queue_received_message_link (transport->connection,
01179                                                         link);
01180         }
01181     }
01182 
01183   if (_dbus_message_loader_get_is_corrupted (transport->loader))
01184     {
01185       _dbus_verbose ("Corrupted message stream, disconnecting\n");
01186       _dbus_transport_disconnect (transport);
01187     }
01188 
01189   return status != DBUS_DISPATCH_NEED_MEMORY;
01190 }
01191 
01198 void
01199 _dbus_transport_set_max_message_size (DBusTransport  *transport,
01200                                       long            size)
01201 {
01202   _dbus_message_loader_set_max_message_size (transport->loader, size);
01203 }
01204 
01211 void
01212 _dbus_transport_set_max_message_unix_fds (DBusTransport  *transport,
01213                                           long            n)
01214 {
01215   _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
01216 }
01217 
01224 long
01225 _dbus_transport_get_max_message_size (DBusTransport  *transport)
01226 {
01227   return _dbus_message_loader_get_max_message_size (transport->loader);
01228 }
01229 
01236 long
01237 _dbus_transport_get_max_message_unix_fds (DBusTransport  *transport)
01238 {
01239   return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
01240 }
01241 
01248 void
01249 _dbus_transport_set_max_received_size (DBusTransport  *transport,
01250                                        long            size)
01251 {
01252   transport->max_live_messages_size = size;
01253   _dbus_counter_set_notify (transport->live_messages,
01254                             transport->max_live_messages_size,
01255                             transport->max_live_messages_unix_fds,
01256                             live_messages_notify,
01257                             transport);
01258 }
01259 
01266 void
01267 _dbus_transport_set_max_received_unix_fds (DBusTransport  *transport,
01268                                            long            n)
01269 {
01270   transport->max_live_messages_unix_fds = n;
01271   _dbus_counter_set_notify (transport->live_messages,
01272                             transport->max_live_messages_size,
01273                             transport->max_live_messages_unix_fds,
01274                             live_messages_notify,
01275                             transport);
01276 }
01277 
01284 long
01285 _dbus_transport_get_max_received_size (DBusTransport  *transport)
01286 {
01287   return transport->max_live_messages_size;
01288 }
01289 
01296 long
01297 _dbus_transport_get_max_received_unix_fds (DBusTransport  *transport)
01298 {
01299   return transport->max_live_messages_unix_fds;
01300 }
01301 
01309 dbus_bool_t
01310 _dbus_transport_get_unix_user (DBusTransport *transport,
01311                                unsigned long *uid)
01312 {
01313   DBusCredentials *auth_identity;
01314 
01315   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
01316                            * case of bugs in the caller. Caller should
01317                            * never use this value on purpose, however.
01318                            */
01319   
01320   if (!transport->authenticated)
01321     return FALSE;
01322   
01323   auth_identity = _dbus_auth_get_identity (transport->auth);
01324 
01325   if (_dbus_credentials_include (auth_identity,
01326                                  DBUS_CREDENTIAL_UNIX_USER_ID))
01327     {
01328       *uid = _dbus_credentials_get_unix_uid (auth_identity);
01329       return TRUE;
01330     }
01331   else
01332     return FALSE;
01333 }
01334 
01342 dbus_bool_t
01343 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01344                                      unsigned long *pid)
01345 {
01346   DBusCredentials *auth_identity;
01347 
01348   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
01349                           * but we set it to a safe number, INT_MAX,
01350                           * just to root out possible bugs in bad callers.
01351                           */
01352   
01353   if (!transport->authenticated)
01354     return FALSE;
01355   
01356   auth_identity = _dbus_auth_get_identity (transport->auth);
01357 
01358   if (_dbus_credentials_include (auth_identity,
01359                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
01360     {
01361       *pid = _dbus_credentials_get_pid (auth_identity);
01362       return TRUE;
01363     }
01364   else
01365     return FALSE;
01366 }
01367 
01376 dbus_bool_t
01377 _dbus_transport_get_adt_audit_session_data (DBusTransport      *transport,
01378                                             void              **data,
01379                                             int                *data_size)
01380 {
01381   DBusCredentials *auth_identity;
01382 
01383   *data = NULL;
01384   *data_size = 0;
01385   
01386   if (!transport->authenticated)
01387     return FALSE;
01388   
01389   auth_identity = _dbus_auth_get_identity (transport->auth);
01390 
01391   if (_dbus_credentials_include (auth_identity,
01392                                  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
01393     {
01394       *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
01395       *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
01396       return TRUE;
01397     }
01398   else
01399     return FALSE;
01400 }
01401 
01412 void
01413 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
01414                                         DBusAllowUnixUserFunction  function,
01415                                         void                      *data,
01416                                         DBusFreeFunction           free_data_function,
01417                                         void                     **old_data,
01418                                         DBusFreeFunction          *old_free_data_function)
01419 {  
01420   *old_data = transport->unix_user_data;
01421   *old_free_data_function = transport->free_unix_user_data;
01422 
01423   transport->unix_user_function = function;
01424   transport->unix_user_data = data;
01425   transport->free_unix_user_data = free_data_function;
01426 }
01427 
01428 dbus_bool_t
01429 _dbus_transport_get_linux_security_label (DBusTransport  *transport,
01430                                           char          **label_p)
01431 {
01432   DBusCredentials *auth_identity;
01433 
01434   *label_p = NULL;
01435 
01436   if (!transport->authenticated)
01437     return FALSE;
01438 
01439   auth_identity = _dbus_auth_get_identity (transport->auth);
01440 
01441   if (_dbus_credentials_include (auth_identity,
01442                                  DBUS_CREDENTIAL_LINUX_SECURITY_LABEL))
01443     {
01444       /* If no memory, we are supposed to return TRUE and set NULL */
01445       *label_p = _dbus_strdup (_dbus_credentials_get_linux_security_label (auth_identity));
01446 
01447       return TRUE;
01448     }
01449   else
01450     {
01451       return FALSE;
01452     }
01453 }
01454 
01462 dbus_bool_t
01463 _dbus_transport_get_windows_user (DBusTransport              *transport,
01464                                   char                      **windows_sid_p)
01465 {
01466   DBusCredentials *auth_identity;
01467 
01468   *windows_sid_p = NULL;
01469   
01470   if (!transport->authenticated)
01471     return FALSE;
01472   
01473   auth_identity = _dbus_auth_get_identity (transport->auth);
01474 
01475   if (_dbus_credentials_include (auth_identity,
01476                                  DBUS_CREDENTIAL_WINDOWS_SID))
01477     {
01478       /* If no memory, we are supposed to return TRUE and set NULL */
01479       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01480 
01481       return TRUE;
01482     }
01483   else
01484     return FALSE;
01485 }
01486 
01498 void
01499 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
01500                                            DBusAllowWindowsUserFunction   function,
01501                                            void                       *data,
01502                                            DBusFreeFunction            free_data_function,
01503                                            void                      **old_data,
01504                                            DBusFreeFunction           *old_free_data_function)
01505 {
01506   *old_data = transport->windows_user_data;
01507   *old_free_data_function = transport->free_windows_user_data;
01508 
01509   transport->windows_user_function = function;
01510   transport->windows_user_data = data;
01511   transport->free_windows_user_data = free_data_function;
01512 }
01513 
01522 dbus_bool_t
01523 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
01524                                      const char    **mechanisms)
01525 {
01526   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01527 }
01528 
01535 void
01536 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
01537                                      dbus_bool_t                 value)
01538 {
01539   transport->allow_anonymous = value != FALSE;
01540 }
01541 
01547 int
01548 _dbus_transport_get_pending_fds_count (DBusTransport *transport)
01549 {
01550   return _dbus_message_loader_get_pending_fds_count (transport->loader);
01551 }
01552 
01560 void
01561 _dbus_transport_set_pending_fds_function (DBusTransport *transport,
01562                                            void (* callback) (void *),
01563                                            void *data)
01564 {
01565   _dbus_message_loader_set_pending_fds_function (transport->loader,
01566                                                  callback, data);
01567 }
01568 
01569 #ifdef DBUS_ENABLE_STATS
01570 void
01571 _dbus_transport_get_stats (DBusTransport  *transport,
01572                            dbus_uint32_t  *queue_bytes,
01573                            dbus_uint32_t  *queue_fds,
01574                            dbus_uint32_t  *peak_queue_bytes,
01575                            dbus_uint32_t  *peak_queue_fds)
01576 {
01577   if (queue_bytes != NULL)
01578     *queue_bytes = _dbus_counter_get_size_value (transport->live_messages);
01579 
01580   if (queue_fds != NULL)
01581     *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages);
01582 
01583   if (peak_queue_bytes != NULL)
01584     *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages);
01585 
01586   if (peak_queue_fds != NULL)
01587     *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages);
01588 }
01589 #endif /* DBUS_ENABLE_STATS */
01590