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