D-Bus  1.4.18
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-private.h"
00035 #include "dbus-marshal-header.h"
00036 #ifdef DBUS_BUILD_TESTS
00037 #include "dbus-server-debug-pipe.h"
00038 #endif
00039 
00061 static void
00062 live_messages_notify (DBusCounter *counter,
00063                            void        *user_data)
00064 {
00065   DBusTransport *transport = user_data;
00066 
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     (* transport->vtable->live_messages_changed) (transport);
00081 
00082   _dbus_transport_unref (transport);
00083 }
00084 
00098 dbus_bool_t
00099 _dbus_transport_init_base (DBusTransport             *transport,
00100                            const DBusTransportVTable *vtable,
00101                            const DBusString          *server_guid,
00102                            const DBusString          *address)
00103 {
00104   DBusMessageLoader *loader;
00105   DBusAuth *auth;
00106   DBusCounter *counter;
00107   char *address_copy;
00108   DBusCredentials *creds;
00109   
00110   loader = _dbus_message_loader_new ();
00111   if (loader == NULL)
00112     return FALSE;
00113   
00114   if (server_guid)
00115     auth = _dbus_auth_server_new (server_guid);
00116   else
00117     auth = _dbus_auth_client_new ();
00118   if (auth == NULL)
00119     {
00120       _dbus_message_loader_unref (loader);
00121       return FALSE;
00122     }
00123 
00124   counter = _dbus_counter_new ();
00125   if (counter == NULL)
00126     {
00127       _dbus_auth_unref (auth);
00128       _dbus_message_loader_unref (loader);
00129       return FALSE;
00130     }  
00131 
00132   creds = _dbus_credentials_new ();
00133   if (creds == NULL)
00134     {
00135       _dbus_counter_unref (counter);
00136       _dbus_auth_unref (auth);
00137       _dbus_message_loader_unref (loader);
00138       return FALSE;
00139     }
00140   
00141   if (server_guid)
00142     {
00143       _dbus_assert (address == NULL);
00144       address_copy = NULL;
00145     }
00146   else
00147     {
00148       _dbus_assert (address != NULL);
00149 
00150       if (!_dbus_string_copy_data (address, &address_copy))
00151         {
00152           _dbus_credentials_unref (creds);
00153           _dbus_counter_unref (counter);
00154           _dbus_auth_unref (auth);
00155           _dbus_message_loader_unref (loader);
00156           return FALSE;
00157         }
00158     }
00159   
00160   transport->refcount = 1;
00161   transport->vtable = vtable;
00162   transport->loader = loader;
00163   transport->auth = auth;
00164   transport->live_messages = counter;
00165   transport->authenticated = FALSE;
00166   transport->disconnected = FALSE;
00167   transport->is_server = (server_guid != NULL);
00168   transport->send_credentials_pending = !transport->is_server;
00169   transport->receive_credentials_pending = transport->is_server;
00170   transport->address = address_copy;
00171   
00172   transport->unix_user_function = NULL;
00173   transport->unix_user_data = NULL;
00174   transport->free_unix_user_data = NULL;
00175 
00176   transport->windows_user_function = NULL;
00177   transport->windows_user_data = NULL;
00178   transport->free_windows_user_data = NULL;
00179   
00180   transport->expected_guid = NULL;
00181   
00182   /* Try to default to something that won't totally hose the system,
00183    * but doesn't impose too much of a limitation.
00184    */
00185   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
00186 
00187   /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
00188      should be more than enough */
00189   transport->max_live_messages_unix_fds = 4096;
00190 
00191   /* credentials read from socket if any */
00192   transport->credentials = creds;
00193 
00194   _dbus_counter_set_notify (transport->live_messages,
00195                             transport->max_live_messages_size,
00196                             transport->max_live_messages_unix_fds,
00197                             live_messages_notify,
00198                             transport);
00199 
00200   if (transport->address)
00201     _dbus_verbose ("Initialized transport on address %s\n", transport->address);
00202 
00203   return TRUE;
00204 }
00205 
00212 void
00213 _dbus_transport_finalize_base (DBusTransport *transport)
00214 {
00215   if (!transport->disconnected)
00216     _dbus_transport_disconnect (transport);
00217 
00218   if (transport->free_unix_user_data != NULL)
00219     (* transport->free_unix_user_data) (transport->unix_user_data);
00220 
00221   if (transport->free_windows_user_data != NULL)
00222     (* transport->free_windows_user_data) (transport->windows_user_data);
00223   
00224   _dbus_message_loader_unref (transport->loader);
00225   _dbus_auth_unref (transport->auth);
00226   _dbus_counter_set_notify (transport->live_messages,
00227                             0, 0, NULL, NULL);
00228   _dbus_counter_unref (transport->live_messages);
00229   dbus_free (transport->address);
00230   dbus_free (transport->expected_guid);
00231   if (transport->credentials)
00232     _dbus_credentials_unref (transport->credentials);
00233 }
00234 
00235 
00245 static DBusTransport*
00246 check_address (const char *address, DBusError *error)
00247 {
00248   DBusAddressEntry **entries;
00249   DBusTransport *transport = NULL;
00250   int len, i;
00251 
00252   _dbus_assert (address != NULL);
00253   _dbus_assert (*address != '\0');
00254 
00255   if (!dbus_parse_address (address, &entries, &len, error))
00256     return NULL;              /* not a valid address */
00257 
00258   for (i = 0; i < len; i++)
00259     {
00260       transport = _dbus_transport_open (entries[i], error);
00261       if (transport != NULL)
00262         break;
00263     }
00264 
00265   dbus_address_entries_free (entries);
00266   return transport;
00267 }
00268 
00276 static DBusTransport*
00277 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
00278 {
00279   DBusString address;
00280   DBusTransport *result = NULL;
00281 
00282   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00283 
00284   if (!_dbus_string_init (&address))
00285     {
00286       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00287       return NULL;
00288     }
00289 
00290   if (!_dbus_get_autolaunch_address (scope, &address, error))
00291     {
00292       _DBUS_ASSERT_ERROR_IS_SET (error);
00293       goto out;
00294     }
00295 
00296   result = check_address (_dbus_string_get_const_data (&address), error);
00297   if (result == NULL)
00298     _DBUS_ASSERT_ERROR_IS_SET (error);
00299   else
00300     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00301 
00302  out:
00303   _dbus_string_free (&address);
00304   return result;
00305 }
00306 
00307 static DBusTransportOpenResult
00308 _dbus_transport_open_autolaunch (DBusAddressEntry  *entry,
00309                                  DBusTransport    **transport_p,
00310                                  DBusError         *error)
00311 {
00312   const char *method;
00313   
00314   method = dbus_address_entry_get_method (entry);
00315   _dbus_assert (method != NULL);
00316 
00317   if (strcmp (method, "autolaunch") == 0)
00318     {
00319       const char *scope = dbus_address_entry_get_value (entry, "scope");
00320 
00321       *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
00322 
00323       if (*transport_p == NULL)
00324         {
00325           _DBUS_ASSERT_ERROR_IS_SET (error);
00326           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00327         }
00328       else
00329         {
00330           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00331           return DBUS_TRANSPORT_OPEN_OK;
00332         }      
00333     }
00334   else
00335     {
00336       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00337       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
00338     }
00339 }
00340 
00341 static const struct {
00342   DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
00343                                     DBusTransport   **transport_p,
00344                                     DBusError        *error);
00345 } open_funcs[] = {
00346   { _dbus_transport_open_socket },
00347   { _dbus_transport_open_platform_specific },
00348   { _dbus_transport_open_autolaunch }
00349 #ifdef DBUS_BUILD_TESTS
00350   , { _dbus_transport_open_debug_pipe }
00351 #endif
00352 };
00353 
00362 DBusTransport*
00363 _dbus_transport_open (DBusAddressEntry *entry,
00364                       DBusError        *error)
00365 {
00366   DBusTransport *transport;
00367   const char *expected_guid_orig;
00368   char *expected_guid;
00369   int i;
00370   DBusError tmp_error = DBUS_ERROR_INIT;
00371 
00372   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00373   
00374   transport = NULL;
00375   expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
00376   expected_guid = _dbus_strdup (expected_guid_orig);
00377 
00378   if (expected_guid_orig != NULL && expected_guid == NULL)
00379     {
00380       _DBUS_SET_OOM (error);
00381       return NULL;
00382     }
00383 
00384   for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
00385     {
00386       DBusTransportOpenResult result;
00387 
00388       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00389       result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
00390 
00391       switch (result)
00392         {
00393         case DBUS_TRANSPORT_OPEN_OK:
00394           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00395           goto out;
00396           break;
00397         case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
00398           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00399           /* keep going through the loop of open funcs */
00400           break;
00401         case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
00402           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00403           goto out;
00404           break;
00405         case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
00406           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00407           goto out;
00408           break;
00409         }
00410     }
00411 
00412  out:
00413   
00414   if (transport == NULL)
00415     {
00416       if (!dbus_error_is_set (&tmp_error))
00417         _dbus_set_bad_address (&tmp_error,
00418                                NULL, NULL,
00419                                "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
00420       
00421       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00422       dbus_move_error(&tmp_error, error);
00423       dbus_free (expected_guid);
00424     }
00425   else
00426     {
00427       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00428 
00429       /* In the case of autostart the initial guid is NULL
00430        * and the autostart transport recursively calls
00431        * _dbus_open_transport wich returns a transport
00432        * with a guid.  That guid is the definitive one.
00433        *
00434        * FIXME: if more transports are added they may have
00435        * an effect on the expected_guid semantics (i.e. 
00436        * expected_guid and transport->expected_guid may
00437        * both have values).  This is very unlikely though
00438        * we should either throw asserts here for those 
00439        * corner cases or refactor the code so it is 
00440        * clearer on what is expected and what is not
00441        */
00442       if(expected_guid)
00443         transport->expected_guid = expected_guid;
00444     }
00445 
00446   return transport;
00447 }
00448 
00455 DBusTransport *
00456 _dbus_transport_ref (DBusTransport *transport)
00457 {
00458   _dbus_assert (transport->refcount > 0);
00459   
00460   transport->refcount += 1;
00461 
00462   return transport;
00463 }
00464 
00472 void
00473 _dbus_transport_unref (DBusTransport *transport)
00474 {
00475   _dbus_assert (transport != NULL);
00476   _dbus_assert (transport->refcount > 0);
00477   
00478   transport->refcount -= 1;
00479   if (transport->refcount == 0)
00480     {
00481       _dbus_verbose ("finalizing\n");
00482       
00483       _dbus_assert (transport->vtable->finalize != NULL);
00484       
00485       (* transport->vtable->finalize) (transport);
00486     }
00487 }
00488 
00497 void
00498 _dbus_transport_disconnect (DBusTransport *transport)
00499 {
00500   _dbus_verbose ("start\n");
00501   
00502   _dbus_assert (transport->vtable->disconnect != NULL);
00503   
00504   if (transport->disconnected)
00505     return;
00506 
00507   (* transport->vtable->disconnect) (transport);
00508   
00509   transport->disconnected = TRUE;
00510 
00511   _dbus_verbose ("end\n");
00512 }
00513 
00522 dbus_bool_t
00523 _dbus_transport_get_is_connected (DBusTransport *transport)
00524 {
00525   return !transport->disconnected;
00526 }
00527 
00528 static dbus_bool_t
00529 auth_via_unix_user_function (DBusTransport *transport)
00530 {
00531   DBusCredentials *auth_identity;
00532   dbus_bool_t allow;
00533   DBusConnection *connection;
00534   DBusAllowUnixUserFunction unix_user_function;
00535   void *unix_user_data;
00536   dbus_uid_t uid;
00537 
00538   /* Dropping the lock here probably isn't that safe. */
00539   
00540   auth_identity = _dbus_auth_get_identity (transport->auth);
00541   _dbus_assert (auth_identity != NULL);
00542 
00543   connection = transport->connection;
00544   unix_user_function = transport->unix_user_function;
00545   unix_user_data = transport->unix_user_data;
00546   uid = _dbus_credentials_get_unix_uid (auth_identity);
00547               
00548   _dbus_verbose ("unlock\n");
00549   _dbus_connection_unlock (connection);
00550 
00551   allow = (* unix_user_function) (connection,
00552                                   uid,
00553                                   unix_user_data);
00554               
00555   _dbus_verbose ("lock post unix user function\n");
00556   _dbus_connection_lock (connection);
00557 
00558   if (allow)
00559     {
00560       _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
00561     }
00562   else
00563     {
00564       _dbus_verbose ("Client UID "DBUS_UID_FORMAT
00565                      " was rejected, disconnecting\n",
00566                      _dbus_credentials_get_unix_uid (auth_identity));
00567       _dbus_transport_disconnect (transport);
00568     }
00569 
00570   return allow;
00571 }
00572 
00573 static dbus_bool_t
00574 auth_via_windows_user_function (DBusTransport *transport)
00575 {
00576   DBusCredentials *auth_identity;  
00577   dbus_bool_t allow;
00578   DBusConnection *connection;
00579   DBusAllowWindowsUserFunction windows_user_function;
00580   void *windows_user_data;
00581   char *windows_sid;
00582 
00583   /* Dropping the lock here probably isn't that safe. */
00584   
00585   auth_identity = _dbus_auth_get_identity (transport->auth);
00586   _dbus_assert (auth_identity != NULL);
00587 
00588   connection = transport->connection;
00589   windows_user_function = transport->windows_user_function;
00590   windows_user_data = transport->unix_user_data;
00591   windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
00592 
00593   if (windows_sid == NULL)
00594     {
00595       /* OOM */
00596       return FALSE;
00597     }
00598                 
00599   _dbus_verbose ("unlock\n");
00600   _dbus_connection_unlock (connection);
00601 
00602   allow = (* windows_user_function) (connection,
00603                                      windows_sid,
00604                                      windows_user_data);
00605               
00606   _dbus_verbose ("lock post windows user function\n");
00607   _dbus_connection_lock (connection);
00608 
00609   if (allow)
00610     {
00611       _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
00612     }
00613   else
00614     {
00615       _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
00616                      _dbus_credentials_get_windows_sid (auth_identity));
00617       _dbus_transport_disconnect (transport);
00618     }
00619 
00620   return allow;
00621 }
00622 
00623 static dbus_bool_t
00624 auth_via_default_rules (DBusTransport *transport)
00625 {
00626   DBusCredentials *auth_identity;
00627   DBusCredentials *our_identity;
00628   dbus_bool_t allow;
00629   
00630   auth_identity = _dbus_auth_get_identity (transport->auth);
00631   _dbus_assert (auth_identity != NULL);
00632 
00633   /* By default, connection is allowed if the client is 1) root or 2)
00634    * has the same UID as us or 3) anonymous is allowed.
00635    */
00636   
00637   our_identity = _dbus_credentials_new_from_current_process ();
00638   if (our_identity == NULL)
00639     {
00640       /* OOM */
00641       return FALSE;
00642     }
00643               
00644   if (transport->allow_anonymous ||
00645       _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
00646       _dbus_credentials_same_user (our_identity,
00647                                    auth_identity))
00648     {
00649       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00650           _dbus_verbose ("Client authorized as SID '%s'"
00651                          "matching our SID '%s'\n",
00652                          _dbus_credentials_get_windows_sid(auth_identity),
00653                          _dbus_credentials_get_windows_sid(our_identity));
00654       else
00655           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00656                          " matching our UID "DBUS_UID_FORMAT"\n",
00657                          _dbus_credentials_get_unix_uid(auth_identity),
00658                          _dbus_credentials_get_unix_uid(our_identity));
00659       /* We have authenticated! */
00660       allow = TRUE;
00661     }
00662   else
00663     {
00664       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
00665           _dbus_verbose ("Client authorized as SID '%s'"
00666                          " but our SID is '%s', disconnecting\n",
00667                          (_dbus_credentials_get_windows_sid(auth_identity) ?
00668                           _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
00669                          (_dbus_credentials_get_windows_sid(our_identity) ?
00670                           _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
00671       else
00672           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
00673                          " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
00674                          _dbus_credentials_get_unix_uid(auth_identity),
00675                          _dbus_credentials_get_unix_uid(our_identity));
00676       _dbus_transport_disconnect (transport);
00677       allow = FALSE;
00678     }  
00679 
00680   _dbus_credentials_unref (our_identity);
00681   
00682   return allow;
00683 }
00684 
00685 
00696 dbus_bool_t
00697 _dbus_transport_get_is_authenticated (DBusTransport *transport)
00698 {  
00699   if (transport->authenticated)
00700     return TRUE;
00701   else
00702     {
00703       dbus_bool_t maybe_authenticated;
00704       
00705       if (transport->disconnected)
00706         return FALSE;
00707 
00708       /* paranoia ref since we call user callbacks sometimes */
00709       _dbus_connection_ref_unlocked (transport->connection);
00710       
00711       maybe_authenticated =
00712         (!(transport->send_credentials_pending ||
00713            transport->receive_credentials_pending));
00714 
00715       if (maybe_authenticated)
00716         {
00717           switch (_dbus_auth_do_work (transport->auth))
00718             {
00719             case DBUS_AUTH_STATE_AUTHENTICATED:
00720               /* leave as maybe_authenticated */
00721               break;
00722             default:
00723               maybe_authenticated = FALSE;
00724             }
00725         }
00726 
00727       /* If we're the client, verify the GUID
00728        */
00729       if (maybe_authenticated && !transport->is_server)
00730         {
00731           const char *server_guid;
00732 
00733           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00734           _dbus_assert (server_guid != NULL);
00735 
00736           if (transport->expected_guid &&
00737               strcmp (transport->expected_guid, server_guid) != 0)
00738             {
00739               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00740                              transport->expected_guid, server_guid);
00741               _dbus_transport_disconnect (transport);
00742               _dbus_connection_unref_unlocked (transport->connection);
00743               return FALSE;
00744             }
00745         }
00746 
00747       /* If we're the server, see if we want to allow this identity to proceed.
00748        */
00749       if (maybe_authenticated && transport->is_server)
00750         {
00751           dbus_bool_t allow;
00752           DBusCredentials *auth_identity;
00753           
00754           auth_identity = _dbus_auth_get_identity (transport->auth);
00755           _dbus_assert (auth_identity != NULL);
00756           
00757           /* If we have an auth'd user and a user function, delegate
00758            * deciding whether auth credentials are good enough to the
00759            * app; otherwise, use our default decision process.
00760            */
00761           if (transport->unix_user_function != NULL &&
00762               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00763             {
00764               allow = auth_via_unix_user_function (transport);
00765             }
00766           else if (transport->windows_user_function != NULL &&
00767                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00768             {
00769               allow = auth_via_windows_user_function (transport);
00770             }      
00771           else
00772             {
00773               allow = auth_via_default_rules (transport);
00774             }
00775           
00776           if (!allow)
00777             maybe_authenticated = FALSE;
00778         }
00779 
00780       transport->authenticated = maybe_authenticated;
00781 
00782       _dbus_connection_unref_unlocked (transport->connection);
00783       return maybe_authenticated;
00784     }
00785 }
00786 
00793 dbus_bool_t
00794 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00795 {
00796   DBusCredentials *auth_identity;
00797   
00798   if (!transport->authenticated)
00799     return TRUE;
00800   
00801   auth_identity = _dbus_auth_get_identity (transport->auth);
00802 
00803   if (_dbus_credentials_are_anonymous (auth_identity))
00804     return TRUE;
00805   else
00806     return FALSE;
00807 }
00808 
00815 dbus_bool_t
00816 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
00817 {
00818   return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
00819 }
00820 
00828 const char*
00829 _dbus_transport_get_address (DBusTransport *transport)
00830 {
00831   return transport->address;
00832 }
00833 
00841 const char*
00842 _dbus_transport_get_server_id (DBusTransport *transport)
00843 {
00844   if (transport->is_server)
00845     return NULL;
00846   else if (transport->authenticated)
00847     return _dbus_auth_get_guid_from_server (transport->auth);
00848   else
00849     return transport->expected_guid;
00850 }
00851 
00861 dbus_bool_t
00862 _dbus_transport_handle_watch (DBusTransport           *transport,
00863                               DBusWatch               *watch,
00864                               unsigned int             condition)
00865 {
00866   dbus_bool_t retval;
00867   
00868   _dbus_assert (transport->vtable->handle_watch != NULL);
00869 
00870   if (transport->disconnected)
00871     return TRUE;
00872 
00873   if (dbus_watch_get_socket (watch) < 0)
00874     {
00875       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00876       return TRUE;
00877     }
00878   
00879   _dbus_watch_sanitize_condition (watch, &condition);
00880 
00881   _dbus_transport_ref (transport);
00882   _dbus_watch_ref (watch);
00883   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00884   _dbus_watch_unref (watch);
00885   _dbus_transport_unref (transport);
00886 
00887   return retval;
00888 }
00889 
00899 dbus_bool_t
00900 _dbus_transport_set_connection (DBusTransport  *transport,
00901                                 DBusConnection *connection)
00902 {
00903   _dbus_assert (transport->vtable->connection_set != NULL);
00904   _dbus_assert (transport->connection == NULL);
00905   
00906   transport->connection = connection;
00907 
00908   _dbus_transport_ref (transport);
00909   if (!(* transport->vtable->connection_set) (transport))
00910     transport->connection = NULL;
00911   _dbus_transport_unref (transport);
00912 
00913   return transport->connection != NULL;
00914 }
00915 
00923 dbus_bool_t
00924 _dbus_transport_get_socket_fd (DBusTransport *transport,
00925                                int           *fd_p)
00926 {
00927   dbus_bool_t retval;
00928   
00929   if (transport->vtable->get_socket_fd == NULL)
00930     return FALSE;
00931 
00932   if (transport->disconnected)
00933     return FALSE;
00934 
00935   _dbus_transport_ref (transport);
00936 
00937   retval = (* transport->vtable->get_socket_fd) (transport,
00938                                                  fd_p);
00939   
00940   _dbus_transport_unref (transport);
00941 
00942   return retval;
00943 }
00944 
00956 void
00957 _dbus_transport_do_iteration (DBusTransport  *transport,
00958                               unsigned int    flags,
00959                               int             timeout_milliseconds)
00960 {
00961   _dbus_assert (transport->vtable->do_iteration != NULL);
00962 
00963   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00964                  flags, timeout_milliseconds, !transport->disconnected);
00965   
00966   if ((flags & (DBUS_ITERATION_DO_WRITING |
00967                 DBUS_ITERATION_DO_READING)) == 0)
00968     return; /* Nothing to do */
00969 
00970   if (transport->disconnected)
00971     return;
00972 
00973   _dbus_transport_ref (transport);
00974   (* transport->vtable->do_iteration) (transport, flags,
00975                                        timeout_milliseconds);
00976   _dbus_transport_unref (transport);
00977 
00978   _dbus_verbose ("end\n");
00979 }
00980 
00981 static dbus_bool_t
00982 recover_unused_bytes (DBusTransport *transport)
00983 {
00984   if (_dbus_auth_needs_decoding (transport->auth))
00985     {
00986       DBusString plaintext;
00987       const DBusString *encoded;
00988       DBusString *buffer;
00989       int orig_len;
00990       
00991       if (!_dbus_string_init (&plaintext))
00992         goto nomem;
00993       
00994       _dbus_auth_get_unused_bytes (transport->auth,
00995                                    &encoded);
00996 
00997       if (!_dbus_auth_decode_data (transport->auth,
00998                                    encoded, &plaintext))
00999         {
01000           _dbus_string_free (&plaintext);
01001           goto nomem;
01002         }
01003       
01004       _dbus_message_loader_get_buffer (transport->loader,
01005                                        &buffer);
01006       
01007       orig_len = _dbus_string_get_length (buffer);
01008       
01009       if (!_dbus_string_move (&plaintext, 0, buffer,
01010                               orig_len))
01011         {
01012           _dbus_string_free (&plaintext);
01013           goto nomem;
01014         }
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       _dbus_auth_delete_unused_bytes (transport->auth);
01026       
01027       _dbus_string_free (&plaintext);
01028     }
01029   else
01030     {
01031       const DBusString *bytes;
01032       DBusString *buffer;
01033       int orig_len;
01034       dbus_bool_t succeeded;
01035 
01036       _dbus_message_loader_get_buffer (transport->loader,
01037                                        &buffer);
01038                 
01039       orig_len = _dbus_string_get_length (buffer);
01040                 
01041       _dbus_auth_get_unused_bytes (transport->auth,
01042                                    &bytes);
01043 
01044       succeeded = TRUE;
01045       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01046         succeeded = FALSE;
01047       
01048       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01049                      _dbus_string_get_length (buffer) -
01050                      orig_len);
01051       
01052       _dbus_message_loader_return_buffer (transport->loader,
01053                                           buffer,
01054                                           _dbus_string_get_length (buffer) -
01055                                           orig_len);
01056 
01057       if (succeeded)
01058         _dbus_auth_delete_unused_bytes (transport->auth);
01059       else
01060         goto nomem;
01061     }
01062 
01063   return TRUE;
01064 
01065  nomem:
01066   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01067   return FALSE;
01068 }
01069 
01077 DBusDispatchStatus
01078 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01079 {
01080   if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
01081       _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
01082     return DBUS_DISPATCH_COMPLETE; /* complete for now */
01083 
01084   if (!_dbus_transport_get_is_authenticated (transport))
01085     {
01086       if (_dbus_auth_do_work (transport->auth) ==
01087           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01088         return DBUS_DISPATCH_NEED_MEMORY;
01089       else if (!_dbus_transport_get_is_authenticated (transport))
01090         return DBUS_DISPATCH_COMPLETE;
01091     }
01092 
01093   if (!transport->unused_bytes_recovered &&
01094       !recover_unused_bytes (transport))
01095     return DBUS_DISPATCH_NEED_MEMORY;
01096 
01097   transport->unused_bytes_recovered = TRUE;
01098   
01099   if (!_dbus_message_loader_queue_messages (transport->loader))
01100     return DBUS_DISPATCH_NEED_MEMORY;
01101 
01102   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01103     return DBUS_DISPATCH_DATA_REMAINS;
01104   else
01105     return DBUS_DISPATCH_COMPLETE;
01106 }
01107 
01116 dbus_bool_t
01117 _dbus_transport_queue_messages (DBusTransport *transport)
01118 {
01119   DBusDispatchStatus status;
01120 
01121 #if 0
01122   _dbus_verbose ("_dbus_transport_queue_messages()\n");
01123 #endif
01124   
01125   /* Queue any messages */
01126   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01127     {
01128       DBusMessage *message;
01129       DBusList *link;
01130 
01131       link = _dbus_message_loader_pop_message_link (transport->loader);
01132       _dbus_assert (link != NULL);
01133       
01134       message = link->data;
01135       
01136       _dbus_verbose ("queueing received message %p\n", message);
01137 
01138       if (!_dbus_message_add_counter (message, transport->live_messages))
01139         {
01140           _dbus_message_loader_putback_message_link (transport->loader,
01141                                                      link);
01142           status = DBUS_DISPATCH_NEED_MEMORY;
01143           break;
01144         }
01145       else
01146         {
01147           /* pass ownership of link and message ref to connection */
01148           _dbus_connection_queue_received_message_link (transport->connection,
01149                                                         link);
01150         }
01151     }
01152 
01153   if (_dbus_message_loader_get_is_corrupted (transport->loader))
01154     {
01155       _dbus_verbose ("Corrupted message stream, disconnecting\n");
01156       _dbus_transport_disconnect (transport);
01157     }
01158 
01159   return status != DBUS_DISPATCH_NEED_MEMORY;
01160 }
01161 
01168 void
01169 _dbus_transport_set_max_message_size (DBusTransport  *transport,
01170                                       long            size)
01171 {
01172   _dbus_message_loader_set_max_message_size (transport->loader, size);
01173 }
01174 
01181 void
01182 _dbus_transport_set_max_message_unix_fds (DBusTransport  *transport,
01183                                           long            n)
01184 {
01185   _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
01186 }
01187 
01194 long
01195 _dbus_transport_get_max_message_size (DBusTransport  *transport)
01196 {
01197   return _dbus_message_loader_get_max_message_size (transport->loader);
01198 }
01199 
01206 long
01207 _dbus_transport_get_max_message_unix_fds (DBusTransport  *transport)
01208 {
01209   return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
01210 }
01211 
01218 void
01219 _dbus_transport_set_max_received_size (DBusTransport  *transport,
01220                                        long            size)
01221 {
01222   transport->max_live_messages_size = size;
01223   _dbus_counter_set_notify (transport->live_messages,
01224                             transport->max_live_messages_size,
01225                             transport->max_live_messages_unix_fds,
01226                             live_messages_notify,
01227                             transport);
01228 }
01229 
01236 void
01237 _dbus_transport_set_max_received_unix_fds (DBusTransport  *transport,
01238                                            long            n)
01239 {
01240   transport->max_live_messages_unix_fds = n;
01241   _dbus_counter_set_notify (transport->live_messages,
01242                             transport->max_live_messages_size,
01243                             transport->max_live_messages_unix_fds,
01244                             live_messages_notify,
01245                             transport);
01246 }
01247 
01254 long
01255 _dbus_transport_get_max_received_size (DBusTransport  *transport)
01256 {
01257   return transport->max_live_messages_size;
01258 }
01259 
01266 long
01267 _dbus_transport_get_max_received_unix_fds (DBusTransport  *transport)
01268 {
01269   return transport->max_live_messages_unix_fds;
01270 }
01271 
01279 dbus_bool_t
01280 _dbus_transport_get_unix_user (DBusTransport *transport,
01281                                unsigned long *uid)
01282 {
01283   DBusCredentials *auth_identity;
01284 
01285   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
01286                            * case of bugs in the caller. Caller should
01287                            * never use this value on purpose, however.
01288                            */
01289   
01290   if (!transport->authenticated)
01291     return FALSE;
01292   
01293   auth_identity = _dbus_auth_get_identity (transport->auth);
01294 
01295   if (_dbus_credentials_include (auth_identity,
01296                                  DBUS_CREDENTIAL_UNIX_USER_ID))
01297     {
01298       *uid = _dbus_credentials_get_unix_uid (auth_identity);
01299       return TRUE;
01300     }
01301   else
01302     return FALSE;
01303 }
01304 
01312 dbus_bool_t
01313 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01314                                      unsigned long *pid)
01315 {
01316   DBusCredentials *auth_identity;
01317 
01318   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
01319                           * but we set it to a safe number, INT_MAX,
01320                           * just to root out possible bugs in bad callers.
01321                           */
01322   
01323   if (!transport->authenticated)
01324     return FALSE;
01325   
01326   auth_identity = _dbus_auth_get_identity (transport->auth);
01327 
01328   if (_dbus_credentials_include (auth_identity,
01329                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
01330     {
01331       *pid = _dbus_credentials_get_unix_pid (auth_identity);
01332       return TRUE;
01333     }
01334   else
01335     return FALSE;
01336 }
01337 
01346 dbus_bool_t
01347 _dbus_transport_get_adt_audit_session_data (DBusTransport      *transport,
01348                                             void              **data,
01349                                             int                *data_size)
01350 {
01351   DBusCredentials *auth_identity;
01352 
01353   *data = NULL;
01354   *data_size = 0;
01355   
01356   if (!transport->authenticated)
01357     return FALSE;
01358   
01359   auth_identity = _dbus_auth_get_identity (transport->auth);
01360 
01361   if (_dbus_credentials_include (auth_identity,
01362                                  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
01363     {
01364       *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
01365       *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
01366       return TRUE;
01367     }
01368   else
01369     return FALSE;
01370 }
01371 
01382 void
01383 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
01384                                         DBusAllowUnixUserFunction  function,
01385                                         void                      *data,
01386                                         DBusFreeFunction           free_data_function,
01387                                         void                     **old_data,
01388                                         DBusFreeFunction          *old_free_data_function)
01389 {  
01390   *old_data = transport->unix_user_data;
01391   *old_free_data_function = transport->free_unix_user_data;
01392 
01393   transport->unix_user_function = function;
01394   transport->unix_user_data = data;
01395   transport->free_unix_user_data = free_data_function;
01396 }
01397 
01405 dbus_bool_t
01406 _dbus_transport_get_windows_user (DBusTransport              *transport,
01407                                   char                      **windows_sid_p)
01408 {
01409   DBusCredentials *auth_identity;
01410 
01411   *windows_sid_p = NULL;
01412   
01413   if (!transport->authenticated)
01414     return FALSE;
01415   
01416   auth_identity = _dbus_auth_get_identity (transport->auth);
01417 
01418   if (_dbus_credentials_include (auth_identity,
01419                                  DBUS_CREDENTIAL_WINDOWS_SID))
01420     {
01421       /* If no memory, we are supposed to return TRUE and set NULL */
01422       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01423 
01424       return TRUE;
01425     }
01426   else
01427     return FALSE;
01428 }
01429 
01441 void
01442 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
01443                                            DBusAllowWindowsUserFunction   function,
01444                                            void                       *data,
01445                                            DBusFreeFunction            free_data_function,
01446                                            void                      **old_data,
01447                                            DBusFreeFunction           *old_free_data_function)
01448 {
01449   *old_data = transport->windows_user_data;
01450   *old_free_data_function = transport->free_windows_user_data;
01451 
01452   transport->windows_user_function = function;
01453   transport->windows_user_data = data;
01454   transport->free_windows_user_data = free_data_function;
01455 }
01456 
01465 dbus_bool_t
01466 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
01467                                      const char    **mechanisms)
01468 {
01469   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01470 }
01471 
01478 void
01479 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
01480                                      dbus_bool_t                 value)
01481 {
01482   transport->allow_anonymous = value != FALSE;
01483 }
01484