blob: cc8d1f2639b6ab13dac2f7c24a4654691e269773 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25#include <config.h>
26#include "activation.h"
27#include "connection.h"
28#include "driver.h"
29#include "dispatch.h"
30#include "services.h"
31#include "selinux.h"
32#include "signals.h"
33#include "utils.h"
34#include <dbus/dbus-string.h>
35#include <dbus/dbus-internals.h>
36#include <dbus/dbus-message.h>
37#include <dbus/dbus-marshal-recursive.h>
38#include <string.h>
39
40static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
41 DBusMessage *hello_message,
42 BusTransaction *transaction,
43 DBusError *error);
44
45dbus_bool_t
46bus_driver_send_service_owner_changed (const char *service_name,
47 const char *old_owner,
48 const char *new_owner,
49 BusTransaction *transaction,
50 DBusError *error)
51{
52 DBusMessage *message;
53 dbus_bool_t retval;
54 const char *null_service;
55
56 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
57
58 null_service = "";
59 _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n",
60 service_name,
61 old_owner ? old_owner : null_service,
62 new_owner ? new_owner : null_service);
63
64 message = dbus_message_new_signal (DBUS_PATH_DBUS,
65 DBUS_INTERFACE_DBUS,
66 "NameOwnerChanged");
67
68 if (message == NULL)
69 {
70 BUS_SET_OOM (error);
71 return FALSE;
72 }
73
74 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
75 goto oom;
76
77 if (!dbus_message_append_args (message,
78 DBUS_TYPE_STRING, &service_name,
79 DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service,
80 DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service,
81 DBUS_TYPE_INVALID))
82 goto oom;
83
84 _dbus_assert (dbus_message_has_signature (message, "sss"));
85
86 retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
87 dbus_message_unref (message);
88
89 return retval;
90
91 oom:
92 dbus_message_unref (message);
93 BUS_SET_OOM (error);
94 return FALSE;
95}
96
97dbus_bool_t
98bus_driver_send_service_lost (DBusConnection *connection,
99 const char *service_name,
100 BusTransaction *transaction,
101 DBusError *error)
102{
103 DBusMessage *message;
104
105 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
106
107 message = dbus_message_new_signal (DBUS_PATH_DBUS,
108 DBUS_INTERFACE_DBUS,
109 "NameLost");
110
111 if (message == NULL)
112 {
113 BUS_SET_OOM (error);
114 return FALSE;
115 }
116
117 if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
118 !dbus_message_append_args (message,
119 DBUS_TYPE_STRING, &service_name,
120 DBUS_TYPE_INVALID))
121 {
122 dbus_message_unref (message);
123 BUS_SET_OOM (error);
124 return FALSE;
125 }
126
127 if (!bus_transaction_send_from_driver (transaction, connection, message))
128 {
129 dbus_message_unref (message);
130 BUS_SET_OOM (error);
131 return FALSE;
132 }
133 else
134 {
135 dbus_message_unref (message);
136 return TRUE;
137 }
138}
139
140dbus_bool_t
141bus_driver_send_service_acquired (DBusConnection *connection,
142 const char *service_name,
143 BusTransaction *transaction,
144 DBusError *error)
145{
146 DBusMessage *message;
147
148 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
149
150 message = dbus_message_new_signal (DBUS_PATH_DBUS,
151 DBUS_INTERFACE_DBUS,
152 "NameAcquired");
153
154 if (message == NULL)
155 {
156 BUS_SET_OOM (error);
157 return FALSE;
158 }
159
160 if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
161 !dbus_message_append_args (message,
162 DBUS_TYPE_STRING, &service_name,
163 DBUS_TYPE_INVALID))
164 {
165 dbus_message_unref (message);
166 BUS_SET_OOM (error);
167 return FALSE;
168 }
169
170 if (!bus_transaction_send_from_driver (transaction, connection, message))
171 {
172 dbus_message_unref (message);
173 BUS_SET_OOM (error);
174 return FALSE;
175 }
176 else
177 {
178 dbus_message_unref (message);
179 return TRUE;
180 }
181}
182
183static dbus_bool_t
184create_unique_client_name (BusRegistry *registry,
185 DBusString *str)
186{
187 /* We never want to use the same unique client name twice, because
188 * we want to guarantee that if you send a message to a given unique
189 * name, you always get the same application. So we use two numbers
190 * for INT_MAX * INT_MAX combinations, should be pretty safe against
191 * wraparound.
192 */
193 /* FIXME these should be in BusRegistry rather than static vars */
194 static int next_major_number = 0;
195 static int next_minor_number = 0;
196 int len;
197
198 len = _dbus_string_get_length (str);
199
200 while (TRUE)
201 {
202 /* start out with 1-0, go to 1-1, 1-2, 1-3,
203 * up to 1-MAXINT, then 2-0, 2-1, etc.
204 */
205 if (next_minor_number <= 0)
206 {
207 next_major_number += 1;
208 next_minor_number = 0;
209 if (next_major_number <= 0)
210 _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
211 }
212
213 _dbus_assert (next_major_number > 0);
214 _dbus_assert (next_minor_number >= 0);
215
216 /* appname:MAJOR-MINOR */
217
218 if (!_dbus_string_append (str, ":"))
219 return FALSE;
220
221 if (!_dbus_string_append_int (str, next_major_number))
222 return FALSE;
223
224 if (!_dbus_string_append (str, "."))
225 return FALSE;
226
227 if (!_dbus_string_append_int (str, next_minor_number))
228 return FALSE;
229
230 next_minor_number += 1;
231
232 /* Check if a client with the name exists */
233 if (bus_registry_lookup (registry, str) == NULL)
234 break;
235
236 /* drop the number again, try the next one. */
237 _dbus_string_set_length (str, len);
238 }
239
240 return TRUE;
241}
242
243static dbus_bool_t
244bus_driver_handle_hello (DBusConnection *connection,
245 BusTransaction *transaction,
246 DBusMessage *message,
247 DBusError *error)
248{
249 DBusString unique_name;
250 BusService *service;
251 dbus_bool_t retval;
252 BusRegistry *registry;
253 BusConnections *connections;
254
255 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
256
257 if (bus_connection_is_active (connection))
258 {
259 /* We already handled an Hello message for this connection. */
260 dbus_set_error (error, DBUS_ERROR_FAILED,
261 "Already handled an Hello message");
262 return FALSE;
263 }
264
265 /* Note that when these limits are exceeded we don't disconnect the
266 * connection; we just sort of leave it hanging there until it times
267 * out or disconnects itself or is dropped due to the max number of
268 * incomplete connections. It's even OK if the connection wants to
269 * retry the hello message, we support that.
270 */
271 connections = bus_connection_get_connections (connection);
272 if (!bus_connections_check_limits (connections, connection,
273 error))
274 {
275 _DBUS_ASSERT_ERROR_IS_SET (error);
276 return FALSE;
277 }
278
279 if (!_dbus_string_init (&unique_name))
280 {
281 BUS_SET_OOM (error);
282 return FALSE;
283 }
284
285 retval = FALSE;
286
287 registry = bus_connection_get_registry (connection);
288
289 if (!create_unique_client_name (registry, &unique_name))
290 {
291 BUS_SET_OOM (error);
292 goto out_0;
293 }
294
295 if (!bus_connection_complete (connection, &unique_name, error))
296 {
297 _DBUS_ASSERT_ERROR_IS_SET (error);
298 goto out_0;
299 }
300
301 if (!dbus_message_set_sender (message,
302 bus_connection_get_name (connection)))
303 {
304 BUS_SET_OOM (error);
305 goto out_0;
306 }
307
308 if (!bus_driver_send_welcome_message (connection, message, transaction, error))
309 goto out_0;
310
311 /* Create the service */
312 service = bus_registry_ensure (registry,
313 &unique_name, connection, 0, transaction, error);
314 if (service == NULL)
315 goto out_0;
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 dbus_free_string_array (services);
442
443 if (!dbus_message_iter_close_container (&iter, &sub))
444 {
445 dbus_message_unref (reply);
446 BUS_SET_OOM (error);
447 return FALSE;
448 }
449
450 if (!bus_transaction_send_from_driver (transaction, connection, reply))
451 {
452 dbus_message_unref (reply);
453 BUS_SET_OOM (error);
454 return FALSE;
455 }
456 else
457 {
458 dbus_message_unref (reply);
459 return TRUE;
460 }
461}
462
463static dbus_bool_t
464bus_driver_handle_list_activatable_services (DBusConnection *connection,
465 BusTransaction *transaction,
466 DBusMessage *message,
467 DBusError *error)
468{
469 DBusMessage *reply;
470 int len;
471 char **services;
472 BusActivation *activation;
473 int i;
474 DBusMessageIter iter;
475 DBusMessageIter sub;
476
477 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
478
479 activation = bus_connection_get_activation (connection);
480
481 reply = dbus_message_new_method_return (message);
482 if (reply == NULL)
483 {
484 BUS_SET_OOM (error);
485 return FALSE;
486 }
487
488 if (!bus_activation_list_services (activation, &services, &len))
489 {
490 dbus_message_unref (reply);
491 BUS_SET_OOM (error);
492 return FALSE;
493 }
494
495 dbus_message_iter_init_append (reply, &iter);
496
497 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
498 DBUS_TYPE_STRING_AS_STRING,
499 &sub))
500 {
501 dbus_free_string_array (services);
502 dbus_message_unref (reply);
503 BUS_SET_OOM (error);
504 return FALSE;
505 }
506
507 {
508 /* Include the bus driver in the list */
509 const char *v_STRING = DBUS_SERVICE_DBUS;
510 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
511 &v_STRING))
512 {
513 dbus_free_string_array (services);
514 dbus_message_unref (reply);
515 BUS_SET_OOM (error);
516 return FALSE;
517 }
518 }
519
520 i = 0;
521 while (i < len)
522 {
523 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
524 &services[i]))
525 {
526 dbus_free_string_array (services);
527 dbus_message_unref (reply);
528 BUS_SET_OOM (error);
529 return FALSE;
530 }
531 ++i;
532 }
533
534 dbus_free_string_array (services);
535
536 if (!dbus_message_iter_close_container (&iter, &sub))
537 {
538 dbus_message_unref (reply);
539 BUS_SET_OOM (error);
540 return FALSE;
541 }
542
543 if (!bus_transaction_send_from_driver (transaction, connection, reply))
544 {
545 dbus_message_unref (reply);
546 BUS_SET_OOM (error);
547 return FALSE;
548 }
549 else
550 {
551 dbus_message_unref (reply);
552 return TRUE;
553 }
554}
555
556static dbus_bool_t
557bus_driver_handle_acquire_service (DBusConnection *connection,
558 BusTransaction *transaction,
559 DBusMessage *message,
560 DBusError *error)
561{
562 DBusMessage *reply;
563 DBusString service_name;
564 const char *name;
565 dbus_uint32_t service_reply;
566 dbus_uint32_t flags;
567 dbus_bool_t retval;
568 BusRegistry *registry;
569
570 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
571
572 registry = bus_connection_get_registry (connection);
573
574 if (!dbus_message_get_args (message, error,
575 DBUS_TYPE_STRING, &name,
576 DBUS_TYPE_UINT32, &flags,
577 DBUS_TYPE_INVALID))
578 return FALSE;
579
580 _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags);
581
582 retval = FALSE;
583 reply = NULL;
584
585 _dbus_string_init_const (&service_name, name);
586
587 if (!bus_registry_acquire_service (registry, connection,
588 &service_name, flags,
589 &service_reply, transaction,
590 error))
591 goto out;
592
593 reply = dbus_message_new_method_return (message);
594 if (reply == NULL)
595 {
596 BUS_SET_OOM (error);
597 goto out;
598 }
599
600 if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
601 {
602 BUS_SET_OOM (error);
603 goto out;
604 }
605
606 if (!bus_transaction_send_from_driver (transaction, connection, reply))
607 {
608 BUS_SET_OOM (error);
609 goto out;
610 }
611
612 retval = TRUE;
613
614 out:
615 if (reply)
616 dbus_message_unref (reply);
617 return retval;
618}
619
620static dbus_bool_t
621bus_driver_handle_release_service (DBusConnection *connection,
622 BusTransaction *transaction,
623 DBusMessage *message,
624 DBusError *error)
625{
626 DBusMessage *reply;
627 DBusString service_name;
628 const char *name;
629 dbus_uint32_t service_reply;
630 dbus_bool_t retval;
631 BusRegistry *registry;
632
633 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
634
635 registry = bus_connection_get_registry (connection);
636
637 if (!dbus_message_get_args (message, error,
638 DBUS_TYPE_STRING, &name,
639 DBUS_TYPE_INVALID))
640 return FALSE;
641
642 _dbus_verbose ("Trying to release name %s\n", name);
643
644 retval = FALSE;
645 reply = NULL;
646
647 _dbus_string_init_const (&service_name, name);
648
649 if (!bus_registry_release_service (registry, connection,
650 &service_name, &service_reply,
651 transaction, error))
652 goto out;
653
654 reply = dbus_message_new_method_return (message);
655 if (reply == NULL)
656 {
657 BUS_SET_OOM (error);
658 goto out;
659 }
660
661 if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
662 {
663 BUS_SET_OOM (error);
664 goto out;
665 }
666
667 if (!bus_transaction_send_from_driver (transaction, connection, reply))
668 {
669 BUS_SET_OOM (error);
670 goto out;
671 }
672
673 retval = TRUE;
674
675 out:
676 if (reply)
677 dbus_message_unref (reply);
678 return retval;
679}
680
681static dbus_bool_t
682bus_driver_handle_service_exists (DBusConnection *connection,
683 BusTransaction *transaction,
684 DBusMessage *message,
685 DBusError *error)
686{
687 DBusMessage *reply;
688 DBusString service_name;
689 BusService *service;
690 dbus_bool_t service_exists;
691 const char *name;
692 dbus_bool_t retval;
693 BusRegistry *registry;
694
695 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
696
697 registry = bus_connection_get_registry (connection);
698
699 if (!dbus_message_get_args (message, error,
700 DBUS_TYPE_STRING, &name,
701 DBUS_TYPE_INVALID))
702 return FALSE;
703
704 retval = FALSE;
705
706 if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
707 {
708 service_exists = TRUE;
709 }
710 else
711 {
712 _dbus_string_init_const (&service_name, name);
713 service = bus_registry_lookup (registry, &service_name);
714 service_exists = service != NULL;
715 }
716
717 reply = dbus_message_new_method_return (message);
718 if (reply == NULL)
719 {
720 BUS_SET_OOM (error);
721 goto out;
722 }
723
724 if (!dbus_message_append_args (reply,
725 DBUS_TYPE_BOOLEAN, &service_exists,
726 0))
727 {
728 BUS_SET_OOM (error);
729 goto out;
730 }
731
732 if (!bus_transaction_send_from_driver (transaction, connection, reply))
733 {
734 BUS_SET_OOM (error);
735 goto out;
736 }
737
738 retval = TRUE;
739
740 out:
741 if (reply)
742 dbus_message_unref (reply);
743
744 return retval;
745}
746
747static dbus_bool_t
748bus_driver_handle_activate_service (DBusConnection *connection,
749 BusTransaction *transaction,
750 DBusMessage *message,
751 DBusError *error)
752{
753 dbus_uint32_t flags;
754 const char *name;
755 dbus_bool_t retval;
756 BusActivation *activation;
757
758 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
759
760 activation = bus_connection_get_activation (connection);
761
762 if (!dbus_message_get_args (message, error,
763 DBUS_TYPE_STRING, &name,
764 DBUS_TYPE_UINT32, &flags,
765 DBUS_TYPE_INVALID))
766 {
767 _DBUS_ASSERT_ERROR_IS_SET (error);
768 _dbus_verbose ("No memory to get arguments to StartServiceByName\n");
769 return FALSE;
770 }
771
772 retval = FALSE;
773
774 if (!bus_activation_activate_service (activation, connection, transaction, FALSE,
775 message, name, error))
776 {
777 _DBUS_ASSERT_ERROR_IS_SET (error);
778 _dbus_verbose ("bus_activation_activate_service() failed\n");
779 goto out;
780 }
781
782 retval = TRUE;
783
784 out:
785 return retval;
786}
787
788static dbus_bool_t
789send_ack_reply (DBusConnection *connection,
790 BusTransaction *transaction,
791 DBusMessage *message,
792 DBusError *error)
793{
794 DBusMessage *reply;
795
796 if (dbus_message_get_no_reply (message))
797 return TRUE;
798
799 reply = dbus_message_new_method_return (message);
800 if (reply == NULL)
801 {
802 BUS_SET_OOM (error);
803 return FALSE;
804 }
805
806 if (!bus_transaction_send_from_driver (transaction, connection, reply))
807 {
808 BUS_SET_OOM (error);
809 dbus_message_unref (reply);
810 return FALSE;
811 }
812
813 dbus_message_unref (reply);
814
815 return TRUE;
816}
817
818static dbus_bool_t
819bus_driver_handle_update_activation_environment (DBusConnection *connection,
820 BusTransaction *transaction,
821 DBusMessage *message,
822 DBusError *error)
823{
824 dbus_bool_t retval;
825 BusActivation *activation;
826 DBusMessageIter iter;
827 DBusMessageIter dict_iter;
828 DBusMessageIter dict_entry_iter;
829 int msg_type;
830 int array_type;
831 int key_type;
832 DBusList *keys, *key_link;
833 DBusList *values, *value_link;
834
835 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
836
837 activation = bus_connection_get_activation (connection);
838
839 dbus_message_iter_init (message, &iter);
840
841 /* The message signature has already been checked for us,
842 * so let's just assert it's right.
843 */
844 msg_type = dbus_message_iter_get_arg_type (&iter);
845
846 _dbus_assert (msg_type == DBUS_TYPE_ARRAY);
847
848 dbus_message_iter_recurse (&iter, &dict_iter);
849
850 retval = FALSE;
851
852 /* Then loop through the sent dictionary, add the location of
853 * the environment keys and values to lists. The result will
854 * be in reverse order, so we don't have to constantly search
855 * for the end of the list in a loop.
856 */
857 keys = NULL;
858 values = NULL;
859 while ((array_type = dbus_message_iter_get_arg_type (&dict_iter)) == DBUS_TYPE_DICT_ENTRY)
860 {
861 dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
862
863 while ((key_type = dbus_message_iter_get_arg_type (&dict_entry_iter)) == DBUS_TYPE_STRING)
864 {
865 char *key;
866 char *value;
867 int value_type;
868
869 dbus_message_iter_get_basic (&dict_entry_iter, &key);
870 dbus_message_iter_next (&dict_entry_iter);
871
872 value_type = dbus_message_iter_get_arg_type (&dict_entry_iter);
873
874 if (value_type != DBUS_TYPE_STRING)
875 break;
876
877 dbus_message_iter_get_basic (&dict_entry_iter, &value);
878
879 if (!_dbus_list_append (&keys, key))
880 {
881 BUS_SET_OOM (error);
882 break;
883 }
884
885 if (!_dbus_list_append (&values, value))
886 {
887 BUS_SET_OOM (error);
888 break;
889 }
890
891 dbus_message_iter_next (&dict_entry_iter);
892 }
893
894 if (key_type != DBUS_TYPE_INVALID)
895 break;
896
897 dbus_message_iter_next (&dict_iter);
898 }
899
900 if (array_type != DBUS_TYPE_INVALID)
901 goto out;
902
903 _dbus_assert (_dbus_list_get_length (&keys) == _dbus_list_get_length (&values));
904
905 key_link = keys;
906 value_link = values;
907 while (key_link != NULL)
908 {
909 const char *key;
910 const char *value;
911
912 key = key_link->data;
913 value = value_link->data;
914
915 if (!bus_activation_set_environment_variable (activation,
916 key, value, error))
917 {
918 _DBUS_ASSERT_ERROR_IS_SET (error);
919 _dbus_verbose ("bus_activation_set_environment_variable() failed\n");
920 break;
921 }
922 key_link = _dbus_list_get_next_link (&keys, key_link);
923 value_link = _dbus_list_get_next_link (&values, value_link);
924 }
925
926 /* FIXME: We can fail early having set only some of the environment variables,
927 * (because of OOM failure). It's sort of hard to fix and it doesn't really
928 * matter, so we're punting for now.
929 */
930 if (key_link != NULL)
931 goto out;
932
933 if (!send_ack_reply (connection, transaction,
934 message, error))
935 goto out;
936
937 retval = TRUE;
938
939 out:
940 _dbus_list_clear (&keys);
941 _dbus_list_clear (&values);
942 return retval;
943}
944
945static dbus_bool_t
946bus_driver_handle_add_match (DBusConnection *connection,
947 BusTransaction *transaction,
948 DBusMessage *message,
949 DBusError *error)
950{
951 BusMatchRule *rule;
952 const char *text;
953 DBusString str;
954 BusMatchmaker *matchmaker;
955
956 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
957
958 text = NULL;
959 rule = NULL;
960
961 if (bus_connection_get_n_match_rules (connection) >=
962 bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
963 {
964 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
965 "Connection \"%s\" is not allowed to add more match rules "
966 "(increase limits in configuration file if required)",
967 bus_connection_is_active (connection) ?
968 bus_connection_get_name (connection) :
969 "(inactive)");
970 goto failed;
971 }
972
973 if (!dbus_message_get_args (message, error,
974 DBUS_TYPE_STRING, &text,
975 DBUS_TYPE_INVALID))
976 {
977 _dbus_verbose ("No memory to get arguments to AddMatch\n");
978 goto failed;
979 }
980
981 _dbus_string_init_const (&str, text);
982
983 rule = bus_match_rule_parse (connection, &str, error);
984 if (rule == NULL)
985 goto failed;
986
987 matchmaker = bus_connection_get_matchmaker (connection);
988
989 if (!bus_matchmaker_add_rule (matchmaker, rule))
990 {
991 BUS_SET_OOM (error);
992 goto failed;
993 }
994
995 if (!send_ack_reply (connection, transaction,
996 message, error))
997 {
998 bus_matchmaker_remove_rule (matchmaker, rule);
999 goto failed;
1000 }
1001
1002 bus_match_rule_unref (rule);
1003
1004 return TRUE;
1005
1006 failed:
1007 _DBUS_ASSERT_ERROR_IS_SET (error);
1008 if (rule)
1009 bus_match_rule_unref (rule);
1010 return FALSE;
1011}
1012
1013static dbus_bool_t
1014bus_driver_handle_remove_match (DBusConnection *connection,
1015 BusTransaction *transaction,
1016 DBusMessage *message,
1017 DBusError *error)
1018{
1019 BusMatchRule *rule;
1020 const char *text;
1021 DBusString str;
1022 BusMatchmaker *matchmaker;
1023
1024 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1025
1026 text = NULL;
1027 rule = NULL;
1028
1029 if (!dbus_message_get_args (message, error,
1030 DBUS_TYPE_STRING, &text,
1031 DBUS_TYPE_INVALID))
1032 {
1033 _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
1034 goto failed;
1035 }
1036
1037 _dbus_string_init_const (&str, text);
1038
1039 rule = bus_match_rule_parse (connection, &str, error);
1040 if (rule == NULL)
1041 goto failed;
1042
1043 /* Send the ack before we remove the rule, since the ack is undone
1044 * on transaction cancel, but rule removal isn't.
1045 */
1046 if (!send_ack_reply (connection, transaction,
1047 message, error))
1048 goto failed;
1049
1050 matchmaker = bus_connection_get_matchmaker (connection);
1051
1052 if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
1053 goto failed;
1054
1055 bus_match_rule_unref (rule);
1056
1057 return TRUE;
1058
1059 failed:
1060 _DBUS_ASSERT_ERROR_IS_SET (error);
1061 if (rule)
1062 bus_match_rule_unref (rule);
1063 return FALSE;
1064}
1065
1066static dbus_bool_t
1067bus_driver_handle_get_service_owner (DBusConnection *connection,
1068 BusTransaction *transaction,
1069 DBusMessage *message,
1070 DBusError *error)
1071{
1072 const char *text;
1073 const char *base_name;
1074 DBusString str;
1075 BusRegistry *registry;
1076 BusService *service;
1077 DBusMessage *reply;
1078
1079 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1080
1081 registry = bus_connection_get_registry (connection);
1082
1083 text = NULL;
1084 reply = NULL;
1085
1086 if (! dbus_message_get_args (message, error,
1087 DBUS_TYPE_STRING, &text,
1088 DBUS_TYPE_INVALID))
1089 goto failed;
1090
1091 _dbus_string_init_const (&str, text);
1092 service = bus_registry_lookup (registry, &str);
1093 if (service == NULL &&
1094 _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
1095 {
1096 /* ORG_FREEDESKTOP_DBUS owns itself */
1097 base_name = DBUS_SERVICE_DBUS;
1098 }
1099 else if (service == NULL)
1100 {
1101 dbus_set_error (error,
1102 DBUS_ERROR_NAME_HAS_NO_OWNER,
1103 "Could not get owner of name '%s': no such name", text);
1104 goto failed;
1105 }
1106 else
1107 {
1108 base_name = bus_connection_get_name (bus_service_get_primary_owners_connection (service));
1109 if (base_name == NULL)
1110 {
1111 /* FIXME - how is this error possible? */
1112 dbus_set_error (error,
1113 DBUS_ERROR_FAILED,
1114 "Could not determine unique name for '%s'", text);
1115 goto failed;
1116 }
1117 _dbus_assert (*base_name == ':');
1118 }
1119
1120 _dbus_assert (base_name != NULL);
1121
1122 reply = dbus_message_new_method_return (message);
1123 if (reply == NULL)
1124 goto oom;
1125
1126 if (! dbus_message_append_args (reply,
1127 DBUS_TYPE_STRING, &base_name,
1128 DBUS_TYPE_INVALID))
1129 goto oom;
1130
1131 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1132 goto oom;
1133
1134 dbus_message_unref (reply);
1135
1136 return TRUE;
1137
1138 oom:
1139 BUS_SET_OOM (error);
1140
1141 failed:
1142 _DBUS_ASSERT_ERROR_IS_SET (error);
1143 if (reply)
1144 dbus_message_unref (reply);
1145 return FALSE;
1146}
1147
1148static dbus_bool_t
1149bus_driver_handle_list_queued_owners (DBusConnection *connection,
1150 BusTransaction *transaction,
1151 DBusMessage *message,
1152 DBusError *error)
1153{
1154 const char *text;
1155 DBusList *base_names;
1156 DBusList *link;
1157 DBusString str;
1158 BusRegistry *registry;
1159 BusService *service;
1160 DBusMessage *reply;
1161 DBusMessageIter iter, array_iter;
1162 char *dbus_service_name = DBUS_SERVICE_DBUS;
1163
1164 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1165
1166 registry = bus_connection_get_registry (connection);
1167
1168 base_names = NULL;
1169 text = NULL;
1170 reply = NULL;
1171
1172 if (! dbus_message_get_args (message, error,
1173 DBUS_TYPE_STRING, &text,
1174 DBUS_TYPE_INVALID))
1175 goto failed;
1176
1177 _dbus_string_init_const (&str, text);
1178 service = bus_registry_lookup (registry, &str);
1179 if (service == NULL &&
1180 _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
1181 {
1182 /* ORG_FREEDESKTOP_DBUS owns itself */
1183 if (! _dbus_list_append (&base_names, dbus_service_name))
1184 goto oom;
1185 }
1186 else if (service == NULL)
1187 {
1188 dbus_set_error (error,
1189 DBUS_ERROR_NAME_HAS_NO_OWNER,
1190 "Could not get owners of name '%s': no such name", text);
1191 goto failed;
1192 }
1193 else
1194 {
1195 if (!bus_service_list_queued_owners (service,
1196 &base_names,
1197 error))
1198 goto failed;
1199 }
1200
1201 _dbus_assert (base_names != NULL);
1202
1203 reply = dbus_message_new_method_return (message);
1204 if (reply == NULL)
1205 goto oom;
1206
1207 dbus_message_iter_init_append (reply, &iter);
1208 if (!dbus_message_iter_open_container (&iter,
1209 DBUS_TYPE_ARRAY,
1210 DBUS_TYPE_STRING_AS_STRING,
1211 &array_iter))
1212 goto oom;
1213
1214 link = _dbus_list_get_first_link (&base_names);
1215 while (link != NULL)
1216 {
1217 char *uname;
1218
1219 _dbus_assert (link->data != NULL);
1220 uname = (char *)link->data;
1221
1222 if (!dbus_message_iter_append_basic (&array_iter,
1223 DBUS_TYPE_STRING,
1224 &uname))
1225 goto oom;
1226
1227 link = _dbus_list_get_next_link (&base_names, link);
1228 }
1229
1230 if (! dbus_message_iter_close_container (&iter, &array_iter))
1231 goto oom;
1232
1233
1234 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1235 goto oom;
1236
1237 dbus_message_unref (reply);
1238
1239 return TRUE;
1240
1241 oom:
1242 BUS_SET_OOM (error);
1243
1244 failed:
1245 _DBUS_ASSERT_ERROR_IS_SET (error);
1246 if (reply)
1247 dbus_message_unref (reply);
1248
1249 if (base_names)
1250 _dbus_list_clear (&base_names);
1251
1252 return FALSE;
1253}
1254
1255static dbus_bool_t
1256bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
1257 BusTransaction *transaction,
1258 DBusMessage *message,
1259 DBusError *error)
1260{
1261 const char *service;
1262 DBusString str;
1263 BusRegistry *registry;
1264 BusService *serv;
1265 DBusConnection *conn;
1266 DBusMessage *reply;
1267 unsigned long uid;
1268 dbus_uint32_t uid32;
1269
1270 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1271
1272 registry = bus_connection_get_registry (connection);
1273
1274 service = NULL;
1275 reply = NULL;
1276
1277 if (! dbus_message_get_args (message, error,
1278 DBUS_TYPE_STRING, &service,
1279 DBUS_TYPE_INVALID))
1280 goto failed;
1281
1282 _dbus_verbose ("asked for UID of connection %s\n", service);
1283
1284 _dbus_string_init_const (&str, service);
1285 serv = bus_registry_lookup (registry, &str);
1286 if (serv == NULL)
1287 {
1288 dbus_set_error (error,
1289 DBUS_ERROR_NAME_HAS_NO_OWNER,
1290 "Could not get UID of name '%s': no such name", service);
1291 goto failed;
1292 }
1293
1294 conn = bus_service_get_primary_owners_connection (serv);
1295
1296 reply = dbus_message_new_method_return (message);
1297 if (reply == NULL)
1298 goto oom;
1299
1300 if (!dbus_connection_get_unix_user (conn, &uid))
1301 {
1302 dbus_set_error (error,
1303 DBUS_ERROR_FAILED,
1304 "Could not determine UID for '%s'", service);
1305 goto failed;
1306 }
1307
1308 uid32 = uid;
1309 if (! dbus_message_append_args (reply,
1310 DBUS_TYPE_UINT32, &uid32,
1311 DBUS_TYPE_INVALID))
1312 goto oom;
1313
1314 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1315 goto oom;
1316
1317 dbus_message_unref (reply);
1318
1319 return TRUE;
1320
1321 oom:
1322 BUS_SET_OOM (error);
1323
1324 failed:
1325 _DBUS_ASSERT_ERROR_IS_SET (error);
1326 if (reply)
1327 dbus_message_unref (reply);
1328 return FALSE;
1329}
1330
1331static dbus_bool_t
1332bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
1333 BusTransaction *transaction,
1334 DBusMessage *message,
1335 DBusError *error)
1336{
1337 const char *service;
1338 DBusString str;
1339 BusRegistry *registry;
1340 BusService *serv;
1341 DBusConnection *conn;
1342 DBusMessage *reply;
1343 unsigned long pid;
1344 dbus_uint32_t pid32;
1345
1346 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1347
1348 registry = bus_connection_get_registry (connection);
1349
1350 service = NULL;
1351 reply = NULL;
1352
1353 if (! dbus_message_get_args (message, error,
1354 DBUS_TYPE_STRING, &service,
1355 DBUS_TYPE_INVALID))
1356 goto failed;
1357
1358 _dbus_verbose ("asked for PID of connection %s\n", service);
1359
1360 _dbus_string_init_const (&str, service);
1361 serv = bus_registry_lookup (registry, &str);
1362 if (serv == NULL)
1363 {
1364 dbus_set_error (error,
1365 DBUS_ERROR_NAME_HAS_NO_OWNER,
1366 "Could not get PID of name '%s': no such name", service);
1367 goto failed;
1368 }
1369
1370 conn = bus_service_get_primary_owners_connection (serv);
1371
1372 reply = dbus_message_new_method_return (message);
1373 if (reply == NULL)
1374 goto oom;
1375
1376 if (!dbus_connection_get_unix_process_id (conn, &pid))
1377 {
1378 dbus_set_error (error,
1379 DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
1380 "Could not determine PID for '%s'", service);
1381 goto failed;
1382 }
1383
1384 pid32 = pid;
1385 if (! dbus_message_append_args (reply,
1386 DBUS_TYPE_UINT32, &pid32,
1387 DBUS_TYPE_INVALID))
1388 goto oom;
1389
1390 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1391 goto oom;
1392
1393 dbus_message_unref (reply);
1394
1395 return TRUE;
1396
1397 oom:
1398 BUS_SET_OOM (error);
1399
1400 failed:
1401 _DBUS_ASSERT_ERROR_IS_SET (error);
1402 if (reply)
1403 dbus_message_unref (reply);
1404 return FALSE;
1405}
1406
1407static dbus_bool_t
1408bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection,
1409 BusTransaction *transaction,
1410 DBusMessage *message,
1411 DBusError *error)
1412{
1413 const char *service;
1414 DBusString str;
1415 BusRegistry *registry;
1416 BusService *serv;
1417 DBusConnection *conn;
1418 DBusMessage *reply;
1419 void *data = NULL;
1420 dbus_uint32_t data_size;
1421
1422 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1423
1424 registry = bus_connection_get_registry (connection);
1425
1426 service = NULL;
1427 reply = NULL;
1428
1429 if (! dbus_message_get_args (message, error,
1430 DBUS_TYPE_STRING, &service,
1431 DBUS_TYPE_INVALID))
1432 goto failed;
1433
1434 _dbus_verbose ("asked for audit session data for connection %s\n", service);
1435
1436 _dbus_string_init_const (&str, service);
1437 serv = bus_registry_lookup (registry, &str);
1438 if (serv == NULL)
1439 {
1440 dbus_set_error (error,
1441 DBUS_ERROR_NAME_HAS_NO_OWNER,
1442 "Could not get audit session data for name '%s': no such name", service);
1443 goto failed;
1444 }
1445
1446 conn = bus_service_get_primary_owners_connection (serv);
1447
1448 reply = dbus_message_new_method_return (message);
1449 if (reply == NULL)
1450 goto oom;
1451
1452 if (!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) || data == NULL)
1453 {
1454 dbus_set_error (error,
1455 DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,
1456 "Could not determine audit session data for '%s'", service);
1457 goto failed;
1458 }
1459
1460 if (! dbus_message_append_args (reply,
1461 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_size,
1462 DBUS_TYPE_INVALID))
1463 goto oom;
1464
1465 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1466 goto oom;
1467
1468 dbus_message_unref (reply);
1469
1470 return TRUE;
1471
1472 oom:
1473 BUS_SET_OOM (error);
1474
1475 failed:
1476 _DBUS_ASSERT_ERROR_IS_SET (error);
1477 if (reply)
1478 dbus_message_unref (reply);
1479 return FALSE;
1480}
1481
1482static dbus_bool_t
1483bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection,
1484 BusTransaction *transaction,
1485 DBusMessage *message,
1486 DBusError *error)
1487{
1488 const char *service;
1489 DBusString str;
1490 BusRegistry *registry;
1491 BusService *serv;
1492 DBusConnection *conn;
1493 DBusMessage *reply;
1494 BusSELinuxID *context;
1495
1496 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1497
1498 registry = bus_connection_get_registry (connection);
1499
1500 service = NULL;
1501 reply = NULL;
1502
1503 if (! dbus_message_get_args (message, error,
1504 DBUS_TYPE_STRING, &service,
1505 DBUS_TYPE_INVALID))
1506 goto failed;
1507
1508 _dbus_verbose ("asked for security context of connection %s\n", service);
1509
1510 _dbus_string_init_const (&str, service);
1511 serv = bus_registry_lookup (registry, &str);
1512 if (serv == NULL)
1513 {
1514 dbus_set_error (error,
1515 DBUS_ERROR_NAME_HAS_NO_OWNER,
1516 "Could not get security context of name '%s': no such name", service);
1517 goto failed;
1518 }
1519
1520 conn = bus_service_get_primary_owners_connection (serv);
1521
1522 reply = dbus_message_new_method_return (message);
1523 if (reply == NULL)
1524 goto oom;
1525
1526 context = bus_connection_get_selinux_id (conn);
1527 if (!context)
1528 {
1529 dbus_set_error (error,
1530 DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
1531 "Could not determine security context for '%s'", service);
1532 goto failed;
1533 }
1534
1535 if (! bus_selinux_append_context (reply, context, error))
1536 goto failed;
1537
1538 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1539 goto oom;
1540
1541 dbus_message_unref (reply);
1542
1543 return TRUE;
1544
1545 oom:
1546 BUS_SET_OOM (error);
1547
1548 failed:
1549 _DBUS_ASSERT_ERROR_IS_SET (error);
1550 if (reply)
1551 dbus_message_unref (reply);
1552 return FALSE;
1553}
1554
1555static dbus_bool_t
1556bus_driver_handle_reload_config (DBusConnection *connection,
1557 BusTransaction *transaction,
1558 DBusMessage *message,
1559 DBusError *error)
1560{
1561 BusContext *context;
1562 DBusMessage *reply;
1563
1564 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1565
1566 reply = NULL;
1567
1568 context = bus_connection_get_context (connection);
1569 if (!bus_context_reload_config (context, error))
1570 goto failed;
1571
1572 reply = dbus_message_new_method_return (message);
1573 if (reply == NULL)
1574 goto oom;
1575
1576 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1577 goto oom;
1578
1579 dbus_message_unref (reply);
1580 return TRUE;
1581
1582 oom:
1583 BUS_SET_OOM (error);
1584
1585 failed:
1586 _DBUS_ASSERT_ERROR_IS_SET (error);
1587 if (reply)
1588 dbus_message_unref (reply);
1589 return FALSE;
1590}
1591
1592static dbus_bool_t
1593bus_driver_handle_get_id (DBusConnection *connection,
1594 BusTransaction *transaction,
1595 DBusMessage *message,
1596 DBusError *error)
1597{
1598 BusContext *context;
1599 DBusMessage *reply;
1600 DBusString uuid;
1601 const char *v_STRING;
1602
1603 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1604
1605 if (!_dbus_string_init (&uuid))
1606 {
1607 BUS_SET_OOM (error);
1608 return FALSE;
1609 }
1610
1611 reply = NULL;
1612
1613 context = bus_connection_get_context (connection);
1614 if (!bus_context_get_id (context, &uuid))
1615 goto oom;
1616
1617 reply = dbus_message_new_method_return (message);
1618 if (reply == NULL)
1619 goto oom;
1620
1621 v_STRING = _dbus_string_get_const_data (&uuid);
1622 if (!dbus_message_append_args (reply,
1623 DBUS_TYPE_STRING, &v_STRING,
1624 DBUS_TYPE_INVALID))
1625 goto oom;
1626
1627 _dbus_assert (dbus_message_has_signature (reply, "s"));
1628
1629 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1630 goto oom;
1631
1632 _dbus_string_free (&uuid);
1633 dbus_message_unref (reply);
1634 return TRUE;
1635
1636 oom:
1637 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1638
1639 BUS_SET_OOM (error);
1640
1641 if (reply)
1642 dbus_message_unref (reply);
1643 _dbus_string_free (&uuid);
1644 return FALSE;
1645}
1646
1647/* For speed it might be useful to sort this in order of
1648 * frequency of use (but doesn't matter with only a few items
1649 * anyhow)
1650 */
1651static struct
1652{
1653 const char *name;
1654 const char *in_args;
1655 const char *out_args;
1656 dbus_bool_t (* handler) (DBusConnection *connection,
1657 BusTransaction *transaction,
1658 DBusMessage *message,
1659 DBusError *error);
1660} message_handlers[] = {
1661 { "Hello",
1662 "",
1663 DBUS_TYPE_STRING_AS_STRING,
1664 bus_driver_handle_hello },
1665 { "RequestName",
1666 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1667 DBUS_TYPE_UINT32_AS_STRING,
1668 bus_driver_handle_acquire_service },
1669 { "ReleaseName",
1670 DBUS_TYPE_STRING_AS_STRING,
1671 DBUS_TYPE_UINT32_AS_STRING,
1672 bus_driver_handle_release_service },
1673 { "StartServiceByName",
1674 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1675 DBUS_TYPE_UINT32_AS_STRING,
1676 bus_driver_handle_activate_service },
1677 { "UpdateActivationEnvironment",
1678 DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
1679 "",
1680 bus_driver_handle_update_activation_environment },
1681 { "NameHasOwner",
1682 DBUS_TYPE_STRING_AS_STRING,
1683 DBUS_TYPE_BOOLEAN_AS_STRING,
1684 bus_driver_handle_service_exists },
1685 { "ListNames",
1686 "",
1687 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1688 bus_driver_handle_list_services },
1689 { "ListActivatableNames",
1690 "",
1691 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1692 bus_driver_handle_list_activatable_services },
1693 { "AddMatch",
1694 DBUS_TYPE_STRING_AS_STRING,
1695 "",
1696 bus_driver_handle_add_match },
1697 { "RemoveMatch",
1698 DBUS_TYPE_STRING_AS_STRING,
1699 "",
1700 bus_driver_handle_remove_match },
1701 { "GetNameOwner",
1702 DBUS_TYPE_STRING_AS_STRING,
1703 DBUS_TYPE_STRING_AS_STRING,
1704 bus_driver_handle_get_service_owner },
1705 { "ListQueuedOwners",
1706 DBUS_TYPE_STRING_AS_STRING,
1707 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1708 bus_driver_handle_list_queued_owners },
1709 { "GetConnectionUnixUser",
1710 DBUS_TYPE_STRING_AS_STRING,
1711 DBUS_TYPE_UINT32_AS_STRING,
1712 bus_driver_handle_get_connection_unix_user },
1713 { "GetConnectionUnixProcessID",
1714 DBUS_TYPE_STRING_AS_STRING,
1715 DBUS_TYPE_UINT32_AS_STRING,
1716 bus_driver_handle_get_connection_unix_process_id },
1717 { "GetAdtAuditSessionData",
1718 DBUS_TYPE_STRING_AS_STRING,
1719 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1720 bus_driver_handle_get_adt_audit_session_data },
1721 { "GetConnectionSELinuxSecurityContext",
1722 DBUS_TYPE_STRING_AS_STRING,
1723 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1724 bus_driver_handle_get_connection_selinux_security_context },
1725 { "ReloadConfig",
1726 "",
1727 "",
1728 bus_driver_handle_reload_config },
1729 { "GetId",
1730 "",
1731 DBUS_TYPE_STRING_AS_STRING,
1732 bus_driver_handle_get_id }
1733};
1734
1735static dbus_bool_t
1736write_args_for_direction (DBusString *xml,
1737 const char *signature,
1738 dbus_bool_t in)
1739{
1740 DBusTypeReader typereader;
1741 DBusString sigstr;
1742 int current_type;
1743
1744 _dbus_string_init_const (&sigstr, signature);
1745 _dbus_type_reader_init_types_only (&typereader, &sigstr, 0);
1746
1747 while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID)
1748 {
1749 const DBusString *subsig;
1750 int start, len;
1751
1752 _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len);
1753 if (!_dbus_string_append_printf (xml, " <arg direction=\"%s\" type=\"",
1754 in ? "in" : "out"))
1755 goto oom;
1756 if (!_dbus_string_append_len (xml,
1757 _dbus_string_get_const_data (subsig) + start,
1758 len))
1759 goto oom;
1760 if (!_dbus_string_append (xml, "\"/>\n"))
1761 goto oom;
1762
1763 _dbus_type_reader_next (&typereader);
1764 }
1765 return TRUE;
1766 oom:
1767 return FALSE;
1768}
1769
1770dbus_bool_t
1771bus_driver_generate_introspect_string (DBusString *xml)
1772{
1773 int i;
1774
1775 if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
1776 return FALSE;
1777 if (!_dbus_string_append (xml, "<node>\n"))
1778 return FALSE;
1779 if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
1780 return FALSE;
1781 if (!_dbus_string_append (xml, " <method name=\"Introspect\">\n"))
1782 return FALSE;
1783 if (!_dbus_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
1784 return FALSE;
1785 if (!_dbus_string_append (xml, " </method>\n"))
1786 return FALSE;
1787 if (!_dbus_string_append (xml, " </interface>\n"))
1788 return FALSE;
1789
1790 if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
1791 DBUS_INTERFACE_DBUS))
1792 return FALSE;
1793
1794 i = 0;
1795 while (i < _DBUS_N_ELEMENTS (message_handlers))
1796 {
1797
1798 if (!_dbus_string_append_printf (xml, " <method name=\"%s\">\n",
1799 message_handlers[i].name))
1800 return FALSE;
1801
1802 if (!write_args_for_direction (xml, message_handlers[i].in_args, TRUE))
1803 return FALSE;
1804
1805 if (!write_args_for_direction (xml, message_handlers[i].out_args, FALSE))
1806 return FALSE;
1807
1808 if (!_dbus_string_append (xml, " </method>\n"))
1809 return FALSE;
1810
1811 ++i;
1812 }
1813
1814 if (!_dbus_string_append_printf (xml, " <signal name=\"NameOwnerChanged\">\n"))
1815 return FALSE;
1816
1817 if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
1818 return FALSE;
1819
1820 if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
1821 return FALSE;
1822
1823 if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
1824 return FALSE;
1825
1826 if (!_dbus_string_append_printf (xml, " </signal>\n"))
1827 return FALSE;
1828
1829
1830
1831 if (!_dbus_string_append_printf (xml, " <signal name=\"NameLost\">\n"))
1832 return FALSE;
1833
1834 if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
1835 return FALSE;
1836
1837 if (!_dbus_string_append_printf (xml, " </signal>\n"))
1838 return FALSE;
1839
1840
1841
1842 if (!_dbus_string_append_printf (xml, " <signal name=\"NameAcquired\">\n"))
1843 return FALSE;
1844
1845 if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
1846 return FALSE;
1847
1848 if (!_dbus_string_append_printf (xml, " </signal>\n"))
1849 return FALSE;
1850
1851 if (!_dbus_string_append (xml, " </interface>\n"))
1852 return FALSE;
1853
1854 if (!_dbus_string_append (xml, "</node>\n"))
1855 return FALSE;
1856
1857 return TRUE;
1858}
1859
1860static dbus_bool_t
1861bus_driver_handle_introspect (DBusConnection *connection,
1862 BusTransaction *transaction,
1863 DBusMessage *message,
1864 DBusError *error)
1865{
1866 DBusString xml;
1867 DBusMessage *reply;
1868 const char *v_STRING;
1869
1870 _dbus_verbose ("Introspect() on bus driver\n");
1871
1872 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1873
1874 reply = NULL;
1875
1876 if (! dbus_message_get_args (message, error,
1877 DBUS_TYPE_INVALID))
1878 {
1879 _DBUS_ASSERT_ERROR_IS_SET (error);
1880 return FALSE;
1881 }
1882
1883 if (!_dbus_string_init (&xml))
1884 {
1885 BUS_SET_OOM (error);
1886 return FALSE;
1887 }
1888
1889 if (!bus_driver_generate_introspect_string (&xml))
1890 goto oom;
1891
1892 v_STRING = _dbus_string_get_const_data (&xml);
1893
1894 reply = dbus_message_new_method_return (message);
1895 if (reply == NULL)
1896 goto oom;
1897
1898 if (! dbus_message_append_args (reply,
1899 DBUS_TYPE_STRING, &v_STRING,
1900 DBUS_TYPE_INVALID))
1901 goto oom;
1902
1903 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1904 goto oom;
1905
1906 dbus_message_unref (reply);
1907 _dbus_string_free (&xml);
1908
1909 return TRUE;
1910
1911 oom:
1912 BUS_SET_OOM (error);
1913
1914 if (reply)
1915 dbus_message_unref (reply);
1916
1917 _dbus_string_free (&xml);
1918
1919 return FALSE;
1920}
1921
1922dbus_bool_t
1923bus_driver_handle_message (DBusConnection *connection,
1924 BusTransaction *transaction,
1925 DBusMessage *message,
1926 DBusError *error)
1927{
1928 const char *name, *sender, *interface;
1929 int i;
1930
1931 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1932
1933 if (dbus_message_is_signal (message, "org.freedesktop.systemd1.Activator", "ActivationFailure"))
1934 {
1935 BusContext *context;
1936
1937 context = bus_connection_get_context (connection);
1938 return dbus_activation_systemd_failure(bus_context_get_activation(context), message);
1939 }
1940
1941 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
1942 {
1943 _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
1944 return TRUE; /* we just ignore this */
1945 }
1946
1947 if (dbus_message_is_method_call (message,
1948 DBUS_INTERFACE_INTROSPECTABLE,
1949 "Introspect"))
1950 return bus_driver_handle_introspect (connection, transaction, message, error);
1951
1952 interface = dbus_message_get_interface (message);
1953 if (interface == NULL)
1954 interface = DBUS_INTERFACE_DBUS;
1955
1956 _dbus_assert (dbus_message_get_member (message) != NULL);
1957
1958 name = dbus_message_get_member (message);
1959 sender = dbus_message_get_sender (message);
1960
1961 if (strcmp (interface,
1962 DBUS_INTERFACE_DBUS) != 0)
1963 {
1964 _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
1965 interface);
1966 goto unknown;
1967 }
1968
1969 _dbus_verbose ("Driver got a method call: %s\n",
1970 dbus_message_get_member (message));
1971
1972 /* security checks should have kept this from getting here */
1973 _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
1974
1975 i = 0;
1976 while (i < _DBUS_N_ELEMENTS (message_handlers))
1977 {
1978 if (strcmp (message_handlers[i].name, name) == 0)
1979 {
1980 _dbus_verbose ("Found driver handler for %s\n", name);
1981
1982 if (!dbus_message_has_signature (message, message_handlers[i].in_args))
1983 {
1984 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1985 _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
1986 name, dbus_message_get_signature (message),
1987 message_handlers[i].in_args);
1988
1989 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1990 "Call to %s has wrong args (%s, expected %s)\n",
1991 name, dbus_message_get_signature (message),
1992 message_handlers[i].in_args);
1993 _DBUS_ASSERT_ERROR_IS_SET (error);
1994 return FALSE;
1995 }
1996
1997 if ((* message_handlers[i].handler) (connection, transaction, message, error))
1998 {
1999 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2000 _dbus_verbose ("Driver handler succeeded\n");
2001 return TRUE;
2002 }
2003 else
2004 {
2005 _DBUS_ASSERT_ERROR_IS_SET (error);
2006 _dbus_verbose ("Driver handler returned failure\n");
2007 return FALSE;
2008 }
2009 }
2010
2011 ++i;
2012 }
2013
2014 unknown:
2015 _dbus_verbose ("No driver handler for message \"%s\"\n",
2016 name);
2017
2018 dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
2019 "%s does not understand message %s",
2020 DBUS_SERVICE_DBUS, name);
2021
2022 return FALSE;
2023}
2024
2025void
2026bus_driver_remove_connection (DBusConnection *connection)
2027{
2028 /* FIXME 1.0 Does nothing for now, should unregister the connection
2029 * with the bus driver.
2030 */
2031}