bus.c 25.9 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 32
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
33 34 35 36 37
#include <dbus/dbus-internals.h>

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

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
static int server_data_slot = -1;
static int server_data_slot_refcount = 0;

typedef struct
{
  BusContext *context;
} BusServerData;

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

static dbus_bool_t
server_data_slot_ref (void)
{
  if (server_data_slot < 0)
    {
      server_data_slot = dbus_server_allocate_data_slot ();
      
      if (server_data_slot < 0)
        return FALSE;

      _dbus_assert (server_data_slot_refcount == 0);
    }  

  server_data_slot_refcount += 1;

  return TRUE;
}

static void
server_data_slot_unref (void)
{
  _dbus_assert (server_data_slot_refcount > 0);

  server_data_slot_refcount -= 1;
  
  if (server_data_slot_refcount == 0)
    {
      dbus_server_free_data_slot (server_data_slot);
      server_data_slot = -1;
    }
}

static BusContext*
server_get_context (DBusServer *server)
{
  BusContext *context;
  BusServerData *bd;
  
  if (!server_data_slot_ref ())
    return NULL;

  bd = BUS_SERVER_DATA (server);
  if (bd == NULL)
104 105 106 107
    {
      server_data_slot_unref ();
      return NULL;
    }
108 109 110 111 112 113 114 115

  context = bd->context;

  server_data_slot_unref ();

  return context;
}

116
static dbus_bool_t
117 118 119 120
server_watch_callback (DBusWatch     *watch,
                       unsigned int   condition,
                       void          *data)
{
121 122 123 124 125 126
  /* 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);
127 128
}

129
static dbus_bool_t
130
add_server_watch (DBusWatch  *watch,
131
                  void       *data)
132
{
133 134 135 136 137
  DBusServer *server = data;
  BusContext *context;
  
  context = server_get_context (server);
  
138 139 140
  return _dbus_loop_add_watch (context->loop,
                               watch, server_watch_callback, server,
                               NULL);
141 142 143 144
}

static void
remove_server_watch (DBusWatch  *watch,
145
                     void       *data)
146
{
147 148 149 150 151
  DBusServer *server = data;
  BusContext *context;
  
  context = server_get_context (server);
  
152 153
  _dbus_loop_remove_watch (context->loop,
                           watch, server_watch_callback, server);
154 155
}

156

157 158 159 160
static void
server_timeout_callback (DBusTimeout   *timeout,
                         void          *data)
{
161
  /* can return FALSE on OOM but we just let it fire again later */
162 163 164 165 166
  dbus_timeout_handle (timeout);
}

static dbus_bool_t
add_server_timeout (DBusTimeout *timeout,
167
                    void        *data)
168
{
169 170 171 172 173
  DBusServer *server = data;
  BusContext *context;
  
  context = server_get_context (server);

174 175
  return _dbus_loop_add_timeout (context->loop,
                                 timeout, server_timeout_callback, server, NULL);
176 177 178 179
}

static void
remove_server_timeout (DBusTimeout *timeout,
180
                       void        *data)
181
{
182 183 184 185 186
  DBusServer *server = data;
  BusContext *context;
  
  context = server_get_context (server);
  
187 188
  _dbus_loop_remove_timeout (context->loop,
                             timeout, server_timeout_callback, server);
189 190
}

191 192 193 194 195 196 197 198
static void
new_connection_callback (DBusServer     *server,
                         DBusConnection *new_connection,
                         void           *data)
{
  BusContext *context = data;
  
  if (!bus_connections_setup_connection (context->connections, new_connection))
199 200
    {
      _dbus_verbose ("No memory to setup new connection\n");
201

202 203 204 205 206 207 208
      /* 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);
    }
209 210

  dbus_connection_set_max_received_size (new_connection,
211
                                         context->limits.max_incoming_bytes);
212 213

  dbus_connection_set_max_message_size (new_connection,
214
                                        context->limits.max_message_size);
215
  
216
  /* on OOM, we won't have ref'd the connection so it will die. */
217 218
}

219 220 221 222 223 224 225 226
static void
free_server_data (void *data)
{
  BusServerData *bd = data;  
  
  dbus_free (bd);
}

227 228 229
static dbus_bool_t
setup_server (BusContext *context,
              DBusServer *server,
230
              char      **auth_mechanisms,
231
              DBusError  *error)
232
{
233
  BusServerData *bd;
234 235 236 237 238 239 240 241 242 243 244 245

  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;
246
  
247 248 249 250 251 252
  if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
    {
      BUS_SET_OOM (error);
      return FALSE;
    }
  
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
  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;
    }
277
  
278 279 280
  return TRUE;
}

281
BusContext*
282
bus_context_new (const DBusString *config_file,
283
                 dbus_bool_t       force_fork,
284
                 int               print_addr_fd,
285
                 int               print_pid_fd,
286
                 DBusError        *error)
287 288
{
  BusContext *context;
289 290 291 292
  DBusList *link;
  DBusList **addresses;
  BusConfigParser *parser;
  DBusString full_address;
293
  const char *user, *pidfile;
294 295 296
  char **auth_mechanisms;
  DBusList **auth_mechanisms_list;
  int len;
297
  
298
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
299

300
  if (!_dbus_string_init (&full_address))
301 302 303 304
    {
      BUS_SET_OOM (error);
      return NULL;
    }
305

306 307 308 309 310 311 312
  if (!server_data_slot_ref ())
    {
      BUS_SET_OOM (error);
      _dbus_string_free (&full_address);
      return NULL;
    }
  
313 314
  parser = NULL;
  context = NULL;
315
  auth_mechanisms = NULL;
316
  
317
  parser = bus_config_load (config_file, TRUE, error);
318 319
  if (parser == NULL)
    goto failed;
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344

  /* 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;
	}
    }
345 346 347 348 349
  
  context = dbus_new0 (BusContext, 1);
  if (context == NULL)
    {
      BUS_SET_OOM (error);
350
      goto failed;
351 352 353
    }
  
  context->refcount = 1;
354

355 356 357
  /* get our limits and timeout lengths */
  bus_config_parser_get_limits (parser, &context->limits);
  
358 359 360 361 362
  /* we need another ref of the server data slot for the context
   * to own
   */
  if (!server_data_slot_ref ())
    _dbus_assert_not_reached ("second ref of server data slot failed");
363
  
364 365 366 367 368 369
  context->user_database = _dbus_user_database_new ();
  if (context->user_database == NULL)
    {
      BUS_SET_OOM (error);
      goto failed;
    }
370
  
371
  context->loop = _dbus_loop_new ();
372 373 374 375 376 377
  if (context->loop == NULL)
    {
      BUS_SET_OOM (error);
      goto failed;
    }
  
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
  /* 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 */
407 408 409 410 411 412 413 414 415 416 417
  
  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;
418
      else if (!setup_server (context, server, auth_mechanisms, error))
419 420 421 422 423 424 425 426 427 428 429
        goto failed;

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

430 431
  /* note that type may be NULL */
  context->type = _dbus_strdup (bus_config_parser_get_type (parser));
432
  
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
  /* 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;
            }
        }
456

457 458 459 460 461 462 463 464 465 466 467 468
      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))
469 470 471 472
    {
      BUS_SET_OOM (error);
      goto failed;
    }
473

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
  /* 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);
    }
  
516
  /* Create activation subsystem */
517
  
518
  context->activation = bus_activation_new (context, &full_address,
519 520
                                            bus_config_parser_get_service_dirs (parser),
                                            error);
521 522 523 524 525 526 527 528 529 530 531 532 533
  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;
    }

534
  context->registry = bus_registry_new (context);
535 536 537 538 539
  if (context->registry == NULL)
    {
      BUS_SET_OOM (error);
      goto failed;
    }
540

541 542 543
  context->policy = bus_config_parser_steal_policy (parser);
  _dbus_assert (context->policy != NULL);
  
544
  /* Now become a daemon if appropriate */
545
  if (force_fork || bus_config_parser_get_fork (parser))
546
    {
547 548 549 550 551 552
      DBusString u;

      if (pidfile)
        _dbus_string_init_const (&u, pidfile);
      
      if (!_dbus_become_daemon (pidfile ? &u : NULL, error))
553 554
        goto failed;
    }
555 556 557 558 559 560 561 562 563 564 565 566 567
  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;
        }
    }
568 569 570

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

572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
  /* 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);
    }
  
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
  /* 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;
    }
632
  
633 634
  bus_config_parser_unref (parser);
  _dbus_string_free (&full_address);
635
  dbus_free_string_array (auth_mechanisms);
636
  server_data_slot_unref ();
637 638 639
  
  return context;
  
640
 failed:  
641 642 643 644 645 646 647
  if (parser != NULL)
    bus_config_parser_unref (parser);

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

  _dbus_string_free (&full_address);
648
  dbus_free_string_array (auth_mechanisms);
649 650 651

  server_data_slot_unref ();
  
652 653 654
  return NULL;
}

655 656 657
static void
shutdown_server (BusContext *context,
                 DBusServer *server)
658
{
659 660
  if (server == NULL ||
      !dbus_server_get_is_connected (server))
661 662
    return;
  
663
  if (!dbus_server_set_watch_functions (server,
664
                                        NULL, NULL, NULL,
665 666 667 668
                                        context,
                                        NULL))
    _dbus_assert_not_reached ("setting watch functions to NULL failed");
  
669
  if (!dbus_server_set_timeout_functions (server,
670
                                          NULL, NULL, NULL,
671 672 673 674
                                          context,
                                          NULL))
    _dbus_assert_not_reached ("setting timeout functions to NULL failed");
  
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
  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);
    }
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
}

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)
    {
707 708
      DBusList *link;
      
709 710
      _dbus_verbose ("Finalizing bus context %p\n", context);
      
711
      bus_context_shutdown (context);
712 713 714 715 716 717

      if (context->connections)
        {
          bus_connections_unref (context->connections);
          context->connections = NULL;
        }
718
      
719
      if (context->registry)
720 721 722 723 724
        {
          bus_registry_unref (context->registry);
          context->registry = NULL;
        }
      
725
      if (context->activation)
726 727 728 729
        {
          bus_activation_unref (context->activation);
          context->activation = NULL;
        }
730 731 732

      link = _dbus_list_get_first_link (&context->servers);
      while (link != NULL)
733
        {
734 735 736
          dbus_server_unref (link->data);
          
          link = _dbus_list_get_next_link (&context->servers, link);
737
        }
738
      _dbus_list_clear (&context->servers);
739

740
      if (context->policy)
741
        {
742 743
          bus_policy_unref (context->policy);
          context->policy = NULL;
744
        }
745
      
746 747
      if (context->loop)
        {
748
          _dbus_loop_unref (context->loop);
749 750 751
          context->loop = NULL;
        }
      
752
      dbus_free (context->type);
753
      dbus_free (context->address);
754 755 756 757 758 759 760 761 762 763 764 765 766 767

      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); 
	}

768 769
      _dbus_user_database_unref (context->user_database);
      
770
      dbus_free (context);
771 772

      server_data_slot_unref ();
773 774 775
    }
}

776 777 778 779 780 781 782
/* type may be NULL */
const char*
bus_context_get_type (BusContext *context)
{
  return context->type;
}

783 784 785 786 787 788
const char*
bus_context_get_address (BusContext *context)
{
  return context->address;
}

789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805
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;
}
806

807
DBusLoop*
808 809 810 811 812
bus_context_get_loop (BusContext *context)
{
  return context->loop;
}

813 814 815 816 817 818
DBusUserDatabase*
bus_context_get_user_database (BusContext *context)
{
  return context->user_database;
}

819 820 821 822
dbus_bool_t
bus_context_allow_user (BusContext   *context,
                        unsigned long uid)
{
823 824 825
  return bus_policy_allow_user (context->policy,
                                context->user_database,
                                uid);
826 827
}

828 829
BusClientPolicy*
bus_context_create_client_policy (BusContext      *context,
830 831
                                  DBusConnection  *connection,
                                  DBusError       *error)
832
{
833 834 835
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  return bus_policy_create_client_policy (context->policy, connection,
                                          error);
836
}
837 838 839 840 841

int
bus_context_get_activation_timeout (BusContext *context)
{
  
842
  return context->limits.activation_timeout;
843
}
844

845 846 847
int
bus_context_get_auth_timeout (BusContext *context)
{
848
  return context->limits.auth_timeout;
849 850 851 852 853
}

int
bus_context_get_max_completed_connections (BusContext *context)
{
854
  return context->limits.max_completed_connections;
855 856 857 858 859
}

int
bus_context_get_max_incomplete_connections (BusContext *context)
{
860
  return context->limits.max_incomplete_connections;
861 862 863 864 865
}

int
bus_context_get_max_connections_per_user (BusContext *context)
{
866
  return context->limits.max_connections_per_user;
867 868
}

869 870 871 872 873 874 875 876 877 878 879 880
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;
}

881 882 883 884 885 886 887 888 889 890 891
dbus_bool_t
bus_context_check_security_policy (BusContext     *context,
                                   DBusConnection *sender,
                                   DBusConnection *recipient,
                                   DBusMessage    *message,
                                   DBusError      *error)
{
  BusClientPolicy *sender_policy;
  BusClientPolicy *recipient_policy;

  /* NULL sender/receiver means the bus driver */
892

893 894
  if (sender != NULL)
    {
895
      if (bus_connection_is_active (sender))
896
        {
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
          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
           */
          if (recipient == NULL &&
              dbus_message_has_name (message, DBUS_MESSAGE_HELLO))
            {
              _dbus_verbose ("security check allowing %s message\n",
                             DBUS_MESSAGE_HELLO);
              return TRUE;
            }
          else
            {
              _dbus_verbose ("security check disallowing non-%s message\n",
                             DBUS_MESSAGE_HELLO);

              dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                              "Client tried to send a message other than %s without being registered",
                              DBUS_MESSAGE_HELLO);
              
              return FALSE;
            }
923
        }
924 925 926 927
    }
  else
    sender_policy = NULL;

928 929 930
  _dbus_assert ((sender != NULL && sender_policy != NULL) ||
                (sender == NULL && sender_policy == NULL));
  
931 932
  if (recipient != NULL)
    {
933 934 935 936 937
      /* 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.
       */
      if (bus_connection_is_active (recipient))
938
        {
939 940 941 942 943 944 945 946 947 948 949 950
          recipient_policy = bus_connection_get_policy (recipient);
          _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;
951
        }
952 953 954
    }
  else
    recipient_policy = NULL;
955 956 957 958 959 960
  
  _dbus_assert ((recipient != NULL && recipient_policy != NULL) ||
                (recipient != NULL && sender == NULL && recipient_policy == NULL) ||
                (recipient == NULL && recipient_policy == NULL));
  
  if (sender_policy &&
961 962 963 964
      !bus_client_policy_check_can_send (sender_policy,
                                         context->registry, recipient,
                                         message))
    {
965
      const char *dest = dbus_message_get_destination (message);
966 967 968 969 970 971 972
      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 "
                      "had name \"%s\" destination \"%s\")",
                      dbus_message_get_name (message),
                      dest ? dest : DBUS_SERVICE_DBUS);
973
      _dbus_verbose ("security policy disallowing message due to sender policy\n");
974 975 976
      return FALSE;
    }

977
  if (recipient_policy &&
978 979 980 981
      !bus_client_policy_check_can_receive (recipient_policy,
                                            context->registry, sender,
                                            message))
    {
982
      const char *dest = dbus_message_get_destination (message);
983 984 985 986 987 988 989
      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 "
                      "had name \"%s\" destination \"%s\")",
                      dbus_message_get_name (message),
                      dest ? dest : DBUS_SERVICE_DBUS);
990
      _dbus_verbose ("security policy disallowing message due to recipient policy\n");
991 992 993
      return FALSE;
    }

994 995 996
  /* See if limits on size have been exceeded */
  if (recipient &&
      dbus_connection_get_outgoing_size (recipient) >
997
      context->limits.max_outgoing_bytes)
998
    {
999
      const char *dest = dbus_message_get_destination (message);
1000 1001 1002
      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
                      "The destination service \"%s\" has a full message queue",
                      dest ? dest : DBUS_SERVICE_DBUS);
1003
      _dbus_verbose ("security policy disallowing message due to full message queue\n");
1004 1005
      return FALSE;
    }
1006 1007

  _dbus_verbose ("security policy allowing message\n");
1008 1009
  return TRUE;
}