• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

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     {
00081       _dbus_connection_lock (transport->connection);
00082       (* transport->vtable->live_messages_changed) (transport);
00083       _dbus_connection_unlock (transport->connection);
00084     }
00085 
00086   _dbus_transport_unref (transport);
00087 }
00088 
00102 dbus_bool_t
00103 _dbus_transport_init_base (DBusTransport             *transport,
00104                            const DBusTransportVTable *vtable,
00105                            const DBusString          *server_guid,
00106                            const DBusString          *address)
00107 {
00108   DBusMessageLoader *loader;
00109   DBusAuth *auth;
00110   DBusCounter *counter;
00111   char *address_copy;
00112   DBusCredentials *creds;
00113   
00114   loader = _dbus_message_loader_new ();
00115   if (loader == NULL)
00116     return FALSE;
00117   
00118   if (server_guid)
00119     auth = _dbus_auth_server_new (server_guid);
00120   else
00121     auth = _dbus_auth_client_new ();
00122   if (auth == NULL)
00123     {
00124       _dbus_message_loader_unref (loader);
00125       return FALSE;
00126     }
00127 
00128   counter = _dbus_counter_new ();
00129   if (counter == NULL)
00130     {
00131       _dbus_auth_unref (auth);
00132       _dbus_message_loader_unref (loader);
00133       return FALSE;
00134     }  
00135 
00136   creds = _dbus_credentials_new ();
00137   if (creds == NULL)
00138     {
00139       _dbus_counter_unref (counter);
00140       _dbus_auth_unref (auth);
00141       _dbus_message_loader_unref (loader);
00142       return FALSE;
00143     }
00144   
00145   if (server_guid)
00146     {
00147       _dbus_assert (address == NULL);
00148       address_copy = NULL;
00149     }
00150   else
00151     {
00152       _dbus_assert (address != NULL);
00153 
00154       if (!_dbus_string_copy_data (address, &address_copy))
00155         {
00156           _dbus_credentials_unref (creds);
00157           _dbus_counter_unref (counter);
00158           _dbus_auth_unref (auth);
00159           _dbus_message_loader_unref (loader);
00160           return FALSE;
00161         }
00162     }
00163   
00164   transport->refcount = 1;
00165   transport->vtable = vtable;
00166   transport->loader = loader;
00167   transport->auth = auth;
00168   transport->live_messages = counter;
00169   transport->authenticated = FALSE;
00170   transport->disconnected = FALSE;
00171   transport->is_server = (server_guid != NULL);
00172   transport->send_credentials_pending = !transport->is_server;
00173   transport->receive_credentials_pending = transport->is_server;
00174   transport->address = address_copy;
00175   
00176   transport->unix_user_function = NULL;
00177   transport->unix_user_data = NULL;
00178   transport->free_unix_user_data = NULL;
00179 
00180   transport->windows_user_function = NULL;
00181   transport->windows_user_data = NULL;
00182   transport->free_windows_user_data = NULL;
00183   
00184   transport->expected_guid = NULL;
00185   
00186   /* Try to default to something that won't totally hose the system,
00187    * but doesn't impose too much of a limitation.
00188    */
00189   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
00190 
00191   /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
00192      should be more than enough */
00193   transport->max_live_messages_unix_fds = 4096;
00194 
00195   /* credentials read from socket if any */
00196   transport->credentials = creds;
00197 
00198   _dbus_counter_set_notify (transport->live_messages,
00199                             transport->max_live_messages_size,
00200                             transport->max_live_messages_unix_fds,
00201                             live_messages_notify,
00202                             transport);
00203 
00204   if (transport->address)
00205     _dbus_verbose ("Initialized transport on address %s\n", transport->address);
00206 
00207   return TRUE;
00208 }
00209 
00216 void
00217 _dbus_transport_finalize_base (DBusTransport *transport)
00218 {
00219   if (!transport->disconnected)
00220     _dbus_transport_disconnect (transport);
00221 
00222   if (transport->free_unix_user_data != NULL)
00223     (* transport->free_unix_user_data) (transport->unix_user_data);
00224 
00225   if (transport->free_windows_user_data != NULL)
00226     (* transport->free_windows_user_data) (transport->windows_user_data);
00227   
00228   _dbus_message_loader_unref (transport->loader);
00229   _dbus_auth_unref (transport->auth);
00230   _dbus_counter_set_notify (transport->live_messages,
00231                             0, 0, NULL, NULL);
00232   _dbus_counter_unref (transport->live_messages);
00233   dbus_free (transport->address);
00234   dbus_free (transport->expected_guid);
00235   if (transport->credentials)
00236     _dbus_credentials_unref (transport->credentials);
00237 }
00238 
00239 
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   _dbus_assert (*address != '\0');
00258 
00259   if (!dbus_parse_address (address, &entries, &len, error))
00260     return NULL;              /* not a valid address */
00261 
00262   for (i = 0; i < len; i++)
00263     {
00264       transport = _dbus_transport_open (entries[i], error);
00265       if (transport != NULL)
00266         break;
00267     }
00268 
00269   dbus_address_entries_free (entries);
00270   return transport;
00271 }
00272 
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_BUILD_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 
00689 
00700 dbus_bool_t
00701 _dbus_transport_get_is_authenticated (DBusTransport *transport)
00702 {  
00703   if (transport->authenticated)
00704     return TRUE;
00705   else
00706     {
00707       dbus_bool_t maybe_authenticated;
00708       
00709       if (transport->disconnected)
00710         return FALSE;
00711 
00712       /* paranoia ref since we call user callbacks sometimes */
00713       _dbus_connection_ref_unlocked (transport->connection);
00714       
00715       maybe_authenticated =
00716         (!(transport->send_credentials_pending ||
00717            transport->receive_credentials_pending));
00718 
00719       if (maybe_authenticated)
00720         {
00721           switch (_dbus_auth_do_work (transport->auth))
00722             {
00723             case DBUS_AUTH_STATE_AUTHENTICATED:
00724               /* leave as maybe_authenticated */
00725               break;
00726             default:
00727               maybe_authenticated = FALSE;
00728             }
00729         }
00730 
00731       /* If we're the client, verify the GUID
00732        */
00733       if (maybe_authenticated && !transport->is_server)
00734         {
00735           const char *server_guid;
00736 
00737           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
00738           _dbus_assert (server_guid != NULL);
00739 
00740           if (transport->expected_guid &&
00741               strcmp (transport->expected_guid, server_guid) != 0)
00742             {
00743               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
00744                              transport->expected_guid, server_guid);
00745               _dbus_transport_disconnect (transport);
00746               _dbus_connection_unref_unlocked (transport->connection);
00747               return FALSE;
00748             }
00749         }
00750 
00751       /* If we're the server, see if we want to allow this identity to proceed.
00752        */
00753       if (maybe_authenticated && transport->is_server)
00754         {
00755           dbus_bool_t allow;
00756           DBusCredentials *auth_identity;
00757           
00758           auth_identity = _dbus_auth_get_identity (transport->auth);
00759           _dbus_assert (auth_identity != NULL);
00760           
00761           /* If we have an auth'd user and a user function, delegate
00762            * deciding whether auth credentials are good enough to the
00763            * app; otherwise, use our default decision process.
00764            */
00765           if (transport->unix_user_function != NULL &&
00766               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
00767             {
00768               allow = auth_via_unix_user_function (transport);
00769             }
00770           else if (transport->windows_user_function != NULL &&
00771                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
00772             {
00773               allow = auth_via_windows_user_function (transport);
00774             }      
00775           else
00776             {
00777               allow = auth_via_default_rules (transport);
00778             }
00779           
00780           if (!allow)
00781             maybe_authenticated = FALSE;
00782         }
00783 
00784       transport->authenticated = maybe_authenticated;
00785 
00786       _dbus_connection_unref_unlocked (transport->connection);
00787       return maybe_authenticated;
00788     }
00789 }
00790 
00797 dbus_bool_t
00798 _dbus_transport_get_is_anonymous (DBusTransport *transport)
00799 {
00800   DBusCredentials *auth_identity;
00801   
00802   if (!transport->authenticated)
00803     return TRUE;
00804   
00805   auth_identity = _dbus_auth_get_identity (transport->auth);
00806 
00807   if (_dbus_credentials_are_anonymous (auth_identity))
00808     return TRUE;
00809   else
00810     return FALSE;
00811 }
00812 
00819 dbus_bool_t
00820 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
00821 {
00822   return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
00823 }
00824 
00832 const char*
00833 _dbus_transport_get_address (DBusTransport *transport)
00834 {
00835   return transport->address;
00836 }
00837 
00845 const char*
00846 _dbus_transport_get_server_id (DBusTransport *transport)
00847 {
00848   if (transport->is_server)
00849     return NULL;
00850   else if (transport->authenticated)
00851     return _dbus_auth_get_guid_from_server (transport->auth);
00852   else
00853     return transport->expected_guid;
00854 }
00855 
00865 dbus_bool_t
00866 _dbus_transport_handle_watch (DBusTransport           *transport,
00867                               DBusWatch               *watch,
00868                               unsigned int             condition)
00869 {
00870   dbus_bool_t retval;
00871   
00872   _dbus_assert (transport->vtable->handle_watch != NULL);
00873 
00874   if (transport->disconnected)
00875     return TRUE;
00876 
00877   if (dbus_watch_get_socket (watch) < 0)
00878     {
00879       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
00880       return TRUE;
00881     }
00882   
00883   _dbus_watch_sanitize_condition (watch, &condition);
00884 
00885   _dbus_transport_ref (transport);
00886   _dbus_watch_ref (watch);
00887   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
00888   _dbus_watch_unref (watch);
00889   _dbus_transport_unref (transport);
00890 
00891   return retval;
00892 }
00893 
00903 dbus_bool_t
00904 _dbus_transport_set_connection (DBusTransport  *transport,
00905                                 DBusConnection *connection)
00906 {
00907   _dbus_assert (transport->vtable->connection_set != NULL);
00908   _dbus_assert (transport->connection == NULL);
00909   
00910   transport->connection = connection;
00911 
00912   _dbus_transport_ref (transport);
00913   if (!(* transport->vtable->connection_set) (transport))
00914     transport->connection = NULL;
00915   _dbus_transport_unref (transport);
00916 
00917   return transport->connection != NULL;
00918 }
00919 
00927 dbus_bool_t
00928 _dbus_transport_get_socket_fd (DBusTransport *transport,
00929                                int           *fd_p)
00930 {
00931   dbus_bool_t retval;
00932   
00933   if (transport->vtable->get_socket_fd == NULL)
00934     return FALSE;
00935 
00936   if (transport->disconnected)
00937     return FALSE;
00938 
00939   _dbus_transport_ref (transport);
00940 
00941   retval = (* transport->vtable->get_socket_fd) (transport,
00942                                                  fd_p);
00943   
00944   _dbus_transport_unref (transport);
00945 
00946   return retval;
00947 }
00948 
00960 void
00961 _dbus_transport_do_iteration (DBusTransport  *transport,
00962                               unsigned int    flags,
00963                               int             timeout_milliseconds)
00964 {
00965   _dbus_assert (transport->vtable->do_iteration != NULL);
00966 
00967   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
00968                  flags, timeout_milliseconds, !transport->disconnected);
00969   
00970   if ((flags & (DBUS_ITERATION_DO_WRITING |
00971                 DBUS_ITERATION_DO_READING)) == 0)
00972     return; /* Nothing to do */
00973 
00974   if (transport->disconnected)
00975     return;
00976 
00977   _dbus_transport_ref (transport);
00978   (* transport->vtable->do_iteration) (transport, flags,
00979                                        timeout_milliseconds);
00980   _dbus_transport_unref (transport);
00981 
00982   _dbus_verbose ("end\n");
00983 }
00984 
00985 static dbus_bool_t
00986 recover_unused_bytes (DBusTransport *transport)
00987 {
00988   if (_dbus_auth_needs_decoding (transport->auth))
00989     {
00990       DBusString plaintext;
00991       const DBusString *encoded;
00992       DBusString *buffer;
00993       int orig_len;
00994       
00995       if (!_dbus_string_init (&plaintext))
00996         goto nomem;
00997       
00998       _dbus_auth_get_unused_bytes (transport->auth,
00999                                    &encoded);
01000 
01001       if (!_dbus_auth_decode_data (transport->auth,
01002                                    encoded, &plaintext))
01003         {
01004           _dbus_string_free (&plaintext);
01005           goto nomem;
01006         }
01007       
01008       _dbus_message_loader_get_buffer (transport->loader,
01009                                        &buffer);
01010       
01011       orig_len = _dbus_string_get_length (buffer);
01012       
01013       if (!_dbus_string_move (&plaintext, 0, buffer,
01014                               orig_len))
01015         {
01016           _dbus_string_free (&plaintext);
01017           goto nomem;
01018         }
01019       
01020       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01021                      _dbus_string_get_length (buffer) -
01022                      orig_len);
01023       
01024       _dbus_message_loader_return_buffer (transport->loader,
01025                                           buffer,
01026                                           _dbus_string_get_length (buffer) -
01027                                           orig_len);
01028 
01029       _dbus_auth_delete_unused_bytes (transport->auth);
01030       
01031       _dbus_string_free (&plaintext);
01032     }
01033   else
01034     {
01035       const DBusString *bytes;
01036       DBusString *buffer;
01037       int orig_len;
01038       dbus_bool_t succeeded;
01039 
01040       _dbus_message_loader_get_buffer (transport->loader,
01041                                        &buffer);
01042                 
01043       orig_len = _dbus_string_get_length (buffer);
01044                 
01045       _dbus_auth_get_unused_bytes (transport->auth,
01046                                    &bytes);
01047 
01048       succeeded = TRUE;
01049       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
01050         succeeded = FALSE;
01051       
01052       _dbus_verbose (" %d unused bytes sent to message loader\n", 
01053                      _dbus_string_get_length (buffer) -
01054                      orig_len);
01055       
01056       _dbus_message_loader_return_buffer (transport->loader,
01057                                           buffer,
01058                                           _dbus_string_get_length (buffer) -
01059                                           orig_len);
01060 
01061       if (succeeded)
01062         _dbus_auth_delete_unused_bytes (transport->auth);
01063       else
01064         goto nomem;
01065     }
01066 
01067   return TRUE;
01068 
01069  nomem:
01070   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
01071   return FALSE;
01072 }
01073 
01081 DBusDispatchStatus
01082 _dbus_transport_get_dispatch_status (DBusTransport *transport)
01083 {
01084   if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
01085       _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
01086     return DBUS_DISPATCH_COMPLETE; /* complete for now */
01087 
01088   if (!_dbus_transport_get_is_authenticated (transport))
01089     {
01090       if (_dbus_auth_do_work (transport->auth) ==
01091           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
01092         return DBUS_DISPATCH_NEED_MEMORY;
01093       else if (!_dbus_transport_get_is_authenticated (transport))
01094         return DBUS_DISPATCH_COMPLETE;
01095     }
01096 
01097   if (!transport->unused_bytes_recovered &&
01098       !recover_unused_bytes (transport))
01099     return DBUS_DISPATCH_NEED_MEMORY;
01100 
01101   transport->unused_bytes_recovered = TRUE;
01102   
01103   if (!_dbus_message_loader_queue_messages (transport->loader))
01104     return DBUS_DISPATCH_NEED_MEMORY;
01105 
01106   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
01107     return DBUS_DISPATCH_DATA_REMAINS;
01108   else
01109     return DBUS_DISPATCH_COMPLETE;
01110 }
01111 
01120 dbus_bool_t
01121 _dbus_transport_queue_messages (DBusTransport *transport)
01122 {
01123   DBusDispatchStatus status;
01124 
01125 #if 0
01126   _dbus_verbose ("_dbus_transport_queue_messages()\n");
01127 #endif
01128   
01129   /* Queue any messages */
01130   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
01131     {
01132       DBusMessage *message;
01133       DBusList *link;
01134 
01135       link = _dbus_message_loader_pop_message_link (transport->loader);
01136       _dbus_assert (link != NULL);
01137       
01138       message = link->data;
01139       
01140       _dbus_verbose ("queueing received message %p\n", message);
01141 
01142       if (!_dbus_message_add_counter (message, transport->live_messages))
01143         {
01144           _dbus_message_loader_putback_message_link (transport->loader,
01145                                                      link);
01146           status = DBUS_DISPATCH_NEED_MEMORY;
01147           break;
01148         }
01149       else
01150         {
01151           /* We didn't call the notify function when we added the counter, so
01152            * catch up now. Since we have the connection's lock, it's desirable
01153            * that we bypass the notify function and call this virtual method
01154            * directly. */
01155           if (transport->vtable->live_messages_changed)
01156             (* transport->vtable->live_messages_changed) (transport);
01157 
01158           /* pass ownership of link and message ref to connection */
01159           _dbus_connection_queue_received_message_link (transport->connection,
01160                                                         link);
01161         }
01162     }
01163 
01164   if (_dbus_message_loader_get_is_corrupted (transport->loader))
01165     {
01166       _dbus_verbose ("Corrupted message stream, disconnecting\n");
01167       _dbus_transport_disconnect (transport);
01168     }
01169 
01170   return status != DBUS_DISPATCH_NEED_MEMORY;
01171 }
01172 
01179 void
01180 _dbus_transport_set_max_message_size (DBusTransport  *transport,
01181                                       long            size)
01182 {
01183   _dbus_message_loader_set_max_message_size (transport->loader, size);
01184 }
01185 
01192 void
01193 _dbus_transport_set_max_message_unix_fds (DBusTransport  *transport,
01194                                           long            n)
01195 {
01196   _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
01197 }
01198 
01205 long
01206 _dbus_transport_get_max_message_size (DBusTransport  *transport)
01207 {
01208   return _dbus_message_loader_get_max_message_size (transport->loader);
01209 }
01210 
01217 long
01218 _dbus_transport_get_max_message_unix_fds (DBusTransport  *transport)
01219 {
01220   return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
01221 }
01222 
01229 void
01230 _dbus_transport_set_max_received_size (DBusTransport  *transport,
01231                                        long            size)
01232 {
01233   transport->max_live_messages_size = size;
01234   _dbus_counter_set_notify (transport->live_messages,
01235                             transport->max_live_messages_size,
01236                             transport->max_live_messages_unix_fds,
01237                             live_messages_notify,
01238                             transport);
01239 }
01240 
01247 void
01248 _dbus_transport_set_max_received_unix_fds (DBusTransport  *transport,
01249                                            long            n)
01250 {
01251   transport->max_live_messages_unix_fds = n;
01252   _dbus_counter_set_notify (transport->live_messages,
01253                             transport->max_live_messages_size,
01254                             transport->max_live_messages_unix_fds,
01255                             live_messages_notify,
01256                             transport);
01257 }
01258 
01265 long
01266 _dbus_transport_get_max_received_size (DBusTransport  *transport)
01267 {
01268   return transport->max_live_messages_size;
01269 }
01270 
01277 long
01278 _dbus_transport_get_max_received_unix_fds (DBusTransport  *transport)
01279 {
01280   return transport->max_live_messages_unix_fds;
01281 }
01282 
01290 dbus_bool_t
01291 _dbus_transport_get_unix_user (DBusTransport *transport,
01292                                unsigned long *uid)
01293 {
01294   DBusCredentials *auth_identity;
01295 
01296   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
01297                            * case of bugs in the caller. Caller should
01298                            * never use this value on purpose, however.
01299                            */
01300   
01301   if (!transport->authenticated)
01302     return FALSE;
01303   
01304   auth_identity = _dbus_auth_get_identity (transport->auth);
01305 
01306   if (_dbus_credentials_include (auth_identity,
01307                                  DBUS_CREDENTIAL_UNIX_USER_ID))
01308     {
01309       *uid = _dbus_credentials_get_unix_uid (auth_identity);
01310       return TRUE;
01311     }
01312   else
01313     return FALSE;
01314 }
01315 
01323 dbus_bool_t
01324 _dbus_transport_get_unix_process_id (DBusTransport *transport,
01325                                      unsigned long *pid)
01326 {
01327   DBusCredentials *auth_identity;
01328 
01329   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
01330                           * but we set it to a safe number, INT_MAX,
01331                           * just to root out possible bugs in bad callers.
01332                           */
01333   
01334   if (!transport->authenticated)
01335     return FALSE;
01336   
01337   auth_identity = _dbus_auth_get_identity (transport->auth);
01338 
01339   if (_dbus_credentials_include (auth_identity,
01340                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
01341     {
01342       *pid = _dbus_credentials_get_unix_pid (auth_identity);
01343       return TRUE;
01344     }
01345   else
01346     return FALSE;
01347 }
01348 
01357 dbus_bool_t
01358 _dbus_transport_get_adt_audit_session_data (DBusTransport      *transport,
01359                                             void              **data,
01360                                             int                *data_size)
01361 {
01362   DBusCredentials *auth_identity;
01363 
01364   *data = NULL;
01365   *data_size = 0;
01366   
01367   if (!transport->authenticated)
01368     return FALSE;
01369   
01370   auth_identity = _dbus_auth_get_identity (transport->auth);
01371 
01372   if (_dbus_credentials_include (auth_identity,
01373                                  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
01374     {
01375       *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
01376       *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
01377       return TRUE;
01378     }
01379   else
01380     return FALSE;
01381 }
01382 
01393 void
01394 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
01395                                         DBusAllowUnixUserFunction  function,
01396                                         void                      *data,
01397                                         DBusFreeFunction           free_data_function,
01398                                         void                     **old_data,
01399                                         DBusFreeFunction          *old_free_data_function)
01400 {  
01401   *old_data = transport->unix_user_data;
01402   *old_free_data_function = transport->free_unix_user_data;
01403 
01404   transport->unix_user_function = function;
01405   transport->unix_user_data = data;
01406   transport->free_unix_user_data = free_data_function;
01407 }
01408 
01416 dbus_bool_t
01417 _dbus_transport_get_windows_user (DBusTransport              *transport,
01418                                   char                      **windows_sid_p)
01419 {
01420   DBusCredentials *auth_identity;
01421 
01422   *windows_sid_p = NULL;
01423   
01424   if (!transport->authenticated)
01425     return FALSE;
01426   
01427   auth_identity = _dbus_auth_get_identity (transport->auth);
01428 
01429   if (_dbus_credentials_include (auth_identity,
01430                                  DBUS_CREDENTIAL_WINDOWS_SID))
01431     {
01432       /* If no memory, we are supposed to return TRUE and set NULL */
01433       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
01434 
01435       return TRUE;
01436     }
01437   else
01438     return FALSE;
01439 }
01440 
01452 void
01453 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
01454                                            DBusAllowWindowsUserFunction   function,
01455                                            void                       *data,
01456                                            DBusFreeFunction            free_data_function,
01457                                            void                      **old_data,
01458                                            DBusFreeFunction           *old_free_data_function)
01459 {
01460   *old_data = transport->windows_user_data;
01461   *old_free_data_function = transport->free_windows_user_data;
01462 
01463   transport->windows_user_function = function;
01464   transport->windows_user_data = data;
01465   transport->free_windows_user_data = free_data_function;
01466 }
01467 
01476 dbus_bool_t
01477 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
01478                                      const char    **mechanisms)
01479 {
01480   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
01481 }
01482 
01489 void
01490 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
01491                                      dbus_bool_t                 value)
01492 {
01493   transport->allow_anonymous = value != FALSE;
01494 }
01495 

Generated on Fri Jul 11 2014 20:42:03 for D-Bus by  doxygen 1.7.1