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