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

Generated on Tue Dec 21 2010 for D-Bus by  doxygen 1.7.1