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

Generated on Wed Oct 22 14:05:00 2003 for D-BUS by doxygen1.3-rc3