bus.c 28 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 887
/*
 * 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).
 */
888 889 890
dbus_bool_t
bus_context_check_security_policy (BusContext     *context,
                                   DBusConnection *sender,
891 892
                                   DBusConnection *addressed_recipient,
                                   DBusConnection *proposed_recipient,
893 894 895 896 897 898
                                   DBusMessage    *message,
                                   DBusError      *error)
{
  BusClientPolicy *sender_policy;
  BusClientPolicy *recipient_policy;

899 900 901
  _dbus_assert (dbus_message_get_destination (message) == NULL || /* Signal */
                (addressed_recipient != NULL ||
                 strcmp (dbus_message_get_destination (message), DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0)); /* Destination specified or is the bus driver */
902
  
903 904
  if (sender != NULL)
    {
905
      if (bus_connection_is_active (sender))
906
        {
907 908 909 910 911 912 913 914
          sender_policy = bus_connection_get_policy (sender);
          _dbus_assert (sender_policy != NULL);
        }
      else
        {
          /* Policy for inactive connections is that they can only send
           * the hello message to the bus driver
           */
915
          if (proposed_recipient == NULL &&
916 917 918
              dbus_message_is_method_call (message,
                                           DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
                                           "Hello"))
919 920
            {
              _dbus_verbose ("security check allowing %s message\n",
921
                             "Hello");
922 923 924 925 926
              return TRUE;
            }
          else
            {
              _dbus_verbose ("security check disallowing non-%s message\n",
927
                             "Hello");
928 929 930

              dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                              "Client tried to send a message other than %s without being registered",
931
                              "Hello");
932 933 934
              
              return FALSE;
            }
935
        }
936 937 938 939
    }
  else
    sender_policy = NULL;

940 941 942
  _dbus_assert ((sender != NULL && sender_policy != NULL) ||
                (sender == NULL && sender_policy == NULL));
  
943
  if (proposed_recipient != NULL)
944
    {
945 946 947 948
      /* 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.
       */
949
      if (bus_connection_is_active (proposed_recipient))
950
        {
951
          recipient_policy = bus_connection_get_policy (proposed_recipient);
952 953 954 955 956 957 958 959 960 961 962
          _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;
963
        }
964 965 966
    }
  else
    recipient_policy = NULL;
967
  
968 969 970
  _dbus_assert ((proposed_recipient != NULL && recipient_policy != NULL) ||
                (proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) ||
                (proposed_recipient == NULL && recipient_policy == NULL));
971 972
  
  if (sender_policy &&
973
      !bus_client_policy_check_can_send (sender_policy,
974
                                         context->registry, proposed_recipient,
975 976
                                         message))
    {
977
      const char *dest = dbus_message_get_destination (message);
978 979 980 981
      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 "
982 983 984 985 986 987 988 989
                      "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);
990
      _dbus_verbose ("security policy disallowing message due to sender policy\n");
991 992 993
      return FALSE;
    }

994
  if (recipient_policy &&
995 996
      !bus_client_policy_check_can_receive (recipient_policy,
                                            context->registry, sender,
997
                                            addressed_recipient, proposed_recipient,
998 999
                                            message))
    {
1000
      const char *dest = dbus_message_get_destination (message);
1001 1002 1003 1004
      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 "
1005 1006 1007 1008 1009 1010 1011 1012
                      "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);
1013
      _dbus_verbose ("security policy disallowing message due to recipient policy\n");
1014 1015 1016
      return FALSE;
    }

1017
  /* See if limits on size have been exceeded */
1018 1019
  if (proposed_recipient &&
      dbus_connection_get_outgoing_size (proposed_recipient) >
1020
      context->limits.max_outgoing_bytes)
1021
    {
1022
      const char *dest = dbus_message_get_destination (message);
1023 1024
      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
                      "The destination service \"%s\" has a full message queue",
1025 1026 1027
                      dest ? dest : (proposed_recipient ?
                                     bus_connection_get_name (proposed_recipient) : 
                                     DBUS_SERVICE_ORG_FREEDESKTOP_DBUS));
1028
      _dbus_verbose ("security policy disallowing message due to full message queue\n");
1029 1030
      return FALSE;
    }
1031 1032

  _dbus_verbose ("security policy allowing message\n");
1033 1034
  return TRUE;
}