driver.c revision 66e1cb9e68ba37980f7a90c396950be1587cdcd7
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* driver.c Bus client (driver) 3 * 4 * Copyright (C) 2003 CodeFactory AB 5 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc. 6 * 7 * Licensed under the Academic Free License version 2.1 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 */ 24 25#include "activation.h" 26#include "connection.h" 27#include "driver.h" 28#include "dispatch.h" 29#include "services.h" 30#include "selinux.h" 31#include "signals.h" 32#include "utils.h" 33#include <dbus/dbus-string.h> 34#include <dbus/dbus-internals.h> 35#include <dbus/dbus-marshal-recursive.h> 36#include <string.h> 37 38static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection, 39 DBusMessage *hello_message, 40 BusTransaction *transaction, 41 DBusError *error); 42 43dbus_bool_t 44bus_driver_send_service_owner_changed (const char *service_name, 45 const char *old_owner, 46 const char *new_owner, 47 BusTransaction *transaction, 48 DBusError *error) 49{ 50 DBusMessage *message; 51 dbus_bool_t retval; 52 const char *null_service; 53 54 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 55 56 null_service = ""; 57 _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n", 58 service_name, 59 old_owner ? old_owner : null_service, 60 new_owner ? new_owner : null_service); 61 62 message = dbus_message_new_signal (DBUS_PATH_DBUS, 63 DBUS_INTERFACE_DBUS, 64 "NameOwnerChanged"); 65 66 if (message == NULL) 67 { 68 BUS_SET_OOM (error); 69 return FALSE; 70 } 71 72 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) 73 goto oom; 74 75 if (!dbus_message_append_args (message, 76 DBUS_TYPE_STRING, &service_name, 77 DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service, 78 DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service, 79 DBUS_TYPE_INVALID)) 80 goto oom; 81 82 _dbus_assert (dbus_message_has_signature (message, "sss")); 83 84 retval = bus_dispatch_matches (transaction, NULL, NULL, message, error); 85 dbus_message_unref (message); 86 87 return retval; 88 89 oom: 90 dbus_message_unref (message); 91 BUS_SET_OOM (error); 92 return FALSE; 93} 94 95dbus_bool_t 96bus_driver_send_service_lost (DBusConnection *connection, 97 const char *service_name, 98 BusTransaction *transaction, 99 DBusError *error) 100{ 101 DBusMessage *message; 102 103 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 104 105 message = dbus_message_new_signal (DBUS_PATH_DBUS, 106 DBUS_INTERFACE_DBUS, 107 "NameLost"); 108 109 if (message == NULL) 110 { 111 BUS_SET_OOM (error); 112 return FALSE; 113 } 114 115 if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) || 116 !dbus_message_append_args (message, 117 DBUS_TYPE_STRING, &service_name, 118 DBUS_TYPE_INVALID)) 119 { 120 dbus_message_unref (message); 121 BUS_SET_OOM (error); 122 return FALSE; 123 } 124 125 if (!bus_transaction_send_from_driver (transaction, connection, message)) 126 { 127 dbus_message_unref (message); 128 BUS_SET_OOM (error); 129 return FALSE; 130 } 131 else 132 { 133 dbus_message_unref (message); 134 return TRUE; 135 } 136} 137 138dbus_bool_t 139bus_driver_send_service_acquired (DBusConnection *connection, 140 const char *service_name, 141 BusTransaction *transaction, 142 DBusError *error) 143{ 144 DBusMessage *message; 145 146 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 147 148 message = dbus_message_new_signal (DBUS_PATH_DBUS, 149 DBUS_INTERFACE_DBUS, 150 "NameAcquired"); 151 152 if (message == NULL) 153 { 154 BUS_SET_OOM (error); 155 return FALSE; 156 } 157 158 if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) || 159 !dbus_message_append_args (message, 160 DBUS_TYPE_STRING, &service_name, 161 DBUS_TYPE_INVALID)) 162 { 163 dbus_message_unref (message); 164 BUS_SET_OOM (error); 165 return FALSE; 166 } 167 168 if (!bus_transaction_send_from_driver (transaction, connection, message)) 169 { 170 dbus_message_unref (message); 171 BUS_SET_OOM (error); 172 return FALSE; 173 } 174 else 175 { 176 dbus_message_unref (message); 177 return TRUE; 178 } 179} 180 181static dbus_bool_t 182create_unique_client_name (BusRegistry *registry, 183 DBusString *str) 184{ 185 /* We never want to use the same unique client name twice, because 186 * we want to guarantee that if you send a message to a given unique 187 * name, you always get the same application. So we use two numbers 188 * for INT_MAX * INT_MAX combinations, should be pretty safe against 189 * wraparound. 190 */ 191 /* FIXME these should be in BusRegistry rather than static vars */ 192 static int next_major_number = 0; 193 static int next_minor_number = 0; 194 int len; 195 196 len = _dbus_string_get_length (str); 197 198 while (TRUE) 199 { 200 /* start out with 1-0, go to 1-1, 1-2, 1-3, 201 * up to 1-MAXINT, then 2-0, 2-1, etc. 202 */ 203 if (next_minor_number <= 0) 204 { 205 next_major_number += 1; 206 next_minor_number = 0; 207 if (next_major_number <= 0) 208 _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added"); 209 } 210 211 _dbus_assert (next_major_number > 0); 212 _dbus_assert (next_minor_number >= 0); 213 214 /* appname:MAJOR-MINOR */ 215 216 if (!_dbus_string_append (str, ":")) 217 return FALSE; 218 219 if (!_dbus_string_append_int (str, next_major_number)) 220 return FALSE; 221 222 if (!_dbus_string_append (str, ".")) 223 return FALSE; 224 225 if (!_dbus_string_append_int (str, next_minor_number)) 226 return FALSE; 227 228 next_minor_number += 1; 229 230 /* Check if a client with the name exists */ 231 if (bus_registry_lookup (registry, str) == NULL) 232 break; 233 234 /* drop the number again, try the next one. */ 235 _dbus_string_set_length (str, len); 236 } 237 238 return TRUE; 239} 240 241static dbus_bool_t 242bus_driver_handle_hello (DBusConnection *connection, 243 BusTransaction *transaction, 244 DBusMessage *message, 245 DBusError *error) 246{ 247 DBusString unique_name; 248 BusService *service; 249 dbus_bool_t retval; 250 BusRegistry *registry; 251 BusConnections *connections; 252 253 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 254 255 if (bus_connection_is_active (connection)) 256 { 257 /* We already handled an Hello message for this connection. */ 258 dbus_set_error (error, DBUS_ERROR_FAILED, 259 "Already handled an Hello message"); 260 return FALSE; 261 } 262 263 /* Note that when these limits are exceeded we don't disconnect the 264 * connection; we just sort of leave it hanging there until it times 265 * out or disconnects itself or is dropped due to the max number of 266 * incomplete connections. It's even OK if the connection wants to 267 * retry the hello message, we support that. 268 */ 269 connections = bus_connection_get_connections (connection); 270 if (!bus_connections_check_limits (connections, connection, 271 error)) 272 { 273 _DBUS_ASSERT_ERROR_IS_SET (error); 274 return FALSE; 275 } 276 277 if (!_dbus_string_init (&unique_name)) 278 { 279 BUS_SET_OOM (error); 280 return FALSE; 281 } 282 283 retval = FALSE; 284 285 registry = bus_connection_get_registry (connection); 286 287 if (!create_unique_client_name (registry, &unique_name)) 288 { 289 BUS_SET_OOM (error); 290 goto out_0; 291 } 292 293 if (!bus_connection_complete (connection, &unique_name, error)) 294 { 295 _DBUS_ASSERT_ERROR_IS_SET (error); 296 goto out_0; 297 } 298 299 if (!dbus_message_set_sender (message, 300 bus_connection_get_name (connection))) 301 { 302 BUS_SET_OOM (error); 303 goto out_0; 304 } 305 306 if (!bus_driver_send_welcome_message (connection, message, transaction, error)) 307 goto out_0; 308 309 /* Create the service */ 310 service = bus_registry_ensure (registry, 311 &unique_name, connection, transaction, error); 312 if (service == NULL) 313 goto out_0; 314 315 bus_service_set_prohibit_replacement (service, TRUE); 316 317 _dbus_assert (bus_connection_is_active (connection)); 318 retval = TRUE; 319 320 out_0: 321 _dbus_string_free (&unique_name); 322 return retval; 323} 324 325static dbus_bool_t 326bus_driver_send_welcome_message (DBusConnection *connection, 327 DBusMessage *hello_message, 328 BusTransaction *transaction, 329 DBusError *error) 330{ 331 DBusMessage *welcome; 332 const char *name; 333 334 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 335 336 name = bus_connection_get_name (connection); 337 _dbus_assert (name != NULL); 338 339 welcome = dbus_message_new_method_return (hello_message); 340 if (welcome == NULL) 341 { 342 BUS_SET_OOM (error); 343 return FALSE; 344 } 345 346 if (!dbus_message_append_args (welcome, 347 DBUS_TYPE_STRING, &name, 348 DBUS_TYPE_INVALID)) 349 { 350 dbus_message_unref (welcome); 351 BUS_SET_OOM (error); 352 return FALSE; 353 } 354 355 _dbus_assert (dbus_message_has_signature (welcome, DBUS_TYPE_STRING_AS_STRING)); 356 357 if (!bus_transaction_send_from_driver (transaction, connection, welcome)) 358 { 359 dbus_message_unref (welcome); 360 BUS_SET_OOM (error); 361 return FALSE; 362 } 363 else 364 { 365 dbus_message_unref (welcome); 366 return TRUE; 367 } 368} 369 370static dbus_bool_t 371bus_driver_handle_list_services (DBusConnection *connection, 372 BusTransaction *transaction, 373 DBusMessage *message, 374 DBusError *error) 375{ 376 DBusMessage *reply; 377 int len; 378 char **services; 379 BusRegistry *registry; 380 int i; 381 DBusMessageIter iter; 382 DBusMessageIter sub; 383 384 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 385 386 registry = bus_connection_get_registry (connection); 387 388 reply = dbus_message_new_method_return (message); 389 if (reply == NULL) 390 { 391 BUS_SET_OOM (error); 392 return FALSE; 393 } 394 395 if (!bus_registry_list_services (registry, &services, &len)) 396 { 397 dbus_message_unref (reply); 398 BUS_SET_OOM (error); 399 return FALSE; 400 } 401 402 dbus_message_iter_init_append (reply, &iter); 403 404 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, 405 DBUS_TYPE_STRING_AS_STRING, 406 &sub)) 407 { 408 dbus_free_string_array (services); 409 dbus_message_unref (reply); 410 BUS_SET_OOM (error); 411 return FALSE; 412 } 413 414 { 415 /* Include the bus driver in the list */ 416 const char *v_STRING = DBUS_SERVICE_DBUS; 417 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, 418 &v_STRING)) 419 { 420 dbus_free_string_array (services); 421 dbus_message_unref (reply); 422 BUS_SET_OOM (error); 423 return FALSE; 424 } 425 } 426 427 i = 0; 428 while (i < len) 429 { 430 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, 431 &services[i])) 432 { 433 dbus_free_string_array (services); 434 dbus_message_unref (reply); 435 BUS_SET_OOM (error); 436 return FALSE; 437 } 438 ++i; 439 } 440 441 if (!dbus_message_iter_close_container (&iter, &sub)) 442 { 443 dbus_free_string_array (services); 444 dbus_message_unref (reply); 445 BUS_SET_OOM (error); 446 return FALSE; 447 } 448 449 dbus_free_string_array (services); 450 451 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 452 { 453 dbus_message_unref (reply); 454 BUS_SET_OOM (error); 455 return FALSE; 456 } 457 else 458 { 459 dbus_message_unref (reply); 460 return TRUE; 461 } 462} 463 464static dbus_bool_t 465bus_driver_handle_acquire_service (DBusConnection *connection, 466 BusTransaction *transaction, 467 DBusMessage *message, 468 DBusError *error) 469{ 470 DBusMessage *reply; 471 DBusString service_name; 472 const char *name; 473 int service_reply; 474 dbus_uint32_t flags; 475 dbus_bool_t retval; 476 BusRegistry *registry; 477 478 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 479 480 registry = bus_connection_get_registry (connection); 481 482 if (!dbus_message_get_args (message, error, 483 DBUS_TYPE_STRING, &name, 484 DBUS_TYPE_UINT32, &flags, 485 DBUS_TYPE_INVALID)) 486 return FALSE; 487 488 _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags); 489 490 retval = FALSE; 491 reply = NULL; 492 493 _dbus_string_init_const (&service_name, name); 494 495 if (!bus_registry_acquire_service (registry, connection, 496 &service_name, flags, 497 &service_reply, transaction, 498 error)) 499 goto out; 500 501 reply = dbus_message_new_method_return (message); 502 if (reply == NULL) 503 { 504 BUS_SET_OOM (error); 505 goto out; 506 } 507 508 if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID)) 509 { 510 BUS_SET_OOM (error); 511 goto out; 512 } 513 514 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 515 { 516 BUS_SET_OOM (error); 517 goto out; 518 } 519 520 retval = TRUE; 521 522 out: 523 if (reply) 524 dbus_message_unref (reply); 525 return retval; 526} 527 528static dbus_bool_t 529bus_driver_handle_service_exists (DBusConnection *connection, 530 BusTransaction *transaction, 531 DBusMessage *message, 532 DBusError *error) 533{ 534 DBusMessage *reply; 535 DBusString service_name; 536 BusService *service; 537 dbus_bool_t service_exists; 538 const char *name; 539 dbus_bool_t retval; 540 BusRegistry *registry; 541 542 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 543 544 registry = bus_connection_get_registry (connection); 545 546 if (!dbus_message_get_args (message, error, 547 DBUS_TYPE_STRING, &name, 548 DBUS_TYPE_INVALID)) 549 return FALSE; 550 551 retval = FALSE; 552 553 if (strcmp (name, DBUS_SERVICE_DBUS) == 0) 554 { 555 service_exists = TRUE; 556 } 557 else 558 { 559 _dbus_string_init_const (&service_name, name); 560 service = bus_registry_lookup (registry, &service_name); 561 service_exists = service != NULL; 562 } 563 564 reply = dbus_message_new_method_return (message); 565 if (reply == NULL) 566 { 567 BUS_SET_OOM (error); 568 goto out; 569 } 570 571 if (!dbus_message_append_args (reply, 572 DBUS_TYPE_BOOLEAN, &service_exists, 573 0)) 574 { 575 BUS_SET_OOM (error); 576 goto out; 577 } 578 579 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 580 { 581 BUS_SET_OOM (error); 582 goto out; 583 } 584 585 retval = TRUE; 586 587 out: 588 if (reply) 589 dbus_message_unref (reply); 590 591 return retval; 592} 593 594static dbus_bool_t 595bus_driver_handle_activate_service (DBusConnection *connection, 596 BusTransaction *transaction, 597 DBusMessage *message, 598 DBusError *error) 599{ 600 dbus_uint32_t flags; 601 const char *name; 602 dbus_bool_t retval; 603 BusActivation *activation; 604 605 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 606 607 activation = bus_connection_get_activation (connection); 608 609 if (!dbus_message_get_args (message, error, 610 DBUS_TYPE_STRING, &name, 611 DBUS_TYPE_UINT32, &flags, 612 DBUS_TYPE_INVALID)) 613 { 614 _DBUS_ASSERT_ERROR_IS_SET (error); 615 _dbus_verbose ("No memory to get arguments to StartServiceByName\n"); 616 return FALSE; 617 } 618 619 retval = FALSE; 620 621 if (!bus_activation_activate_service (activation, connection, transaction, FALSE, 622 message, name, error)) 623 { 624 _DBUS_ASSERT_ERROR_IS_SET (error); 625 _dbus_verbose ("bus_activation_activate_service() failed\n"); 626 goto out; 627 } 628 629 retval = TRUE; 630 631 out: 632 return retval; 633} 634 635static dbus_bool_t 636send_ack_reply (DBusConnection *connection, 637 BusTransaction *transaction, 638 DBusMessage *message, 639 DBusError *error) 640{ 641 DBusMessage *reply; 642 643 reply = dbus_message_new_method_return (message); 644 if (reply == NULL) 645 { 646 BUS_SET_OOM (error); 647 return FALSE; 648 } 649 650 if (!bus_transaction_send_from_driver (transaction, connection, reply)) 651 { 652 BUS_SET_OOM (error); 653 dbus_message_unref (reply); 654 return FALSE; 655 } 656 657 dbus_message_unref (reply); 658 659 return TRUE; 660} 661 662static dbus_bool_t 663bus_driver_handle_add_match (DBusConnection *connection, 664 BusTransaction *transaction, 665 DBusMessage *message, 666 DBusError *error) 667{ 668 BusMatchRule *rule; 669 const char *text; 670 DBusString str; 671 BusMatchmaker *matchmaker; 672 673 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 674 675 text = NULL; 676 rule = NULL; 677 678 if (bus_connection_get_n_match_rules (connection) >= 679 bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction))) 680 { 681 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, 682 "Connection \"%s\" is not allowed to add more match rules " 683 "(increase limits in configuration file if required)", 684 bus_connection_is_active (connection) ? 685 bus_connection_get_name (connection) : 686 "(inactive)"); 687 goto failed; 688 } 689 690 if (!dbus_message_get_args (message, error, 691 DBUS_TYPE_STRING, &text, 692 DBUS_TYPE_INVALID)) 693 { 694 _dbus_verbose ("No memory to get arguments to AddMatch\n"); 695 goto failed; 696 } 697 698 _dbus_string_init_const (&str, text); 699 700 rule = bus_match_rule_parse (connection, &str, error); 701 if (rule == NULL) 702 goto failed; 703 704 matchmaker = bus_connection_get_matchmaker (connection); 705 706 if (!bus_matchmaker_add_rule (matchmaker, rule)) 707 { 708 BUS_SET_OOM (error); 709 goto failed; 710 } 711 712 if (!send_ack_reply (connection, transaction, 713 message, error)) 714 { 715 bus_matchmaker_remove_rule (matchmaker, rule); 716 goto failed; 717 } 718 719 bus_match_rule_unref (rule); 720 721 return TRUE; 722 723 failed: 724 _DBUS_ASSERT_ERROR_IS_SET (error); 725 if (rule) 726 bus_match_rule_unref (rule); 727 return FALSE; 728} 729 730static dbus_bool_t 731bus_driver_handle_remove_match (DBusConnection *connection, 732 BusTransaction *transaction, 733 DBusMessage *message, 734 DBusError *error) 735{ 736 BusMatchRule *rule; 737 const char *text; 738 DBusString str; 739 BusMatchmaker *matchmaker; 740 741 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 742 743 text = NULL; 744 rule = NULL; 745 746 if (!dbus_message_get_args (message, error, 747 DBUS_TYPE_STRING, &text, 748 DBUS_TYPE_INVALID)) 749 { 750 _dbus_verbose ("No memory to get arguments to RemoveMatch\n"); 751 goto failed; 752 } 753 754 _dbus_string_init_const (&str, text); 755 756 rule = bus_match_rule_parse (connection, &str, error); 757 if (rule == NULL) 758 goto failed; 759 760 /* Send the ack before we remove the rule, since the ack is undone 761 * on transaction cancel, but rule removal isn't. 762 */ 763 if (!send_ack_reply (connection, transaction, 764 message, error)) 765 goto failed; 766 767 matchmaker = bus_connection_get_matchmaker (connection); 768 769 if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error)) 770 goto failed; 771 772 bus_match_rule_unref (rule); 773 774 return TRUE; 775 776 failed: 777 _DBUS_ASSERT_ERROR_IS_SET (error); 778 if (rule) 779 bus_match_rule_unref (rule); 780 return FALSE; 781} 782 783static dbus_bool_t 784bus_driver_handle_get_service_owner (DBusConnection *connection, 785 BusTransaction *transaction, 786 DBusMessage *message, 787 DBusError *error) 788{ 789 const char *text; 790 const char *base_name; 791 DBusString str; 792 BusRegistry *registry; 793 BusService *service; 794 DBusMessage *reply; 795 796 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 797 798 registry = bus_connection_get_registry (connection); 799 800 text = NULL; 801 reply = NULL; 802 803 if (! dbus_message_get_args (message, error, 804 DBUS_TYPE_STRING, &text, 805 DBUS_TYPE_INVALID)) 806 goto failed; 807 808 _dbus_string_init_const (&str, text); 809 service = bus_registry_lookup (registry, &str); 810 if (service == NULL && 811 _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS)) 812 { 813 /* ORG_FREEDESKTOP_DBUS owns itself */ 814 base_name = DBUS_SERVICE_DBUS; 815 } 816 else if (service == NULL) 817 { 818 dbus_set_error (error, 819 DBUS_ERROR_NAME_HAS_NO_OWNER, 820 "Could not get owner of name '%s': no such name", text); 821 goto failed; 822 } 823 else 824 { 825 base_name = bus_connection_get_name (bus_service_get_primary_owner (service)); 826 if (base_name == NULL) 827 { 828 /* FIXME - how is this error possible? */ 829 dbus_set_error (error, 830 DBUS_ERROR_FAILED, 831 "Could not determine unique name for '%s'", text); 832 goto failed; 833 } 834 _dbus_assert (*base_name == ':'); 835 } 836 837 _dbus_assert (base_name != NULL); 838 839 reply = dbus_message_new_method_return (message); 840 if (reply == NULL) 841 goto oom; 842 843 if (! dbus_message_append_args (reply, 844 DBUS_TYPE_STRING, &base_name, 845 DBUS_TYPE_INVALID)) 846 goto oom; 847 848 if (! bus_transaction_send_from_driver (transaction, connection, reply)) 849 goto oom; 850 851 dbus_message_unref (reply); 852 853 return TRUE; 854 855 oom: 856 BUS_SET_OOM (error); 857 858 failed: 859 _DBUS_ASSERT_ERROR_IS_SET (error); 860 if (reply) 861 dbus_message_unref (reply); 862 return FALSE; 863} 864 865static dbus_bool_t 866bus_driver_handle_get_connection_unix_user (DBusConnection *connection, 867 BusTransaction *transaction, 868 DBusMessage *message, 869 DBusError *error) 870{ 871 const char *service; 872 DBusString str; 873 BusRegistry *registry; 874 BusService *serv; 875 DBusConnection *conn; 876 DBusMessage *reply; 877 unsigned long uid; 878 dbus_uint32_t uid32; 879 880 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 881 882 registry = bus_connection_get_registry (connection); 883 884 service = NULL; 885 reply = NULL; 886 887 if (! dbus_message_get_args (message, error, 888 DBUS_TYPE_STRING, &service, 889 DBUS_TYPE_INVALID)) 890 goto failed; 891 892 _dbus_verbose ("asked for UID of connection %s\n", service); 893 894 _dbus_string_init_const (&str, service); 895 serv = bus_registry_lookup (registry, &str); 896 if (serv == NULL) 897 { 898 dbus_set_error (error, 899 DBUS_ERROR_NAME_HAS_NO_OWNER, 900 "Could not get UID of name '%s': no such name", service); 901 goto failed; 902 } 903 904 conn = bus_service_get_primary_owner (serv); 905 906 reply = dbus_message_new_method_return (message); 907 if (reply == NULL) 908 goto oom; 909 910 if (!dbus_connection_get_unix_user (conn, &uid)) 911 { 912 dbus_set_error (error, 913 DBUS_ERROR_FAILED, 914 "Could not determine UID for '%s'", service); 915 goto failed; 916 } 917 918 uid32 = uid; 919 if (! dbus_message_append_args (reply, 920 DBUS_TYPE_UINT32, &uid32, 921 DBUS_TYPE_INVALID)) 922 goto oom; 923 924 if (! bus_transaction_send_from_driver (transaction, connection, reply)) 925 goto oom; 926 927 dbus_message_unref (reply); 928 929 return TRUE; 930 931 oom: 932 BUS_SET_OOM (error); 933 934 failed: 935 _DBUS_ASSERT_ERROR_IS_SET (error); 936 if (reply) 937 dbus_message_unref (reply); 938 return FALSE; 939} 940 941static dbus_bool_t 942bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, 943 BusTransaction *transaction, 944 DBusMessage *message, 945 DBusError *error) 946{ 947 const char *service; 948 DBusString str; 949 BusRegistry *registry; 950 BusService *serv; 951 DBusConnection *conn; 952 DBusMessage *reply; 953 unsigned long pid; 954 dbus_uint32_t pid32; 955 956 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 957 958 registry = bus_connection_get_registry (connection); 959 960 service = NULL; 961 reply = NULL; 962 963 if (! dbus_message_get_args (message, error, 964 DBUS_TYPE_STRING, &service, 965 DBUS_TYPE_INVALID)) 966 goto failed; 967 968 _dbus_verbose ("asked for PID of connection %s\n", service); 969 970 _dbus_string_init_const (&str, service); 971 serv = bus_registry_lookup (registry, &str); 972 if (serv == NULL) 973 { 974 dbus_set_error (error, 975 DBUS_ERROR_NAME_HAS_NO_OWNER, 976 "Could not get PID of name '%s': no such name", service); 977 goto failed; 978 } 979 980 conn = bus_service_get_primary_owner (serv); 981 982 reply = dbus_message_new_method_return (message); 983 if (reply == NULL) 984 goto oom; 985 986 if (!dbus_connection_get_unix_process_id (conn, &pid)) 987 { 988 dbus_set_error (error, 989 DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, 990 "Could not determine PID for '%s'", service); 991 goto failed; 992 } 993 994 pid32 = pid; 995 if (! dbus_message_append_args (reply, 996 DBUS_TYPE_UINT32, &pid32, 997 DBUS_TYPE_INVALID)) 998 goto oom; 999 1000 if (! bus_transaction_send_from_driver (transaction, connection, reply)) 1001 goto oom; 1002 1003 dbus_message_unref (reply); 1004 1005 return TRUE; 1006 1007 oom: 1008 BUS_SET_OOM (error); 1009 1010 failed: 1011 _DBUS_ASSERT_ERROR_IS_SET (error); 1012 if (reply) 1013 dbus_message_unref (reply); 1014 return FALSE; 1015} 1016 1017static dbus_bool_t 1018bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection, 1019 BusTransaction *transaction, 1020 DBusMessage *message, 1021 DBusError *error) 1022{ 1023 const char *service; 1024 DBusString str; 1025 BusRegistry *registry; 1026 BusService *serv; 1027 DBusConnection *conn; 1028 DBusMessage *reply; 1029 BusSELinuxID *context; 1030 1031 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1032 1033 registry = bus_connection_get_registry (connection); 1034 1035 service = NULL; 1036 reply = NULL; 1037 1038 if (! dbus_message_get_args (message, error, 1039 DBUS_TYPE_STRING, &service, 1040 DBUS_TYPE_INVALID)) 1041 goto failed; 1042 1043 _dbus_verbose ("asked for security context of connection %s\n", service); 1044 1045 _dbus_string_init_const (&str, service); 1046 serv = bus_registry_lookup (registry, &str); 1047 if (serv == NULL) 1048 { 1049 dbus_set_error (error, 1050 DBUS_ERROR_NAME_HAS_NO_OWNER, 1051 "Could not get security context of name '%s': no such name", service); 1052 goto failed; 1053 } 1054 1055 conn = bus_service_get_primary_owner (serv); 1056 1057 reply = dbus_message_new_method_return (message); 1058 if (reply == NULL) 1059 goto oom; 1060 1061 context = bus_connection_get_selinux_id (conn); 1062 if (!context) 1063 { 1064 dbus_set_error (error, 1065 DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN, 1066 "Could not determine security context for '%s'", service); 1067 goto failed; 1068 } 1069 1070 if (! bus_selinux_append_context (reply, context, error)) 1071 goto failed; 1072 1073 if (! bus_transaction_send_from_driver (transaction, connection, reply)) 1074 goto oom; 1075 1076 dbus_message_unref (reply); 1077 1078 return TRUE; 1079 1080 oom: 1081 BUS_SET_OOM (error); 1082 1083 failed: 1084 _DBUS_ASSERT_ERROR_IS_SET (error); 1085 if (reply) 1086 dbus_message_unref (reply); 1087 return FALSE; 1088} 1089 1090static dbus_bool_t 1091bus_driver_handle_reload_config (DBusConnection *connection, 1092 BusTransaction *transaction, 1093 DBusMessage *message, 1094 DBusError *error) 1095{ 1096 BusContext *context; 1097 dbus_bool_t retval; 1098 1099 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1100 1101 retval = FALSE; 1102 1103 context = bus_connection_get_context (connection); 1104 if (!bus_context_reload_config (context, error)) 1105 { 1106 _DBUS_ASSERT_ERROR_IS_SET (error); 1107 goto out; 1108 } 1109 1110 retval = TRUE; 1111 1112 out: 1113 return retval; 1114} 1115 1116/* For speed it might be useful to sort this in order of 1117 * frequency of use (but doesn't matter with only a few items 1118 * anyhow) 1119 */ 1120struct 1121{ 1122 const char *name; 1123 const char *in_args; 1124 const char *out_args; 1125 dbus_bool_t (* handler) (DBusConnection *connection, 1126 BusTransaction *transaction, 1127 DBusMessage *message, 1128 DBusError *error); 1129} message_handlers[] = { 1130 { "RequestName", 1131 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING, 1132 DBUS_TYPE_UINT32_AS_STRING, 1133 bus_driver_handle_acquire_service }, 1134 { "StartServiceByName", 1135 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING, 1136 DBUS_TYPE_UINT32_AS_STRING, 1137 bus_driver_handle_activate_service }, 1138 { "Hello", 1139 "", 1140 DBUS_TYPE_STRING_AS_STRING, 1141 bus_driver_handle_hello }, 1142 { "NameHasOwner", 1143 DBUS_TYPE_STRING_AS_STRING, 1144 DBUS_TYPE_BOOLEAN_AS_STRING, 1145 bus_driver_handle_service_exists }, 1146 { "ListNames", 1147 "", 1148 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, 1149 bus_driver_handle_list_services }, 1150 { "AddMatch", 1151 DBUS_TYPE_STRING_AS_STRING, 1152 "", 1153 bus_driver_handle_add_match }, 1154 { "RemoveMatch", 1155 DBUS_TYPE_STRING_AS_STRING, 1156 "", 1157 bus_driver_handle_remove_match }, 1158 { "GetNameOwner", 1159 DBUS_TYPE_STRING_AS_STRING, 1160 DBUS_TYPE_STRING_AS_STRING, 1161 bus_driver_handle_get_service_owner }, 1162 { "GetConnectionUnixUser", 1163 DBUS_TYPE_STRING_AS_STRING, 1164 DBUS_TYPE_UINT32_AS_STRING, 1165 bus_driver_handle_get_connection_unix_user }, 1166 { "GetConnectionUnixProcessID", 1167 DBUS_TYPE_STRING_AS_STRING, 1168 DBUS_TYPE_UINT32_AS_STRING, 1169 bus_driver_handle_get_connection_unix_process_id }, 1170 { "GetConnectionSELinuxSecurityContext", 1171 DBUS_TYPE_STRING_AS_STRING, 1172 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, 1173 bus_driver_handle_get_connection_selinux_security_context }, 1174 { "ReloadConfig", 1175 "", 1176 "", 1177 bus_driver_handle_reload_config } 1178}; 1179 1180static dbus_bool_t 1181write_args_for_direction (DBusString *xml, 1182 const char *signature, 1183 dbus_bool_t in) 1184{ 1185 DBusTypeReader typereader; 1186 DBusString sigstr; 1187 int current_type; 1188 1189 _dbus_string_init_const (&sigstr, signature); 1190 _dbus_type_reader_init_types_only (&typereader, &sigstr, 0); 1191 1192 while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID) 1193 { 1194 const DBusString *subsig; 1195 int start, len; 1196 1197 _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len); 1198 if (!_dbus_string_append_printf (xml, " <arg direction=\"%s\" type=\"", 1199 in ? "in" : "out")) 1200 goto oom; 1201 if (!_dbus_string_append_len (xml, 1202 _dbus_string_get_const_data (subsig) + start, 1203 len)) 1204 goto oom; 1205 if (!_dbus_string_append (xml, "\"/>\n")) 1206 goto oom; 1207 1208 _dbus_type_reader_next (&typereader); 1209 } 1210 return TRUE; 1211 oom: 1212 return FALSE; 1213} 1214 1215static dbus_bool_t 1216bus_driver_handle_introspect (DBusConnection *connection, 1217 BusTransaction *transaction, 1218 DBusMessage *message, 1219 DBusError *error) 1220{ 1221 DBusString xml; 1222 DBusMessage *reply; 1223 const char *v_STRING; 1224 int i; 1225 1226 _dbus_verbose ("Introspect() on bus driver\n"); 1227 1228 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1229 1230 reply = NULL; 1231 1232 if (! dbus_message_get_args (message, error, 1233 DBUS_TYPE_INVALID)) 1234 { 1235 _DBUS_ASSERT_ERROR_IS_SET (error); 1236 return FALSE; 1237 } 1238 1239 if (!_dbus_string_init (&xml)) 1240 { 1241 BUS_SET_OOM (error); 1242 return FALSE; 1243 } 1244 1245 if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE)) 1246 goto oom; 1247 if (!_dbus_string_append (&xml, "<node>\n")) 1248 goto oom; 1249 if (!_dbus_string_append_printf (&xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE)) 1250 goto oom; 1251 if (!_dbus_string_append (&xml, " <method name=\"Introspect\">\n")) 1252 goto oom; 1253 if (!_dbus_string_append_printf (&xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING)) 1254 goto oom; 1255 if (!_dbus_string_append (&xml, " </method>\n")) 1256 goto oom; 1257 if (!_dbus_string_append (&xml, " </interface>\n")) 1258 goto oom; 1259 1260 if (!_dbus_string_append_printf (&xml, " <interface name=\"%s\">\n", 1261 DBUS_INTERFACE_DBUS)) 1262 goto oom; 1263 1264 i = 0; 1265 while (i < _DBUS_N_ELEMENTS (message_handlers)) 1266 { 1267 1268 if (!_dbus_string_append_printf (&xml, " <method name=\"%s\">\n", 1269 message_handlers[i].name)) 1270 goto oom; 1271 1272 if (!write_args_for_direction (&xml, message_handlers[i].in_args, TRUE)) 1273 goto oom; 1274 1275 if (!write_args_for_direction (&xml, message_handlers[i].out_args, FALSE)) 1276 goto oom; 1277 1278 if (!_dbus_string_append (&xml, " </method>\n")) 1279 goto oom; 1280 1281 ++i; 1282 } 1283 1284 if (!_dbus_string_append_printf (&xml, " <signal name=\"NameOwnerChanged\">\n")) 1285 goto oom; 1286 1287 if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) 1288 goto oom; 1289 1290 if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) 1291 goto oom; 1292 1293 if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) 1294 goto oom; 1295 1296 if (!_dbus_string_append_printf (&xml, " </signal>\n")) 1297 goto oom; 1298 1299 1300 1301 if (!_dbus_string_append_printf (&xml, " <signal name=\"NameLost\">\n")) 1302 goto oom; 1303 1304 if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) 1305 goto oom; 1306 1307 if (!_dbus_string_append_printf (&xml, " </signal>\n")) 1308 goto oom; 1309 1310 1311 1312 if (!_dbus_string_append_printf (&xml, " <signal name=\"NameAcquired\">\n")) 1313 goto oom; 1314 1315 if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) 1316 goto oom; 1317 1318 if (!_dbus_string_append_printf (&xml, " </signal>\n")) 1319 goto oom; 1320 1321 1322 1323 if (!_dbus_string_append (&xml, " </interface>\n")) 1324 goto oom; 1325 1326 if (!_dbus_string_append (&xml, "</node>\n")) 1327 goto oom; 1328 1329 reply = dbus_message_new_method_return (message); 1330 if (reply == NULL) 1331 goto oom; 1332 1333 v_STRING = _dbus_string_get_const_data (&xml); 1334 if (! dbus_message_append_args (reply, 1335 DBUS_TYPE_STRING, &v_STRING, 1336 DBUS_TYPE_INVALID)) 1337 goto oom; 1338 1339 if (! bus_transaction_send_from_driver (transaction, connection, reply)) 1340 goto oom; 1341 1342 dbus_message_unref (reply); 1343 _dbus_string_free (&xml); 1344 1345 return TRUE; 1346 1347 oom: 1348 BUS_SET_OOM (error); 1349 1350 if (reply) 1351 dbus_message_unref (reply); 1352 1353 _dbus_string_free (&xml); 1354 1355 return FALSE; 1356} 1357 1358dbus_bool_t 1359bus_driver_handle_message (DBusConnection *connection, 1360 BusTransaction *transaction, 1361 DBusMessage *message, 1362 DBusError *error) 1363{ 1364 const char *name, *sender, *interface; 1365 int i; 1366 1367 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1368 1369 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) 1370 { 1371 _dbus_verbose ("Driver got a non-method-call message, ignoring\n"); 1372 return TRUE; /* we just ignore this */ 1373 } 1374 1375 if (dbus_message_is_method_call (message, 1376 DBUS_INTERFACE_INTROSPECTABLE, 1377 "Introspect")) 1378 return bus_driver_handle_introspect (connection, transaction, message, error); 1379 1380 interface = dbus_message_get_interface (message); 1381 if (interface == NULL) 1382 interface = DBUS_INTERFACE_DBUS; 1383 1384 _dbus_assert (dbus_message_get_member (message) != NULL); 1385 1386 name = dbus_message_get_member (message); 1387 sender = dbus_message_get_sender (message); 1388 1389 if (strcmp (interface, 1390 DBUS_INTERFACE_DBUS) != 0) 1391 { 1392 _dbus_verbose ("Driver got message to unknown interface \"%s\"\n", 1393 interface); 1394 goto unknown; 1395 } 1396 1397 _dbus_verbose ("Driver got a method call: %s\n", 1398 dbus_message_get_member (message)); 1399 1400 /* security checks should have kept this from getting here */ 1401 _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0); 1402 1403 i = 0; 1404 while (i < _DBUS_N_ELEMENTS (message_handlers)) 1405 { 1406 if (strcmp (message_handlers[i].name, name) == 0) 1407 { 1408 _dbus_verbose ("Found driver handler for %s\n", name); 1409 1410 if (!dbus_message_has_signature (message, message_handlers[i].in_args)) 1411 { 1412 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1413 _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n", 1414 name, dbus_message_get_signature (message), 1415 message_handlers[i].in_args); 1416 1417 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 1418 "Call to %s has wrong args (%s, expected %s)\n", 1419 name, dbus_message_get_signature (message), 1420 message_handlers[i].in_args); 1421 _DBUS_ASSERT_ERROR_IS_SET (error); 1422 return FALSE; 1423 } 1424 1425 if ((* message_handlers[i].handler) (connection, transaction, message, error)) 1426 { 1427 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1428 _dbus_verbose ("Driver handler succeeded\n"); 1429 return TRUE; 1430 } 1431 else 1432 { 1433 _DBUS_ASSERT_ERROR_IS_SET (error); 1434 _dbus_verbose ("Driver handler returned failure\n"); 1435 return FALSE; 1436 } 1437 } 1438 1439 ++i; 1440 } 1441 1442 unknown: 1443 _dbus_verbose ("No driver handler for message \"%s\"\n", 1444 name); 1445 1446 dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD, 1447 "%s does not understand message %s", 1448 DBUS_SERVICE_DBUS, name); 1449 1450 return FALSE; 1451} 1452 1453void 1454bus_driver_remove_connection (DBusConnection *connection) 1455{ 1456 /* FIXME Does nothing for now, should unregister the connection 1457 * with the bus driver. 1458 */ 1459} 1460