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