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