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 "apparmor.h"
28 #include "connection.h"
29 #include "driver.h"
30 #include "dispatch.h"
31 #include "services.h"
32 #include "selinux.h"
33 #include "signals.h"
34 #include "stats.h"
35 #include "utils.h"
36
37 #include <dbus/dbus-asv-util.h>
38 #include <dbus/dbus-connection-internal.h>
39 #include <dbus/dbus-string.h>
40 #include <dbus/dbus-internals.h>
41 #include <dbus/dbus-message.h>
42 #include <dbus/dbus-marshal-recursive.h>
43 #include <dbus/dbus-marshal-validate.h>
44 #include <string.h>
45
46 static inline const char *
nonnull(const char * maybe_null,const char * if_null)47 nonnull (const char *maybe_null,
48 const char *if_null)
49 {
50 return (maybe_null ? maybe_null : if_null);
51 }
52
53 static DBusConnection *
bus_driver_get_owner_of_name(DBusConnection * connection,const char * name)54 bus_driver_get_owner_of_name (DBusConnection *connection,
55 const char *name)
56 {
57 BusRegistry *registry;
58 BusService *serv;
59 DBusString str;
60
61 registry = bus_connection_get_registry (connection);
62 _dbus_string_init_const (&str, name);
63 serv = bus_registry_lookup (registry, &str);
64
65 if (serv == NULL)
66 return NULL;
67
68 return bus_service_get_primary_owners_connection (serv);
69 }
70
71 BusDriverFound
bus_driver_get_conn_helper(DBusConnection * connection,DBusMessage * message,const char * what_we_want,const char ** name_p,DBusConnection ** peer_conn_p,DBusError * error)72 bus_driver_get_conn_helper (DBusConnection *connection,
73 DBusMessage *message,
74 const char *what_we_want,
75 const char **name_p,
76 DBusConnection **peer_conn_p,
77 DBusError *error)
78 {
79 DBusConnection *conn;
80 const char *name;
81
82 if (!dbus_message_get_args (message, error,
83 DBUS_TYPE_STRING, &name,
84 DBUS_TYPE_INVALID))
85 return BUS_DRIVER_FOUND_ERROR;
86
87 _dbus_assert (name != NULL);
88 _dbus_verbose ("asked for %s of connection %s\n", what_we_want, name);
89
90 if (name_p != NULL)
91 *name_p = name;
92
93 if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
94 return BUS_DRIVER_FOUND_SELF;
95
96 conn = bus_driver_get_owner_of_name (connection, name);
97
98 if (conn == NULL)
99 {
100 dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
101 "Could not get %s of name '%s': no such name",
102 what_we_want, name);
103 return BUS_DRIVER_FOUND_ERROR;
104 }
105
106 if (peer_conn_p != NULL)
107 *peer_conn_p = conn;
108
109 return BUS_DRIVER_FOUND_PEER;
110 }
111
112 /*
113 * Log a security warning and set error unless the uid of the connection
114 * is either the uid of this process, or on Unix, uid 0 (root).
115 *
116 * This is intended to be a second line of defence after <deny> rules,
117 * to mitigate incorrect system bus security policy configuration files
118 * like the ones in CVE-2014-8148 and CVE-2014-8156, and (if present)
119 * LSM rules; so it doesn't need to be perfect, but as long as we have
120 * potentially dangerous functionality in the system bus, it does need
121 * to exist.
122 */
123 static dbus_bool_t
bus_driver_check_caller_is_privileged(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)124 bus_driver_check_caller_is_privileged (DBusConnection *connection,
125 BusTransaction *transaction,
126 DBusMessage *message,
127 DBusError *error)
128 {
129 #ifdef DBUS_UNIX
130 unsigned long uid;
131
132 if (!dbus_connection_get_unix_user (connection, &uid))
133 {
134 const char *method = dbus_message_get_member (message);
135
136 bus_context_log_and_set_error (bus_transaction_get_context (transaction),
137 DBUS_SYSTEM_LOG_SECURITY, error, DBUS_ERROR_ACCESS_DENIED,
138 "rejected attempt to call %s by connection %s (%s) with "
139 "unknown uid", method,
140 nonnull (bus_connection_get_name (connection), "(inactive)"),
141 bus_connection_get_loginfo (connection));
142 return FALSE;
143 }
144
145 /* I'm writing it in this slightly strange form so that it's more
146 * obvious that this security-sensitive code is correct.
147 */
148 if (_dbus_unix_user_is_process_owner (uid))
149 {
150 /* OK */
151 }
152 else if (uid == 0)
153 {
154 /* OK */
155 }
156 else
157 {
158 const char *method = dbus_message_get_member (message);
159
160 bus_context_log_and_set_error (bus_transaction_get_context (transaction),
161 DBUS_SYSTEM_LOG_SECURITY, error, DBUS_ERROR_ACCESS_DENIED,
162 "rejected attempt to call %s by connection %s (%s) with "
163 "uid %lu", method,
164 nonnull (bus_connection_get_name (connection), "(inactive)"),
165 bus_connection_get_loginfo (connection), uid);
166 return FALSE;
167 }
168
169 return TRUE;
170 #elif defined(DBUS_WIN)
171 char *windows_sid = NULL;
172 dbus_bool_t ret = FALSE;
173
174 if (!dbus_connection_get_windows_user (connection, &windows_sid))
175 {
176 const char *method = dbus_message_get_member (message);
177
178 bus_context_log_and_set_error (bus_transaction_get_context (transaction),
179 DBUS_SYSTEM_LOG_SECURITY, error, DBUS_ERROR_ACCESS_DENIED,
180 "rejected attempt to call %s by unknown uid", method);
181 goto out;
182 }
183
184 if (!_dbus_windows_user_is_process_owner (windows_sid))
185 {
186 const char *method = dbus_message_get_member (message);
187
188 bus_context_log_and_set_error (bus_transaction_get_context (transaction),
189 DBUS_SYSTEM_LOG_SECURITY, error, DBUS_ERROR_ACCESS_DENIED,
190 "rejected attempt to call %s by uid %s", method, windows_sid);
191 goto out;
192 }
193
194 ret = TRUE;
195 out:
196 dbus_free (windows_sid);
197 return ret;
198 #else
199 /* make sure we fail closed in the hypothetical case that we are neither
200 * Unix nor Windows */
201 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
202 "please teach bus/driver.c how uids work on this platform");
203 return FALSE;
204 #endif
205 }
206
207 static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
208 DBusMessage *hello_message,
209 BusTransaction *transaction,
210 DBusError *error);
211
212 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)213 bus_driver_send_service_owner_changed (const char *service_name,
214 const char *old_owner,
215 const char *new_owner,
216 BusTransaction *transaction,
217 DBusError *error)
218 {
219 DBusMessage *message;
220 dbus_bool_t retval;
221 const char *null_service;
222
223 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
224
225 null_service = "";
226 _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n",
227 service_name,
228 old_owner ? old_owner : null_service,
229 new_owner ? new_owner : null_service);
230
231 message = dbus_message_new_signal (DBUS_PATH_DBUS,
232 DBUS_INTERFACE_DBUS,
233 "NameOwnerChanged");
234
235 if (message == NULL)
236 {
237 BUS_SET_OOM (error);
238 return FALSE;
239 }
240
241 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
242 goto oom;
243
244 if (!dbus_message_append_args (message,
245 DBUS_TYPE_STRING, &service_name,
246 DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service,
247 DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service,
248 DBUS_TYPE_INVALID))
249 goto oom;
250
251 _dbus_assert (dbus_message_has_signature (message, "sss"));
252
253 if (!bus_transaction_capture (transaction, NULL, NULL, message))
254 goto oom;
255
256 retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
257 dbus_message_unref (message);
258
259 return retval;
260
261 oom:
262 dbus_message_unref (message);
263 BUS_SET_OOM (error);
264 return FALSE;
265 }
266
267 dbus_bool_t
bus_driver_send_service_lost(DBusConnection * connection,const char * service_name,BusTransaction * transaction,DBusError * error)268 bus_driver_send_service_lost (DBusConnection *connection,
269 const char *service_name,
270 BusTransaction *transaction,
271 DBusError *error)
272 {
273 DBusMessage *message;
274
275 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
276
277 message = dbus_message_new_signal (DBUS_PATH_DBUS,
278 DBUS_INTERFACE_DBUS,
279 "NameLost");
280
281 if (message == NULL)
282 {
283 BUS_SET_OOM (error);
284 return FALSE;
285 }
286
287 if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
288 !dbus_message_append_args (message,
289 DBUS_TYPE_STRING, &service_name,
290 DBUS_TYPE_INVALID))
291 {
292 dbus_message_unref (message);
293 BUS_SET_OOM (error);
294 return FALSE;
295 }
296
297 if (!bus_transaction_send_from_driver (transaction, connection, message))
298 {
299 dbus_message_unref (message);
300 BUS_SET_OOM (error);
301 return FALSE;
302 }
303 else
304 {
305 dbus_message_unref (message);
306 return TRUE;
307 }
308 }
309
310 dbus_bool_t
bus_driver_send_service_acquired(DBusConnection * connection,const char * service_name,BusTransaction * transaction,DBusError * error)311 bus_driver_send_service_acquired (DBusConnection *connection,
312 const char *service_name,
313 BusTransaction *transaction,
314 DBusError *error)
315 {
316 DBusMessage *message;
317
318 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
319
320 message = dbus_message_new_signal (DBUS_PATH_DBUS,
321 DBUS_INTERFACE_DBUS,
322 "NameAcquired");
323
324 if (message == NULL)
325 {
326 BUS_SET_OOM (error);
327 return FALSE;
328 }
329
330 if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
331 !dbus_message_append_args (message,
332 DBUS_TYPE_STRING, &service_name,
333 DBUS_TYPE_INVALID))
334 {
335 dbus_message_unref (message);
336 BUS_SET_OOM (error);
337 return FALSE;
338 }
339
340 if (!bus_transaction_send_from_driver (transaction, connection, message))
341 {
342 dbus_message_unref (message);
343 BUS_SET_OOM (error);
344 return FALSE;
345 }
346 else
347 {
348 dbus_message_unref (message);
349 return TRUE;
350 }
351 }
352
353 static dbus_bool_t
create_unique_client_name(BusRegistry * registry,DBusString * str)354 create_unique_client_name (BusRegistry *registry,
355 DBusString *str)
356 {
357 /* We never want to use the same unique client name twice, because
358 * we want to guarantee that if you send a message to a given unique
359 * name, you always get the same application. So we use two numbers
360 * for INT_MAX * INT_MAX combinations, should be pretty safe against
361 * wraparound.
362 */
363 /* FIXME these should be in BusRegistry rather than static vars */
364 static int next_major_number = 0;
365 static int next_minor_number = 0;
366 int len;
367
368 len = _dbus_string_get_length (str);
369
370 while (TRUE)
371 {
372 /* start out with 1-0, go to 1-1, 1-2, 1-3,
373 * up to 1-MAXINT, then 2-0, 2-1, etc.
374 */
375 if (next_minor_number <= 0)
376 {
377 next_major_number += 1;
378 next_minor_number = 0;
379 if (next_major_number <= 0)
380 _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
381 }
382
383 _dbus_assert (next_major_number > 0);
384 _dbus_assert (next_minor_number >= 0);
385
386 /* appname:MAJOR-MINOR */
387
388 if (!_dbus_string_append (str, ":"))
389 return FALSE;
390
391 if (!_dbus_string_append_int (str, next_major_number))
392 return FALSE;
393
394 if (!_dbus_string_append (str, "."))
395 return FALSE;
396
397 if (!_dbus_string_append_int (str, next_minor_number))
398 return FALSE;
399
400 next_minor_number += 1;
401
402 /* Check if a client with the name exists */
403 if (bus_registry_lookup (registry, str) == NULL)
404 break;
405
406 /* drop the number again, try the next one. */
407 _dbus_string_set_length (str, len);
408 }
409
410 return TRUE;
411 }
412
413 static dbus_bool_t
bus_driver_handle_hello(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)414 bus_driver_handle_hello (DBusConnection *connection,
415 BusTransaction *transaction,
416 DBusMessage *message,
417 DBusError *error)
418 {
419 DBusString unique_name;
420 BusService *service;
421 dbus_bool_t retval;
422 BusRegistry *registry;
423 BusConnections *connections;
424 DBusError tmp_error;
425 int limit;
426 const char *limit_name;
427
428 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
429
430 if (bus_connection_is_active (connection))
431 {
432 /* We already handled an Hello message for this connection. */
433 dbus_set_error (error, DBUS_ERROR_FAILED,
434 "Already handled an Hello message");
435 return FALSE;
436 }
437
438 /* Note that when these limits are exceeded we don't disconnect the
439 * connection; we just sort of leave it hanging there until it times
440 * out or disconnects itself or is dropped due to the max number of
441 * incomplete connections. It's even OK if the connection wants to
442 * retry the hello message, we support that.
443 */
444 dbus_error_init (&tmp_error);
445 connections = bus_connection_get_connections (connection);
446 if (!bus_connections_check_limits (connections, connection,
447 &limit_name, &limit,
448 &tmp_error))
449 {
450 BusContext *context;
451
452 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
453 context = bus_connection_get_context (connection);
454 bus_context_log (context, DBUS_SYSTEM_LOG_WARNING, "%s (%s=%d)",
455 tmp_error.message, limit_name, limit);
456 dbus_move_error (&tmp_error, error);
457 return FALSE;
458 }
459
460 if (!_dbus_string_init (&unique_name))
461 {
462 BUS_SET_OOM (error);
463 return FALSE;
464 }
465
466 retval = FALSE;
467
468 registry = bus_connection_get_registry (connection);
469
470 if (!create_unique_client_name (registry, &unique_name))
471 {
472 BUS_SET_OOM (error);
473 goto out_0;
474 }
475
476 if (!bus_connection_complete (connection, &unique_name, error))
477 {
478 _DBUS_ASSERT_ERROR_IS_SET (error);
479 goto out_0;
480 }
481
482 if (!dbus_message_set_sender (message,
483 bus_connection_get_name (connection)))
484 {
485 BUS_SET_OOM (error);
486 goto out_0;
487 }
488
489 if (!bus_driver_send_welcome_message (connection, message, transaction, error))
490 goto out_0;
491
492 /* Create the service */
493 service = bus_registry_ensure (registry,
494 &unique_name, connection, 0, transaction, error);
495 if (service == NULL)
496 goto out_0;
497
498 _dbus_assert (bus_connection_is_active (connection));
499 retval = TRUE;
500
501 out_0:
502 _dbus_string_free (&unique_name);
503 return retval;
504 }
505
506 static dbus_bool_t
bus_driver_send_welcome_message(DBusConnection * connection,DBusMessage * hello_message,BusTransaction * transaction,DBusError * error)507 bus_driver_send_welcome_message (DBusConnection *connection,
508 DBusMessage *hello_message,
509 BusTransaction *transaction,
510 DBusError *error)
511 {
512 DBusMessage *welcome;
513 const char *name;
514
515 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
516
517 name = bus_connection_get_name (connection);
518 _dbus_assert (name != NULL);
519
520 welcome = dbus_message_new_method_return (hello_message);
521 if (welcome == NULL)
522 {
523 BUS_SET_OOM (error);
524 return FALSE;
525 }
526
527 if (!dbus_message_append_args (welcome,
528 DBUS_TYPE_STRING, &name,
529 DBUS_TYPE_INVALID))
530 {
531 dbus_message_unref (welcome);
532 BUS_SET_OOM (error);
533 return FALSE;
534 }
535
536 _dbus_assert (dbus_message_has_signature (welcome, DBUS_TYPE_STRING_AS_STRING));
537
538 if (!bus_transaction_send_from_driver (transaction, connection, welcome))
539 {
540 dbus_message_unref (welcome);
541 BUS_SET_OOM (error);
542 return FALSE;
543 }
544 else
545 {
546 dbus_message_unref (welcome);
547 return TRUE;
548 }
549 }
550
551 static dbus_bool_t
bus_driver_handle_list_services(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)552 bus_driver_handle_list_services (DBusConnection *connection,
553 BusTransaction *transaction,
554 DBusMessage *message,
555 DBusError *error)
556 {
557 DBusMessage *reply;
558 int len;
559 char **services;
560 BusRegistry *registry;
561 int i;
562 DBusMessageIter iter;
563 DBusMessageIter sub;
564
565 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
566
567 registry = bus_connection_get_registry (connection);
568
569 reply = dbus_message_new_method_return (message);
570 if (reply == NULL)
571 {
572 BUS_SET_OOM (error);
573 return FALSE;
574 }
575
576 if (!bus_registry_list_services (registry, &services, &len))
577 {
578 dbus_message_unref (reply);
579 BUS_SET_OOM (error);
580 return FALSE;
581 }
582
583 dbus_message_iter_init_append (reply, &iter);
584
585 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
586 DBUS_TYPE_STRING_AS_STRING,
587 &sub))
588 {
589 dbus_free_string_array (services);
590 dbus_message_unref (reply);
591 BUS_SET_OOM (error);
592 return FALSE;
593 }
594
595 {
596 /* Include the bus driver in the list */
597 const char *v_STRING = DBUS_SERVICE_DBUS;
598 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
599 &v_STRING))
600 {
601 dbus_free_string_array (services);
602 dbus_message_unref (reply);
603 BUS_SET_OOM (error);
604 return FALSE;
605 }
606 }
607
608 i = 0;
609 while (i < len)
610 {
611 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
612 &services[i]))
613 {
614 dbus_free_string_array (services);
615 dbus_message_unref (reply);
616 BUS_SET_OOM (error);
617 return FALSE;
618 }
619 ++i;
620 }
621
622 dbus_free_string_array (services);
623
624 if (!dbus_message_iter_close_container (&iter, &sub))
625 {
626 dbus_message_unref (reply);
627 BUS_SET_OOM (error);
628 return FALSE;
629 }
630
631 if (!bus_transaction_send_from_driver (transaction, connection, reply))
632 {
633 dbus_message_unref (reply);
634 BUS_SET_OOM (error);
635 return FALSE;
636 }
637 else
638 {
639 dbus_message_unref (reply);
640 return TRUE;
641 }
642 }
643
644 static dbus_bool_t
bus_driver_handle_list_activatable_services(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)645 bus_driver_handle_list_activatable_services (DBusConnection *connection,
646 BusTransaction *transaction,
647 DBusMessage *message,
648 DBusError *error)
649 {
650 DBusMessage *reply;
651 int len;
652 char **services;
653 BusActivation *activation;
654 int i;
655 DBusMessageIter iter;
656 DBusMessageIter sub;
657
658 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
659
660 activation = bus_connection_get_activation (connection);
661
662 reply = dbus_message_new_method_return (message);
663 if (reply == NULL)
664 {
665 BUS_SET_OOM (error);
666 return FALSE;
667 }
668
669 if (!bus_activation_list_services (activation, &services, &len))
670 {
671 dbus_message_unref (reply);
672 BUS_SET_OOM (error);
673 return FALSE;
674 }
675
676 dbus_message_iter_init_append (reply, &iter);
677
678 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
679 DBUS_TYPE_STRING_AS_STRING,
680 &sub))
681 {
682 dbus_free_string_array (services);
683 dbus_message_unref (reply);
684 BUS_SET_OOM (error);
685 return FALSE;
686 }
687
688 {
689 /* Include the bus driver in the list */
690 const char *v_STRING = DBUS_SERVICE_DBUS;
691 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
692 &v_STRING))
693 {
694 dbus_free_string_array (services);
695 dbus_message_unref (reply);
696 BUS_SET_OOM (error);
697 return FALSE;
698 }
699 }
700
701 i = 0;
702 while (i < len)
703 {
704 if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
705 &services[i]))
706 {
707 dbus_free_string_array (services);
708 dbus_message_unref (reply);
709 BUS_SET_OOM (error);
710 return FALSE;
711 }
712 ++i;
713 }
714
715 dbus_free_string_array (services);
716
717 if (!dbus_message_iter_close_container (&iter, &sub))
718 {
719 dbus_message_unref (reply);
720 BUS_SET_OOM (error);
721 return FALSE;
722 }
723
724 if (!bus_transaction_send_from_driver (transaction, connection, reply))
725 {
726 dbus_message_unref (reply);
727 BUS_SET_OOM (error);
728 return FALSE;
729 }
730 else
731 {
732 dbus_message_unref (reply);
733 return TRUE;
734 }
735 }
736
737 static dbus_bool_t
bus_driver_handle_acquire_service(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)738 bus_driver_handle_acquire_service (DBusConnection *connection,
739 BusTransaction *transaction,
740 DBusMessage *message,
741 DBusError *error)
742 {
743 DBusMessage *reply;
744 DBusString service_name;
745 const char *name;
746 dbus_uint32_t service_reply;
747 dbus_uint32_t flags;
748 dbus_bool_t retval;
749 BusRegistry *registry;
750
751 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
752
753 registry = bus_connection_get_registry (connection);
754
755 if (!dbus_message_get_args (message, error,
756 DBUS_TYPE_STRING, &name,
757 DBUS_TYPE_UINT32, &flags,
758 DBUS_TYPE_INVALID))
759 return FALSE;
760
761 _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags);
762
763 retval = FALSE;
764 reply = NULL;
765
766 _dbus_string_init_const (&service_name, name);
767
768 if (!bus_registry_acquire_service (registry, connection,
769 &service_name, flags,
770 &service_reply, transaction,
771 error))
772 goto out;
773
774 reply = dbus_message_new_method_return (message);
775 if (reply == NULL)
776 {
777 BUS_SET_OOM (error);
778 goto out;
779 }
780
781 if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
782 {
783 BUS_SET_OOM (error);
784 goto out;
785 }
786
787 if (!bus_transaction_send_from_driver (transaction, connection, reply))
788 {
789 BUS_SET_OOM (error);
790 goto out;
791 }
792
793 retval = TRUE;
794
795 out:
796 if (reply)
797 dbus_message_unref (reply);
798 return retval;
799 }
800
801 static dbus_bool_t
bus_driver_handle_release_service(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)802 bus_driver_handle_release_service (DBusConnection *connection,
803 BusTransaction *transaction,
804 DBusMessage *message,
805 DBusError *error)
806 {
807 DBusMessage *reply;
808 DBusString service_name;
809 const char *name;
810 dbus_uint32_t service_reply;
811 dbus_bool_t retval;
812 BusRegistry *registry;
813
814 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
815
816 registry = bus_connection_get_registry (connection);
817
818 if (!dbus_message_get_args (message, error,
819 DBUS_TYPE_STRING, &name,
820 DBUS_TYPE_INVALID))
821 return FALSE;
822
823 _dbus_verbose ("Trying to release name %s\n", name);
824
825 retval = FALSE;
826 reply = NULL;
827
828 _dbus_string_init_const (&service_name, name);
829
830 if (!bus_registry_release_service (registry, connection,
831 &service_name, &service_reply,
832 transaction, error))
833 goto out;
834
835 reply = dbus_message_new_method_return (message);
836 if (reply == NULL)
837 {
838 BUS_SET_OOM (error);
839 goto out;
840 }
841
842 if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
843 {
844 BUS_SET_OOM (error);
845 goto out;
846 }
847
848 if (!bus_transaction_send_from_driver (transaction, connection, reply))
849 {
850 BUS_SET_OOM (error);
851 goto out;
852 }
853
854 retval = TRUE;
855
856 out:
857 if (reply)
858 dbus_message_unref (reply);
859 return retval;
860 }
861
862 static dbus_bool_t
bus_driver_handle_service_exists(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)863 bus_driver_handle_service_exists (DBusConnection *connection,
864 BusTransaction *transaction,
865 DBusMessage *message,
866 DBusError *error)
867 {
868 DBusMessage *reply;
869 DBusString service_name;
870 BusService *service;
871 dbus_bool_t service_exists;
872 const char *name;
873 dbus_bool_t retval;
874 BusRegistry *registry;
875
876 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
877
878 registry = bus_connection_get_registry (connection);
879
880 if (!dbus_message_get_args (message, error,
881 DBUS_TYPE_STRING, &name,
882 DBUS_TYPE_INVALID))
883 return FALSE;
884
885 retval = FALSE;
886
887 if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
888 {
889 service_exists = TRUE;
890 }
891 else
892 {
893 _dbus_string_init_const (&service_name, name);
894 service = bus_registry_lookup (registry, &service_name);
895 service_exists = service != NULL;
896 }
897
898 reply = dbus_message_new_method_return (message);
899 if (reply == NULL)
900 {
901 BUS_SET_OOM (error);
902 goto out;
903 }
904
905 if (!dbus_message_append_args (reply,
906 DBUS_TYPE_BOOLEAN, &service_exists,
907 0))
908 {
909 BUS_SET_OOM (error);
910 goto out;
911 }
912
913 if (!bus_transaction_send_from_driver (transaction, connection, reply))
914 {
915 BUS_SET_OOM (error);
916 goto out;
917 }
918
919 retval = TRUE;
920
921 out:
922 if (reply)
923 dbus_message_unref (reply);
924
925 return retval;
926 }
927
928 static dbus_bool_t
bus_driver_handle_activate_service(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)929 bus_driver_handle_activate_service (DBusConnection *connection,
930 BusTransaction *transaction,
931 DBusMessage *message,
932 DBusError *error)
933 {
934 dbus_uint32_t flags;
935 const char *name;
936 dbus_bool_t retval;
937 BusActivation *activation;
938
939 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
940
941 activation = bus_connection_get_activation (connection);
942
943 if (!dbus_message_get_args (message, error,
944 DBUS_TYPE_STRING, &name,
945 DBUS_TYPE_UINT32, &flags,
946 DBUS_TYPE_INVALID))
947 {
948 _DBUS_ASSERT_ERROR_IS_SET (error);
949 _dbus_verbose ("No memory to get arguments to StartServiceByName\n");
950 return FALSE;
951 }
952
953 retval = FALSE;
954
955 if (!bus_activation_activate_service (activation, connection, transaction, FALSE,
956 message, name, error))
957 {
958 _DBUS_ASSERT_ERROR_IS_SET (error);
959 _dbus_verbose ("bus_activation_activate_service() failed\n");
960 goto out;
961 }
962
963 retval = TRUE;
964
965 out:
966 return retval;
967 }
968
969 dbus_bool_t
bus_driver_send_ack_reply(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)970 bus_driver_send_ack_reply (DBusConnection *connection,
971 BusTransaction *transaction,
972 DBusMessage *message,
973 DBusError *error)
974 {
975 DBusMessage *reply;
976
977 if (dbus_message_get_no_reply (message))
978 return TRUE;
979
980 reply = dbus_message_new_method_return (message);
981 if (reply == NULL)
982 {
983 BUS_SET_OOM (error);
984 return FALSE;
985 }
986
987 if (!bus_transaction_send_from_driver (transaction, connection, reply))
988 {
989 BUS_SET_OOM (error);
990 dbus_message_unref (reply);
991 return FALSE;
992 }
993
994 dbus_message_unref (reply);
995
996 return TRUE;
997 }
998
999 /*
1000 * Send a message from the driver, activating the destination if necessary.
1001 * The message must already have a destination set.
1002 */
1003 static dbus_bool_t
bus_driver_send_or_activate(BusTransaction * transaction,DBusMessage * message,DBusError * error)1004 bus_driver_send_or_activate (BusTransaction *transaction,
1005 DBusMessage *message,
1006 DBusError *error)
1007 {
1008 BusContext *context;
1009 BusService *service;
1010 const char *service_name;
1011 DBusString service_string;
1012
1013 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1014
1015 service_name = dbus_message_get_destination (message);
1016
1017 _dbus_assert (service_name != NULL);
1018
1019 _dbus_string_init_const (&service_string, service_name);
1020
1021 context = bus_transaction_get_context (transaction);
1022
1023 service = bus_registry_lookup (bus_context_get_registry (context),
1024 &service_string);
1025
1026 if (service == NULL)
1027 {
1028 /* destination isn't connected yet; pass the message to activation */
1029 BusActivation *activation;
1030
1031 activation = bus_context_get_activation (context);
1032
1033 if (!bus_transaction_capture (transaction, NULL, NULL, message))
1034 {
1035 BUS_SET_OOM (error);
1036 _dbus_verbose ("No memory for bus_transaction_capture()");
1037 return FALSE;
1038 }
1039
1040 if (!bus_activation_activate_service (activation, NULL, transaction, TRUE,
1041 message, service_name, error))
1042 {
1043 _DBUS_ASSERT_ERROR_IS_SET (error);
1044 _dbus_verbose ("bus_activation_activate_service() failed");
1045 return FALSE;
1046 }
1047 }
1048 else
1049 {
1050 DBusConnection *service_conn;
1051
1052 service_conn = bus_service_get_primary_owners_connection (service);
1053
1054 if (!bus_transaction_send_from_driver (transaction, service_conn, message))
1055 {
1056 BUS_SET_OOM (error);
1057 _dbus_verbose ("No memory for bus_transaction_send_from_driver()");
1058 return FALSE;
1059 }
1060 }
1061
1062 return TRUE;
1063 }
1064
1065 static dbus_bool_t
bus_driver_handle_update_activation_environment(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1066 bus_driver_handle_update_activation_environment (DBusConnection *connection,
1067 BusTransaction *transaction,
1068 DBusMessage *message,
1069 DBusError *error)
1070 {
1071 dbus_bool_t retval;
1072 BusActivation *activation;
1073 BusContext *context;
1074 DBusMessageIter iter;
1075 DBusMessageIter dict_iter;
1076 DBusMessageIter dict_entry_iter;
1077 int array_type;
1078 int key_type;
1079 DBusList *keys, *key_link;
1080 DBusList *values, *value_link;
1081 DBusMessage *systemd_message;
1082 DBusMessageIter systemd_iter;
1083
1084 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1085
1086 context = bus_connection_get_context (connection);
1087
1088 if (bus_context_get_servicehelper (context) != NULL)
1089 {
1090 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
1091 "Cannot change activation environment "
1092 "on a system bus.");
1093 return FALSE;
1094 }
1095
1096 activation = bus_connection_get_activation (connection);
1097
1098 dbus_message_iter_init (message, &iter);
1099
1100 /* The message signature has already been checked for us,
1101 * so let's just assert it's right.
1102 */
1103 _dbus_assert (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY);
1104
1105 dbus_message_iter_recurse (&iter, &dict_iter);
1106
1107 retval = FALSE;
1108 systemd_message = NULL;
1109
1110 /* Then loop through the sent dictionary, add the location of
1111 * the environment keys and values to lists. The result will
1112 * be in reverse order, so we don't have to constantly search
1113 * for the end of the list in a loop.
1114 */
1115 keys = NULL;
1116 values = NULL;
1117 while ((array_type = dbus_message_iter_get_arg_type (&dict_iter)) == DBUS_TYPE_DICT_ENTRY)
1118 {
1119 dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
1120
1121 while ((key_type = dbus_message_iter_get_arg_type (&dict_entry_iter)) == DBUS_TYPE_STRING)
1122 {
1123 char *key;
1124 char *value;
1125 int value_type;
1126
1127 dbus_message_iter_get_basic (&dict_entry_iter, &key);
1128 dbus_message_iter_next (&dict_entry_iter);
1129
1130 value_type = dbus_message_iter_get_arg_type (&dict_entry_iter);
1131
1132 if (value_type != DBUS_TYPE_STRING)
1133 break;
1134
1135 dbus_message_iter_get_basic (&dict_entry_iter, &value);
1136
1137 if (!_dbus_list_append (&keys, key))
1138 {
1139 BUS_SET_OOM (error);
1140 break;
1141 }
1142
1143 if (!_dbus_list_append (&values, value))
1144 {
1145 BUS_SET_OOM (error);
1146 break;
1147 }
1148
1149 dbus_message_iter_next (&dict_entry_iter);
1150 }
1151
1152 if (key_type != DBUS_TYPE_INVALID)
1153 break;
1154
1155 dbus_message_iter_next (&dict_iter);
1156 }
1157
1158 if (array_type != DBUS_TYPE_INVALID)
1159 goto out;
1160
1161 _dbus_assert (_dbus_list_get_length (&keys) == _dbus_list_get_length (&values));
1162
1163 if (bus_context_get_systemd_activation (bus_connection_get_context (connection)))
1164 {
1165 /* Prepare a call to forward environment updates to systemd */
1166 systemd_message = dbus_message_new_method_call ("org.freedesktop.systemd1",
1167 "/org/freedesktop/systemd1",
1168 "org.freedesktop.systemd1.Manager",
1169 "SetEnvironment");
1170 if (systemd_message == NULL ||
1171 !dbus_message_set_sender (systemd_message, DBUS_SERVICE_DBUS))
1172 {
1173 BUS_SET_OOM (error);
1174 _dbus_verbose ("No memory to create systemd message\n");
1175 goto out;
1176 }
1177
1178 dbus_message_set_no_reply (systemd_message, TRUE);
1179 dbus_message_iter_init_append (systemd_message, &iter);
1180
1181 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
1182 &systemd_iter))
1183 {
1184 BUS_SET_OOM (error);
1185 _dbus_verbose ("No memory to open systemd message container\n");
1186 goto out;
1187 }
1188 }
1189
1190 key_link = keys;
1191 value_link = values;
1192 while (key_link != NULL)
1193 {
1194 const char *key;
1195 const char *value;
1196
1197 key = key_link->data;
1198 value = value_link->data;
1199
1200 if (!bus_activation_set_environment_variable (activation,
1201 key, value, error))
1202 {
1203 _DBUS_ASSERT_ERROR_IS_SET (error);
1204 _dbus_verbose ("bus_activation_set_environment_variable() failed\n");
1205 break;
1206 }
1207
1208 if (systemd_message != NULL)
1209 {
1210 DBusString envline;
1211 const char *s;
1212
1213 /* SetEnvironment wants an array of KEY=VALUE strings */
1214 if (!_dbus_string_init (&envline) ||
1215 !_dbus_string_append_printf (&envline, "%s=%s", key, value))
1216 {
1217 BUS_SET_OOM (error);
1218 _dbus_verbose ("No memory to format systemd environment line\n");
1219 _dbus_string_free (&envline);
1220 break;
1221 }
1222
1223 s = _dbus_string_get_data (&envline);
1224
1225 if (!dbus_message_iter_append_basic (&systemd_iter,
1226 DBUS_TYPE_STRING, &s))
1227 {
1228 BUS_SET_OOM (error);
1229 _dbus_verbose ("No memory to append systemd environment line\n");
1230 _dbus_string_free (&envline);
1231 break;
1232 }
1233
1234 _dbus_string_free (&envline);
1235 }
1236
1237 key_link = _dbus_list_get_next_link (&keys, key_link);
1238 value_link = _dbus_list_get_next_link (&values, value_link);
1239 }
1240
1241 /* FIXME: We can fail early having set only some of the environment variables,
1242 * (because of OOM failure). It's sort of hard to fix and it doesn't really
1243 * matter, so we're punting for now.
1244 */
1245 if (key_link != NULL)
1246 {
1247 if (systemd_message != NULL)
1248 dbus_message_iter_abandon_container (&iter, &systemd_iter);
1249 goto out;
1250 }
1251
1252 if (systemd_message != NULL)
1253 {
1254 if (!dbus_message_iter_close_container (&iter, &systemd_iter))
1255 {
1256 BUS_SET_OOM (error);
1257 _dbus_verbose ("No memory to close systemd message container\n");
1258 goto out;
1259 }
1260
1261 if (!bus_driver_send_or_activate (transaction, systemd_message, error))
1262 {
1263 _DBUS_ASSERT_ERROR_IS_SET (error);
1264 _dbus_verbose ("bus_driver_send_or_activate() failed\n");
1265 goto out;
1266 }
1267 }
1268
1269 if (!bus_driver_send_ack_reply (connection, transaction, message, error))
1270 goto out;
1271
1272 retval = TRUE;
1273
1274 out:
1275 if (systemd_message != NULL)
1276 dbus_message_unref (systemd_message);
1277 _dbus_list_clear (&keys);
1278 _dbus_list_clear (&values);
1279 return retval;
1280 }
1281
1282 static dbus_bool_t
bus_driver_handle_add_match(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1283 bus_driver_handle_add_match (DBusConnection *connection,
1284 BusTransaction *transaction,
1285 DBusMessage *message,
1286 DBusError *error)
1287 {
1288 BusMatchRule *rule;
1289 const char *text, *bustype;
1290 DBusString str;
1291 BusMatchmaker *matchmaker;
1292 int limit;
1293 BusContext *context;
1294
1295 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1296
1297 text = NULL;
1298 rule = NULL;
1299
1300 context = bus_transaction_get_context (transaction);
1301 limit = bus_context_get_max_match_rules_per_connection (context);
1302
1303 if (bus_connection_get_n_match_rules (connection) >= limit)
1304 {
1305 DBusError tmp_error;
1306
1307 dbus_error_init (&tmp_error);
1308 dbus_set_error (&tmp_error, DBUS_ERROR_LIMITS_EXCEEDED,
1309 "Connection \"%s\" is not allowed to add more match rules "
1310 "(increase limits in configuration file if required; "
1311 "max_match_rules_per_connection=%d)",
1312 bus_connection_is_active (connection) ?
1313 bus_connection_get_name (connection) :
1314 "(inactive)",
1315 limit);
1316 bus_context_log (context, DBUS_SYSTEM_LOG_WARNING, "%s",
1317 tmp_error.message);
1318 dbus_move_error (&tmp_error, error);
1319 goto failed;
1320 }
1321
1322 if (!dbus_message_get_args (message, error,
1323 DBUS_TYPE_STRING, &text,
1324 DBUS_TYPE_INVALID))
1325 {
1326 _dbus_verbose ("No memory to get arguments to AddMatch\n");
1327 goto failed;
1328 }
1329
1330 _dbus_string_init_const (&str, text);
1331
1332 rule = bus_match_rule_parse (connection, &str, error);
1333 if (rule == NULL)
1334 goto failed;
1335
1336 bustype = bus_context_get_type (context);
1337
1338 if (bus_match_rule_get_client_is_eavesdropping (rule))
1339 {
1340 if (!bus_driver_check_caller_is_privileged (connection,
1341 transaction,
1342 message,
1343 error) ||
1344 !bus_apparmor_allows_eavesdropping (connection, bustype, error))
1345 goto failed;
1346 }
1347
1348 matchmaker = bus_connection_get_matchmaker (connection);
1349
1350 if (!bus_matchmaker_add_rule (matchmaker, rule))
1351 {
1352 BUS_SET_OOM (error);
1353 goto failed;
1354 }
1355
1356 if (!bus_driver_send_ack_reply (connection, transaction, message, error))
1357 {
1358 bus_matchmaker_remove_rule (matchmaker, rule);
1359 goto failed;
1360 }
1361
1362 bus_match_rule_unref (rule);
1363
1364 return TRUE;
1365
1366 failed:
1367 _DBUS_ASSERT_ERROR_IS_SET (error);
1368 if (rule)
1369 bus_match_rule_unref (rule);
1370 return FALSE;
1371 }
1372
1373 static dbus_bool_t
bus_driver_handle_remove_match(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1374 bus_driver_handle_remove_match (DBusConnection *connection,
1375 BusTransaction *transaction,
1376 DBusMessage *message,
1377 DBusError *error)
1378 {
1379 BusMatchRule *rule;
1380 const char *text;
1381 DBusString str;
1382 BusMatchmaker *matchmaker;
1383
1384 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1385
1386 text = NULL;
1387 rule = NULL;
1388
1389 if (!dbus_message_get_args (message, error,
1390 DBUS_TYPE_STRING, &text,
1391 DBUS_TYPE_INVALID))
1392 {
1393 _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
1394 goto failed;
1395 }
1396
1397 _dbus_string_init_const (&str, text);
1398
1399 rule = bus_match_rule_parse (connection, &str, error);
1400 if (rule == NULL)
1401 goto failed;
1402
1403 /* Send the ack before we remove the rule, since the ack is undone
1404 * on transaction cancel, but rule removal isn't.
1405 */
1406 if (!bus_driver_send_ack_reply (connection, transaction, message, error))
1407 goto failed;
1408
1409 matchmaker = bus_connection_get_matchmaker (connection);
1410
1411 if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
1412 goto failed;
1413
1414 bus_match_rule_unref (rule);
1415
1416 return TRUE;
1417
1418 failed:
1419 _DBUS_ASSERT_ERROR_IS_SET (error);
1420 if (rule)
1421 bus_match_rule_unref (rule);
1422 return FALSE;
1423 }
1424
1425 static dbus_bool_t
bus_driver_handle_get_service_owner(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1426 bus_driver_handle_get_service_owner (DBusConnection *connection,
1427 BusTransaction *transaction,
1428 DBusMessage *message,
1429 DBusError *error)
1430 {
1431 const char *text;
1432 const char *base_name;
1433 DBusString str;
1434 BusRegistry *registry;
1435 BusService *service;
1436 DBusMessage *reply;
1437
1438 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1439
1440 registry = bus_connection_get_registry (connection);
1441
1442 text = NULL;
1443 reply = NULL;
1444
1445 if (! dbus_message_get_args (message, error,
1446 DBUS_TYPE_STRING, &text,
1447 DBUS_TYPE_INVALID))
1448 goto failed;
1449
1450 _dbus_string_init_const (&str, text);
1451 service = bus_registry_lookup (registry, &str);
1452 if (service == NULL &&
1453 _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
1454 {
1455 /* ORG_FREEDESKTOP_DBUS owns itself */
1456 base_name = DBUS_SERVICE_DBUS;
1457 }
1458 else if (service == NULL)
1459 {
1460 dbus_set_error (error,
1461 DBUS_ERROR_NAME_HAS_NO_OWNER,
1462 "Could not get owner of name '%s': no such name", text);
1463 goto failed;
1464 }
1465 else
1466 {
1467 base_name = bus_connection_get_name (bus_service_get_primary_owners_connection (service));
1468 if (base_name == NULL)
1469 {
1470 /* FIXME - how is this error possible? */
1471 dbus_set_error (error,
1472 DBUS_ERROR_FAILED,
1473 "Could not determine unique name for '%s'", text);
1474 goto failed;
1475 }
1476 _dbus_assert (*base_name == ':');
1477 }
1478
1479 _dbus_assert (base_name != NULL);
1480
1481 reply = dbus_message_new_method_return (message);
1482 if (reply == NULL)
1483 goto oom;
1484
1485 if (! dbus_message_append_args (reply,
1486 DBUS_TYPE_STRING, &base_name,
1487 DBUS_TYPE_INVALID))
1488 goto oom;
1489
1490 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1491 goto oom;
1492
1493 dbus_message_unref (reply);
1494
1495 return TRUE;
1496
1497 oom:
1498 BUS_SET_OOM (error);
1499
1500 failed:
1501 _DBUS_ASSERT_ERROR_IS_SET (error);
1502 if (reply)
1503 dbus_message_unref (reply);
1504 return FALSE;
1505 }
1506
1507 static dbus_bool_t
bus_driver_handle_list_queued_owners(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1508 bus_driver_handle_list_queued_owners (DBusConnection *connection,
1509 BusTransaction *transaction,
1510 DBusMessage *message,
1511 DBusError *error)
1512 {
1513 static const char dbus_service_name[] = DBUS_SERVICE_DBUS;
1514
1515 const char *text;
1516 DBusList *base_names;
1517 DBusList *link;
1518 DBusString str;
1519 BusRegistry *registry;
1520 BusService *service;
1521 DBusMessage *reply;
1522 DBusMessageIter iter, array_iter;
1523
1524 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1525
1526 registry = bus_connection_get_registry (connection);
1527
1528 base_names = NULL;
1529 text = NULL;
1530 reply = NULL;
1531
1532 if (! dbus_message_get_args (message, error,
1533 DBUS_TYPE_STRING, &text,
1534 DBUS_TYPE_INVALID))
1535 goto failed;
1536
1537 _dbus_string_init_const (&str, text);
1538 service = bus_registry_lookup (registry, &str);
1539 if (service == NULL &&
1540 _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
1541 {
1542 /* ORG_FREEDESKTOP_DBUS owns itself */
1543 if (! _dbus_list_append (&base_names, (char *) dbus_service_name))
1544 goto oom;
1545 }
1546 else if (service == NULL)
1547 {
1548 dbus_set_error (error,
1549 DBUS_ERROR_NAME_HAS_NO_OWNER,
1550 "Could not get owners of name '%s': no such name", text);
1551 goto failed;
1552 }
1553 else
1554 {
1555 if (!bus_service_list_queued_owners (service,
1556 &base_names,
1557 error))
1558 goto failed;
1559 }
1560
1561 _dbus_assert (base_names != NULL);
1562
1563 reply = dbus_message_new_method_return (message);
1564 if (reply == NULL)
1565 goto oom;
1566
1567 dbus_message_iter_init_append (reply, &iter);
1568 if (!dbus_message_iter_open_container (&iter,
1569 DBUS_TYPE_ARRAY,
1570 DBUS_TYPE_STRING_AS_STRING,
1571 &array_iter))
1572 goto oom;
1573
1574 link = _dbus_list_get_first_link (&base_names);
1575 while (link != NULL)
1576 {
1577 char *uname;
1578
1579 _dbus_assert (link->data != NULL);
1580 uname = (char *)link->data;
1581
1582 if (!dbus_message_iter_append_basic (&array_iter,
1583 DBUS_TYPE_STRING,
1584 &uname))
1585 goto oom;
1586
1587 link = _dbus_list_get_next_link (&base_names, link);
1588 }
1589
1590 if (! dbus_message_iter_close_container (&iter, &array_iter))
1591 goto oom;
1592
1593
1594 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1595 goto oom;
1596
1597 dbus_message_unref (reply);
1598
1599 return TRUE;
1600
1601 oom:
1602 BUS_SET_OOM (error);
1603
1604 failed:
1605 _DBUS_ASSERT_ERROR_IS_SET (error);
1606 if (reply)
1607 dbus_message_unref (reply);
1608
1609 if (base_names)
1610 _dbus_list_clear (&base_names);
1611
1612 return FALSE;
1613 }
1614
1615 static dbus_bool_t
bus_driver_handle_get_connection_unix_user(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1616 bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
1617 BusTransaction *transaction,
1618 DBusMessage *message,
1619 DBusError *error)
1620 {
1621 DBusConnection *conn;
1622 DBusMessage *reply;
1623 dbus_uid_t uid;
1624 dbus_uint32_t uid32;
1625 const char *service;
1626 BusDriverFound found;
1627
1628 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1629
1630 reply = NULL;
1631
1632 found = bus_driver_get_conn_helper (connection, message, "UID", &service,
1633 &conn, error);
1634 switch (found)
1635 {
1636 case BUS_DRIVER_FOUND_SELF:
1637 uid = _dbus_getuid ();
1638 break;
1639 case BUS_DRIVER_FOUND_PEER:
1640 if (!dbus_connection_get_unix_user (conn, &uid))
1641 uid = DBUS_UID_UNSET;
1642 break;
1643 case BUS_DRIVER_FOUND_ERROR:
1644 /* fall through */
1645 default:
1646 goto failed;
1647 }
1648
1649 if (uid == DBUS_UID_UNSET)
1650 {
1651 dbus_set_error (error,
1652 DBUS_ERROR_FAILED,
1653 "Could not determine UID for '%s'", service);
1654 goto failed;
1655 }
1656
1657 reply = dbus_message_new_method_return (message);
1658 if (reply == NULL)
1659 goto oom;
1660
1661 uid32 = uid;
1662 if (! dbus_message_append_args (reply,
1663 DBUS_TYPE_UINT32, &uid32,
1664 DBUS_TYPE_INVALID))
1665 goto oom;
1666
1667 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1668 goto oom;
1669
1670 dbus_message_unref (reply);
1671
1672 return TRUE;
1673
1674 oom:
1675 BUS_SET_OOM (error);
1676
1677 failed:
1678 _DBUS_ASSERT_ERROR_IS_SET (error);
1679 if (reply)
1680 dbus_message_unref (reply);
1681 return FALSE;
1682 }
1683
1684 static dbus_bool_t
bus_driver_handle_get_connection_unix_process_id(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1685 bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
1686 BusTransaction *transaction,
1687 DBusMessage *message,
1688 DBusError *error)
1689 {
1690 DBusConnection *conn;
1691 DBusMessage *reply;
1692 dbus_pid_t pid;
1693 dbus_uint32_t pid32;
1694 const char *service;
1695 BusDriverFound found;
1696
1697 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1698
1699 reply = NULL;
1700
1701 found = bus_driver_get_conn_helper (connection, message, "PID", &service,
1702 &conn, error);
1703 switch (found)
1704 {
1705 case BUS_DRIVER_FOUND_SELF:
1706 pid = _dbus_getpid ();
1707 break;
1708 case BUS_DRIVER_FOUND_PEER:
1709 if (!dbus_connection_get_unix_process_id (conn, &pid))
1710 pid = DBUS_PID_UNSET;
1711 break;
1712 case BUS_DRIVER_FOUND_ERROR:
1713 /* fall through */
1714 default:
1715 goto failed;
1716 }
1717
1718 if (pid == DBUS_PID_UNSET)
1719 {
1720 dbus_set_error (error,
1721 DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
1722 "Could not determine PID for '%s'", service);
1723 goto failed;
1724 }
1725
1726 reply = dbus_message_new_method_return (message);
1727 if (reply == NULL)
1728 goto oom;
1729
1730 pid32 = pid;
1731 if (! dbus_message_append_args (reply,
1732 DBUS_TYPE_UINT32, &pid32,
1733 DBUS_TYPE_INVALID))
1734 goto oom;
1735
1736 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1737 goto oom;
1738
1739 dbus_message_unref (reply);
1740
1741 return TRUE;
1742
1743 oom:
1744 BUS_SET_OOM (error);
1745
1746 failed:
1747 _DBUS_ASSERT_ERROR_IS_SET (error);
1748 if (reply)
1749 dbus_message_unref (reply);
1750 return FALSE;
1751 }
1752
1753 static dbus_bool_t
bus_driver_handle_get_adt_audit_session_data(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1754 bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection,
1755 BusTransaction *transaction,
1756 DBusMessage *message,
1757 DBusError *error)
1758 {
1759 DBusConnection *conn;
1760 DBusMessage *reply;
1761 void *data = NULL;
1762 dbus_int32_t data_size;
1763 const char *service;
1764 BusDriverFound found;
1765
1766 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1767
1768 reply = NULL;
1769
1770 found = bus_driver_get_conn_helper (connection, message, "audit session data",
1771 &service, &conn, error);
1772
1773 if (found == BUS_DRIVER_FOUND_ERROR)
1774 goto failed;
1775
1776 reply = dbus_message_new_method_return (message);
1777 if (reply == NULL)
1778 goto oom;
1779
1780 /* We don't know how to find "ADT audit session data" for the bus daemon
1781 * itself. Is that even meaningful?
1782 * FIXME: Implement this or briefly note it makes no sense.
1783 */
1784 if (found != BUS_DRIVER_FOUND_PEER ||
1785 !dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) ||
1786 data == NULL)
1787 {
1788 dbus_set_error (error,
1789 DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,
1790 "Could not determine audit session data for '%s'", service);
1791 goto failed;
1792 }
1793
1794 if (! dbus_message_append_args (reply,
1795 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_size,
1796 DBUS_TYPE_INVALID))
1797 goto oom;
1798
1799 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1800 goto oom;
1801
1802 dbus_message_unref (reply);
1803
1804 return TRUE;
1805
1806 oom:
1807 BUS_SET_OOM (error);
1808
1809 failed:
1810 _DBUS_ASSERT_ERROR_IS_SET (error);
1811 if (reply)
1812 dbus_message_unref (reply);
1813 return FALSE;
1814 }
1815
1816 static dbus_bool_t
bus_driver_handle_get_connection_selinux_security_context(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1817 bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection,
1818 BusTransaction *transaction,
1819 DBusMessage *message,
1820 DBusError *error)
1821 {
1822 DBusConnection *conn;
1823 DBusMessage *reply;
1824 BusSELinuxID *context;
1825 const char *service;
1826 BusDriverFound found;
1827
1828 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1829
1830 reply = NULL;
1831
1832 found = bus_driver_get_conn_helper (connection, message, "security context",
1833 &service, &conn, error);
1834
1835 if (found == BUS_DRIVER_FOUND_ERROR)
1836 goto failed;
1837
1838 reply = dbus_message_new_method_return (message);
1839 if (reply == NULL)
1840 goto oom;
1841
1842 if (found == BUS_DRIVER_FOUND_SELF)
1843 context = bus_selinux_get_self ();
1844 else if (found == BUS_DRIVER_FOUND_PEER)
1845 context = bus_connection_get_selinux_id (conn);
1846 else
1847 context = NULL;
1848
1849 if (!context)
1850 {
1851 dbus_set_error (error,
1852 DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
1853 "Could not determine security context for '%s'", service);
1854 goto failed;
1855 }
1856
1857 if (! bus_selinux_append_context (reply, context, error))
1858 goto failed;
1859
1860 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1861 goto oom;
1862
1863 dbus_message_unref (reply);
1864
1865 return TRUE;
1866
1867 oom:
1868 BUS_SET_OOM (error);
1869
1870 failed:
1871 _DBUS_ASSERT_ERROR_IS_SET (error);
1872 if (reply)
1873 dbus_message_unref (reply);
1874 return FALSE;
1875 }
1876
1877 static dbus_bool_t
bus_driver_handle_get_connection_credentials(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)1878 bus_driver_handle_get_connection_credentials (DBusConnection *connection,
1879 BusTransaction *transaction,
1880 DBusMessage *message,
1881 DBusError *error)
1882 {
1883 DBusConnection *conn;
1884 DBusMessage *reply;
1885 DBusMessageIter reply_iter;
1886 DBusMessageIter array_iter;
1887 unsigned long ulong_uid, ulong_pid;
1888 char *s;
1889 const char *service;
1890 BusDriverFound found;
1891
1892 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1893
1894 reply = NULL;
1895
1896 found = bus_driver_get_conn_helper (connection, message, "credentials",
1897 &service, &conn, error);
1898
1899 switch (found)
1900 {
1901 case BUS_DRIVER_FOUND_SELF:
1902 ulong_pid = _dbus_getpid ();
1903 ulong_uid = _dbus_getuid ();
1904 break;
1905
1906 case BUS_DRIVER_FOUND_PEER:
1907 if (!dbus_connection_get_unix_process_id (conn, &ulong_pid))
1908 ulong_pid = DBUS_PID_UNSET;
1909 if (!dbus_connection_get_unix_user (conn, &ulong_uid))
1910 ulong_uid = DBUS_UID_UNSET;
1911 break;
1912 case BUS_DRIVER_FOUND_ERROR:
1913 /* fall through */
1914 default:
1915 goto failed;
1916 }
1917
1918 reply = _dbus_asv_new_method_return (message, &reply_iter, &array_iter);
1919 if (reply == NULL)
1920 goto oom;
1921
1922 /* we can't represent > 32-bit pids; if your system needs them, please
1923 * add ProcessID64 to the spec or something */
1924 if (ulong_pid <= _DBUS_UINT32_MAX && ulong_pid != DBUS_PID_UNSET &&
1925 !_dbus_asv_add_uint32 (&array_iter, "ProcessID", ulong_pid))
1926 goto oom;
1927
1928 /* we can't represent > 32-bit uids; if your system needs them, please
1929 * add UnixUserID64 to the spec or something */
1930 if (ulong_uid <= _DBUS_UINT32_MAX && ulong_uid != DBUS_UID_UNSET &&
1931 !_dbus_asv_add_uint32 (&array_iter, "UnixUserID", ulong_uid))
1932 goto oom;
1933
1934 /* FIXME: Obtain the Windows user of the bus daemon itself */
1935 if (found == BUS_DRIVER_FOUND_PEER &&
1936 dbus_connection_get_windows_user (conn, &s))
1937 {
1938 DBusString str;
1939 dbus_bool_t result;
1940
1941 if (s == NULL)
1942 goto oom;
1943
1944 _dbus_string_init_const (&str, s);
1945 result = _dbus_validate_utf8 (&str, 0, _dbus_string_get_length (&str));
1946 _dbus_string_free (&str);
1947 if (result)
1948 {
1949 if (!_dbus_asv_add_string (&array_iter, "WindowsSID", s))
1950 {
1951 dbus_free (s);
1952 goto oom;
1953 }
1954 }
1955 dbus_free (s);
1956 }
1957
1958 /* FIXME: Obtain the security label for the bus daemon itself */
1959 if (found == BUS_DRIVER_FOUND_PEER &&
1960 _dbus_connection_get_linux_security_label (conn, &s))
1961 {
1962 if (s == NULL)
1963 goto oom;
1964
1965 /* use the GVariant bytestring convention for strings of unknown
1966 * encoding: include the \0 in the payload, for zero-copy reading */
1967 if (!_dbus_asv_add_byte_array (&array_iter, "LinuxSecurityLabel",
1968 s, strlen (s) + 1))
1969 {
1970 dbus_free (s);
1971 goto oom;
1972 }
1973
1974 dbus_free (s);
1975 }
1976
1977 if (!_dbus_asv_close (&reply_iter, &array_iter))
1978 goto oom;
1979
1980 if (! bus_transaction_send_from_driver (transaction, connection, reply))
1981 {
1982 /* this time we don't want to close the iterator again, so just
1983 * get rid of the message */
1984 dbus_message_unref (reply);
1985 reply = NULL;
1986 goto oom;
1987 }
1988
1989 dbus_message_unref (reply);
1990
1991 return TRUE;
1992
1993 oom:
1994 BUS_SET_OOM (error);
1995
1996 failed:
1997 _DBUS_ASSERT_ERROR_IS_SET (error);
1998
1999 if (reply)
2000 {
2001 _dbus_asv_abandon (&reply_iter, &array_iter);
2002 dbus_message_unref (reply);
2003 }
2004
2005 return FALSE;
2006 }
2007
2008 static dbus_bool_t
bus_driver_handle_reload_config(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2009 bus_driver_handle_reload_config (DBusConnection *connection,
2010 BusTransaction *transaction,
2011 DBusMessage *message,
2012 DBusError *error)
2013 {
2014 BusContext *context;
2015 DBusMessage *reply;
2016
2017 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2018
2019 reply = NULL;
2020
2021 context = bus_connection_get_context (connection);
2022 if (!bus_context_reload_config (context, error))
2023 goto failed;
2024
2025 reply = dbus_message_new_method_return (message);
2026 if (reply == NULL)
2027 goto oom;
2028
2029 if (! bus_transaction_send_from_driver (transaction, connection, reply))
2030 goto oom;
2031
2032 dbus_message_unref (reply);
2033 return TRUE;
2034
2035 oom:
2036 BUS_SET_OOM (error);
2037
2038 failed:
2039 _DBUS_ASSERT_ERROR_IS_SET (error);
2040 if (reply)
2041 dbus_message_unref (reply);
2042 return FALSE;
2043 }
2044
2045 #ifdef DBUS_ENABLE_VERBOSE_MODE
2046 static dbus_bool_t
bus_driver_handle_enable_verbose(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2047 bus_driver_handle_enable_verbose (DBusConnection *connection,
2048 BusTransaction *transaction,
2049 DBusMessage *message,
2050 DBusError *error)
2051 {
2052 DBusMessage *reply = NULL;
2053
2054 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2055
2056 reply = dbus_message_new_method_return (message);
2057 if (reply == NULL)
2058 goto oom;
2059
2060 if (! bus_transaction_send_from_driver (transaction, connection, reply))
2061 goto oom;
2062
2063 _dbus_set_verbose(TRUE);
2064
2065 dbus_message_unref (reply);
2066 return TRUE;
2067
2068 oom:
2069 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2070
2071 BUS_SET_OOM (error);
2072
2073 if (reply)
2074 dbus_message_unref (reply);
2075 return FALSE;
2076 }
2077
2078 static dbus_bool_t
bus_driver_handle_disable_verbose(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2079 bus_driver_handle_disable_verbose (DBusConnection *connection,
2080 BusTransaction *transaction,
2081 DBusMessage *message,
2082 DBusError *error)
2083 {
2084 DBusMessage *reply = NULL;
2085
2086 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2087
2088 reply = dbus_message_new_method_return (message);
2089 if (reply == NULL)
2090 goto oom;
2091
2092 if (! bus_transaction_send_from_driver (transaction, connection, reply))
2093 goto oom;
2094
2095 _dbus_set_verbose(FALSE);
2096
2097 dbus_message_unref (reply);
2098 return TRUE;
2099
2100 oom:
2101 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2102
2103 BUS_SET_OOM (error);
2104
2105 if (reply)
2106 dbus_message_unref (reply);
2107 return FALSE;
2108 }
2109 #endif
2110
2111 static dbus_bool_t
bus_driver_handle_get_id(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2112 bus_driver_handle_get_id (DBusConnection *connection,
2113 BusTransaction *transaction,
2114 DBusMessage *message,
2115 DBusError *error)
2116 {
2117 BusContext *context;
2118 DBusMessage *reply;
2119 DBusString uuid;
2120 const char *v_STRING;
2121
2122 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2123
2124 if (!_dbus_string_init (&uuid))
2125 {
2126 BUS_SET_OOM (error);
2127 return FALSE;
2128 }
2129
2130 reply = NULL;
2131
2132 context = bus_connection_get_context (connection);
2133 if (!bus_context_get_id (context, &uuid))
2134 goto oom;
2135
2136 reply = dbus_message_new_method_return (message);
2137 if (reply == NULL)
2138 goto oom;
2139
2140 v_STRING = _dbus_string_get_const_data (&uuid);
2141 if (!dbus_message_append_args (reply,
2142 DBUS_TYPE_STRING, &v_STRING,
2143 DBUS_TYPE_INVALID))
2144 goto oom;
2145
2146 _dbus_assert (dbus_message_has_signature (reply, "s"));
2147
2148 if (! bus_transaction_send_from_driver (transaction, connection, reply))
2149 goto oom;
2150
2151 _dbus_string_free (&uuid);
2152 dbus_message_unref (reply);
2153 return TRUE;
2154
2155 oom:
2156 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2157
2158 BUS_SET_OOM (error);
2159
2160 if (reply)
2161 dbus_message_unref (reply);
2162 _dbus_string_free (&uuid);
2163 return FALSE;
2164 }
2165
2166 static dbus_bool_t
bus_driver_handle_become_monitor(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2167 bus_driver_handle_become_monitor (DBusConnection *connection,
2168 BusTransaction *transaction,
2169 DBusMessage *message,
2170 DBusError *error)
2171 {
2172 char **match_rules = NULL;
2173 const char *bustype;
2174 BusContext *context;
2175 BusMatchRule *rule;
2176 DBusList *rules = NULL;
2177 DBusList *iter;
2178 DBusString str;
2179 int i;
2180 int n_match_rules;
2181 dbus_uint32_t flags;
2182 dbus_bool_t ret = FALSE;
2183
2184 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2185
2186 context = bus_transaction_get_context (transaction);
2187 bustype = context ? bus_context_get_type (context) : NULL;
2188 if (!bus_apparmor_allows_eavesdropping (connection, bustype, error))
2189 goto out;
2190
2191 if (!dbus_message_get_args (message, error,
2192 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &match_rules, &n_match_rules,
2193 DBUS_TYPE_UINT32, &flags,
2194 DBUS_TYPE_INVALID))
2195 goto out;
2196
2197 if (flags != 0)
2198 {
2199 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2200 "BecomeMonitor does not support any flags yet");
2201 goto out;
2202 }
2203
2204 /* Special case: a zero-length array becomes [""] */
2205 if (n_match_rules == 0)
2206 {
2207 match_rules = dbus_malloc (2 * sizeof (char *));
2208
2209 if (match_rules == NULL)
2210 {
2211 BUS_SET_OOM (error);
2212 goto out;
2213 }
2214
2215 match_rules[0] = _dbus_strdup ("");
2216
2217 if (match_rules[0] == NULL)
2218 {
2219 BUS_SET_OOM (error);
2220 goto out;
2221 }
2222
2223 match_rules[1] = NULL;
2224 n_match_rules = 1;
2225 }
2226
2227 for (i = 0; i < n_match_rules; i++)
2228 {
2229 _dbus_string_init_const (&str, match_rules[i]);
2230 rule = bus_match_rule_parse (connection, &str, error);
2231
2232 if (rule == NULL)
2233 goto out;
2234
2235 /* monitors always eavesdrop */
2236 bus_match_rule_set_client_is_eavesdropping (rule, TRUE);
2237
2238 if (!_dbus_list_append (&rules, rule))
2239 {
2240 BUS_SET_OOM (error);
2241 bus_match_rule_unref (rule);
2242 goto out;
2243 }
2244 }
2245
2246 /* Send the ack before we remove the rule, since the ack is undone
2247 * on transaction cancel, but becoming a monitor isn't.
2248 */
2249 if (!bus_driver_send_ack_reply (connection, transaction, message, error))
2250 goto out;
2251
2252 if (!bus_connection_be_monitor (connection, transaction, &rules, error))
2253 goto out;
2254
2255 ret = TRUE;
2256
2257 out:
2258 if (ret)
2259 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2260 else
2261 _DBUS_ASSERT_ERROR_IS_SET (error);
2262
2263 for (iter = _dbus_list_get_first_link (&rules);
2264 iter != NULL;
2265 iter = _dbus_list_get_next_link (&rules, iter))
2266 bus_match_rule_unref (iter->data);
2267
2268 _dbus_list_clear (&rules);
2269
2270 dbus_free_string_array (match_rules);
2271 return ret;
2272 }
2273
2274 static dbus_bool_t
bus_driver_handle_get_machine_id(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2275 bus_driver_handle_get_machine_id (DBusConnection *connection,
2276 BusTransaction *transaction,
2277 DBusMessage *message,
2278 DBusError *error)
2279 {
2280 DBusMessage *reply = NULL;
2281 DBusString uuid;
2282 const char *str;
2283
2284 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2285
2286 if (!_dbus_string_init (&uuid))
2287 {
2288 BUS_SET_OOM (error);
2289 return FALSE;
2290 }
2291
2292 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
2293 goto fail;
2294
2295 reply = dbus_message_new_method_return (message);
2296
2297 if (reply == NULL)
2298 goto oom;
2299
2300 str = _dbus_string_get_const_data (&uuid);
2301
2302 if (!dbus_message_append_args (reply,
2303 DBUS_TYPE_STRING, &str,
2304 DBUS_TYPE_INVALID))
2305 goto oom;
2306
2307 _dbus_assert (dbus_message_has_signature (reply, "s"));
2308
2309 if (!bus_transaction_send_from_driver (transaction, connection, reply))
2310 goto oom;
2311
2312 _dbus_string_free (&uuid);
2313 dbus_message_unref (reply);
2314 return TRUE;
2315
2316 oom:
2317 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2318
2319 BUS_SET_OOM (error);
2320
2321 fail:
2322 _DBUS_ASSERT_ERROR_IS_SET (error);
2323
2324 if (reply != NULL)
2325 dbus_message_unref (reply);
2326
2327 _dbus_string_free (&uuid);
2328 return FALSE;
2329 }
2330
2331 static dbus_bool_t
bus_driver_handle_ping(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2332 bus_driver_handle_ping (DBusConnection *connection,
2333 BusTransaction *transaction,
2334 DBusMessage *message,
2335 DBusError *error)
2336 {
2337 return bus_driver_send_ack_reply (connection, transaction, message, error);
2338 }
2339
2340 static dbus_bool_t bus_driver_handle_get (DBusConnection *connection,
2341 BusTransaction *transaction,
2342 DBusMessage *message,
2343 DBusError *error);
2344
2345 static dbus_bool_t bus_driver_handle_get_all (DBusConnection *connection,
2346 BusTransaction *transaction,
2347 DBusMessage *message,
2348 DBusError *error);
2349
2350 static dbus_bool_t bus_driver_handle_set (DBusConnection *connection,
2351 BusTransaction *transaction,
2352 DBusMessage *message,
2353 DBusError *error);
2354
2355 static dbus_bool_t features_getter (BusContext *context,
2356 DBusMessageIter *variant_iter);
2357 static dbus_bool_t interfaces_getter (BusContext *context,
2358 DBusMessageIter *variant_iter);
2359
2360 typedef enum
2361 {
2362 /* Various older methods were available at every object path. We have to
2363 * preserve that behaviour for backwards compatibility, but we can at least
2364 * stop doing that for newly added methods.
2365 * The special Peer interface should also work at any object path.
2366 * <https://bugs.freedesktop.org/show_bug.cgi?id=101256> */
2367 METHOD_FLAG_ANY_PATH = (1 << 0),
2368
2369 /* If set, callers must be privileged. On Unix, the uid of the connection
2370 * must either be the uid of this process, or 0 (root). On Windows,
2371 * the SID of the connection must be the SID of this process. */
2372 METHOD_FLAG_PRIVILEGED = (1 << 1),
2373
2374 METHOD_FLAG_NONE = 0
2375 } MethodFlags;
2376
2377 typedef struct
2378 {
2379 const char *name;
2380 const char *in_args;
2381 const char *out_args;
2382 dbus_bool_t (* handler) (DBusConnection *connection,
2383 BusTransaction *transaction,
2384 DBusMessage *message,
2385 DBusError *error);
2386 MethodFlags flags;
2387 } MessageHandler;
2388
2389 typedef struct
2390 {
2391 const char *name;
2392 const char *type;
2393 dbus_bool_t (* getter) (BusContext *context,
2394 DBusMessageIter *variant_iter);
2395 } PropertyHandler;
2396
2397 /* For speed it might be useful to sort this in order of
2398 * frequency of use (but doesn't matter with only a few items
2399 * anyhow)
2400 */
2401 static const MessageHandler dbus_message_handlers[] = {
2402 { "Hello",
2403 "",
2404 DBUS_TYPE_STRING_AS_STRING,
2405 bus_driver_handle_hello,
2406 METHOD_FLAG_ANY_PATH },
2407 { "RequestName",
2408 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
2409 DBUS_TYPE_UINT32_AS_STRING,
2410 bus_driver_handle_acquire_service,
2411 METHOD_FLAG_ANY_PATH },
2412 { "ReleaseName",
2413 DBUS_TYPE_STRING_AS_STRING,
2414 DBUS_TYPE_UINT32_AS_STRING,
2415 bus_driver_handle_release_service,
2416 METHOD_FLAG_ANY_PATH },
2417 { "StartServiceByName",
2418 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
2419 DBUS_TYPE_UINT32_AS_STRING,
2420 bus_driver_handle_activate_service,
2421 METHOD_FLAG_ANY_PATH },
2422 { "UpdateActivationEnvironment",
2423 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,
2424 "",
2425 bus_driver_handle_update_activation_environment,
2426 METHOD_FLAG_PRIVILEGED },
2427 { "NameHasOwner",
2428 DBUS_TYPE_STRING_AS_STRING,
2429 DBUS_TYPE_BOOLEAN_AS_STRING,
2430 bus_driver_handle_service_exists,
2431 METHOD_FLAG_ANY_PATH },
2432 { "ListNames",
2433 "",
2434 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
2435 bus_driver_handle_list_services,
2436 METHOD_FLAG_ANY_PATH },
2437 { "ListActivatableNames",
2438 "",
2439 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
2440 bus_driver_handle_list_activatable_services,
2441 METHOD_FLAG_ANY_PATH },
2442 { "AddMatch",
2443 DBUS_TYPE_STRING_AS_STRING,
2444 "",
2445 bus_driver_handle_add_match,
2446 METHOD_FLAG_ANY_PATH },
2447 { "RemoveMatch",
2448 DBUS_TYPE_STRING_AS_STRING,
2449 "",
2450 bus_driver_handle_remove_match,
2451 METHOD_FLAG_ANY_PATH },
2452 { "GetNameOwner",
2453 DBUS_TYPE_STRING_AS_STRING,
2454 DBUS_TYPE_STRING_AS_STRING,
2455 bus_driver_handle_get_service_owner,
2456 METHOD_FLAG_ANY_PATH },
2457 { "ListQueuedOwners",
2458 DBUS_TYPE_STRING_AS_STRING,
2459 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
2460 bus_driver_handle_list_queued_owners,
2461 METHOD_FLAG_ANY_PATH },
2462 { "GetConnectionUnixUser",
2463 DBUS_TYPE_STRING_AS_STRING,
2464 DBUS_TYPE_UINT32_AS_STRING,
2465 bus_driver_handle_get_connection_unix_user,
2466 METHOD_FLAG_ANY_PATH },
2467 { "GetConnectionUnixProcessID",
2468 DBUS_TYPE_STRING_AS_STRING,
2469 DBUS_TYPE_UINT32_AS_STRING,
2470 bus_driver_handle_get_connection_unix_process_id,
2471 METHOD_FLAG_ANY_PATH },
2472 { "GetAdtAuditSessionData",
2473 DBUS_TYPE_STRING_AS_STRING,
2474 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
2475 bus_driver_handle_get_adt_audit_session_data,
2476 METHOD_FLAG_ANY_PATH },
2477 { "GetConnectionSELinuxSecurityContext",
2478 DBUS_TYPE_STRING_AS_STRING,
2479 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
2480 bus_driver_handle_get_connection_selinux_security_context,
2481 METHOD_FLAG_ANY_PATH },
2482 { "ReloadConfig",
2483 "",
2484 "",
2485 bus_driver_handle_reload_config,
2486 METHOD_FLAG_ANY_PATH },
2487 { "GetId",
2488 "",
2489 DBUS_TYPE_STRING_AS_STRING,
2490 bus_driver_handle_get_id,
2491 METHOD_FLAG_ANY_PATH },
2492 { "GetConnectionCredentials", "s", "a{sv}",
2493 bus_driver_handle_get_connection_credentials,
2494 METHOD_FLAG_ANY_PATH },
2495 { NULL, NULL, NULL, NULL }
2496 };
2497
2498 static const PropertyHandler dbus_property_handlers[] = {
2499 { "Features", "as", features_getter },
2500 { "Interfaces", "as", interfaces_getter },
2501 { NULL, NULL, NULL }
2502 };
2503
2504 static dbus_bool_t bus_driver_handle_introspect (DBusConnection *,
2505 BusTransaction *, DBusMessage *, DBusError *);
2506
2507 static const MessageHandler properties_message_handlers[] = {
2508 { "Get", "ss", "v", bus_driver_handle_get, METHOD_FLAG_NONE },
2509 { "GetAll", "s", "a{sv}", bus_driver_handle_get_all, METHOD_FLAG_NONE },
2510 { "Set", "ssv", "", bus_driver_handle_set, METHOD_FLAG_NONE },
2511 { NULL, NULL, NULL, NULL }
2512 };
2513
2514 static const MessageHandler introspectable_message_handlers[] = {
2515 { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect,
2516 METHOD_FLAG_ANY_PATH },
2517 { NULL, NULL, NULL, NULL }
2518 };
2519
2520 static const MessageHandler monitoring_message_handlers[] = {
2521 { "BecomeMonitor", "asu", "", bus_driver_handle_become_monitor,
2522 METHOD_FLAG_PRIVILEGED },
2523 { NULL, NULL, NULL, NULL }
2524 };
2525
2526 #ifdef DBUS_ENABLE_VERBOSE_MODE
2527 static const MessageHandler verbose_message_handlers[] = {
2528 { "EnableVerbose", "", "", bus_driver_handle_enable_verbose,
2529 METHOD_FLAG_NONE },
2530 { "DisableVerbose", "", "", bus_driver_handle_disable_verbose,
2531 METHOD_FLAG_NONE },
2532 { NULL, NULL, NULL, NULL }
2533 };
2534 #endif
2535
2536 #ifdef DBUS_ENABLE_STATS
2537 static const MessageHandler stats_message_handlers[] = {
2538 { "GetStats", "", "a{sv}", bus_stats_handle_get_stats,
2539 METHOD_FLAG_NONE },
2540 { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats,
2541 METHOD_FLAG_NONE },
2542 { "GetAllMatchRules", "", "a{sas}", bus_stats_handle_get_all_match_rules,
2543 METHOD_FLAG_NONE },
2544 { NULL, NULL, NULL, NULL }
2545 };
2546 #endif
2547
2548 static const MessageHandler peer_message_handlers[] = {
2549 { "GetMachineId", "", "s", bus_driver_handle_get_machine_id,
2550 METHOD_FLAG_ANY_PATH },
2551 { "Ping", "", "", bus_driver_handle_ping, METHOD_FLAG_ANY_PATH },
2552 { NULL, NULL, NULL, NULL }
2553 };
2554
2555 typedef enum
2556 {
2557 /* Various older interfaces were available at every object path. We have to
2558 * preserve that behaviour for backwards compatibility, but we can at least
2559 * stop doing that for newly added interfaces:
2560 * <https://bugs.freedesktop.org/show_bug.cgi?id=101256>
2561 * Introspectable and Peer are also useful at all object paths. */
2562 INTERFACE_FLAG_ANY_PATH = (1 << 0),
2563
2564 /* Set this flag for interfaces that should not show up in the
2565 * Interfaces property. */
2566 INTERFACE_FLAG_UNINTERESTING = (1 << 1),
2567
2568 INTERFACE_FLAG_NONE = 0
2569 } InterfaceFlags;
2570
2571 typedef struct {
2572 const char *name;
2573 const MessageHandler *message_handlers;
2574 const char *extra_introspection;
2575 InterfaceFlags flags;
2576 const PropertyHandler *property_handlers;
2577 } InterfaceHandler;
2578
2579 /* These should ideally be sorted by frequency of use, although it
2580 * probably doesn't matter with this few items */
2581 static InterfaceHandler interface_handlers[] = {
2582 { DBUS_INTERFACE_DBUS, dbus_message_handlers,
2583 " <signal name=\"NameOwnerChanged\">\n"
2584 " <arg type=\"s\"/>\n"
2585 " <arg type=\"s\"/>\n"
2586 " <arg type=\"s\"/>\n"
2587 " </signal>\n"
2588 " <signal name=\"NameLost\">\n"
2589 " <arg type=\"s\"/>\n"
2590 " </signal>\n"
2591 " <signal name=\"NameAcquired\">\n"
2592 " <arg type=\"s\"/>\n"
2593 " </signal>\n",
2594 /* Not in the Interfaces property because if you can get the properties
2595 * of the o.fd.DBus interface, then you certainly have the o.fd.DBus
2596 * interface, so there is little point in listing it explicitly.
2597 * Partially available at all paths for backwards compatibility. */
2598 INTERFACE_FLAG_ANY_PATH | INTERFACE_FLAG_UNINTERESTING,
2599 dbus_property_handlers },
2600 { DBUS_INTERFACE_PROPERTIES, properties_message_handlers,
2601 " <signal name=\"PropertiesChanged\">\n"
2602 " <arg type=\"s\" name=\"interface_name\"/>\n"
2603 " <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"
2604 " <arg type=\"as\" name=\"invalidated_properties\"/>\n"
2605 " </signal>\n",
2606 /* Not in the Interfaces property because if you can get the properties
2607 * of the o.fd.DBus interface, then you certainly have Properties. */
2608 INTERFACE_FLAG_UNINTERESTING },
2609 { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL,
2610 /* Not in the Interfaces property because introspection isn't really a
2611 * feature in the same way as e.g. Monitoring.
2612 * Available at all paths so tools like d-feet can start from "/". */
2613 INTERFACE_FLAG_ANY_PATH | INTERFACE_FLAG_UNINTERESTING },
2614 { DBUS_INTERFACE_MONITORING, monitoring_message_handlers, NULL,
2615 INTERFACE_FLAG_NONE },
2616 #ifdef DBUS_ENABLE_VERBOSE_MODE
2617 { DBUS_INTERFACE_VERBOSE, verbose_message_handlers, NULL,
2618 INTERFACE_FLAG_NONE },
2619 #endif
2620 #ifdef DBUS_ENABLE_STATS
2621 { BUS_INTERFACE_STATS, stats_message_handlers, NULL,
2622 INTERFACE_FLAG_NONE },
2623 #endif
2624 { DBUS_INTERFACE_PEER, peer_message_handlers, NULL,
2625 /* Not in the Interfaces property because it's a pseudo-interface
2626 * on all object paths of all connections, rather than a feature of the
2627 * bus driver object. */
2628 INTERFACE_FLAG_ANY_PATH | INTERFACE_FLAG_UNINTERESTING },
2629 { NULL, NULL, NULL }
2630 };
2631
2632 static dbus_bool_t
write_args_for_direction(DBusString * xml,const char * signature,dbus_bool_t in)2633 write_args_for_direction (DBusString *xml,
2634 const char *signature,
2635 dbus_bool_t in)
2636 {
2637 DBusTypeReader typereader;
2638 DBusString sigstr;
2639 int current_type;
2640
2641 _dbus_string_init_const (&sigstr, signature);
2642 _dbus_type_reader_init_types_only (&typereader, &sigstr, 0);
2643
2644 while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID)
2645 {
2646 const DBusString *subsig;
2647 int start, len;
2648
2649 _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len);
2650 if (!_dbus_string_append_printf (xml, " <arg direction=\"%s\" type=\"",
2651 in ? "in" : "out"))
2652 goto oom;
2653 if (!_dbus_string_append_len (xml,
2654 _dbus_string_get_const_data (subsig) + start,
2655 len))
2656 goto oom;
2657 if (!_dbus_string_append (xml, "\"/>\n"))
2658 goto oom;
2659
2660 _dbus_type_reader_next (&typereader);
2661 }
2662 return TRUE;
2663 oom:
2664 return FALSE;
2665 }
2666
2667 dbus_bool_t
bus_driver_generate_introspect_string(DBusString * xml,dbus_bool_t is_canonical_path,DBusMessage * message)2668 bus_driver_generate_introspect_string (DBusString *xml,
2669 dbus_bool_t is_canonical_path,
2670 DBusMessage *message)
2671 {
2672 const InterfaceHandler *ih;
2673 const MessageHandler *mh;
2674 const PropertyHandler *ph;
2675
2676 if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
2677 return FALSE;
2678 if (!_dbus_string_append (xml, "<node>\n"))
2679 return FALSE;
2680
2681 for (ih = interface_handlers; ih->name != NULL; ih++)
2682 {
2683 if (!(is_canonical_path || (ih->flags & INTERFACE_FLAG_ANY_PATH)))
2684 continue;
2685
2686 if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
2687 ih->name))
2688 return FALSE;
2689
2690 for (mh = ih->message_handlers; mh->name != NULL; mh++)
2691 {
2692 if (!_dbus_string_append_printf (xml, " <method name=\"%s\">\n",
2693 mh->name))
2694 return FALSE;
2695
2696 if (!write_args_for_direction (xml, mh->in_args, TRUE))
2697 return FALSE;
2698
2699 if (!write_args_for_direction (xml, mh->out_args, FALSE))
2700 return FALSE;
2701
2702 if (!_dbus_string_append (xml, " </method>\n"))
2703 return FALSE;
2704 }
2705
2706 for (ph = ih->property_handlers; ph != NULL && ph->name != NULL; ph++)
2707 {
2708 /* We only have constant properties so far, so hard-code that bit */
2709 if (!_dbus_string_append_printf (xml,
2710 " <property name=\"%s\" type=\"%s\" access=\"read\">\n",
2711 ph->name, ph->type))
2712 return FALSE;
2713
2714 if (!_dbus_string_append (xml,
2715 " <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n"
2716 " </property>\n"))
2717 return FALSE;
2718 }
2719
2720 if (ih->extra_introspection != NULL &&
2721 !_dbus_string_append (xml, ih->extra_introspection))
2722 return FALSE;
2723
2724 if (!_dbus_string_append (xml, " </interface>\n"))
2725 return FALSE;
2726 }
2727
2728 if (message != NULL)
2729 {
2730 /* Make the bus driver object path discoverable */
2731 if (dbus_message_has_path (message, "/"))
2732 {
2733 if (!_dbus_string_append (xml,
2734 " <node name=\"org/freedesktop/DBus\"/>\n"))
2735 return FALSE;
2736 }
2737 else if (dbus_message_has_path (message, "/org"))
2738 {
2739 if (!_dbus_string_append (xml,
2740 " <node name=\"freedesktop/DBus\"/>\n"))
2741 return FALSE;
2742 }
2743 else if (dbus_message_has_path (message, "/org/freedesktop"))
2744 {
2745 if (!_dbus_string_append (xml, " <node name=\"DBus\"/>\n"))
2746 return FALSE;
2747 }
2748 }
2749
2750 if (!_dbus_string_append (xml, "</node>\n"))
2751 return FALSE;
2752
2753 return TRUE;
2754 }
2755
2756 static dbus_bool_t
bus_driver_handle_introspect(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2757 bus_driver_handle_introspect (DBusConnection *connection,
2758 BusTransaction *transaction,
2759 DBusMessage *message,
2760 DBusError *error)
2761 {
2762 DBusString xml;
2763 DBusMessage *reply;
2764 const char *v_STRING;
2765 dbus_bool_t is_canonical_path;
2766
2767 _dbus_verbose ("Introspect() on bus driver\n");
2768
2769 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2770
2771 reply = NULL;
2772
2773 if (! dbus_message_get_args (message, error,
2774 DBUS_TYPE_INVALID))
2775 {
2776 _DBUS_ASSERT_ERROR_IS_SET (error);
2777 return FALSE;
2778 }
2779
2780 if (!_dbus_string_init (&xml))
2781 {
2782 BUS_SET_OOM (error);
2783 return FALSE;
2784 }
2785
2786 is_canonical_path = dbus_message_has_path (message, DBUS_PATH_DBUS);
2787
2788 if (!bus_driver_generate_introspect_string (&xml, is_canonical_path, message))
2789 goto oom;
2790
2791 v_STRING = _dbus_string_get_const_data (&xml);
2792
2793 reply = dbus_message_new_method_return (message);
2794 if (reply == NULL)
2795 goto oom;
2796
2797 if (! dbus_message_append_args (reply,
2798 DBUS_TYPE_STRING, &v_STRING,
2799 DBUS_TYPE_INVALID))
2800 goto oom;
2801
2802 if (! bus_transaction_send_from_driver (transaction, connection, reply))
2803 goto oom;
2804
2805 dbus_message_unref (reply);
2806 _dbus_string_free (&xml);
2807
2808 return TRUE;
2809
2810 oom:
2811 BUS_SET_OOM (error);
2812
2813 if (reply)
2814 dbus_message_unref (reply);
2815
2816 _dbus_string_free (&xml);
2817
2818 return FALSE;
2819 }
2820
2821 dbus_bool_t
bus_driver_handle_message(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)2822 bus_driver_handle_message (DBusConnection *connection,
2823 BusTransaction *transaction,
2824 DBusMessage *message,
2825 DBusError *error)
2826 {
2827 const char *name, *interface;
2828 const InterfaceHandler *ih;
2829 const MessageHandler *mh;
2830 dbus_bool_t found_interface = FALSE;
2831 dbus_bool_t is_canonical_path;
2832
2833 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2834
2835 if (dbus_message_is_signal (message, "org.freedesktop.systemd1.Activator", "ActivationFailure"))
2836 {
2837 BusContext *context;
2838 DBusConnection *systemd;
2839
2840 /* This is a directed signal, not a method call, so the log message
2841 * is a little weird (it talks about "calling" ActivationFailure),
2842 * but it's close enough */
2843 if (!bus_driver_check_caller_is_privileged (connection,
2844 transaction,
2845 message,
2846 error))
2847 return FALSE;
2848
2849 context = bus_connection_get_context (connection);
2850 systemd = bus_driver_get_owner_of_name (connection,
2851 "org.freedesktop.systemd1");
2852
2853 if (systemd != connection)
2854 {
2855 const char *attacker;
2856
2857 attacker = bus_connection_get_name (connection);
2858 bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY,
2859 "Ignoring forged ActivationFailure message from "
2860 "connection %s (%s)",
2861 attacker ? attacker : "(unauthenticated)",
2862 bus_connection_get_loginfo (connection));
2863 /* ignore it */
2864 return TRUE;
2865 }
2866
2867 if (!bus_context_get_systemd_activation (context))
2868 {
2869 bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
2870 "Ignoring unexpected ActivationFailure message "
2871 "while not using systemd activation");
2872 return FALSE;
2873 }
2874
2875 return dbus_activation_systemd_failure(bus_context_get_activation(context), message);
2876 }
2877
2878 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
2879 {
2880 _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
2881 return TRUE; /* we just ignore this */
2882 }
2883
2884 /* may be NULL, which means "any interface will do" */
2885 interface = dbus_message_get_interface (message);
2886
2887 _dbus_assert (dbus_message_get_member (message) != NULL);
2888
2889 name = dbus_message_get_member (message);
2890
2891 _dbus_verbose ("Driver got a method call: %s\n", name);
2892
2893 /* security checks should have kept this from getting here */
2894 _dbus_assert (dbus_message_get_sender (message) != NULL ||
2895 strcmp (name, "Hello") == 0);
2896
2897 is_canonical_path = dbus_message_has_path (message, DBUS_PATH_DBUS);
2898
2899 for (ih = interface_handlers; ih->name != NULL; ih++)
2900 {
2901 if (!(is_canonical_path || (ih->flags & INTERFACE_FLAG_ANY_PATH)))
2902 continue;
2903
2904 if (interface != NULL && strcmp (interface, ih->name) != 0)
2905 continue;
2906
2907 found_interface = TRUE;
2908
2909 for (mh = ih->message_handlers; mh->name != NULL; mh++)
2910 {
2911 if (strcmp (mh->name, name) != 0)
2912 continue;
2913
2914 _dbus_verbose ("Found driver handler for %s\n", name);
2915
2916 if ((mh->flags & METHOD_FLAG_PRIVILEGED) &&
2917 !bus_driver_check_caller_is_privileged (connection, transaction,
2918 message, error))
2919 {
2920 _DBUS_ASSERT_ERROR_IS_SET (error);
2921 return FALSE;
2922 }
2923
2924 if (!(is_canonical_path || (mh->flags & METHOD_FLAG_ANY_PATH)))
2925 {
2926 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2927 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
2928 "Method '%s' is only available at the canonical object path '%s'",
2929 dbus_message_get_member (message), DBUS_PATH_DBUS);
2930 _DBUS_ASSERT_ERROR_IS_SET (error);
2931 return FALSE;
2932 }
2933
2934 if (!dbus_message_has_signature (message, mh->in_args))
2935 {
2936 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2937 _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
2938 name, dbus_message_get_signature (message),
2939 mh->in_args);
2940
2941 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2942 "Call to %s has wrong args (%s, expected %s)\n",
2943 name, dbus_message_get_signature (message),
2944 mh->in_args);
2945 _DBUS_ASSERT_ERROR_IS_SET (error);
2946 return FALSE;
2947 }
2948
2949 if ((* mh->handler) (connection, transaction, message, error))
2950 {
2951 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2952 _dbus_verbose ("Driver handler succeeded\n");
2953 return TRUE;
2954 }
2955 else
2956 {
2957 _DBUS_ASSERT_ERROR_IS_SET (error);
2958 _dbus_verbose ("Driver handler returned failure\n");
2959 return FALSE;
2960 }
2961 }
2962 }
2963
2964 _dbus_verbose ("No driver handler for message \"%s\"\n",
2965 name);
2966
2967 dbus_set_error (error, found_interface ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_INTERFACE,
2968 "%s does not understand message %s",
2969 DBUS_SERVICE_DBUS, name);
2970
2971 return FALSE;
2972 }
2973
2974 void
bus_driver_remove_connection(DBusConnection * connection)2975 bus_driver_remove_connection (DBusConnection *connection)
2976 {
2977 /* FIXME 1.0 Does nothing for now, should unregister the connection
2978 * with the bus driver.
2979 */
2980 }
2981
2982 static dbus_bool_t
features_getter(BusContext * context,DBusMessageIter * variant_iter)2983 features_getter (BusContext *context,
2984 DBusMessageIter *variant_iter)
2985 {
2986 DBusMessageIter arr_iter;
2987
2988 if (!dbus_message_iter_open_container (variant_iter, DBUS_TYPE_ARRAY,
2989 DBUS_TYPE_STRING_AS_STRING,
2990 &arr_iter))
2991 return FALSE;
2992
2993 if (bus_apparmor_enabled ())
2994 {
2995 const char *s = "AppArmor";
2996
2997 if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_STRING, &s))
2998 goto abandon;
2999 }
3000
3001 if (bus_selinux_enabled ())
3002 {
3003 const char *s = "SELinux";
3004
3005 if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_STRING, &s))
3006 goto abandon;
3007 }
3008
3009 if (bus_context_get_systemd_activation (context))
3010 {
3011 const char *s = "SystemdActivation";
3012
3013 if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_STRING, &s))
3014 goto abandon;
3015 }
3016
3017 return dbus_message_iter_close_container (variant_iter, &arr_iter);
3018
3019 abandon:
3020 dbus_message_iter_abandon_container (variant_iter, &arr_iter);
3021 return FALSE;
3022 }
3023
3024 static dbus_bool_t
interfaces_getter(BusContext * context,DBusMessageIter * variant_iter)3025 interfaces_getter (BusContext *context,
3026 DBusMessageIter *variant_iter)
3027 {
3028 DBusMessageIter arr_iter;
3029 const InterfaceHandler *ih;
3030
3031 if (!dbus_message_iter_open_container (variant_iter, DBUS_TYPE_ARRAY,
3032 DBUS_TYPE_STRING_AS_STRING,
3033 &arr_iter))
3034 return FALSE;
3035
3036 for (ih = interface_handlers; ih->name != NULL; ih++)
3037 {
3038 if (ih->flags & INTERFACE_FLAG_UNINTERESTING)
3039 continue;
3040
3041 if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_STRING,
3042 &ih->name))
3043 goto abandon;
3044 }
3045
3046 return dbus_message_iter_close_container (variant_iter, &arr_iter);
3047
3048 abandon:
3049 dbus_message_iter_abandon_container (variant_iter, &arr_iter);
3050 return FALSE;
3051 }
3052
3053 static const InterfaceHandler *
bus_driver_find_interface(const char * name,dbus_bool_t canonical_path,DBusError * error)3054 bus_driver_find_interface (const char *name,
3055 dbus_bool_t canonical_path,
3056 DBusError *error)
3057 {
3058 const InterfaceHandler *ih;
3059
3060 for (ih = interface_handlers; ih->name != NULL; ih++)
3061 {
3062 if (!(canonical_path || (ih->flags & INTERFACE_FLAG_ANY_PATH)))
3063 continue;
3064
3065 if (strcmp (name, ih->name) == 0)
3066 return ih;
3067 }
3068
3069 dbus_set_error (error, DBUS_ERROR_UNKNOWN_INTERFACE,
3070 "Interface \"%s\" not found", name);
3071 return NULL;
3072 }
3073
3074 static const PropertyHandler *
interface_handler_find_property(const InterfaceHandler * ih,const char * name,DBusError * error)3075 interface_handler_find_property (const InterfaceHandler *ih,
3076 const char *name,
3077 DBusError *error)
3078 {
3079 const PropertyHandler *ph;
3080
3081 for (ph = ih->property_handlers; ph != NULL && ph->name != NULL; ph++)
3082 {
3083 if (strcmp (name, ph->name) == 0)
3084 return ph;
3085 }
3086
3087 dbus_set_error (error, DBUS_ERROR_UNKNOWN_PROPERTY,
3088 "Property \"%s.%s\" not found", ih->name, name);
3089 return NULL;
3090 }
3091
3092 static dbus_bool_t
bus_driver_handle_get(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)3093 bus_driver_handle_get (DBusConnection *connection,
3094 BusTransaction *transaction,
3095 DBusMessage *message,
3096 DBusError *error)
3097 {
3098 const InterfaceHandler *ih;
3099 const PropertyHandler *handler;
3100 const char *iface;
3101 const char *prop;
3102 BusContext *context;
3103 DBusMessage *reply = NULL;
3104 DBusMessageIter iter;
3105 DBusMessageIter var_iter;
3106
3107 /* The message signature has already been checked for us,
3108 * so this should always succeed. */
3109 if (!dbus_message_get_args (message, error,
3110 DBUS_TYPE_STRING, &iface,
3111 DBUS_TYPE_STRING, &prop,
3112 DBUS_TYPE_INVALID))
3113 return FALSE;
3114
3115 /* We only implement Properties on /org/freedesktop/DBus so far. */
3116 ih = bus_driver_find_interface (iface, TRUE, error);
3117
3118 if (ih == NULL)
3119 return FALSE;
3120
3121 handler = interface_handler_find_property (ih, prop, error);
3122
3123 if (handler == NULL)
3124 return FALSE;
3125
3126 context = bus_transaction_get_context (transaction);
3127
3128 reply = dbus_message_new_method_return (message);
3129
3130 if (reply == NULL)
3131 goto oom;
3132
3133 dbus_message_iter_init_append (reply, &iter);
3134
3135 if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT,
3136 handler->type, &var_iter))
3137 goto oom;
3138
3139 if (!handler->getter (context, &var_iter))
3140 {
3141 dbus_message_iter_abandon_container (&iter, &var_iter);
3142 goto oom;
3143 }
3144
3145 if (!dbus_message_iter_close_container (&iter, &var_iter))
3146 goto oom;
3147
3148 if (!bus_transaction_send_from_driver (transaction, connection, reply))
3149 goto oom;
3150
3151 dbus_message_unref (reply);
3152 return TRUE;
3153
3154 oom:
3155 if (reply != NULL)
3156 dbus_message_unref (reply);
3157
3158 BUS_SET_OOM (error);
3159 return FALSE;
3160 }
3161
3162 static dbus_bool_t
bus_driver_handle_get_all(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)3163 bus_driver_handle_get_all (DBusConnection *connection,
3164 BusTransaction *transaction,
3165 DBusMessage *message,
3166 DBusError *error)
3167 {
3168 const InterfaceHandler *ih;
3169 const char *iface;
3170 const PropertyHandler *ph;
3171 DBusMessageIter reply_iter;
3172 DBusMessageIter array_iter;
3173 BusContext *context;
3174 DBusMessage *reply = NULL;
3175
3176 /* The message signature has already been checked for us,
3177 * so this should always succeed. */
3178 if (!dbus_message_get_args (message, error,
3179 DBUS_TYPE_STRING, &iface,
3180 DBUS_TYPE_INVALID))
3181 return FALSE;
3182
3183 /* We only implement Properties on /org/freedesktop/DBus so far. */
3184 ih = bus_driver_find_interface (iface, TRUE, error);
3185
3186 if (ih == NULL)
3187 return FALSE;
3188
3189 context = bus_transaction_get_context (transaction);
3190
3191 reply = _dbus_asv_new_method_return (message, &reply_iter, &array_iter);
3192
3193 if (reply == NULL)
3194 goto oom;
3195
3196 for (ph = ih->property_handlers; ph != NULL && ph->name != NULL; ph++)
3197 {
3198 DBusMessageIter entry_iter;
3199 DBusMessageIter var_iter;
3200
3201 if (!_dbus_asv_open_entry (&array_iter, &entry_iter, ph->name,
3202 ph->type, &var_iter))
3203 goto oom_abandon_message;
3204
3205 if (!ph->getter (context, &var_iter))
3206 {
3207 _dbus_asv_abandon_entry (&array_iter, &entry_iter, &var_iter);
3208 goto oom_abandon_message;
3209 }
3210
3211 if (!_dbus_asv_close_entry (&array_iter, &entry_iter, &var_iter))
3212 goto oom_abandon_message;
3213 }
3214
3215 if (!_dbus_asv_close (&reply_iter, &array_iter))
3216 goto oom;
3217
3218 if (!bus_transaction_send_from_driver (transaction, connection, reply))
3219 goto oom;
3220
3221 dbus_message_unref (reply);
3222 return TRUE;
3223
3224 oom_abandon_message:
3225 _dbus_asv_abandon (&reply_iter, &array_iter);
3226 /* fall through */
3227 oom:
3228 if (reply != NULL)
3229 dbus_message_unref (reply);
3230
3231 BUS_SET_OOM (error);
3232 return FALSE;
3233 }
3234
3235 static dbus_bool_t
bus_driver_handle_set(DBusConnection * connection,BusTransaction * transaction,DBusMessage * message,DBusError * error)3236 bus_driver_handle_set (DBusConnection *connection,
3237 BusTransaction *transaction,
3238 DBusMessage *message,
3239 DBusError *error)
3240 {
3241 const InterfaceHandler *ih;
3242 const char *iface;
3243 const char *prop;
3244 const PropertyHandler *handler;
3245 DBusMessageIter iter;
3246
3247 /* We already checked this in bus_driver_handle_message() */
3248 _dbus_assert (dbus_message_has_signature (message, "ssv"));
3249
3250 if (!dbus_message_iter_init (message, &iter))
3251 _dbus_assert_not_reached ("Message type was already checked to be 'ssv'");
3252
3253 dbus_message_iter_get_basic (&iter, &iface);
3254
3255 if (!dbus_message_iter_next (&iter))
3256 _dbus_assert_not_reached ("Message type was already checked to be 'ssv'");
3257
3258 dbus_message_iter_get_basic (&iter, &prop);
3259
3260 /* We only implement Properties on /org/freedesktop/DBus so far. */
3261 ih = bus_driver_find_interface (iface, TRUE, error);
3262
3263 if (ih == NULL)
3264 return FALSE;
3265
3266 handler = interface_handler_find_property (ih, prop, error);
3267
3268 if (handler == NULL)
3269 return FALSE;
3270
3271 /* We don't implement any properties that can be set yet. */
3272 dbus_set_error (error, DBUS_ERROR_PROPERTY_READ_ONLY,
3273 "Property '%s.%s' cannot be set", iface, prop);
3274 return FALSE;
3275 }
3276