bus.c revision 3df260c07102745c5606c313af862558f105f83e
1/* -*- mode: C; c-file-style: "gnu" -*- */
2/* bus.c  message bus context object
3 *
4 * Copyright (C) 2003 Red Hat, Inc.
5 *
6 * Licensed under the Academic Free License version 1.2
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 <dbus/dbus-list.h>
32#include <dbus/dbus-hash.h>
33#include <dbus/dbus-internals.h>
34
35struct BusContext
36{
37  int refcount;
38  char *type;
39  char *address;
40  char *pidfile;
41  DBusLoop *loop;
42  DBusList *servers;
43  BusConnections *connections;
44  BusActivation *activation;
45  BusRegistry *registry;
46  BusPolicy *policy;
47  DBusUserDatabase *user_database;
48  int activation_timeout;        /**< How long to wait for an activation to time out */
49  int auth_timeout;              /**< How long to wait for an authentication to time out */
50  int max_completed_connections;    /**< Max number of authorized connections */
51  int max_incomplete_connections;   /**< Max number of incomplete connections */
52  int max_connections_per_user;     /**< Max number of connections auth'd as same user */
53};
54
55static int server_data_slot = -1;
56static int server_data_slot_refcount = 0;
57
58typedef struct
59{
60  BusContext *context;
61} BusServerData;
62
63#define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot))
64
65static dbus_bool_t
66server_data_slot_ref (void)
67{
68  if (server_data_slot < 0)
69    {
70      server_data_slot = dbus_server_allocate_data_slot ();
71
72      if (server_data_slot < 0)
73        return FALSE;
74
75      _dbus_assert (server_data_slot_refcount == 0);
76    }
77
78  server_data_slot_refcount += 1;
79
80  return TRUE;
81}
82
83static void
84server_data_slot_unref (void)
85{
86  _dbus_assert (server_data_slot_refcount > 0);
87
88  server_data_slot_refcount -= 1;
89
90  if (server_data_slot_refcount == 0)
91    {
92      dbus_server_free_data_slot (server_data_slot);
93      server_data_slot = -1;
94    }
95}
96
97static BusContext*
98server_get_context (DBusServer *server)
99{
100  BusContext *context;
101  BusServerData *bd;
102
103  if (!server_data_slot_ref ())
104    return NULL;
105
106  bd = BUS_SERVER_DATA (server);
107  if (bd == NULL)
108    {
109      server_data_slot_unref ();
110      return NULL;
111    }
112
113  context = bd->context;
114
115  server_data_slot_unref ();
116
117  return context;
118}
119
120static dbus_bool_t
121server_watch_callback (DBusWatch     *watch,
122                       unsigned int   condition,
123                       void          *data)
124{
125  /* FIXME this can be done in dbus-mainloop.c
126   * if the code in activation.c for the babysitter
127   * watch handler is fixed.
128   */
129
130  return dbus_watch_handle (watch, condition);
131}
132
133static dbus_bool_t
134add_server_watch (DBusWatch  *watch,
135                  void       *data)
136{
137  DBusServer *server = data;
138  BusContext *context;
139
140  context = server_get_context (server);
141
142  return _dbus_loop_add_watch (context->loop,
143                               watch, server_watch_callback, server,
144                               NULL);
145}
146
147static void
148remove_server_watch (DBusWatch  *watch,
149                     void       *data)
150{
151  DBusServer *server = data;
152  BusContext *context;
153
154  context = server_get_context (server);
155
156  _dbus_loop_remove_watch (context->loop,
157                           watch, server_watch_callback, server);
158}
159
160
161static void
162server_timeout_callback (DBusTimeout   *timeout,
163                         void          *data)
164{
165  /* can return FALSE on OOM but we just let it fire again later */
166  dbus_timeout_handle (timeout);
167}
168
169static dbus_bool_t
170add_server_timeout (DBusTimeout *timeout,
171                    void        *data)
172{
173  DBusServer *server = data;
174  BusContext *context;
175
176  context = server_get_context (server);
177
178  return _dbus_loop_add_timeout (context->loop,
179                                 timeout, server_timeout_callback, server, NULL);
180}
181
182static void
183remove_server_timeout (DBusTimeout *timeout,
184                       void        *data)
185{
186  DBusServer *server = data;
187  BusContext *context;
188
189  context = server_get_context (server);
190
191  _dbus_loop_remove_timeout (context->loop,
192                             timeout, server_timeout_callback, server);
193}
194
195static void
196new_connection_callback (DBusServer     *server,
197                         DBusConnection *new_connection,
198                         void           *data)
199{
200  BusContext *context = data;
201
202  if (!bus_connections_setup_connection (context->connections, new_connection))
203    {
204      _dbus_verbose ("No memory to setup new connection\n");
205
206      /* if we don't do this, it will get unref'd without
207       * being disconnected... kind of strange really
208       * that we have to do this, people won't get it right
209       * in general.
210       */
211      dbus_connection_disconnect (new_connection);
212    }
213
214  /* on OOM, we won't have ref'd the connection so it will die. */
215}
216
217static void
218free_server_data (void *data)
219{
220  BusServerData *bd = data;
221
222  dbus_free (bd);
223}
224
225static dbus_bool_t
226setup_server (BusContext *context,
227              DBusServer *server,
228              char      **auth_mechanisms,
229              DBusError  *error)
230{
231  BusServerData *bd;
232
233  bd = dbus_new0 (BusServerData, 1);
234  if (!dbus_server_set_data (server,
235                             server_data_slot,
236                             bd, free_server_data))
237    {
238      dbus_free (bd);
239      BUS_SET_OOM (error);
240      return FALSE;
241    }
242
243  bd->context = context;
244
245  if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
246    {
247      BUS_SET_OOM (error);
248      return FALSE;
249    }
250
251  dbus_server_set_new_connection_function (server,
252                                           new_connection_callback,
253                                           context, NULL);
254
255  if (!dbus_server_set_watch_functions (server,
256                                        add_server_watch,
257                                        remove_server_watch,
258                                        NULL,
259                                        server,
260                                        NULL))
261    {
262      BUS_SET_OOM (error);
263      return FALSE;
264    }
265
266  if (!dbus_server_set_timeout_functions (server,
267                                          add_server_timeout,
268                                          remove_server_timeout,
269                                          NULL,
270                                          server, NULL))
271    {
272      BUS_SET_OOM (error);
273      return FALSE;
274    }
275
276  return TRUE;
277}
278
279BusContext*
280bus_context_new (const DBusString *config_file,
281                 int               print_addr_fd,
282                 DBusError        *error)
283{
284  BusContext *context;
285  DBusList *link;
286  DBusList **addresses;
287  BusConfigParser *parser;
288  DBusString full_address;
289  const char *user, *pidfile;
290  char **auth_mechanisms;
291  DBusList **auth_mechanisms_list;
292  int len;
293
294  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
295
296  if (!_dbus_string_init (&full_address))
297    {
298      BUS_SET_OOM (error);
299      return NULL;
300    }
301
302  if (!server_data_slot_ref ())
303    {
304      BUS_SET_OOM (error);
305      _dbus_string_free (&full_address);
306      return NULL;
307    }
308
309  parser = NULL;
310  context = NULL;
311  auth_mechanisms = NULL;
312
313  parser = bus_config_load (config_file, error);
314  if (parser == NULL)
315    goto failed;
316
317  /* Check for an existing pid file. Of course this is a race;
318   * we'd have to use fcntl() locks on the pid file to
319   * avoid that. But we want to check for the pid file
320   * before overwriting any existing sockets, etc.
321   */
322  pidfile = bus_config_parser_get_pidfile (parser);
323  if (pidfile != NULL)
324    {
325      DBusString u;
326      DBusStat stbuf;
327      DBusError tmp_error;
328
329      dbus_error_init (&tmp_error);
330      _dbus_string_init_const (&u, pidfile);
331
332      if (_dbus_stat (&u, &stbuf, &tmp_error))
333	{
334	  dbus_set_error (error, DBUS_ERROR_FAILED,
335			  "The pid file \"%s\" exists, if the message bus is not running, remove this file",
336			  pidfile);
337	  dbus_error_free (&tmp_error);
338	  goto failed;
339	}
340    }
341
342  context = dbus_new0 (BusContext, 1);
343  if (context == NULL)
344    {
345      BUS_SET_OOM (error);
346      goto failed;
347    }
348
349  context->refcount = 1;
350
351  /* we need another ref of the server data slot for the context
352   * to own
353   */
354  if (!server_data_slot_ref ())
355    _dbus_assert_not_reached ("second ref of server data slot failed");
356
357#ifdef DBUS_BUILD_TESTS
358  context->activation_timeout = 6000;  /* 6 seconds */
359#else
360  context->activation_timeout = 15000; /* 15 seconds */
361#endif
362
363  /* Making this long risks making a DOS attack easier, but too short
364   * and legitimate auth will fail.  If interactive auth (ask user for
365   * password) is allowed, then potentially it has to be quite long.
366   * Ultimately it needs to come from the configuration file.
367   */
368  context->auth_timeout = 3000; /* 3 seconds */
369
370  context->max_incomplete_connections = 32;
371  context->max_connections_per_user = 128;
372
373  /* Note that max_completed_connections / max_connections_per_user
374   * is the number of users that would have to work together to
375   * DOS all the other users.
376   */
377  context->max_completed_connections = 1024;
378
379  context->user_database = _dbus_user_database_new ();
380  if (context->user_database == NULL)
381    {
382      BUS_SET_OOM (error);
383      goto failed;
384    }
385
386  context->loop = _dbus_loop_new ();
387  if (context->loop == NULL)
388    {
389      BUS_SET_OOM (error);
390      goto failed;
391    }
392
393  /* Build an array of auth mechanisms */
394
395  auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
396  len = _dbus_list_get_length (auth_mechanisms_list);
397
398  if (len > 0)
399    {
400      int i;
401
402      auth_mechanisms = dbus_new0 (char*, len + 1);
403      if (auth_mechanisms == NULL)
404        goto failed;
405
406      i = 0;
407      link = _dbus_list_get_first_link (auth_mechanisms_list);
408      while (link != NULL)
409        {
410          auth_mechanisms[i] = _dbus_strdup (link->data);
411          if (auth_mechanisms[i] == NULL)
412            goto failed;
413          link = _dbus_list_get_next_link (auth_mechanisms_list, link);
414        }
415    }
416  else
417    {
418      auth_mechanisms = NULL;
419    }
420
421  /* Listen on our addresses */
422
423  addresses = bus_config_parser_get_addresses (parser);
424
425  link = _dbus_list_get_first_link (addresses);
426  while (link != NULL)
427    {
428      DBusServer *server;
429
430      server = dbus_server_listen (link->data, error);
431      if (server == NULL)
432        goto failed;
433      else if (!setup_server (context, server, auth_mechanisms, error))
434        goto failed;
435
436      if (!_dbus_list_append (&context->servers, server))
437        {
438          BUS_SET_OOM (error);
439          goto failed;
440        }
441
442      link = _dbus_list_get_next_link (addresses, link);
443    }
444
445  /* note that type may be NULL */
446  context->type = _dbus_strdup (bus_config_parser_get_type (parser));
447
448  /* We have to build the address backward, so that
449   * <listen> later in the config file have priority
450   */
451  link = _dbus_list_get_last_link (&context->servers);
452  while (link != NULL)
453    {
454      char *addr;
455
456      addr = dbus_server_get_address (link->data);
457      if (addr == NULL)
458        {
459          BUS_SET_OOM (error);
460          goto failed;
461        }
462
463      if (_dbus_string_get_length (&full_address) > 0)
464        {
465          if (!_dbus_string_append (&full_address, ";"))
466            {
467              BUS_SET_OOM (error);
468              goto failed;
469            }
470        }
471
472      if (!_dbus_string_append (&full_address, addr))
473        {
474          BUS_SET_OOM (error);
475          goto failed;
476        }
477
478      dbus_free (addr);
479
480      link = _dbus_list_get_prev_link (&context->servers, link);
481    }
482
483  if (!_dbus_string_copy_data (&full_address, &context->address))
484    {
485      BUS_SET_OOM (error);
486      goto failed;
487    }
488
489  /* Note that we don't know whether the print_addr_fd is
490   * one of the sockets we're using to listen on, or some
491   * other random thing. But I think the answer is "don't do
492   * that then"
493   */
494  if (print_addr_fd >= 0)
495    {
496      DBusString addr;
497      const char *a = bus_context_get_address (context);
498      int bytes;
499
500      _dbus_assert (a != NULL);
501      if (!_dbus_string_init (&addr))
502        {
503          BUS_SET_OOM (error);
504          goto failed;
505        }
506
507      if (!_dbus_string_append (&addr, a) ||
508          !_dbus_string_append (&addr, "\n"))
509        {
510          _dbus_string_free (&addr);
511          BUS_SET_OOM (error);
512          goto failed;
513        }
514
515      bytes = _dbus_string_get_length (&addr);
516      if (_dbus_write (print_addr_fd, &addr, 0, bytes) != bytes)
517        {
518          dbus_set_error (error, DBUS_ERROR_FAILED,
519                          "Printing message bus address: %s\n",
520                          _dbus_strerror (errno));
521          _dbus_string_free (&addr);
522          goto failed;
523        }
524
525      if (print_addr_fd > 2)
526        _dbus_close (print_addr_fd, NULL);
527
528      _dbus_string_free (&addr);
529    }
530
531  /* Create activation subsystem */
532
533  context->activation = bus_activation_new (context, &full_address,
534                                            bus_config_parser_get_service_dirs (parser),
535                                            error);
536  if (context->activation == NULL)
537    {
538      _DBUS_ASSERT_ERROR_IS_SET (error);
539      goto failed;
540    }
541
542  context->connections = bus_connections_new (context);
543  if (context->connections == NULL)
544    {
545      BUS_SET_OOM (error);
546      goto failed;
547    }
548
549  context->registry = bus_registry_new (context);
550  if (context->registry == NULL)
551    {
552      BUS_SET_OOM (error);
553      goto failed;
554    }
555
556  context->policy = bus_config_parser_steal_policy (parser);
557  _dbus_assert (context->policy != NULL);
558
559  /* Now become a daemon if appropriate */
560  if (bus_config_parser_get_fork (parser))
561    {
562      DBusString u;
563
564      if (pidfile)
565        _dbus_string_init_const (&u, pidfile);
566
567      if (!_dbus_become_daemon (pidfile ? &u : NULL, error))
568        goto failed;
569    }
570  else
571    {
572      /* Need to write PID file for ourselves, not for the child process */
573      if (pidfile != NULL)
574        {
575          DBusString u;
576
577          _dbus_string_init_const (&u, pidfile);
578
579          if (!_dbus_write_pid_file (&u, _dbus_getpid (), error))
580            goto failed;
581        }
582    }
583
584  /* keep around the pid filename so we can delete it later */
585  context->pidfile = _dbus_strdup (pidfile);
586
587  /* Here we change our credentials if required,
588   * as soon as we've set up our sockets and pidfile
589   */
590  user = bus_config_parser_get_user (parser);
591  if (user != NULL)
592    {
593      DBusCredentials creds;
594      DBusString u;
595
596      _dbus_string_init_const (&u, user);
597
598      if (!_dbus_credentials_from_username (&u, &creds) ||
599          creds.uid < 0 ||
600          creds.gid < 0)
601        {
602          dbus_set_error (error, DBUS_ERROR_FAILED,
603                          "Could not get UID and GID for username \"%s\"",
604                          user);
605          goto failed;
606        }
607
608      if (!_dbus_change_identity (creds.uid, creds.gid, error))
609        goto failed;
610    }
611
612  bus_config_parser_unref (parser);
613  _dbus_string_free (&full_address);
614  dbus_free_string_array (auth_mechanisms);
615  server_data_slot_unref ();
616
617  return context;
618
619 failed:
620  if (parser != NULL)
621    bus_config_parser_unref (parser);
622
623  if (context != NULL)
624    bus_context_unref (context);
625
626  _dbus_string_free (&full_address);
627  dbus_free_string_array (auth_mechanisms);
628
629  server_data_slot_unref ();
630
631  return NULL;
632}
633
634static void
635shutdown_server (BusContext *context,
636                 DBusServer *server)
637{
638  if (server == NULL ||
639      !dbus_server_get_is_connected (server))
640    return;
641
642  if (!dbus_server_set_watch_functions (server,
643                                        NULL, NULL, NULL,
644                                        context,
645                                        NULL))
646    _dbus_assert_not_reached ("setting watch functions to NULL failed");
647
648  if (!dbus_server_set_timeout_functions (server,
649                                          NULL, NULL, NULL,
650                                          context,
651                                          NULL))
652    _dbus_assert_not_reached ("setting timeout functions to NULL failed");
653
654  dbus_server_disconnect (server);
655}
656
657void
658bus_context_shutdown (BusContext  *context)
659{
660  DBusList *link;
661
662  link = _dbus_list_get_first_link (&context->servers);
663  while (link != NULL)
664    {
665      shutdown_server (context, link->data);
666
667      link = _dbus_list_get_next_link (&context->servers, link);
668    }
669}
670
671void
672bus_context_ref (BusContext *context)
673{
674  _dbus_assert (context->refcount > 0);
675  context->refcount += 1;
676}
677
678void
679bus_context_unref (BusContext *context)
680{
681  _dbus_assert (context->refcount > 0);
682  context->refcount -= 1;
683
684  if (context->refcount == 0)
685    {
686      DBusList *link;
687
688      _dbus_verbose ("Finalizing bus context %p\n", context);
689
690      bus_context_shutdown (context);
691
692      if (context->connections)
693        {
694          bus_connections_unref (context->connections);
695          context->connections = NULL;
696        }
697
698      if (context->registry)
699        {
700          bus_registry_unref (context->registry);
701          context->registry = NULL;
702        }
703
704      if (context->activation)
705        {
706          bus_activation_unref (context->activation);
707          context->activation = NULL;
708        }
709
710      link = _dbus_list_get_first_link (&context->servers);
711      while (link != NULL)
712        {
713          dbus_server_unref (link->data);
714
715          link = _dbus_list_get_next_link (&context->servers, link);
716        }
717      _dbus_list_clear (&context->servers);
718
719      if (context->policy)
720        {
721          bus_policy_unref (context->policy);
722          context->policy = NULL;
723        }
724
725      if (context->loop)
726        {
727          _dbus_loop_unref (context->loop);
728          context->loop = NULL;
729        }
730
731      dbus_free (context->type);
732      dbus_free (context->address);
733
734      if (context->pidfile)
735	{
736          DBusString u;
737          _dbus_string_init_const (&u, context->pidfile);
738
739          /* Deliberately ignore errors here, since there's not much
740	   * we can do about it, and we're exiting anyways.
741	   */
742	  _dbus_delete_file (&u, NULL);
743
744          dbus_free (context->pidfile);
745	}
746
747      _dbus_user_database_unref (context->user_database);
748
749      dbus_free (context);
750
751      server_data_slot_unref ();
752    }
753}
754
755/* type may be NULL */
756const char*
757bus_context_get_type (BusContext *context)
758{
759  return context->type;
760}
761
762const char*
763bus_context_get_address (BusContext *context)
764{
765  return context->address;
766}
767
768BusRegistry*
769bus_context_get_registry (BusContext  *context)
770{
771  return context->registry;
772}
773
774BusConnections*
775bus_context_get_connections (BusContext  *context)
776{
777  return context->connections;
778}
779
780BusActivation*
781bus_context_get_activation (BusContext  *context)
782{
783  return context->activation;
784}
785
786DBusLoop*
787bus_context_get_loop (BusContext *context)
788{
789  return context->loop;
790}
791
792DBusUserDatabase*
793bus_context_get_user_database (BusContext *context)
794{
795  return context->user_database;
796}
797
798dbus_bool_t
799bus_context_allow_user (BusContext   *context,
800                        unsigned long uid)
801{
802  return bus_policy_allow_user (context->policy,
803                                context->user_database,
804                                uid);
805}
806
807BusClientPolicy*
808bus_context_create_client_policy (BusContext      *context,
809                                  DBusConnection  *connection)
810{
811  return bus_policy_create_client_policy (context->policy, connection);
812}
813
814int
815bus_context_get_activation_timeout (BusContext *context)
816{
817
818  return context->activation_timeout;
819}
820
821dbus_bool_t
822bus_context_check_security_policy (BusContext     *context,
823                                   DBusConnection *sender,
824                                   DBusConnection *recipient,
825                                   DBusMessage    *message,
826                                   DBusError      *error)
827{
828  BusClientPolicy *sender_policy;
829  BusClientPolicy *recipient_policy;
830
831  /* NULL sender/receiver means the bus driver */
832
833  if (sender != NULL)
834    {
835      _dbus_assert (dbus_connection_get_is_authenticated (sender));
836      sender_policy = bus_connection_get_policy (sender);
837    }
838  else
839    sender_policy = NULL;
840
841  if (recipient != NULL)
842    {
843      _dbus_assert (dbus_connection_get_is_authenticated (recipient));
844      recipient_policy = bus_connection_get_policy (recipient);
845    }
846  else
847    recipient_policy = NULL;
848
849  if (sender_policy &&
850      !bus_client_policy_check_can_send (sender_policy,
851                                         context->registry, recipient,
852                                         message))
853    {
854      const char *dest = dbus_message_get_service (message);
855      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
856                      "A security policy in place prevents this sender "
857                      "from sending this message to this recipient, "
858                      "see message bus configuration file (rejected message "
859                      "had name \"%s\" destination \"%s\")",
860                      dbus_message_get_name (message),
861                      dest ? dest : DBUS_SERVICE_DBUS);
862      return FALSE;
863    }
864
865  if (recipient_policy &&
866      !bus_client_policy_check_can_receive (recipient_policy,
867                                            context->registry, sender,
868                                            message))
869    {
870      const char *dest = dbus_message_get_service (message);
871      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
872                      "A security policy in place prevents this recipient "
873                      "from receiving this message from this sender, "
874                      "see message bus configuration file (rejected message "
875                      "had name \"%s\" destination \"%s\")",
876                      dbus_message_get_name (message),
877                      dest ? dest : DBUS_SERVICE_DBUS);
878      return FALSE;
879    }
880
881  return TRUE;
882}
883