(linenum→info "unix/slp.c:2238")

dbus/1.0.2/bus/bus.c

    1: /* -*- mode: C; c-file-style: "gnu" -*- */
    2: /* bus.c  message bus context object
    3:  *
    4:  * Copyright (C) 2003, 2004 Red Hat, Inc.
    5:  *
    6:  * Licensed under the Academic Free License version 2.1
    7:  * 
    8:  * This program is free software; you can redistribute it and/or modify
    9:  * it under the terms of the GNU General Public License as published by
   10:  * the Free Software Foundation; either version 2 of the License, or
   11:  * (at your option) any later version.
   12:  *
   13:  * This program is distributed in the hope that it will be useful,
   14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:  * GNU General Public License for more details.
   17:  * 
   18:  * You should have received a copy of the GNU General Public License
   19:  * along with this program; if not, write to the Free Software
   20:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21:  *
   22:  */
   23: 
   24: #include "bus.h"
   25: #include "activation.h"
   26: #include "connection.h"
   27: #include "services.h"
   28: #include "utils.h"
   29: #include "policy.h"
   30: #include "config-parser.h"
   31: #include "signals.h"
   32: #include "selinux.h"
   33: #include "dir-watch.h"
   34: #include <dbus/dbus-list.h>
   35: #include <dbus/dbus-hash.h>
   36: #include <dbus/dbus-internals.h>
   37: 
   38: struct BusContext
   39: {
   40:   int refcount;
   41:   char *config_file;
   42:   char *type;
   43:   char *address;
   44:   char *pidfile;
   45:   char *user;
   46:   DBusLoop *loop;
   47:   DBusList *servers;
   48:   BusConnections *connections;
   49:   BusActivation *activation;
   50:   BusRegistry *registry;
   51:   BusPolicy *policy;
   52:   BusMatchmaker *matchmaker;
   53:   DBusUserDatabase *user_database;
   54:   BusLimits limits;
   55:   unsigned int fork : 1;
   56: };
   57: 
   58: static dbus_int32_t server_data_slot = -1;
   59: 
   60: typedef struct
   61: {
   62:   BusContext *context;
   63: } BusServerData;
   64: 
   65: #define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot))
   66: 
   67: static BusContext*
   68: server_get_context (DBusServer *server)
   69: {
   70:   BusContext *context;
   71:   BusServerData *bd;
   72:   
   73:   if (!dbus_server_allocate_data_slot (&server_data_slot))
   74:     return NULL;
   75: 
   76:   bd = BUS_SERVER_DATA (server);
   77:   if (bd == NULL)
   78:     {
   79:       dbus_server_free_data_slot (&server_data_slot);
   80:       return NULL;
   81:     }
   82: 
   83:   context = bd->context;
   84: 
   85:   dbus_server_free_data_slot (&server_data_slot);
   86: 
   87:   return context;
   88: }
   89: 
   90: static dbus_bool_t
   91: server_watch_callback (DBusWatch     *watch,
   92:                        unsigned int   condition,
   93:                        void          *data)
   94: {
   95:   /* FIXME this can be done in dbus-mainloop.c
   96:    * if the code in activation.c for the babysitter
   97:    * watch handler is fixed.
   98:    */
   99:   
  100:   return dbus_watch_handle (watch, condition);
  101: }
  102: 
  103: static dbus_bool_t
  104: add_server_watch (DBusWatch  *watch,
  105:                   void       *data)
  106: {
  107:   DBusServer *server = data;
  108:   BusContext *context;
  109:   
  110:   context = server_get_context (server);
  111:   
  112:   return _dbus_loop_add_watch (context->loop,
  113:                                watch, server_watch_callback, server,
  114:                                NULL);
  115: }
  116: 
  117: static void
  118: remove_server_watch (DBusWatch  *watch,
  119:                      void       *data)
  120: {
  121:   DBusServer *server = data;
  122:   BusContext *context;
  123:   
  124:   context = server_get_context (server);
  125:   
  126:   _dbus_loop_remove_watch (context->loop,
  127:                            watch, server_watch_callback, server);
  128: }
  129: 
  130: 
  131: static void
  132: server_timeout_callback (DBusTimeout   *timeout,
  133:                          void          *data)
  134: {
  135:   /* can return FALSE on OOM but we just let it fire again later */
  136:   dbus_timeout_handle (timeout);
  137: }
  138: 
  139: static dbus_bool_t
  140: add_server_timeout (DBusTimeout *timeout,
  141:                     void        *data)
  142: {
  143:   DBusServer *server = data;
  144:   BusContext *context;
  145:   
  146:   context = server_get_context (server);
  147: 
  148:   return _dbus_loop_add_timeout (context->loop,
  149:                                  timeout, server_timeout_callback, server, NULL);
  150: }
  151: 
  152: static void
  153: remove_server_timeout (DBusTimeout *timeout,
  154:                        void        *data)
  155: {
  156:   DBusServer *server = data;
  157:   BusContext *context;
  158:   
  159:   context = server_get_context (server);
  160:   
  161:   _dbus_loop_remove_timeout (context->loop,
  162:                              timeout, server_timeout_callback, server);
  163: }
  164: 
  165: static void
  166: new_connection_callback (DBusServer     *server,
  167:                          DBusConnection *new_connection,
  168:                          void           *data)
  169: {
  170:   BusContext *context = data;
  171:   
  172:   if (!bus_connections_setup_connection (context->connections, new_connection))
  173:     {
  174:       _dbus_verbose ("No memory to setup new connection\n");
  175: 
  176:       /* if we don't do this, it will get unref'd without
  177:        * being disconnected... kind of strange really
  178:        * that we have to do this, people won't get it right
  179:        * in general.
  180:        */
  181:       dbus_connection_close (new_connection);
  182:     }
  183: 
  184:   dbus_connection_set_max_received_size (new_connection,
  185:                                          context->limits.max_incoming_bytes);
  186: 
  187:   dbus_connection_set_max_message_size (new_connection,
  188:                                         context->limits.max_message_size);
  189:   
  190:   /* on OOM, we won't have ref'd the connection so it will die. */
  191: }
  192: 
  193: static void
  194: free_server_data (void *data)
  195: {
  196:   BusServerData *bd = data;  
  197:   
  198:   dbus_free (bd);
  199: }
  200: 
  201: static dbus_bool_t
  202: setup_server (BusContext *context,
  203:               DBusServer *server,
  204:               char      **auth_mechanisms,
  205:               DBusError  *error)
  206: {
  207:   BusServerData *bd;
  208: 
  209:   bd = dbus_new0 (BusServerData, 1);
  210:   if (!dbus_server_set_data (server,
  211:                              server_data_slot,
  212:                              bd, free_server_data))
  213:     {
  214:       dbus_free (bd);
  215:       BUS_SET_OOM (error);
  216:       return FALSE;
  217:     }
  218: 
  219:   bd->context = context;
  220:   
  221:   if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
  222:     {
  223:       BUS_SET_OOM (error);
  224:       return FALSE;
  225:     }
  226:   
  227:   dbus_server_set_new_connection_function (server,
  228:                                            new_connection_callback,
  229:                                            context, NULL);
  230:   
  231:   if (!dbus_server_set_watch_functions (server,
  232:                                         add_server_watch,
  233:                                         remove_server_watch,
  234:                                         NULL,
  235:                                         server,
  236:                                         NULL))
  237:     {
  238:       BUS_SET_OOM (error);
  239:       return FALSE;
  240:     }
  241: 
  242:   if (!dbus_server_set_timeout_functions (server,
  243:                                           add_server_timeout,
  244:                                           remove_server_timeout,
  245:                                           NULL,
  246:                                           server, NULL))
  247:     {
  248:       BUS_SET_OOM (error);
  249:       return FALSE;
  250:     }
  251:   
  252:   return TRUE;
  253: }
  254: 
  255: /* This code only gets executed the first time the
  256:    config files are parsed.  It is not executed
  257:    when config files are reloaded.*/
  258: static dbus_bool_t
  259: process_config_first_time_only (BusContext      *context,
  260:                                 BusConfigParser *parser,
  261:                                 DBusError       *error)
  262: {
  263:   DBusList *link;
  264:   DBusList **addresses;
  265:   const char *user, *pidfile;
  266:   char **auth_mechanisms;
  267:   DBusList **auth_mechanisms_list;
  268:   int len;
  269:   dbus_bool_t retval;
  270: 
  271:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  272: 
  273:   retval = FALSE;
  274:   auth_mechanisms = NULL;
  275: 
  276:   /* Check for an existing pid file. Of course this is a race;
  277:    * we'd have to use fcntl() locks on the pid file to
  278:    * avoid that. But we want to check for the pid file
  279:    * before overwriting any existing sockets, etc.
  280:    */
  281:   pidfile = bus_config_parser_get_pidfile (parser);
  282:   if (pidfile != NULL)
  283:     {
  284:       DBusString u;
  285:       DBusStat stbuf;
  286:       
  287:       _dbus_string_init_const (&u, pidfile);
  288:       
  289:       if (_dbus_stat (&u, &stbuf, NULL))
  290:         {
  291:           dbus_set_error (error, DBUS_ERROR_FAILED,
  292:                           "The pid file \"%s\" exists, if the message bus is not running, remove this file",
  293:                           pidfile);
  294:           goto failed;
  295:         }
  296:     }
  297:   
  298:   /* keep around the pid filename so we can delete it later */
  299:   context->pidfile = _dbus_strdup (pidfile);
  300: 
  301:   /* Build an array of auth mechanisms */
  302:   
  303:   auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
  304:   len = _dbus_list_get_length (auth_mechanisms_list);
  305: 
  306:   if (len > 0)
  307:     {
  308:       int i;
  309: 
  310:       auth_mechanisms = dbus_new0 (char*, len + 1);
  311:       if (auth_mechanisms == NULL)
  312:         {
  313:           BUS_SET_OOM (error);
  314:           goto failed;
  315:         }
  316:       
  317:       i = 0;
  318:       link = _dbus_list_get_first_link (auth_mechanisms_list);
  319:       while (link != NULL)
  320:         {
  321:           auth_mechanisms[i] = _dbus_strdup (link->data);
  322:           if (auth_mechanisms[i] == NULL)
  323:             {
  324:               BUS_SET_OOM (error);
  325:               goto failed;
  326:             }
  327:           link = _dbus_list_get_next_link (auth_mechanisms_list, link);
  328:         }
  329:     }
  330:   else
  331:     {
  332:       auth_mechanisms = NULL;
  333:     }
  334: 
  335:   /* Listen on our addresses */
  336:   
  337:   addresses = bus_config_parser_get_addresses (parser);  
  338:   
  339:   link = _dbus_list_get_first_link (addresses);
  340:   while (link != NULL)
  341:     {
  342:       DBusServer *server;
  343:       
  344:       server = dbus_server_listen (link->data, error);
  345:       if (server == NULL)
  346:         {
  347:           _DBUS_ASSERT_ERROR_IS_SET (error);
  348:           goto failed;
  349:         }
  350:       else if (!setup_server (context, server, auth_mechanisms, error))
  351:         {
  352:           _DBUS_ASSERT_ERROR_IS_SET (error);
  353:           goto failed;
  354:         }
  355: 
  356:       if (!_dbus_list_append (&context->servers, server))
  357:         {
  358:           BUS_SET_OOM (error);
  359:           goto failed;
  360:         }          
  361:       
  362:       link = _dbus_list_get_next_link (addresses, link);
  363:     }
  364: 
  365:   /* note that type may be NULL */
  366:   context->type = _dbus_strdup (bus_config_parser_get_type (parser));
  367:   if (bus_config_parser_get_type (parser) != NULL && context->type == NULL)
  368:     {
  369:       BUS_SET_OOM (error);
  370:       goto failed;
  371:     }
  372: 
  373:   user = bus_config_parser_get_user (parser);
  374:   if (user != NULL)
  375:     {
  376:       context->user = _dbus_strdup (user);
  377:       if (context->user == NULL)
  378:         {
  379:           BUS_SET_OOM (error);
  380:           goto failed;
  381:         }
  382:     }
  383: 
  384:   context->fork = bus_config_parser_get_fork (parser);
  385:   
  386:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  387:   retval = TRUE;
  388: 
  389:  failed:
  390:   dbus_free_string_array (auth_mechanisms);
  391:   return retval;
  392: }
  393: 
  394: /* This code gets executed every time the config files
  395:    are parsed: both during BusContext construction
  396:    and on reloads. */
  397: static dbus_bool_t
  398: process_config_every_time (BusContext      *context,
  399:                            BusConfigParser *parser,
  400:                            dbus_bool_t      is_reload,
  401:                            DBusError       *error)
  402: {
  403:   DBusString full_address;
  404:   DBusList *link;
  405:   char *addr;
  406: 
  407:   dbus_bool_t retval;
  408: 
  409:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  410: 
  411:   addr = NULL;
  412:   retval = FALSE;
  413: 
  414:   if (!_dbus_string_init (&full_address))
  415:     {
  416:       BUS_SET_OOM (error);
  417:       return FALSE;
  418:     }
  419: 
  420:   /* get our limits and timeout lengths */
  421:   bus_config_parser_get_limits (parser, &context->limits);
  422: 
  423:   context->policy = bus_config_parser_steal_policy (parser);
  424:   _dbus_assert (context->policy != NULL);
  425: 
  426:   /* We have to build the address backward, so that
  427:    * <listen> later in the config file have priority
  428:    */
  429:   link = _dbus_list_get_last_link (&context->servers);
  430:   while (link != NULL)
  431:     {
  432:       addr = dbus_server_get_address (link->data);
  433:       if (addr == NULL)
  434:         {
  435:           BUS_SET_OOM (error);
  436:           goto failed;
  437:         }
  438: 
  439:       if (_dbus_string_get_length (&full_address) > 0)
  440:         {
  441:           if (!_dbus_string_append (&full_address, ";"))
  442:             {
  443:               BUS_SET_OOM (error);
  444:               goto failed;
  445:             }
  446:         }
  447: 
  448:       if (!_dbus_string_append (&full_address, addr))
  449:         {
  450:           BUS_SET_OOM (error);
  451:           goto failed;
  452:         }
  453: 
  454:       dbus_free (addr);
  455:       addr = NULL;
  456: 
  457:       link = _dbus_list_get_prev_link (&context->servers, link);
  458:     }
  459: 
  460:   if (is_reload)
  461:     dbus_free (context->address);
  462: 
  463:   if (!_dbus_string_copy_data (&full_address, &context->address))
  464:     {
  465:       BUS_SET_OOM (error);
  466:       goto failed;
  467:     }
  468: 
  469:   /* Create activation subsystem */
  470:   
  471:   if (is_reload)
  472:     bus_activation_unref (context->activation);
  473:   
  474:   context->activation = bus_activation_new (context, &full_address,
  475:                                             bus_config_parser_get_service_dirs (parser),
  476:                                             error);
  477:   if (context->activation == NULL)
  478:     {
  479:       _DBUS_ASSERT_ERROR_IS_SET (error);
  480:       goto failed;
  481:     }
  482: 
  483:   /* Drop existing conf-dir watches (if applicable) */
  484: 
  485:   if (is_reload)
  486:     bus_drop_all_directory_watches ();
  487: 
  488:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  489:   retval = TRUE;
  490: 
  491:  failed:
  492:   _dbus_string_free (&full_address);
  493:   
  494:   if (addr)
  495:     dbus_free (addr);
  496: 
  497:   return retval;
  498: }
  499: 
  500: static dbus_bool_t
  501: process_config_postinit (BusContext      *context,
  502:                          BusConfigParser *parser,
  503:                          DBusError       *error)
  504: {
  505:   DBusHashTable *service_context_table;
  506: 
  507:   service_context_table = bus_config_parser_steal_service_context_table (parser);
  508:   if (!bus_registry_set_service_context_table (context->registry,
  509:                                                service_context_table))
  510:     {
  511:       BUS_SET_OOM (error);
  512:       return FALSE;
  513:     }
  514: 
  515:   _dbus_hash_table_unref (service_context_table);
  516: 
  517:   /* Watch all conf directories */
  518:   _dbus_list_foreach (bus_config_parser_get_conf_dirs (parser),
  519:                       (DBusForeachFunction) bus_watch_directory,
  520:                       context);
  521: 
  522:   return TRUE;
  523: }
  524: 
  525: BusContext*
  526: bus_context_new (const DBusString *config_file,
  527:                  ForceForkSetting  force_fork,
  528:                  int               print_addr_fd,
  529:                  int               print_pid_fd,
  530:                  DBusError        *error)
  531: {
  532:   BusContext *context;
  533:   BusConfigParser *parser;
  534:   DBusCredentials creds;
  535: 
  536:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  537: 
  538:   context = NULL;
  539:   parser = NULL;
  540: 
  541:   if (!dbus_server_allocate_data_slot (&server_data_slot))
  542:     {
  543:       BUS_SET_OOM (error);
  544:       return NULL;
  545:     }
  546: 
  547:   context = dbus_new0 (BusContext, 1);
  548:   if (context == NULL)
  549:     {
  550:       BUS_SET_OOM (error);
  551:       goto failed;
  552:     }
  553:   context->refcount = 1;
  554: 
  555:   if (!_dbus_string_copy_data (config_file, &context->config_file))
  556:     {
  557:       BUS_SET_OOM (error);
  558:       goto failed;
  559:     }
  560: 
  561:   context->loop = _dbus_loop_new ();
  562:   if (context->loop == NULL)
  563:     {
  564:       BUS_SET_OOM (error);
  565:       goto failed;
  566:     }
  567: 
  568:   context->registry = bus_registry_new (context);
  569:   if (context->registry == NULL)
  570:     {
  571:       BUS_SET_OOM (error);
  572:       goto failed;
  573:     }
  574: 
  575:   parser = bus_config_load (config_file, TRUE, NULL, error);
  576:   if (parser == NULL)
  577:     {
  578:       _DBUS_ASSERT_ERROR_IS_SET (error);
  579:       goto failed;
  580:     }
  581:   
  582:   if (!process_config_first_time_only (context, parser, error))
  583:     {
  584:       _DBUS_ASSERT_ERROR_IS_SET (error);
  585:       goto failed;
  586:     }
  587:   if (!process_config_every_time (context, parser, FALSE, error))
  588:     {
  589:       _DBUS_ASSERT_ERROR_IS_SET (error);
  590:       goto failed;
  591:     }
  592:   
  593:   /* we need another ref of the server data slot for the context
  594:    * to own
  595:    */
  596:   if (!dbus_server_allocate_data_slot (&server_data_slot))
  597:     _dbus_assert_not_reached ("second ref of server data slot failed");
  598: 
  599:   context->user_database = _dbus_user_database_new ();
  600:   if (context->user_database == NULL)
  601:     {
  602:       BUS_SET_OOM (error);
  603:       goto failed;
  604:     }
  605:   
  606:   /* Note that we don't know whether the print_addr_fd is
  607:    * one of the sockets we're using to listen on, or some
  608:    * other random thing. But I think the answer is "don't do
  609:    * that then"
  610:    */
  611:   if (print_addr_fd >= 0)
  612:     {
  613:       DBusString addr;
  614:       const char *a = bus_context_get_address (context);
  615:       int bytes;
  616:       
  617:       _dbus_assert (a != NULL);
  618:       if (!_dbus_string_init (&addr))
  619:         {
  620:           BUS_SET_OOM (error);
  621:           goto failed;
  622:         }
  623:       
  624:       if (!_dbus_string_append (&addr, a) ||
  625:           !_dbus_string_append (&addr, "\n"))
  626:         {
  627:           _dbus_string_free (&addr);
  628:           BUS_SET_OOM (error);
  629:           goto failed;
  630:         }
  631: 
  632:       bytes = _dbus_string_get_length (&addr);
  633:       if (_dbus_write_socket (print_addr_fd, &addr, 0, bytes) != bytes)
  634:         {
  635:           dbus_set_error (error, DBUS_ERROR_FAILED,
  636:                           "Printing message bus address: %s\n",
  637:                           _dbus_strerror (errno));
  638:           _dbus_string_free (&addr);
  639:           goto failed;
  640:         }
  641: 
  642:       if (print_addr_fd > 2)
  643:         _dbus_close_socket (print_addr_fd, NULL);
  644: 
  645:       _dbus_string_free (&addr);
  646:     }
  647:   
  648:   context->connections = bus_connections_new (context);
  649:   if (context->connections == NULL)
  650:     {
  651:       BUS_SET_OOM (error);
  652:       goto failed;
  653:     }
  654: 
  655:   context->matchmaker = bus_matchmaker_new ();
  656:   if (context->matchmaker == NULL)
  657:     {
  658:       BUS_SET_OOM (error);
  659:       goto failed;
  660:     }
  661: 
  662:   /* check user before we fork */
  663:   if (context->user != NULL)
  664:     {
  665:       DBusString u;
  666: 
  667:       _dbus_string_init_const (&u, context->user);
  668: