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