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