bus.c 30.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/* -*- mode: C; c-file-style: "gnu" -*- */
/* bus.c  message bus context object
 *
 * Copyright (C) 2003 Red Hat, Inc.
 *
 * Licensed under the Academic Free License version 1.2
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "bus.h"
#include "activation.h"
#include "connection.h"
#include "services.h"
#include "utils.h"
29
#include "policy.h"
30
#include "config-parser.h"
31
#include "signals.h"
32 33
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
34 35 36 37 38
#include <dbus/dbus-internals.h>

struct BusContext
{
  int refcount;
39
  char *type;
40
  char *address;
41
  char *pidfile;
42
  DBusLoop *loop;
43
  DBusList *servers;
44 45 46
  BusConnections *connections;
  BusActivation *activation;
  BusRegistry *registry;
47
  BusPolicy *policy;
48
  BusMatchmaker *matchmaker;
49
  DBusUserDatabase *user_database;
50
  BusLimits limits;
51 52
};

53
static dbus_int32_t server_data_slot = -1;
54 55 56 57 58 59 60 61 62 63 64 65 66 67

typedef struct
{
  BusContext *context;
} BusServerData;

#define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot))

static BusContext*
server_get_context (DBusServer *server)
{
  BusContext *context;
  BusServerData *bd;
  
68
  if (!dbus_server_allocate_data_slot (&server_data_slot))
69 70 71 72
    return NULL;

  bd = BUS_SERVER_DATA (server);
  if (bd == NULL)
73
    {
74
      dbus_server_free_data_slot (&server_data_slot);
75 76
      return NULL;
    }
77 78 79

  context = bd->context;

80
  dbus_server_free_data_slot (&server_data_slot);
81 82 83 84

  return context;
}

85
static dbus_bool_t
86 87 88 89
server_watch_callback (DBusWatch     *watch,
                       unsigned int   condition,
                       void          *data)
{
90 91 92 93 94 95
  /* FIXME this can be done in dbus-mainloop.c
   * if the code in activation.c for the babysitter
   * watch handler is fixed.
   */
  
  return dbus_watch_handle (watch, condition);
96 97
}

98
static dbus_bool_t
99
add_server_watch (DBusWatch  *watch,
100
                  void       *data)
101
{
102 103 104 105 106
  DBusServer *server = data;
  BusContext *context;
  
  context = server_get_context (server);
  
107 108 109
  return _dbus_loop_add_watch (context->loop,
                               watch, server_watch_callback, server,
                               NULL);
110 111 112 113
}

static void
remove_server_watch (DBusWatch  *watch,
114
                     void       *data)
115
{
116 117 118 119 120
  DBusServer *server = data;
  BusContext *context;
  
  context = server_get_context (server);
  
121 122
  _dbus_loop_remove_watch (context->loop,
                           watch, server_watch_callback, server);
123 124
}

125

126 127 128 129
static void
server_timeout_callback (DBusTimeout   *timeout,
                         void          *data)
{
130
  /* can return FALSE on OOM but we just let it fire again later */
131 132 133 134 135
  dbus_timeout_handle (timeout);
}

static dbus_bool_t
add_server_timeout (DBusTimeout *timeout,
136
                    void        *data)
137
{
138 139 140 141 142
  DBusServer *server = data;
  BusContext *context;
  
  context = server_get_context (server);

143 144
  return _dbus_loop_add_timeout (context->loop,
                                 timeout, server_timeout_callback, server, NULL);
145 146 147 148
}

static void
remove_server_timeout (DBusTimeout *timeout,
149
                       void        *data)
150
{
151 152 153 154 155
  DBusServer *server = data;
  BusContext *context;
  
  context = server_get_context (server);
  
156 157
  _dbus_loop_remove_timeout (context->loop,
                             timeout, server_timeout_callback, server);
158 159
}

160 161 162 163 164 165 166 167
static void
new_connection_callback (DBusServer     *server,
                         DBusConnection *new_connection,
                         void           *data)
{
  BusContext *context = data;
  
  if (!bus_connections_setup_connection (context->connections, new_connection))
168 169
    {
      _dbus_verbose ("No memory to setup new connection\n");
170

171 172 173 174 175 176 177
      /* if we don't do this, it will get unref'd without
       * being disconnected... kind of strange really
       * that we have to do this, people won't get it right
       * in general.
       */
      dbus_connection_disconnect (new_connection);
    }
178 179

  dbus_connection_set_max_received_size (new_connection,
180
                                         context->limits.max_incoming_bytes);
181 182

  dbus_connection_set_max_message_size (new_connection,
183
                                        context->limits.max_message_size);
184
  
185
  /* on OOM, we won't have ref'd the connection so it will die. */
186 187
}

188 189 190 191 192 193 194 195
static void
free_server_data (void *data)
{
  BusServerData *bd = data;  
  
  dbus_free (bd);
}

196 197 198
static dbus_bool_t
setup_server (BusContext *context,
              DBusServer *server,
199
              char      **auth_mechanisms,
200
              DBusError  *error)
201
{
202
  BusServerData *bd;
203 204 205 206 207 208 209 210 211 212 213 214

  bd = dbus_new0 (BusServerData, 1);
  if (!dbus_server_set_data (server,
                             server_data_slot,
                             bd, free_server_data))
    {
      dbus_free (bd);
      BUS_SET_OOM (error);
      return FALSE;
    }

  bd->context = context;
215
  
216 217 218 219 220 221
  if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
    {
      BUS_SET_OOM (error);
      return FALSE;
    }
  
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
  dbus_server_set_new_connection_function (server,
                                           new_connection_callback,
                                           context, NULL);
  
  if (!dbus_server_set_watch_functions (server,
                                        add_server_watch,
                                        remove_server_watch,
                                        NULL,
                                        server,
                                        NULL))
    {
      BUS_SET_OOM (error);
      return FALSE;
    }

  if (!dbus_server_set_timeout_functions (server,
                                          add_server_timeout,
                                          remove_server_timeout,
                                          NULL,
                                          server, NULL))
    {
      BUS_SET_OOM (error);
      return FALSE;
    }
246
  
247 248 249
  return TRUE;
}

250
BusContext*
251
bus_context_new (const DBusString *config_file,
252
                 dbus_bool_t       force_fork,
253
                 int               print_addr_fd,
254
                 int               print_pid_fd,
255
                 DBusError        *error)
256 257
{
  BusContext *context;
258 259 260 261
  DBusList *link;
  DBusList **addresses;
  BusConfigParser *parser;
  DBusString full_address;
262
  const char *user, *pidfile;
263 264 265
  char **auth_mechanisms;
  DBusList **auth_mechanisms_list;
  int len;
266
  
267
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
268

269
  if (!_dbus_string_init (&full_address))
270 271 272 273
    {
      BUS_SET_OOM (error);
      return NULL;
    }
274

275
  if (!dbus_server_allocate_data_slot (&server_data_slot))
276 277 278 279 280 281
    {
      BUS_SET_OOM (error);
      _dbus_string_free (&full_address);
      return NULL;
    }
  
282 283
  parser = NULL;
  context = NULL;
284
  auth_mechanisms = NULL;
285
  
286
  parser = bus_config_load (config_file, TRUE, error);
287 288
  if (parser == NULL)
    goto failed;
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313

  /* Check for an existing pid file. Of course this is a race;
   * we'd have to use fcntl() locks on the pid file to
   * avoid that. But we want to check for the pid file
   * before overwriting any existing sockets, etc.
   */
  pidfile = bus_config_parser_get_pidfile (parser);
  if (pidfile != NULL)
    {
      DBusString u;
      DBusStat stbuf;
      DBusError tmp_error;
      
      dbus_error_init (&tmp_error);
      _dbus_string_init_const (&u, pidfile);
      
      if (_dbus_stat (&u, &stbuf, &tmp_error))
	{
	  dbus_set_error (error, DBUS_ERROR_FAILED,
			  "The pid file \"%s\" exists, if the message bus is not running, remove this file",
			  pidfile);
	  dbus_error_free (&tmp_error);
	  goto failed;
	}
    }
314 315 316 317 318
  
  context = dbus_new0 (BusContext, 1);
  if (context == NULL)
    {
      BUS_SET_OOM (error);
319
      goto failed;
320 321 322
    }
  
  context->refcount = 1;
323

324 325 326
  /* get our limits and timeout lengths */
  bus_config_parser_get_limits (parser, &context->limits);
  
327 328 329
  /* we need another ref of the server data slot for the context
   * to own
   */
330
  if (!dbus_server_allocate_data_slot (&server_data_slot))
331
    _dbus_assert_not_reached ("second ref of server data slot failed");
332
  
333 334 335 336 337 338
  context->user_database = _dbus_user_database_new ();
  if (context->user_database == NULL)
    {
      BUS_SET_OOM (error);
      goto failed;
    }
339
  
340
  context->loop = _dbus_loop_new ();
341 342 343 344 345 346
  if (context->loop == NULL)
    {
      BUS_SET_OOM (error);
      goto failed;
    }
  
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
  /* Build an array of auth mechanisms */
  
  auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
  len = _dbus_list_get_length (auth_mechanisms_list);

  if (len > 0)
    {
      int i;

      auth_mechanisms = dbus_new0 (char*, len + 1);
      if (auth_mechanisms == NULL)
        goto failed;
      
      i = 0;
      link = _dbus_list_get_first_link (auth_mechanisms_list);
      while (link != NULL)
        {
          auth_mechanisms[i] = _dbus_strdup (link->data);
          if (auth_mechanisms[i] == NULL)
            goto failed;
          link = _dbus_list_get_next_link (auth_mechanisms_list, link);
        }
    }
  else
    {
      auth_mechanisms = NULL;
    }

  /* Listen on our addresses */
376 377 378 379 380 381 382 383 384 385 386
  
  addresses = bus_config_parser_get_addresses (parser);  
  
  link = _dbus_list_get_first_link (addresses);
  while (link != NULL)
    {
      DBusServer *server;
      
      server = dbus_server_listen (link->data, error);
      if (server == NULL)
        goto failed;
387
      else if (!setup_server (context, server, auth_mechanisms, error))
388 389 390 391 392 393 394 395 396 397 398
        goto failed;

      if (!_dbus_list_append (&context->servers, server))
        {
          BUS_SET_OOM (error);
          goto failed;
        }          
      
      link = _dbus_list_get_next_link (addresses, link);
    }

399 400
  /* note that type may be NULL */
  context->type = _dbus_strdup (bus_config_parser_get_type (parser));
401
  
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
  /* We have to build the address backward, so that
   * <listen> later in the config file have priority
   */
  link = _dbus_list_get_last_link (&context->servers);
  while (link != NULL)
    {
      char *addr;
      
      addr = dbus_server_get_address (link->data);
      if (addr == NULL)
        {
          BUS_SET_OOM (error);
          goto failed;
        }

      if (_dbus_string_get_length (&full_address) > 0)
        {
          if (!_dbus_string_append (&full_address, ";"))
            {
              BUS_SET_OOM (error);
              goto failed;
            }
        }
425

426 427 428 429 430 431 432 433 434 435 436 437
      if (!_dbus_string_append (&full_address, addr))
        {
          BUS_SET_OOM (error);
          goto failed;
        }

      dbus_free (addr);

      link = _dbus_list_get_prev_link (&context->servers, link);
    }

  if (!_dbus_string_copy_data (&full_address, &context->address))
438 439 440 441
    {
      BUS_SET_OOM (error);
      goto failed;
    }
442

443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
  /* Note that we don't know whether the print_addr_fd is
   * one of the sockets we're using to listen on, or some
   * other random thing. But I think the answer is "don't do
   * that then"
   */
  if (print_addr_fd >= 0)
    {
      DBusString addr;
      const char *a = bus_context_get_address (context);
      int bytes;
      
      _dbus_assert (a != NULL);
      if (!_dbus_string_init (&addr))
        {
          BUS_SET_OOM (error);
          goto failed;
        }
      
      if (!_dbus_string_append (&addr, a) ||
          !_dbus_string_append (&addr, "\n"))
        {
          _dbus_string_free (&addr);
          BUS_SET_OOM (error);
          goto failed;
        }

      bytes = _dbus_string_get_length (&addr);
      if (_dbus_write (print_addr_fd, &addr, 0, bytes) != bytes)
        {
          dbus_set_error (error, DBUS_ERROR_FAILED,
                          "Printing message bus address: %s\n",
                          _dbus_strerror (errno));
          _dbus_string_free (&addr);
          goto failed;
        }

      if (print_addr_fd > 2)
        _dbus_close (print_addr_fd, NULL);

      _dbus_string_free (&addr);
    }
  
485
  /* Create activation subsystem */
486
  
487
  context->activation = bus_activation_new (context, &full_address,
488 489
                                            bus_config_parser_get_service_dirs (parser),
                                            error);
490 491 492 493 494 495 496 497 498 499 500 501 502
  if (context->activation == NULL)
    {
      _DBUS_ASSERT_ERROR_IS_SET (error);
      goto failed;
    }

  context->connections = bus_connections_new (context);
  if (context->connections == NULL)
    {
      BUS_SET_OOM (error);
      goto failed;
    }

503
  context->registry = bus_registry_new (context);
504 505 506 507 508
  if (context->registry == NULL)
    {
      BUS_SET_OOM (error);
      goto failed;
    }
509

510 511 512 513 514 515 516
  context->matchmaker = bus_matchmaker_new ();
  if (context->matchmaker == NULL)
    {
      BUS_SET_OOM (error);
      goto failed;
    }
  
517 518 519
  context->policy = bus_config_parser_steal_policy (parser);
  _dbus_assert (context->policy != NULL);
  
520
  /* Now become a daemon if appropriate */
521
  if (force_fork || bus_config_parser_get_fork (parser))
522
    {
523 524 525 526 527 528
      DBusString u;

      if (pidfile)
        _dbus_string_init_const (&u, pidfile);
      
      if (!_dbus_become_daemon (pidfile ? &u : NULL, error))
529 530
        goto failed;
    }
531 532 533 534 535 536 537 538 539 540 541 542 543
  else
    {
      /* Need to write PID file for ourselves, not for the child process */
      if (pidfile != NULL)
        {
          DBusString u;

          _dbus_string_init_const (&u, pidfile);
          
          if (!_dbus_write_pid_file (&u, _dbus_getpid (), error))
            goto failed;
        }
    }
544 545 546

  /* keep around the pid filename so we can delete it later */
  context->pidfile = _dbus_strdup (pidfile);
547

548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
  /* Write PID if requested */
  if (print_pid_fd >= 0)
    {
      DBusString pid;
      int bytes;

      if (!_dbus_string_init (&pid))
        {
          BUS_SET_OOM (error);
          goto failed;
        }
      
      if (!_dbus_string_append_int (&pid, _dbus_getpid ()) ||
          !_dbus_string_append (&pid, "\n"))
        {
          _dbus_string_free (&pid);
          BUS_SET_OOM (error);
          goto failed;
        }

      bytes = _dbus_string_get_length (&pid);
      if (_dbus_write (print_pid_fd, &pid, 0, bytes) != bytes)
        {
          dbus_set_error (error, DBUS_ERROR_FAILED,
                          "Printing message bus PID: %s\n",
                          _dbus_strerror (errno));
          _dbus_string_free (&pid);
          goto failed;
        }

      if (print_pid_fd > 2)
        _dbus_close (print_pid_fd, NULL);
      
      _dbus_string_free (&pid);
    }
  
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
  /* Here we change our credentials if required,
   * as soon as we've set up our sockets and pidfile
   */
  user = bus_config_parser_get_user (parser);
  if (user != NULL)
    {
      DBusCredentials creds;
      DBusString u;

      _dbus_string_init_const (&u, user);

      if (!_dbus_credentials_from_username (&u, &creds) ||
          creds.uid < 0 ||
          creds.gid < 0)
        {
          dbus_set_error (error, DBUS_ERROR_FAILED,
                          "Could not get UID and GID for username \"%s\"",
                          user);
          goto failed;
        }
      
      if (!_dbus_change_identity (creds.uid, creds.gid, error))
        goto failed;
    }
608
  
609 610
  bus_config_parser_unref (parser);
  _dbus_string_free (&full_address);
611
  dbus_free_string_array (auth_mechanisms);
612
  dbus_server_free_data_slot (&server_data_slot);
613 614 615
  
  return context;
  
616
 failed:  
617 618 619 620 621 622 623
  if (parser != NULL)
    bus_config_parser_unref (parser);

  if (context != NULL)
    bus_context_unref (context);

  _dbus_string_free (&full_address);
624
  dbus_free_string_array (auth_mechanisms);
625

626
  dbus_server_free_data_slot (&server_data_slot);
627
  
628 629 630
  return NULL;
}

631 632 633
static void
shutdown_server (BusContext *context,
                 DBusServer *server)
634
{
635 636
  if (server == NULL ||
      !dbus_server_get_is_connected (server))
637 638
    return;
  
639
  if (!dbus_server_set_watch_functions (server,
640
                                        NULL, NULL, NULL,
641 642 643 644
                                        context,
                                        NULL))
    _dbus_assert_not_reached ("setting watch functions to NULL failed");
  
645
  if (!dbus_server_set_timeout_functions (server,
646
                                          NULL, NULL, NULL,
647 648 649 650
                                          context,
                                          NULL))
    _dbus_assert_not_reached ("setting timeout functions to NULL failed");
  
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
  dbus_server_disconnect (server);
}

void
bus_context_shutdown (BusContext  *context)
{
  DBusList *link;

  link = _dbus_list_get_first_link (&context->servers);
  while (link != NULL)
    {
      shutdown_server (context, link->data);

      link = _dbus_list_get_next_link (&context->servers, link);
    }
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
}

void
bus_context_ref (BusContext *context)
{
  _dbus_assert (context->refcount > 0);
  context->refcount += 1;
}

void
bus_context_unref (BusContext *context)
{
  _dbus_assert (context->refcount > 0);
  context->refcount -= 1;

  if (context->refcount == 0)
    {
683 684
      DBusList *link;
      
685 686
      _dbus_verbose ("Finalizing bus context %p\n", context);
      
687
      bus_context_shutdown (context);
688 689 690 691 692 693

      if (context->connections)
        {
          bus_connections_unref (context->connections);
          context->connections = NULL;
        }
694
      
695
      if (context->registry)
696 697 698 699 700
        {
          bus_registry_unref (context->registry);
          context->registry = NULL;
        }
      
701
      if (context->activation)
702 703 704 705
        {
          bus_activation_unref (context->activation);
          context->activation = NULL;
        }
706 707 708

      link = _dbus_list_get_first_link (&context->servers);
      while (link != NULL)
709
        {
710 711 712
          dbus_server_unref (link->data);
          
          link = _dbus_list_get_next_link (&context->servers, link);
713
        }
714
      _dbus_list_clear (&context->servers);
715

716
      if (context->policy)
717
        {
718 719
          bus_policy_unref (context->policy);
          context->policy = NULL;
720
        }
721
      
722 723
      if (context->loop)
        {
724
          _dbus_loop_unref (context->loop);
725 726
          context->loop = NULL;
        }
727 728 729 730 731 732

      if (context->matchmaker)
        {
          bus_matchmaker_unref (context->matchmaker);
          context->matchmaker = NULL;
        }
733
      
734
      dbus_free (context->type);
735
      dbus_free (context->address);
736 737 738 739 740 741 742 743 744 745 746 747 748 749

      if (context->pidfile)
	{
          DBusString u;
          _dbus_string_init_const (&u, context->pidfile);

          /* Deliberately ignore errors here, since there's not much
	   * we can do about it, and we're exiting anyways.
	   */
	  _dbus_delete_file (&u, NULL);

          dbus_free (context->pidfile); 
	}

750 751
      _dbus_user_database_unref (context->user_database);
      
752
      dbus_free (context);
753

754
      dbus_server_free_data_slot (&server_data_slot);
755 756 757
    }
}

758 759 760 761 762 763 764
/* type may be NULL */
const char*
bus_context_get_type (BusContext *context)
{
  return context->type;
}

765 766 767 768 769 770
const char*
bus_context_get_address (BusContext *context)
{
  return context->address;
}

771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
BusRegistry*
bus_context_get_registry (BusContext  *context)
{
  return context->registry;
}

BusConnections*
bus_context_get_connections (BusContext  *context)
{
  return context->connections;
}

BusActivation*
bus_context_get_activation (BusContext  *context)
{
  return context->activation;
}
788

789 790 791 792 793 794
BusMatchmaker*
bus_context_get_matchmaker (BusContext  *context)
{
  return context->matchmaker;
}

795
DBusLoop*
796 797 798 799 800
bus_context_get_loop (BusContext *context)
{
  return context->loop;
}

801 802 803 804 805 806
DBusUserDatabase*
bus_context_get_user_database (BusContext *context)
{
  return context->user_database;
}

807 808 809 810
dbus_bool_t
bus_context_allow_user (BusContext   *context,
                        unsigned long uid)
{
811 812 813
  return bus_policy_allow_user (context->policy,
                                context->user_database,
                                uid);
814 815
}

816 817
BusClientPolicy*
bus_context_create_client_policy (BusContext      *context,
818 819
                                  DBusConnection  *connection,
                                  DBusError       *error)
820
{
821 822 823
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  return bus_policy_create_client_policy (context->policy, connection,
                                          error);
824
}
825 826 827 828 829

int
bus_context_get_activation_timeout (BusContext *context)
{
  
830
  return context->limits.activation_timeout;
831
}
832

833 834 835
int
bus_context_get_auth_timeout (BusContext *context)
{
836
  return context->limits.auth_timeout;
837 838 839 840 841
}

int
bus_context_get_max_completed_connections (BusContext *context)
{
842
  return context->limits.max_completed_connections;
843 844 845 846 847
}

int
bus_context_get_max_incomplete_connections (BusContext *context)
{
848
  return context->limits.max_incomplete_connections;
849 850 851 852 853
}

int
bus_context_get_max_connections_per_user (BusContext *context)
{
854
  return context->limits.max_connections_per_user;
855 856
}

857 858 859 860 861 862 863 864 865 866 867 868
int
bus_context_get_max_pending_activations (BusContext *context)
{
  return context->limits.max_pending_activations;
}

int
bus_context_get_max_services_per_connection (BusContext *context)
{
  return context->limits.max_services_per_connection;
}

869 870 871 872 873 874
int
bus_context_get_max_match_rules_per_connection (BusContext *context)
{
  return context->limits.max_match_rules_per_connection;
}

875 876 877 878 879 880 881 882 883 884 885 886
int
bus_context_get_max_replies_per_connection (BusContext *context)
{
  return context->limits.max_replies_per_connection;
}

int
bus_context_get_reply_timeout (BusContext *context)
{
  return context->limits.reply_timeout;
}

887 888 889 890 891 892 893 894 895 896 897 898 899
/*
 * addressed_recipient is the recipient specified in the message.
 *
 * proposed_recipient is the recipient we're considering sending
 * to right this second, and may be an eavesdropper.
 *
 * sender is the sender of the message.
 *
 * NULL for proposed_recipient or sender definitely means the bus driver.
 *
 * NULL for addressed_recipient may mean the bus driver, or may mean
 * no destination was specified in the message (e.g. a signal).
 */
900 901
dbus_bool_t
bus_context_check_security_policy (BusContext     *context,
902
                                   BusTransaction *transaction,
903
                                   DBusConnection *sender,
904 905
                                   DBusConnection *addressed_recipient,
                                   DBusConnection *proposed_recipient,
906 907 908 909 910
                                   DBusMessage    *message,
                                   DBusError      *error)
{
  BusClientPolicy *sender_policy;
  BusClientPolicy *recipient_policy;
911 912 913 914 915 916 917 918 919 920
  int type;
  
  type = dbus_message_get_type (message);
  
  /* dispatch.c was supposed to ensure these invariants */
  _dbus_assert (dbus_message_get_destination (message) != NULL ||
                type == DBUS_MESSAGE_TYPE_SIGNAL);
  _dbus_assert (type == DBUS_MESSAGE_TYPE_SIGNAL ||
                addressed_recipient != NULL ||
                strcmp (dbus_message_get_destination (message), DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0);
921
  
922 923
  if (sender != NULL)
    {
924
      if (bus_connection_is_active (sender))
925
        {
926 927
          sender_policy = bus_connection_get_policy (sender);
          _dbus_assert (sender_policy != NULL);
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965

          switch (type)
            {
            case DBUS_MESSAGE_TYPE_METHOD_CALL:
            case DBUS_MESSAGE_TYPE_SIGNAL:

              /* Continue below to check security policy */
              break;
              
            case DBUS_MESSAGE_TYPE_METHOD_RETURN:
            case DBUS_MESSAGE_TYPE_ERROR:
              /* These are only allowed if the reply is listed
               * as pending, or the connection is eavesdropping.
               * The idea is to prohibit confusing/fake replies.
               * FIXME In principle a client that's asked to eavesdrop
               * specifically should probably get bogus replies
               * even to itself, but here we prohibit that.
               */
              
              if (proposed_recipient != NULL /* not to the bus driver */ &&
                  addressed_recipient == proposed_recipient /* not eavesdropping */ &&
                  !bus_connections_check_reply (bus_connection_get_connections (sender),
                                                transaction,
                                                sender, addressed_recipient, message,
                                                error))
                return FALSE;

              /* Continue below to check security policy, since reply was expected */
              break;
              
            default:
              _dbus_verbose ("security check disallowing message of unknown type\n");

              dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                              "Message bus will not accept messages of unknown type\n");
              
              return FALSE;
            }
966 967 968 969 970 971
        }
      else
        {
          /* Policy for inactive connections is that they can only send
           * the hello message to the bus driver
           */
972
          if (proposed_recipient == NULL &&
973 974 975
              dbus_message_is_method_call (message,
                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
                                           "Hello"))
976 977
            {
              _dbus_verbose ("security check allowing %s message\n",
978
                             "Hello");
979 980 981 982 983
              return TRUE;
            }
          else
            {
              _dbus_verbose ("security check disallowing non-%s message\n",
984
                             "Hello");
985 986 987

              dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                              "Client tried to send a message other than %s without being registered",
988
                              "Hello");
989 990 991
              
              return FALSE;
            }
992
        }
993 994 995 996
    }
  else
    sender_policy = NULL;

997 998 999
  _dbus_assert ((sender != NULL && sender_policy != NULL) ||
                (sender == NULL && sender_policy == NULL));
  
1000
  if (proposed_recipient != NULL)
1001
    {
1002 1003 1004 1005
      /* only the bus driver can send to an inactive recipient (as it
       * owns no services, so other apps can't address it). Inactive
       * recipients can receive any message.
       */
1006
      if (bus_connection_is_active (proposed_recipient))
1007
        {
1008
          recipient_policy = bus_connection_get_policy (proposed_recipient);
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
          _dbus_assert (recipient_policy != NULL);
        }
      else if (sender == NULL)
        {
          _dbus_verbose ("security check using NULL recipient policy for message from bus\n");
          recipient_policy = NULL;
        }
      else
        {
          _dbus_assert_not_reached ("a message was somehow sent to an inactive recipient from a source other than the message bus\n");
          recipient_policy = NULL;
1020
        }
1021 1022 1023
    }
  else
    recipient_policy = NULL;
1024
  
1025 1026 1027
  _dbus_assert ((proposed_recipient != NULL && recipient_policy != NULL) ||
                (proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) ||
                (proposed_recipient == NULL && recipient_policy == NULL));
1028 1029
  
  if (sender_policy &&
1030
      !bus_client_policy_check_can_send (sender_policy,
1031
                                         context->registry, proposed_recipient,
1032 1033
                                         message))
    {
1034
      const char *dest = dbus_message_get_destination (message);
1035 1036 1037 1038
      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                      "A security policy in place prevents this sender "
                      "from sending this message to this recipient, "
                      "see message bus configuration file (rejected message "
1039 1040 1041 1042 1043 1044 1045 1046
                      "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")",
                      dbus_message_get_interface (message) ?
                      dbus_message_get_interface (message) : "(unset)",
                      dbus_message_get_member (message) ?
                      dbus_message_get_member (message) : "(unset)",
                      dbus_message_get_error_name (message) ?
                      dbus_message_get_error_name (message) : "(unset)",
                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
1047
      _dbus_verbose ("security policy disallowing message due to sender policy\n");
1048 1049 1050
      return FALSE;
    }

1051
  if (recipient_policy &&
1052 1053
      !bus_client_policy_check_can_receive (recipient_policy,
                                            context->registry, sender,
1054
                                            addressed_recipient, proposed_recipient,
1055 1056
                                            message))
    {
1057
      const char *dest = dbus_message_get_destination (message);
1058 1059 1060 1061
      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                      "A security policy in place prevents this recipient "
                      "from receiving this message from this sender, "
                      "see message bus configuration file (rejected message "
1062 1063 1064 1065 1066 1067 1068 1069
                      "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")",
                      dbus_message_get_interface (message) ?
                      dbus_message_get_interface (message) : "(unset)",
                      dbus_message_get_member (message) ?
                      dbus_message_get_member (message) : "(unset)",
                      dbus_message_get_error_name (message) ?
                      dbus_message_get_error_name (message) : "(unset)",
                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
1070
      _dbus_verbose ("security policy disallowing message due to recipient policy\n");
1071 1072 1073
      return FALSE;
    }

1074
  /* See if limits on size have been exceeded */
1075 1076
  if (proposed_recipient &&
      dbus_connection_get_outgoing_size (proposed_recipient) >
1077
      context->limits.max_outgoing_bytes)
1078
    {
1079
      const char *dest = dbus_message_get_destination (message);
1080 1081
      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
                      "The destination service \"%s\" has a full message queue",
1082 1083 1084
                      dest ? dest : (proposed_recipient ?
                                     bus_connection_get_name (proposed_recipient) : 
                                     DBUS_SERVICE_ORG_FREEDESKTOP_DBUS));
1085
      _dbus_verbose ("security policy disallowing message due to full message queue\n");
1086 1087
      return FALSE;
    }
1088

1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
  if (type == DBUS_MESSAGE_TYPE_METHOD_CALL)
    {
      /* Record that we will allow a reply here in the future (don't
       * bother if the recipient is the bus). Only the addressed recipient
       * may reply.
       */
      if (sender && addressed_recipient &&
          !bus_connections_expect_reply (bus_connection_get_connections (sender),
                                         transaction,
                                         sender, addressed_recipient,
                                         message, error))
        {
          _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
          return FALSE;
        }
    }
  
1106
  _dbus_verbose ("security policy allowing message\n");
1107 1108
  return TRUE;
}