Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

bus.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* bus.c  message bus context object
00003  *
00004  * Copyright (C) 2003 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 1.2
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include "bus.h"
00025 #include "activation.h"
00026 #include "connection.h"
00027 #include "services.h"
00028 #include "utils.h"
00029 #include "policy.h"
00030 #include "config-parser.h"
00031 #include "signals.h"
00032 #include <dbus/dbus-list.h>
00033 #include <dbus/dbus-hash.h>
00034 #include <dbus/dbus-internals.h>
00035 
00036 struct BusContext
00037 {
00038   int refcount;
00039   char *type;
00040   char *address;
00041   char *pidfile;
00042   DBusLoop *loop;
00043   DBusList *servers;
00044   BusConnections *connections;
00045   BusActivation *activation;
00046   BusRegistry *registry;
00047   BusPolicy *policy;
00048   BusMatchmaker *matchmaker;
00049   DBusUserDatabase *user_database;
00050   BusLimits limits;
00051 };
00052 
00053 static dbus_int32_t server_data_slot = -1;
00054 
00055 typedef struct
00056 {
00057   BusContext *context;
00058 } BusServerData;
00059 
00060 #define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot))
00061 
00062 static BusContext*
00063 server_get_context (DBusServer *server)
00064 {
00065   BusContext *context;
00066   BusServerData *bd;
00067   
00068   if (!dbus_server_allocate_data_slot (&server_data_slot))
00069     return NULL;
00070 
00071   bd = BUS_SERVER_DATA (server);
00072   if (bd == NULL)
00073     {
00074       dbus_server_free_data_slot (&server_data_slot);
00075       return NULL;
00076     }
00077 
00078   context = bd->context;
00079 
00080   dbus_server_free_data_slot (&server_data_slot);
00081 
00082   return context;
00083 }
00084 
00085 static dbus_bool_t
00086 server_watch_callback (DBusWatch     *watch,
00087                        unsigned int   condition,
00088                        void          *data)
00089 {
00090   /* FIXME this can be done in dbus-mainloop.c
00091    * if the code in activation.c for the babysitter
00092    * watch handler is fixed.
00093    */
00094   
00095   return dbus_watch_handle (watch, condition);
00096 }
00097 
00098 static dbus_bool_t
00099 add_server_watch (DBusWatch  *watch,
00100                   void       *data)
00101 {
00102   DBusServer *server = data;
00103   BusContext *context;
00104   
00105   context = server_get_context (server);
00106   
00107   return _dbus_loop_add_watch (context->loop,
00108                                watch, server_watch_callback, server,
00109                                NULL);
00110 }
00111 
00112 static void
00113 remove_server_watch (DBusWatch  *watch,
00114                      void       *data)
00115 {
00116   DBusServer *server = data;
00117   BusContext *context;
00118   
00119   context = server_get_context (server);
00120   
00121   _dbus_loop_remove_watch (context->loop,
00122                            watch, server_watch_callback, server);
00123 }
00124 
00125 
00126 static void
00127 server_timeout_callback (DBusTimeout   *timeout,
00128                          void          *data)
00129 {
00130   /* can return FALSE on OOM but we just let it fire again later */
00131   dbus_timeout_handle (timeout);
00132 }
00133 
00134 static dbus_bool_t
00135 add_server_timeout (DBusTimeout *timeout,
00136                     void        *data)
00137 {
00138   DBusServer *server = data;
00139   BusContext *context;
00140   
00141   context = server_get_context (server);
00142 
00143   return _dbus_loop_add_timeout (context->loop,
00144                                  timeout, server_timeout_callback, server, NULL);
00145 }
00146 
00147 static void
00148 remove_server_timeout (DBusTimeout *timeout,
00149                        void        *data)
00150 {
00151   DBusServer *server = data;
00152   BusContext *context;
00153   
00154   context = server_get_context (server);
00155   
00156   _dbus_loop_remove_timeout (context->loop,
00157                              timeout, server_timeout_callback, server);
00158 }
00159 
00160 static void
00161 new_connection_callback (DBusServer     *server,
00162                          DBusConnection *new_connection,
00163                          void           *data)
00164 {
00165   BusContext *context = data;
00166   
00167   if (!bus_connections_setup_connection (context->connections, new_connection))
00168     {
00169       _dbus_verbose ("No memory to setup new connection\n");
00170 
00171       /* if we don't do this, it will get unref'd without
00172        * being disconnected... kind of strange really
00173        * that we have to do this, people won't get it right
00174        * in general.
00175        */
00176       dbus_connection_disconnect (new_connection);
00177     }
00178 
00179   dbus_connection_set_max_received_size (new_connection,
00180                                          context->limits.max_incoming_bytes);
00181 
00182   dbus_connection_set_max_message_size (new_connection,
00183                                         context->limits.max_message_size);
00184   
00185   /* on OOM, we won't have ref'd the connection so it will die. */
00186 }
00187 
00188 static void
00189 free_server_data (void *data)
00190 {
00191   BusServerData *bd = data;  
00192   
00193   dbus_free (bd);
00194 }
00195 
00196 static dbus_bool_t
00197 setup_server (BusContext *context,
00198               DBusServer *server,
00199               char      **auth_mechanisms,
00200               DBusError  *error)
00201 {
00202   BusServerData *bd;
00203 
00204   bd = dbus_new0 (BusServerData, 1);
00205   if (!dbus_server_set_data (server,
00206                              server_data_slot,
00207                              bd, free_server_data))
00208     {
00209       dbus_free (bd);
00210       BUS_SET_OOM (error);
00211       return FALSE;
00212     }
00213 
00214   bd->context = context;
00215   
00216   if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
00217     {
00218       BUS_SET_OOM (error);
00219       return FALSE;
00220     }
00221   
00222   dbus_server_set_new_connection_function (server,
00223                                            new_connection_callback,
00224                                            context, NULL);
00225   
00226   if (!dbus_server_set_watch_functions (server,
00227                                         add_server_watch,
00228                                         remove_server_watch,
00229                                         NULL,
00230                                         server,
00231                                         NULL))
00232     {
00233       BUS_SET_OOM (error);
00234       return FALSE;
00235     }
00236 
00237   if (!dbus_server_set_timeout_functions (server,
00238                                           add_server_timeout,
00239                                           remove_server_timeout,
00240                                           NULL,
00241                                           server, NULL))
00242     {
00243       BUS_SET_OOM (error);
00244       return FALSE;
00245     }
00246   
00247   return TRUE;
00248 }
00249 
00250 BusContext*
00251 bus_context_new (const DBusString *config_file,
00252                  dbus_bool_t       force_fork,
00253                  int               print_addr_fd,
00254                  int               print_pid_fd,
00255                  DBusError        *error)
00256 {
00257   BusContext *context;
00258   DBusList *link;
00259   DBusList **addresses;
00260   BusConfigParser *parser;
00261   DBusString full_address;
00262   const char *user, *pidfile;
00263   char **auth_mechanisms;
00264   DBusList **auth_mechanisms_list;
00265   int len;
00266   
00267   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00268 
00269   if (!_dbus_string_init (&full_address))
00270     {
00271       BUS_SET_OOM (error);
00272       return NULL;
00273     }
00274 
00275   if (!dbus_server_allocate_data_slot (&server_data_slot))
00276     {
00277       BUS_SET_OOM (error);
00278       _dbus_string_free (&full_address);
00279       return NULL;
00280     }
00281   
00282   parser = NULL;
00283   context = NULL;
00284   auth_mechanisms = NULL;
00285   
00286   parser = bus_config_load (config_file, TRUE, error);
00287   if (parser == NULL)
00288     goto failed;
00289 
00290   /* Check for an existing pid file. Of course this is a race;
00291    * we'd have to use fcntl() locks on the pid file to
00292    * avoid that. But we want to check for the pid file
00293    * before overwriting any existing sockets, etc.
00294    */
00295   pidfile = bus_config_parser_get_pidfile (parser);
00296   if (pidfile != NULL)
00297     {
00298       DBusString u;
00299       DBusStat stbuf;
00300       DBusError tmp_error;
00301       
00302       dbus_error_init (&tmp_error);
00303       _dbus_string_init_const (&u, pidfile);
00304       
00305       if (_dbus_stat (&u, &stbuf, &tmp_error))
00306         {
00307           dbus_set_error (error, DBUS_ERROR_FAILED,
00308                           "The pid file \"%s\" exists, if the message bus is not running, remove this file",
00309                           pidfile);
00310           dbus_error_free (&tmp_error);
00311           goto failed;
00312         }
00313     }
00314   
00315   context = dbus_new0 (BusContext, 1);
00316   if (context == NULL)
00317     {
00318       BUS_SET_OOM (error);
00319       goto failed;
00320     }
00321   
00322   context->refcount = 1;
00323 
00324   /* get our limits and timeout lengths */
00325   bus_config_parser_get_limits (parser, &context->limits);
00326   
00327   /* we need another ref of the server data slot for the context
00328    * to own
00329    */
00330   if (!dbus_server_allocate_data_slot (&server_data_slot))
00331     _dbus_assert_not_reached ("second ref of server data slot failed");
00332   
00333   context->user_database = _dbus_user_database_new ();
00334   if (context->user_database == NULL)
00335     {
00336       BUS_SET_OOM (error);
00337       goto failed;
00338     }
00339   
00340   context->loop = _dbus_loop_new ();
00341   if (context->loop == NULL)
00342     {
00343       BUS_SET_OOM (error);
00344       goto failed;
00345     }
00346   
00347   /* Build an array of auth mechanisms */
00348   
00349   auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
00350   len = _dbus_list_get_length (auth_mechanisms_list);
00351 
00352   if (len > 0)
00353     {
00354       int i;
00355 
00356       auth_mechanisms = dbus_new0 (char*, len + 1);
00357       if (auth_mechanisms == NULL)
00358         goto failed;
00359       
00360       i = 0;
00361       link = _dbus_list_get_first_link (auth_mechanisms_list);
00362       while (link != NULL)
00363         {
00364           auth_mechanisms[i] = _dbus_strdup (link->data);
00365           if (auth_mechanisms[i] == NULL)
00366             goto failed;
00367           link = _dbus_list_get_next_link (auth_mechanisms_list, link);
00368         }
00369     }
00370   else
00371     {
00372       auth_mechanisms = NULL;
00373     }
00374 
00375   /* Listen on our addresses */
00376   
00377   addresses = bus_config_parser_get_addresses (parser);  
00378   
00379   link = _dbus_list_get_first_link (addresses);
00380   while (link != NULL)
00381     {
00382       DBusServer *server;
00383       
00384       server = dbus_server_listen (link->data, error);
00385       if (server == NULL)
00386         goto failed;
00387       else if (!setup_server (context, server, auth_mechanisms, error))
00388         goto failed;
00389 
00390       if (!_dbus_list_append (&context->servers, server))
00391         {
00392           BUS_SET_OOM (error);
00393           goto failed;
00394         }          
00395       
00396       link = _dbus_list_get_next_link (addresses, link);
00397     }
00398 
00399   /* note that type may be NULL */
00400   context->type = _dbus_strdup (bus_config_parser_get_type (parser));
00401   
00402   /* We have to build the address backward, so that
00403    * <listen> later in the config file have priority
00404    */
00405   link = _dbus_list_get_last_link (&context->servers);
00406   while (link != NULL)
00407     {
00408       char *addr;
00409       
00410       addr = dbus_server_get_address (link->data);
00411       if (addr == NULL)
00412         {
00413           BUS_SET_OOM (error);
00414           goto failed;
00415         }
00416 
00417       if (_dbus_string_get_length (&full_address) > 0)
00418         {
00419           if (!_dbus_string_append (&full_address, ";"))
00420             {
00421               BUS_SET_OOM (error);
00422               goto failed;
00423             }
00424         }
00425 
00426       if (!_dbus_string_append (&full_address, addr))
00427         {
00428           BUS_SET_OOM (error);
00429           goto failed;
00430         }
00431 
00432       dbus_free (addr);
00433 
00434       link = _dbus_list_get_prev_link (&context->servers, link);
00435     }
00436 
00437   if (!_dbus_string_copy_data (&full_address, &context->address))
00438     {
00439       BUS_SET_OOM (error);
00440       goto failed;
00441     }
00442 
00443   /* Note that we don't know whether the print_addr_fd is
00444    * one of the sockets we're using to listen on, or some
00445    * other random thing. But I think the answer is "don't do
00446    * that then"
00447    */
00448   if (print_addr_fd >= 0)
00449     {
00450       DBusString addr;
00451       const char *a = bus_context_get_address (context);
00452       int bytes;
00453       
00454       _dbus_assert (a != NULL);
00455       if (!_dbus_string_init (&addr))
00456         {
00457           BUS_SET_OOM (error);
00458           goto failed;
00459         }
00460       
00461       if (!_dbus_string_append (&addr, a) ||
00462           !_dbus_string_append (&addr, "\n"))
00463         {
00464           _dbus_string_free (&addr);
00465           BUS_SET_OOM (error);
00466           goto failed;
00467         }
00468 
00469       bytes = _dbus_string_get_length (&addr);
00470       if (_dbus_write (print_addr_fd, &addr, 0, bytes) != bytes)
00471         {
00472           dbus_set_error (error, DBUS_ERROR_FAILED,
00473                           "Printing message bus address: %s\n",
00474                           _dbus_strerror (errno));
00475           _dbus_string_free (&addr);
00476           goto failed;
00477         }
00478 
00479       if (print_addr_fd > 2)
00480         _dbus_close (print_addr_fd, NULL);
00481 
00482       _dbus_string_free (&addr);
00483     }
00484   
00485   /* Create activation subsystem */
00486   
00487   context->activation = bus_activation_new (context, &full_address,
00488                                             bus_config_parser_get_service_dirs (parser),
00489                                             error);
00490   if (context->activation == NULL)
00491     {
00492       _DBUS_ASSERT_ERROR_IS_SET (error);
00493       goto failed;
00494     }
00495 
00496   context->connections = bus_connections_new (context);
00497   if (context->connections == NULL)
00498     {
00499       BUS_SET_OOM (error);
00500       goto failed;
00501     }
00502 
00503   context->registry = bus_registry_new (context);
00504   if (context->registry == NULL)
00505     {
00506       BUS_SET_OOM (error);
00507       goto failed;
00508     }
00509 
00510   context->matchmaker = bus_matchmaker_new ();
00511   if (context->matchmaker == NULL)
00512     {
00513       BUS_SET_OOM (error);
00514       goto failed;
00515     }
00516   
00517   context->policy = bus_config_parser_steal_policy (parser);
00518   _dbus_assert (context->policy != NULL);
00519   
00520   /* Now become a daemon if appropriate */
00521   if (force_fork || bus_config_parser_get_fork (parser))
00522     {
00523       DBusString u;
00524 
00525       if (pidfile)
00526         _dbus_string_init_const (&u, pidfile);
00527       
00528       if (!_dbus_become_daemon (pidfile ? &u : NULL, error))
00529         goto failed;
00530     }
00531   else
00532     {
00533       /* Need to write PID file for ourselves, not for the child process */
00534       if (pidfile != NULL)
00535         {
00536           DBusString u;
00537 
00538           _dbus_string_init_const (&u, pidfile);
00539           
00540           if (!_dbus_write_pid_file (&u, _dbus_getpid (), error))
00541             goto failed;
00542         }
00543     }
00544 
00545   /* keep around the pid filename so we can delete it later */
00546   context->pidfile = _dbus_strdup (pidfile);
00547 
00548   /* Write PID if requested */
00549   if (print_pid_fd >= 0)
00550     {
00551       DBusString pid;
00552       int bytes;
00553 
00554       if (!_dbus_string_init (&pid))
00555         {
00556           BUS_SET_OOM (error);
00557           goto failed;
00558         }
00559       
00560       if (!_dbus_string_append_int (&pid, _dbus_getpid ()) ||
00561           !_dbus_string_append (&pid, "\n"))
00562         {
00563           _dbus_string_free (&pid);
00564           BUS_SET_OOM (error);
00565           goto failed;
00566         }
00567 
00568       bytes = _dbus_string_get_length (&pid);
00569       if (_dbus_write (print_pid_fd, &pid, 0, bytes) != bytes)
00570         {
00571           dbus_set_error (error, DBUS_ERROR_FAILED,
00572                           "Printing message bus PID: %s\n",
00573                           _dbus_strerror (errno));
00574           _dbus_string_free (&pid);
00575           goto failed;
00576         }
00577 
00578       if (print_pid_fd > 2)
00579         _dbus_close (print_pid_fd, NULL);
00580       
00581       _dbus_string_free (&pid);
00582     }
00583   
00584   /* Here we change our credentials if required,
00585    * as soon as we've set up our sockets and pidfile
00586    */
00587   user = bus_config_parser_get_user (parser);
00588   if (user != NULL)
00589     {
00590       DBusCredentials creds;
00591       DBusString u;
00592 
00593       _dbus_string_init_const (&u, user);
00594 
00595       if (!_dbus_credentials_from_username (&u, &creds) ||
00596           creds.uid < 0 ||
00597           creds.gid < 0)
00598         {
00599           dbus_set_error (error, DBUS_ERROR_FAILED,
00600                           "Could not get UID and GID for username \"%s\"",
00601                           user);
00602           goto failed;
00603         }
00604       
00605       if (!_dbus_change_identity (creds.uid, creds.gid, error))
00606         goto failed;
00607     }
00608   
00609   bus_config_parser_unref (parser);
00610   _dbus_string_free (&full_address);
00611   dbus_free_string_array (auth_mechanisms);
00612   dbus_server_free_data_slot (&server_data_slot);
00613   
00614   return context;
00615   
00616  failed:  
00617   if (parser != NULL)
00618     bus_config_parser_unref (parser);
00619 
00620   if (context != NULL)
00621     bus_context_unref (context);
00622 
00623   _dbus_string_free (&full_address);
00624   dbus_free_string_array (auth_mechanisms);
00625 
00626   dbus_server_free_data_slot (&server_data_slot);
00627   
00628   return NULL;
00629 }
00630 
00631 static void
00632 shutdown_server (BusContext *context,
00633                  DBusServer *server)
00634 {
00635   if (server == NULL ||
00636       !dbus_server_get_is_connected (server))
00637     return;
00638   
00639   if (!dbus_server_set_watch_functions (server,
00640                                         NULL, NULL, NULL,
00641                                         context,
00642                                         NULL))
00643     _dbus_assert_not_reached ("setting watch functions to NULL failed");
00644   
00645   if (!dbus_server_set_timeout_functions (server,
00646                                           NULL, NULL, NULL,
00647                                           context,
00648                                           NULL))
00649     _dbus_assert_not_reached ("setting timeout functions to NULL failed");
00650   
00651   dbus_server_disconnect (server);
00652 }
00653 
00654 void
00655 bus_context_shutdown (BusContext  *context)
00656 {
00657   DBusList *link;
00658 
00659   link = _dbus_list_get_first_link (&context->servers);
00660   while (link != NULL)
00661     {
00662       shutdown_server (context, link->data);
00663 
00664       link = _dbus_list_get_next_link (&context->servers, link);
00665     }
00666 }
00667 
00668 void
00669 bus_context_ref (BusContext *context)
00670 {
00671   _dbus_assert (context->refcount > 0);
00672   context->refcount += 1;
00673 }
00674 
00675 void
00676 bus_context_unref (BusContext *context)
00677 {
00678   _dbus_assert (context->refcount > 0);
00679   context->refcount -= 1;
00680 
00681   if (context->refcount == 0)
00682     {
00683       DBusList *link;
00684       
00685       _dbus_verbose ("Finalizing bus context %p\n", context);
00686       
00687       bus_context_shutdown (context);
00688 
00689       if (context->connections)
00690         {
00691           bus_connections_unref (context->connections);
00692           context->connections = NULL;
00693         }
00694       
00695       if (context->registry)
00696         {
00697           bus_registry_unref (context->registry);
00698           context->registry = NULL;
00699         }
00700       
00701       if (context->activation)
00702         {
00703           bus_activation_unref (context->activation);
00704           context->activation = NULL;
00705         }
00706 
00707       link = _dbus_list_get_first_link (&context->servers);
00708       while (link != NULL)
00709         {
00710           dbus_server_unref (link->data);
00711           
00712           link = _dbus_list_get_next_link (&context->servers, link);
00713         }
00714       _dbus_list_clear (&context->servers);
00715 
00716       if (context->policy)
00717         {
00718           bus_policy_unref (context->policy);
00719           context->policy = NULL;
00720         }
00721       
00722       if (context->loop)
00723         {
00724           _dbus_loop_unref (context->loop);
00725           context->loop = NULL;
00726         }
00727 
00728       if (context->matchmaker)
00729         {
00730           bus_matchmaker_unref (context->matchmaker);
00731           context->matchmaker = NULL;
00732         }
00733       
00734       dbus_free (context->type);
00735       dbus_free (context->address);
00736 
00737       if (context->pidfile)
00738         {
00739           DBusString u;
00740           _dbus_string_init_const (&u, context->pidfile);
00741 
00742           /* Deliberately ignore errors here, since there's not much
00743            * we can do about it, and we're exiting anyways.
00744            */
00745           _dbus_delete_file (&u, NULL);
00746 
00747           dbus_free (context->pidfile); 
00748         }
00749 
00750       _dbus_user_database_unref (context->user_database);
00751       
00752       dbus_free (context);
00753 
00754       dbus_server_free_data_slot (&server_data_slot);
00755     }
00756 }
00757 
00758 /* type may be NULL */
00759 const char*
00760 bus_context_get_type (BusContext *context)
00761 {
00762   return context->type;
00763 }
00764 
00765 const char*
00766 bus_context_get_address (BusContext *context)
00767 {
00768   return context->address;
00769 }
00770 
00771 BusRegistry*
00772 bus_context_get_registry (BusContext  *context)
00773 {
00774   return context->registry;
00775 }
00776 
00777 BusConnections*
00778 bus_context_get_connections (BusContext  *context)
00779 {
00780   return context->connections;
00781 }
00782 
00783 BusActivation*
00784 bus_context_get_activation (BusContext  *context)
00785 {
00786   return context->activation;
00787 }
00788 
00789 BusMatchmaker*
00790 bus_context_get_matchmaker (BusContext  *context)
00791 {
00792   return context->matchmaker;
00793 }
00794 
00795 DBusLoop*
00796 bus_context_get_loop (BusContext *context)
00797 {
00798   return context->loop;
00799 }
00800 
00801 DBusUserDatabase*
00802 bus_context_get_user_database (BusContext *context)
00803 {
00804   return context->user_database;
00805 }
00806 
00807 dbus_bool_t
00808 bus_context_allow_user (BusContext   *context,
00809                         unsigned long uid)
00810 {
00811   return bus_policy_allow_user (context->policy,
00812                                 context->user_database,
00813                                 uid);
00814 }
00815 
00816 BusClientPolicy*
00817 bus_context_create_client_policy (BusContext      *context,
00818                                   DBusConnection  *connection,
00819                                   DBusError       *error)
00820 {
00821   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00822   return bus_policy_create_client_policy (context->policy, connection,
00823                                           error);
00824 }
00825 
00826 int
00827 bus_context_get_activation_timeout (BusContext *context)
00828 {
00829   
00830   return context->limits.activation_timeout;
00831 }
00832 
00833 int
00834 bus_context_get_auth_timeout (BusContext *context)
00835 {
00836   return context->limits.auth_timeout;
00837 }
00838 
00839 int
00840 bus_context_get_max_completed_connections (BusContext *context)
00841 {
00842   return context->limits.max_completed_connections;
00843 }
00844 
00845 int
00846 bus_context_get_max_incomplete_connections (BusContext *context)
00847 {
00848   return context->limits.max_incomplete_connections;
00849 }
00850 
00851 int
00852 bus_context_get_max_connections_per_user (BusContext *context)
00853 {
00854   return context->limits.max_connections_per_user;
00855 }
00856 
00857 int
00858 bus_context_get_max_pending_activations (BusContext *context)
00859 {
00860   return context->limits.max_pending_activations;
00861 }
00862 
00863 int
00864 bus_context_get_max_services_per_connection (BusContext *context)
00865 {
00866   return context->limits.max_services_per_connection;
00867 }
00868 
00869 int
00870 bus_context_get_max_match_rules_per_connection (BusContext *context)
00871 {
00872   return context->limits.max_match_rules_per_connection;
00873 }
00874 
00875 dbus_bool_t
00876 bus_context_check_security_policy (BusContext     *context,
00877                                    DBusConnection *sender,
00878                                    DBusConnection *addressed_recipient,
00879                                    DBusConnection *proposed_recipient,
00880                                    DBusMessage    *message,
00881                                    DBusError      *error)
00882 {
00883   BusClientPolicy *sender_policy;
00884   BusClientPolicy *recipient_policy;
00885 
00886   /* NULL sender, proposed_recipient means the bus driver.  NULL
00887    * addressed_recipient means the message didn't specify an explicit
00888    * target. If proposed_recipient is NULL, then addressed_recipient
00889    * is also NULL but is implicitly the bus driver.
00890    */
00891 
00892   _dbus_assert (proposed_recipient == NULL ||
00893                 (dbus_message_get_destination (message) == NULL ||
00894                  addressed_recipient != NULL));
00895   
00896   if (sender != NULL)
00897     {
00898       if (bus_connection_is_active (sender))
00899         {
00900           sender_policy = bus_connection_get_policy (sender);
00901           _dbus_assert (sender_policy != NULL);
00902         }
00903       else
00904         {
00905           /* Policy for inactive connections is that they can only send
00906            * the hello message to the bus driver
00907            */
00908           if (proposed_recipient == NULL &&
00909               dbus_message_is_method_call (message,
00910                                            DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
00911                                            "Hello"))
00912             {
00913               _dbus_verbose ("security check allowing %s message\n",
00914                              "Hello");
00915               return TRUE;
00916             }
00917           else
00918             {
00919               _dbus_verbose ("security check disallowing non-%s message\n",
00920                              "Hello");
00921 
00922               dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
00923                               "Client tried to send a message other than %s without being registered",
00924                               "Hello");
00925               
00926               return FALSE;
00927             }
00928         }
00929     }
00930   else
00931     sender_policy = NULL;
00932 
00933   _dbus_assert ((sender != NULL && sender_policy != NULL) ||
00934                 (sender == NULL && sender_policy == NULL));
00935   
00936   if (proposed_recipient != NULL)
00937     {
00938       /* only the bus driver can send to an inactive recipient (as it
00939        * owns no services, so other apps can't address it). Inactive
00940        * recipients can receive any message.
00941        */
00942       if (bus_connection_is_active (proposed_recipient))
00943         {
00944           recipient_policy = bus_connection_get_policy (proposed_recipient);
00945           _dbus_assert (recipient_policy != NULL);
00946         }
00947       else if (sender == NULL)
00948         {
00949           _dbus_verbose ("security check using NULL recipient policy for message from bus\n");
00950           recipient_policy = NULL;
00951         }
00952       else
00953         {
00954           _dbus_assert_not_reached ("a message was somehow sent to an inactive recipient from a source other than the message bus\n");
00955           recipient_policy = NULL;
00956         }
00957     }
00958   else
00959     recipient_policy = NULL;
00960   
00961   _dbus_assert ((proposed_recipient != NULL && recipient_policy != NULL) ||
00962                 (proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) ||
00963                 (proposed_recipient == NULL && recipient_policy == NULL));
00964   
00965   if (sender_policy &&
00966       !bus_client_policy_check_can_send (sender_policy,
00967                                          context->registry, proposed_recipient,
00968                                          message))
00969     {
00970       const char *dest = dbus_message_get_destination (message);
00971       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
00972                       "A security policy in place prevents this sender "
00973                       "from sending this message to this recipient, "
00974                       "see message bus configuration file (rejected message "
00975                       "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")",
00976                       dbus_message_get_interface (message) ?
00977                       dbus_message_get_interface (message) : "(unset)",
00978                       dbus_message_get_member (message) ?
00979                       dbus_message_get_member (message) : "(unset)",
00980                       dbus_message_get_error_name (message) ?
00981                       dbus_message_get_error_name (message) : "(unset)",
00982                       dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
00983       _dbus_verbose ("security policy disallowing message due to sender policy\n");
00984       return FALSE;
00985     }
00986 
00987   if (recipient_policy &&
00988       !bus_client_policy_check_can_receive (recipient_policy,
00989                                             context->registry, sender,
00990                                             addressed_recipient, proposed_recipient,
00991                                             message))
00992     {
00993       const char *dest = dbus_message_get_destination (message);
00994       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
00995                       "A security policy in place prevents this recipient "
00996                       "from receiving this message from this sender, "
00997                       "see message bus configuration file (rejected message "
00998                       "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")",
00999                       dbus_message_get_interface (message) ?
01000                       dbus_message_get_interface (message) : "(unset)",
01001                       dbus_message_get_member (message) ?
01002                       dbus_message_get_member (message) : "(unset)",
01003                       dbus_message_get_error_name (message) ?
01004                       dbus_message_get_error_name (message) : "(unset)",
01005                       dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
01006       _dbus_verbose ("security policy disallowing message due to recipient policy\n");
01007       return FALSE;
01008     }
01009 
01010   /* See if limits on size have been exceeded */
01011   if (proposed_recipient &&
01012       dbus_connection_get_outgoing_size (proposed_recipient) >
01013       context->limits.max_outgoing_bytes)
01014     {
01015       const char *dest = dbus_message_get_destination (message);
01016       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
01017                       "The destination service \"%s\" has a full message queue",
01018                       dest ? dest : (proposed_recipient ?
01019                                      bus_connection_get_name (proposed_recipient) : 
01020                                      DBUS_SERVICE_ORG_FREEDESKTOP_DBUS));
01021       _dbus_verbose ("security policy disallowing message due to full message queue\n");
01022       return FALSE;
01023     }
01024 
01025   _dbus_verbose ("security policy allowing message\n");
01026   return TRUE;
01027 }

Generated on Mon Sep 29 21:30:59 2003 for D-BUS by doxygen1.2.15